Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net/lagg lagg: renew MAC addresses to change the value o...
details: https://anonhg.NetBSD.org/src/rev/28e8d3425871
branches: trunk
changeset: 1025163:28e8d3425871
user: yamaguchi <yamaguchi%NetBSD.org@localhost>
date: Mon Nov 08 06:22:16 2021 +0000
description:
lagg: renew MAC addresses to change the value of interface type
The interface type(ifnet::if_type) is changed on adding to lagg(4)
and deleting from it.
diffstat:
sys/net/lagg/if_lagg.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 124 insertions(+), 8 deletions(-)
diffs (190 lines):
diff -r 14181d6e8e2d -r 28e8d3425871 sys/net/lagg/if_lagg.c
--- a/sys/net/lagg/if_lagg.c Mon Nov 08 06:17:05 2021 +0000
+++ b/sys/net/lagg/if_lagg.c Mon Nov 08 06:22:16 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_lagg.c,v 1.18 2021/11/08 06:17:05 yamaguchi Exp $ */
+/* $NetBSD: if_lagg.c,v 1.19 2021/11/08 06:22:16 yamaguchi Exp $ */
/*
* Copyright (c) 2005, 2006 Reyk Floeter <reyk%openbsd.org@localhost>
@@ -20,7 +20,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.18 2021/11/08 06:17:05 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.19 2021/11/08 06:22:16 yamaguchi Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -31,6 +31,7 @@
#include <sys/types.h>
#include <sys/cprng.h>
+#include <sys/cpu.h>
#include <sys/device.h>
#include <sys/evcnt.h>
#include <sys/hash.h>
@@ -133,6 +134,7 @@
},
};
+static int lagg_chg_sadl(struct ifnet *, uint8_t *, size_t);
static struct mbuf *
lagg_input_ethernet(struct ifnet *, struct mbuf *);
static int lagg_clone_create(struct if_clone *, int);
@@ -2086,8 +2088,8 @@
break;
}
- if_set_sadl(ifp_port, lladdr,
- ETHER_ADDR_LEN, false);
+ lagg_chg_sadl(ifp_port,
+ lladdr, ETHER_ADDR_LEN);
if (!ISSET(ifp_port->if_flags, IFF_RUNNING)) {
break;
@@ -2123,11 +2125,11 @@
switch (lp->lp_iftype) {
case IFT_ETHER:
- /* reset if_type before if_set_sadl */
+ /* reset if_type before changing ifp->if_sadl */
ifp_port->if_type = lp->lp_iftype;
- if_set_sadl(ifp_port, lp->lp_lladdr,
- ETHER_ADDR_LEN, false);
+ lagg_chg_sadl(ifp_port,
+ lp->lp_lladdr, ETHER_ADDR_LEN);
if (!ISSET(ifp_port->if_flags, IFF_RUNNING)) {
break;
@@ -2237,7 +2239,7 @@
if (lagg_lladdr_equal(lladdr_prev, lladdr) == false)
return;
- if_set_sadl(ifp, sc->sc_lladdr, ETHER_ADDR_LEN, false);
+ lagg_chg_sadl(ifp, sc->sc_lladdr, ETHER_ADDR_LEN);
LAGG_PORTS_FOREACH(sc, lp) {
IFNET_LOCK(lp->lp_ifp);
@@ -2899,6 +2901,120 @@
workqueue_wait(wq, &lw->lw_cookie);
}
+static int
+lagg_chg_sadl(struct ifnet *ifp, uint8_t *lla, size_t lla_len)
+{
+ struct psref psref_cur, psref_next;
+ struct ifaddr *ifa_cur, *ifa_next, *ifa_lla;
+ const struct sockaddr_dl *sdl, *nsdl;
+ int s, error;
+
+ KASSERT(!cpu_intr_p() && !cpu_softintr_p());
+ KASSERT(IFNET_LOCKED(ifp));
+ KASSERT(ifp->if_addrlen == lla_len);
+
+ error = 0;
+ ifa_lla = NULL;
+
+ while (1) {
+ s = pserialize_read_enter();
+ IFADDR_READER_FOREACH(ifa_cur, ifp) {
+ sdl = satocsdl(ifa_cur->ifa_addr);
+ if (sdl->sdl_family != AF_LINK)
+ continue;
+
+ if (sdl->sdl_type != ifp->if_type) {
+ ifa_acquire(ifa_cur, &psref_cur);
+ break;
+ }
+ }
+ pserialize_read_exit(s);
+
+ if (ifa_cur == NULL)
+ break;
+
+ ifa_next = if_dl_create(ifp, &nsdl);
+ if (ifa_next == NULL) {
+ error = ENOMEM;
+ ifa_release(ifa_cur, &psref_cur);
+ goto done;
+ }
+ ifa_acquire(ifa_next, &psref_next);
+ (void)sockaddr_dl_setaddr(__UNCONST(nsdl), nsdl->sdl_len,
+ CLLADDR(sdl), ifp->if_addrlen);
+ ifa_insert(ifp, ifa_next);
+
+ if (ifa_lla == NULL &&
+ memcmp(CLLADDR(sdl), lla, lla_len) == 0) {
+ ifa_lla = ifa_next;
+ ifaref(ifa_lla);
+ }
+
+ if (ifa_cur == ifp->if_dl)
+ if_activate_sadl(ifp, ifa_next, nsdl);
+
+ if (ifa_cur == ifp->if_hwdl) {
+ ifp->if_hwdl = ifa_next;
+ ifaref(ifa_next);
+ ifafree(ifa_cur);
+ }
+
+ ifaref(ifa_cur);
+ ifa_release(ifa_cur, &psref_cur);
+ ifa_remove(ifp, ifa_cur);
+ KASSERTMSG(ifa_cur->ifa_refcnt == 1,
+ "ifa_refcnt=%d", ifa_cur->ifa_refcnt);
+ ifafree(ifa_cur);
+ ifa_release(ifa_next, &psref_next);
+ }
+
+ if (ifa_lla != NULL) {
+ ifa_next = ifa_lla;
+
+ ifa_acquire(ifa_next, &psref_next);
+ ifafree(ifa_lla);
+
+ nsdl = satocsdl(ifa_next->ifa_addr);
+ } else {
+ ifa_next = if_dl_create(ifp, &nsdl);
+ if (ifa_next == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+ ifa_acquire(ifa_next, &psref_next);
+ (void)sockaddr_dl_setaddr(__UNCONST(nsdl),
+ nsdl->sdl_len, lla, ifp->if_addrlen);
+ ifa_insert(ifp, ifa_next);
+ }
+
+ if (ifa_next != ifp->if_dl) {
+ ifa_cur = ifp->if_dl;
+ if (ifa_cur != NULL)
+ ifa_acquire(ifa_cur, &psref_cur);
+
+ if_activate_sadl(ifp, ifa_next, nsdl);
+
+ if (ifa_cur != NULL) {
+ if (ifa_cur != ifp->if_hwdl) {
+ ifaref(ifa_cur);
+ ifa_release(ifa_cur, &psref_cur);
+ ifa_remove(ifp, ifa_cur);
+ KASSERTMSG(ifa_cur->ifa_refcnt == 1,
+ "ifa_refcnt=%d",
+ ifa_cur->ifa_refcnt);
+ ifafree(ifa_cur);
+ } else {
+ ifa_release(ifa_cur, &psref_cur);
+ }
+ }
+ }
+
+ ifa_release(ifa_next, &psref_next);
+
+done:
+ return error;
+}
+
/*
* Module infrastructure
*/
Home |
Main Index |
Thread Index |
Old Index