Module Name: src
Committed By: yamaguchi
Date: Mon Nov 8 06:22:16 UTC 2021
Modified Files:
src/sys/net/lagg: if_lagg.c
Log Message:
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.
To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.19 src/sys/net/lagg/if_lagg.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/net/lagg/if_lagg.c
diff -u src/sys/net/lagg/if_lagg.c:1.18 src/sys/net/lagg/if_lagg.c:1.19
--- src/sys/net/lagg/if_lagg.c:1.18 Mon Nov 8 06:17:05 2021
+++ src/sys/net/lagg/if_lagg.c Mon Nov 8 06:22:16 2021
@@ -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 <[email protected]>
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v
#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 const struct lagg_proto lagg_prot
},
};
+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 @@ lagg_port_setsadl(struct lagg_port *lp,
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 @@ lagg_port_unsetsadl(struct lagg_port *lp
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 @@ lagg_sadl_update(struct lagg_softc *sc,
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 @@ lagg_workq_wait(struct workqueue *wq, st
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
*/