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