Module Name: src Committed By: yamaguchi Date: Tue Oct 19 07:52:33 UTC 2021
Modified Files: src/sys/net/lagg: if_lagg.c if_lagg_lacp.c if_laggproto.h Log Message: lagg: support l2tp(4) aggregation - Accept "ifconfig lagg* laggport l2tp*" - Set promiscuous mode when the added interface is l2tp* - check IFF_UP in addition to IFF_RUNNING on SIOCSIFFLAGS to a child interface. To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/sys/net/lagg/if_lagg.c cvs rdiff -u -r1.5 -r1.6 src/sys/net/lagg/if_lagg_lacp.c cvs rdiff -u -r1.8 -r1.9 src/sys/net/lagg/if_laggproto.h 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.14 src/sys/net/lagg/if_lagg.c:1.15 --- src/sys/net/lagg/if_lagg.c:1.14 Tue Oct 19 07:40:52 2021 +++ src/sys/net/lagg/if_lagg.c Tue Oct 19 07:52:33 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_lagg.c,v 1.14 2021/10/19 07:40:52 yamaguchi Exp $ */ +/* $NetBSD: if_lagg.c,v 1.15 2021/10/19 07:52:33 yamaguchi Exp $ */ /* * Copyright (c) 2005, 2006 Reyk Floeter <r...@openbsd.org> @@ -20,7 +20,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.14 2021/10/19 07:40:52 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.15 2021/10/19 07:52:33 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1141,6 +1141,7 @@ lagg_input_ethernet(struct ifnet *ifp_po m = lagg_proto_input(lp->lp_softc, lp, m); if (m != NULL) { m_set_rcvif(m, ifp); + m->m_flags &= ~M_PROMISC; if_input(ifp, m); m = NULL; } @@ -2073,25 +2074,81 @@ lagg_port_setsadl(struct lagg_port *lp, KASSERT(LAGG_LOCKED(lp->lp_softc)); KASSERT(IFNET_LOCKED(ifp_port)); - lladdr_changed = false; - if (iftype_changed) { - lladdr_changed = true; - } else if (lagg_lladdr_equal(lladdr, - CLLADDR(ifp_port->if_sadl)) == false) { - lladdr_changed = true; - } + switch (lp->lp_iftype) { + case IFT_ETHER: + lladdr_changed = lagg_lladdr_equal(lladdr, + CLLADDR(ifp_port->if_sadl)) ? false : true; + + if (lladdr_changed == false && + iftype_changed == false) { + break; + } - if (lladdr_changed) { if_set_sadl(ifp_port, lladdr, ETHER_ADDR_LEN, false); - if (ISSET(ifp_port->if_flags, IFF_RUNNING)) { - error = ifp_port->if_init(ifp_port); - if (error != 0) { - lagg_log(lp->lp_softc, LOG_WARNING, - "%s failed to if_init() on %d\n", - ifp_port->if_xname, error); - } + + if (!ISSET(ifp_port->if_flags, IFF_RUNNING)) { + break; + } + + error = ifp_port->if_init(ifp_port); + if (error != 0) { + lagg_log(lp->lp_softc, LOG_WARNING, + "%s failed to if_init() on %d\n", + ifp_port->if_xname, error); + } + break; + default: + if_alloc_sadl(ifp_port); + if (lp->lp_promisc == false) { + ifpromisc_locked(ifp_port, 1); + lp->lp_promisc = true; + } + break; + } +} + +static void +lagg_port_unsetsadl(struct lagg_port *lp) +{ + struct ifnet *ifp_port; + int error; + + ifp_port = lp->lp_ifp; + + KASSERT(LAGG_LOCKED(lp->lp_softc)); + KASSERT(IFNET_LOCKED(ifp_port)); + + switch (lp->lp_iftype) { + case IFT_ETHER: + /* reset if_type before if_set_sadl */ + ifp_port->if_type = lp->lp_iftype; + + if_set_sadl(ifp_port, lp->lp_lladdr, + ETHER_ADDR_LEN, false); + + if (!ISSET(ifp_port->if_flags, IFF_RUNNING)) { + break; + } + + error = ifp_port->if_init(ifp_port); + if (error != 0) { + lagg_log(lp->lp_softc, LOG_WARNING, + "%s failed to if_init() on %d\n", + ifp_port->if_xname, error); } + break; + + default: + /* reset if_type before if_alloc_sadl */ + ifp_port->if_type = lp->lp_iftype; + if_alloc_sadl(ifp_port); + + if (lp->lp_promisc == true) { + ifpromisc_locked(ifp_port, 0); + lp->lp_promisc = false; + } + break; } } @@ -2152,11 +2209,9 @@ lagg_lladdr_update(struct lagg_softc *sc lagg_lladdr_cpy(sc->sc_lladdr, lladdr); LAGG_PORTS_FOREACH(sc, lp) { - if (lp->lp_iftype == IFT_ETHER) { - IFNET_LOCK(lp->lp_ifp); - lagg_port_setsadl(lp, sc->sc_lladdr, false); - IFNET_UNLOCK(lp->lp_ifp); - } + IFNET_LOCK(lp->lp_ifp); + lagg_port_setsadl(lp, sc->sc_lladdr, false); + IFNET_UNLOCK(lp->lp_ifp); } } @@ -2217,6 +2272,7 @@ lagg_port_setup(struct lagg_softc *sc, switch (ifp_port->if_type) { case IFT_ETHER: case IFT_L2VLAN: + case IFT_L2TP: if_type = IFT_IEEE8023ADLAG; break; default: @@ -2253,7 +2309,8 @@ lagg_port_setup(struct lagg_softc *sc, iftype_changed = (lp->lp_iftype != ifp_port->if_type); - if (ISSET(ifp_port->if_flags, IFF_RUNNING)) { + if (ISSET(ifp_port->if_flags, IFF_RUNNING) && + ifp_port->if_init != NULL) { ifp_port->if_stop(ifp_port, 0); stopped = true; } @@ -2268,8 +2325,8 @@ lagg_port_setup(struct lagg_softc *sc, if (lp->lp_iftype == IFT_ETHER) { lagg_setup_lladdr(sc, lp); - lagg_port_setsadl(lp, sc->sc_lladdr, iftype_changed); } + lagg_port_setsadl(lp, sc->sc_lladdr, iftype_changed); IFNET_UNLOCK(ifp_port); @@ -2307,11 +2364,8 @@ remove_port: teardown_lladdr: IFNET_LOCK(ifp_port); lagg_teardown_mtu(sc, lp); + lagg_port_unsetsadl(lp); if (lp->lp_iftype == IFT_ETHER) { - /* restore iftype before if_set_sadl */ - ifp_port->if_type = lp->lp_iftype; - lagg_port_setsadl(lp, lp->lp_lladdr, iftype_changed); - lagg_teardown_lladdr(sc, lp); } restore_ipv6lla: @@ -2345,7 +2399,7 @@ lagg_port_teardown(struct lagg_softc *sc bool is_ifdetach) { struct ifnet *ifp_port; - bool stopped, iftype_changed; + bool stopped; KASSERT(LAGG_LOCKED(sc)); @@ -2376,12 +2430,12 @@ lagg_port_teardown(struct lagg_softc *sc lagg_teardown_lladdr(sc, lp); IFNET_LOCK(ifp_port); - if (ISSET(ifp_port->if_flags, IFF_RUNNING)) { + if (ISSET(ifp_port->if_flags, IFF_RUNNING) && + ifp_port->if_init != NULL) { ifp_port->if_stop(ifp_port, 0); stopped = true; } - iftype_changed = (ifp_port->if_type != lp->lp_iftype); ifp_port->if_type = lp->lp_iftype; if (ifp_port->if_ioctl == lagg_port_ioctl) ifp_port->if_ioctl = lp->lp_ioctl; @@ -2400,9 +2454,7 @@ lagg_port_teardown(struct lagg_softc *sc lagg_setethcaps(lp, lp->lp_eccapenable); IFNET_LOCK(ifp_port); - if (ifp_port->if_type == IFT_ETHER) - lagg_port_setsadl(lp, lp->lp_lladdr, iftype_changed); - + lagg_port_unsetsadl(lp); lagg_in6_ifattach(ifp_port); IFNET_UNLOCK(ifp_port); } @@ -2638,7 +2690,7 @@ lagg_port_ioctl(struct ifnet *ifp, u_lon error = LAGG_PORT_IOCTL(lp, cmd, data); ifflags ^= ifp->if_flags; - if (ISSET(ifflags, IFF_RUNNING)) { + if ((ifflags & (IFF_UP | IFF_RUNNING)) != 0) { lagg_proto_linkstate(sc, lp); } break; Index: src/sys/net/lagg/if_lagg_lacp.c diff -u src/sys/net/lagg/if_lagg_lacp.c:1.5 src/sys/net/lagg/if_lagg_lacp.c:1.6 --- src/sys/net/lagg/if_lagg_lacp.c:1.5 Sat Oct 2 22:14:32 2021 +++ src/sys/net/lagg/if_lagg_lacp.c Tue Oct 19 07:52:33 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_lagg_lacp.c,v 1.5 2021/10/02 22:14:32 mrg Exp $ */ +/* $NetBSD: if_lagg_lacp.c,v 1.6 2021/10/19 07:52:33 yamaguchi Exp $ */ /*- * SPDX-License-Identifier: BSD-2-Clause-NetBSD @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.5 2021/10/02 22:14:32 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.6 2021/10/19 07:52:33 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_lagg.h" @@ -111,6 +111,7 @@ struct lacp_portinfo { struct lacp_port { struct lagg_port *lp_laggport; + bool lp_added_multi; int lp_timer[LACP_NTIMER]; uint32_t lp_marker_xid; enum lacp_selected lp_selected; @@ -629,6 +630,7 @@ lacp_allocport(struct lagg_proto_softc * struct lacp_softc *lsc; struct lacp_port *lacpp; struct ifreq ifr; + bool added_multi; int error; lsc = (struct lacp_softc *)xlsc; @@ -641,7 +643,14 @@ lacp_allocport(struct lagg_proto_softc * error = lp->lp_ioctl(lp->lp_ifp, SIOCADDMULTI, (void *)&ifr); IFNET_UNLOCK(lp->lp_ifp); - if (error != 0) { + switch (error) { + case 0: + added_multi = true; + break; + case EAFNOSUPPORT: + added_multi = false; + break; + default: lagg_log(sc, LOG_ERR, "SIOCADDMULTI failed on %s\n", lp->lp_ifp->if_xname); return error; @@ -651,6 +660,7 @@ lacp_allocport(struct lagg_proto_softc * if (lacpp == NULL) return ENOMEM; + lacpp->lp_added_multi = added_multi; lagg_work_set(&lacpp->lp_work_smtx, lacp_sm_tx_work, lsc); lagg_work_set(&lacpp->lp_work_marker, lacp_marker_work, lsc); @@ -715,11 +725,13 @@ lacp_freeport(struct lagg_proto_softc *x lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_smtx); lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_marker); - lacp_mcastaddr(&ifr, LACP_PORT_XNAME(lacpp)); + if (lacpp->lp_added_multi) { + lacp_mcastaddr(&ifr, LACP_PORT_XNAME(lacpp)); - IFNET_LOCK(lp->lp_ifp); - (void)lp->lp_ioctl(lp->lp_ifp, SIOCDELMULTI, (void *)&ifr); - IFNET_UNLOCK(lp->lp_ifp); + IFNET_LOCK(lp->lp_ifp); + (void)lp->lp_ioctl(lp->lp_ifp, SIOCDELMULTI, (void *)&ifr); + IFNET_UNLOCK(lp->lp_ifp); + } lp->lp_proto_ctx = NULL; kmem_free(lacpp, sizeof(*lacpp)); Index: src/sys/net/lagg/if_laggproto.h diff -u src/sys/net/lagg/if_laggproto.h:1.8 src/sys/net/lagg/if_laggproto.h:1.9 --- src/sys/net/lagg/if_laggproto.h:1.8 Tue Oct 12 08:30:58 2021 +++ src/sys/net/lagg/if_laggproto.h Tue Oct 19 07:52:33 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_laggproto.h,v 1.8 2021/10/12 08:30:58 yamaguchi Exp $ */ +/* $NetBSD: if_laggproto.h,v 1.9 2021/10/19 07:52:33 yamaguchi Exp $ */ /* * Copyright (c) 2021 Internet Initiative Japan Inc. @@ -68,6 +68,7 @@ struct lagg_port { struct lagg_softc *lp_softc; /* parent lagg */ void *lp_proto_ctx; bool lp_ifdetaching; + bool lp_promisc; void *lp_linkstate_hook; void *lp_ifdetach_hook; @@ -215,7 +216,6 @@ struct lagg_softc { (_lp)->lp_ioctl == NULL ? ENOTTY : \ (_lp)->lp_ioctl((_lp)->lp_ifp, (_cmd), (_data)) - static inline const void * lagg_m_extract(struct mbuf *m, size_t off, size_t reqlen, void *buf) {