Module Name: src
Committed By: yamaguchi
Date: Fri Apr 1 07:26:51 UTC 2022
Modified Files:
src/sys/net/lagg: if_lagg.c if_lagg_lacp.c
Log Message:
lagg(4): reimplement add and delete port
The IFNET_LOCK for the adding or deleting port became to
be held the whole time while the ifnet of the port is changed.
To generate a diff of this commit:
cvs rdiff -u -r1.44 -r1.45 src/sys/net/lagg/if_lagg.c
cvs rdiff -u -r1.21 -r1.22 src/sys/net/lagg/if_lagg_lacp.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.44 src/sys/net/lagg/if_lagg.c:1.45
--- src/sys/net/lagg/if_lagg.c:1.44 Thu Mar 31 07:59:05 2022
+++ src/sys/net/lagg/if_lagg.c Fri Apr 1 07:26:51 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: if_lagg.c,v 1.44 2022/03/31 07:59:05 yamaguchi Exp $ */
+/* $NetBSD: if_lagg.c,v 1.45 2022/04/01 07:26:51 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.44 2022/03/31 07:59:05 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.45 2022/04/01 07:26:51 yamaguchi Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -133,7 +133,7 @@ static const struct lagg_proto lagg_prot
},
};
-static int lagg_chg_sadl(struct ifnet *, uint8_t *, size_t);
+static int lagg_chg_sadl(struct ifnet *, const uint8_t *, size_t);
static struct mbuf *
lagg_input_ethernet(struct ifnet *, struct mbuf *);
static int lagg_clone_create(struct if_clone *, int);
@@ -195,10 +195,10 @@ static void lagg_port_teardown(struct la
bool);
static void lagg_port_syncvlan(struct lagg_softc *, struct lagg_port *);
static void lagg_port_purgevlan(struct lagg_softc *, struct lagg_port *);
-static void lagg_lladdr_update(struct lagg_softc *);
static void lagg_capabilities_update(struct lagg_softc *);
static void lagg_sync_ifcaps(struct lagg_softc *);
static void lagg_sync_ethcaps(struct lagg_softc *);
+static void lagg_sync_sadl(struct lagg_softc *);
static struct if_clone lagg_cloner =
IF_CLONE_INITIALIZER("lagg", lagg_clone_create, lagg_clone_destroy);
@@ -212,11 +212,13 @@ static enum lagg_iftypes
lagg_iftype = LAGG_IF_TYPE_ETHERNET;
#ifdef LAGG_DEBUG
+#define __LAGGDEBUGUSED
#define LAGG_DPRINTF(_sc, _fmt, _args...) do { \
printf("%s: " _fmt, (_sc) != NULL ? \
(_sc)->sc_if.if_xname : "lagg", ##_args); \
} while (0)
#else
+#define __LAGGDEBUGUSED __unused
#define LAGG_DPRINTF(_sc, _fmt, _args...) __nothing
#endif
@@ -413,7 +415,7 @@ lagg_clone_create(struct if_clone *ifc,
sc->sc_lladdr_rand[0] |= 0x02; /* set G/L bit */
lagg_lladdr_cpy(sc->sc_lladdr, sc->sc_lladdr_rand);
ether_set_vlan_cb((struct ethercom *)ifp, lagg_vlan_cb);
- ether_ifattach(ifp, sc->sc_lladdr);
+ ether_ifattach(ifp, sc->sc_lladdr_rand);
break;
default:
panic("unknown if type");
@@ -500,7 +502,7 @@ lagg_init_locked(struct lagg_softc *sc)
if (ISSET(ifp->if_flags, IFF_RUNNING))
lagg_stop_locked(sc);
- lagg_lladdr_update(sc);
+ lagg_sync_sadl(sc);
SET(ifp->if_flags, IFF_RUNNING);
@@ -2009,85 +2011,42 @@ lagg_capabilities_update(struct lagg_sof
}
static int
-lagg_setup_mtu(struct lagg_softc *sc, struct lagg_port *lp)
+lagg_setmtu(struct ifnet *ifp, uint64_t mtu)
{
- struct ifnet *ifp, *ifp_port;
+ struct lagg_softc *sc __LAGGDEBUGUSED;
+ struct lagg_port *lp;
struct ifreq ifr;
int error;
- ifp = &sc->sc_if;
- ifp_port = lp->lp_ifp;
-
- KASSERT(IFNET_LOCKED(ifp_port));
+ KASSERT(IFNET_LOCKED(ifp));
- error = 0;
memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_mtu = mtu;
+ lp = ifp->if_lagg;
- if (SIMPLEQ_EMPTY(&sc->sc_ports)) {
- ifr.ifr_mtu = lp->lp_mtu;
-
- if (ifp->if_mtu != (uint64_t)ifr.ifr_mtu) {
- KASSERT(IFNET_LOCKED(ifp));
- error = ether_ioctl(ifp, SIOCSIFMTU, &ifr);
- }
+ if (lp != NULL) {
+ /* ioctl for port interface */
+ error = lp->lp_ioctl(ifp, SIOCSIFMTU, &ifr);
+ sc = lp->lp_softc;
} else {
- ifr.ifr_mtu = sc->sc_if.if_mtu;
-
- if (lp->lp_mtu != (uint64_t)ifr.ifr_mtu) {
- if (lp->lp_ioctl == NULL) {
- LAGG_DPRINTF(sc,
- "cannot change MTU for %s\n",
- ifp_port->if_xname);
- return EINVAL;
- }
+ /* ioctl for lagg interface */
+ error = ether_ioctl(ifp, SIOCSIFMTU, &ifr);
+ sc = ifp->if_softc;
+ }
- strlcpy(ifr.ifr_name, ifp_port->if_xname,
- sizeof(ifr.ifr_name));
- error = lp->lp_ioctl(ifp_port,
- SIOCSIFMTU, (void *)&ifr);
- if (error != 0) {
- LAGG_DPRINTF(sc,
- "invalid MTU %d for %s\n",
- ifr.ifr_mtu, ifp_port->if_xname);
- }
- }
+ if (error != 0) {
+ LAGG_DPRINTF(sc,
+ "couldn't change MTU for %s\n",
+ ifp->if_xname);
}
return error;
}
static void
-lagg_teardown_mtu(struct lagg_softc *sc, struct lagg_port *lp)
-{
- struct ifnet *ifp_port;
- struct ifreq ifr;
- int error;
-
- if (lp->lp_ioctl == NULL)
- return;
-
- ifp_port = lp->lp_ifp;
- KASSERT(IFNET_LOCKED(ifp_port));
-
- if (ifp_port->if_mtu != lp->lp_mtu) {
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifp_port->if_xname, sizeof(ifr.ifr_name));
- ifr.ifr_mtu = lp->lp_mtu;
- error = lp->lp_ioctl(ifp_port, SIOCSIFMTU, (void *)&ifr);
- if (error != 0) {
- LAGG_LOG(sc, LOG_WARNING,
- "failed to reset MTU %d to %s\n",
- ifr.ifr_mtu, ifp_port->if_xname);
- }
- }
-}
-
-static void
-lagg_port_setsadl(struct lagg_port *lp, uint8_t *lladdr,
- bool iftype_changed)
+lagg_port_setsadl(struct lagg_port *lp, const uint8_t *lladdr)
{
struct ifnet *ifp_port;
- bool lladdr_changed;
int error;
ifp_port = lp->lp_ifp;
@@ -2097,58 +2056,16 @@ lagg_port_setsadl(struct lagg_port *lp,
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;
- }
-
- lagg_chg_sadl(ifp_port,
- lladdr, ETHER_ADDR_LEN);
-
- if (ifp_port->if_init != NULL) {
- error = 0;
- if (ISSET(ifp_port->if_flags, IFF_RUNNING))
- error = 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 (lladdr == NULL) {
+ lladdr = lp->lp_lladdr;
} else {
- if (lp->lp_promisc == false) {
- ifpromisc_locked(ifp_port, 1);
- lp->lp_promisc = true;
- }
+ if (lagg_lladdr_equal(lladdr,
+ CLLADDR(ifp_port->if_sadl)))
+ break;
}
- break;
- default:
- if_alloc_sadl(ifp_port);
- 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 changing ifp->if_sadl */
- ifp_port->if_type = lp->lp_iftype;
lagg_chg_sadl(ifp_port,
- lp->lp_lladdr, ETHER_ADDR_LEN);
+ lladdr, ETHER_ADDR_LEN);
if (ifp_port->if_init != NULL) {
error = 0;
@@ -2160,129 +2077,74 @@ lagg_port_unsetsadl(struct lagg_port *lp
"%s failed to if_init() on %d\n",
ifp_port->if_xname, error);
}
- } else {
- if (lp->lp_promisc == true) {
- ifpromisc_locked(ifp_port, 0);
- lp->lp_promisc = false;
- }
}
break;
-
default:
- /* reset if_type before if_alloc_sadl */
- ifp_port->if_type = lp->lp_iftype;
if_alloc_sadl(ifp_port);
break;
}
}
static void
-lagg_setup_lladdr(struct lagg_softc *sc, struct lagg_port *lp)
-{
-
- KASSERT(LAGG_LOCKED(sc));
-
- if (lagg_lladdr_equal(sc->sc_lladdr, sc->sc_lladdr_rand))
- lagg_lladdr_cpy(sc->sc_lladdr, lp->lp_lladdr);
-}
-
-static void
-lagg_teardown_lladdr(struct lagg_softc *sc, struct lagg_port *lp)
-{
- struct lagg_port *lp0;
- uint8_t *lladdr_next;
-
- KASSERT(LAGG_LOCKED(sc));
-
- if (lagg_lladdr_equal(sc->sc_lladdr,
- lp->lp_lladdr) == false) {
- return;
- }
-
- lladdr_next = sc->sc_lladdr_rand;
-
- LAGG_PORTS_FOREACH(sc, lp0) {
- if (lp0->lp_iftype == IFT_ETHER) {
- lladdr_next = lp0->lp_lladdr;
- break;
- }
- }
-
- lagg_lladdr_cpy(sc->sc_lladdr, lladdr_next);
-}
-
-static void
-lagg_lladdr_update(struct lagg_softc *sc)
+lagg_if_setsadl(struct lagg_softc *sc, uint8_t *lladdr)
{
struct ifnet *ifp;
- struct lagg_port *lp;
- const uint8_t *lladdr;
-
- ifp = &sc->sc_if;
KASSERT(LAGG_LOCKED(sc));
- KASSERT(IFNET_LOCKED(ifp));
- KASSERT(!ISSET(ifp->if_flags, IFF_RUNNING));
- lladdr = CLLADDR(ifp->if_sadl);
+ ifp = &sc->sc_if;
- if (lagg_lladdr_equal(sc->sc_lladdr, lladdr))
+ if (lagg_lladdr_equal(CLLADDR(ifp->if_sadl), lladdr))
return;
- lagg_lladdr_cpy(sc->sc_lladdr, lladdr);
+ lagg_chg_sadl(ifp, lladdr, ETHER_ADDR_LEN);
- LAGG_PORTS_FOREACH(sc, lp) {
- IFNET_LOCK(lp->lp_ifp);
- lagg_port_setsadl(lp, sc->sc_lladdr, false);
- IFNET_UNLOCK(lp->lp_ifp);
- }
+ LAGG_UNLOCK(sc);
+ lagg_in6_ifdetach(ifp);
+ lagg_in6_ifattach(ifp);
+ LAGG_LOCK(sc);
+
+ lagg_sync_sadl(sc);
}
static void
-lagg_sadl_update(struct lagg_softc *sc, uint8_t *lladdr_prev)
+lagg_sync_sadl(struct lagg_softc *sc)
{
struct ifnet *ifp;
struct lagg_port *lp;
- const uint8_t *lladdr;
+ const uint8_t *lla;
ifp = &sc->sc_if;
-
- KASSERT(LAGG_LOCKED(sc));
KASSERT(IFNET_LOCKED(ifp));
- lladdr = CLLADDR(ifp->if_sadl);
-
- if (lagg_lladdr_equal(sc->sc_lladdr, lladdr))
- return;
-
- if (lagg_lladdr_equal(lladdr_prev, lladdr) == false)
+ lla = CLLADDR(ifp->if_sadl);
+ if (lagg_lladdr_equal(lla, sc->sc_lladdr))
return;
- lagg_chg_sadl(ifp, sc->sc_lladdr, ETHER_ADDR_LEN);
+ lagg_lladdr_cpy(sc->sc_lladdr, lla);
LAGG_PORTS_FOREACH(sc, lp) {
IFNET_LOCK(lp->lp_ifp);
- lagg_port_setsadl(lp, sc->sc_lladdr, false);
+ lagg_port_setsadl(lp, lla);
IFNET_UNLOCK(lp->lp_ifp);
}
-
- LAGG_UNLOCK(sc);
- lagg_in6_ifdetach(ifp);
- lagg_in6_ifattach(ifp);
- LAGG_LOCK(sc);
}
static int
lagg_port_setup(struct lagg_softc *sc,
struct lagg_port *lp, struct ifnet *ifp_port)
{
+ struct ifnet *ifp;
u_char if_type;
int error;
- bool stopped, iftype_changed;
+ bool stopped, is_1st_port;
KASSERT(LAGG_LOCKED(sc));
IFNET_ASSERT_UNLOCKED(ifp_port);
+ ifp = &sc->sc_if;
+ is_1st_port = SIMPLEQ_EMPTY(&sc->sc_ports);
+
if (&sc->sc_if == ifp_port) {
LAGG_DPRINTF(sc, "cannot add a lagg to itself as a port\n");
return EINVAL;
@@ -2318,6 +2180,17 @@ lagg_port_setup(struct lagg_softc *sc,
psref_target_init(&lp->lp_psref, lagg_port_psref_class);
IFNET_LOCK(ifp_port);
+ /* stop packet processing */
+ if (ISSET(ifp_port->if_flags, IFF_RUNNING) &&
+ ifp_port->if_init != NULL) {
+ if_stop(ifp_port, 0);
+ stopped = true;
+ }
+
+ /* to delete ipv6 link local address */
+ lagg_in6_ifdetach(ifp_port);
+
+ /* backup members */
lp->lp_iftype = ifp_port->if_type;
lp->lp_ioctl = ifp_port->if_ioctl;
lp->lp_output = ifp_port->if_output;
@@ -2331,81 +2204,85 @@ lagg_port_setup(struct lagg_softc *sc,
lp->lp_eccapenable = ec->ec_capenable;
}
+ /* change callbacks and others */
+ atomic_store_release(&ifp_port->if_lagg, (void *)lp);
ifp_port->if_type = if_type;
ifp_port->if_ioctl = lagg_port_ioctl;
-
- iftype_changed = (lp->lp_iftype != ifp_port->if_type);
-
- if (ISSET(ifp_port->if_flags, IFF_RUNNING) &&
- ifp_port->if_init != NULL) {
- if_stop(ifp_port, 0);
- stopped = true;
+ ifp_port->if_output = lagg_port_output;
+ if (is_1st_port) {
+ if (lp->lp_iftype != ifp_port->if_type)
+ lagg_port_setsadl(lp, NULL);
+ } else {
+ lagg_port_setsadl(lp, CLLADDR(ifp->if_sadl));
+ error = lagg_setmtu(ifp_port, ifp->if_mtu);
+ if (error != 0)
+ goto restore_sadl;
}
- /* to delete ipv6 link local address */
- lagg_in6_ifdetach(ifp_port);
-
- lagg_capabilities_update(sc);
-
- error = lagg_setup_mtu(sc, lp);
+ error = lagg_proto_allocport(sc, lp);
if (error != 0)
- goto restore_ipv6lla;
-
- if (lp->lp_iftype == IFT_ETHER)
- lagg_setup_lladdr(sc, lp);
+ goto restore_mtu;
- lagg_port_setsadl(lp, sc->sc_lladdr, iftype_changed);
+ /* restart packet processing */
+ if (stopped) {
+ error = if_init(ifp_port);
+ if (error != 0)
+ goto free_port;
+ }
+ /* setup of ifp_port is complete */
IFNET_UNLOCK(ifp_port);
- error = lagg_proto_allocport(sc, lp);
- if (error != 0)
- goto teardown_lladdr;
+ if (is_1st_port) {
+ error = lagg_setmtu(ifp, lp->lp_mtu);
+ if (error != 0)
+ goto restore_ifp_port;
+ if (lp->lp_iftype == IFT_ETHER &&
+ lagg_lladdr_equal(sc->sc_lladdr_rand,
+ CLLADDR(ifp->if_sadl))) {
+ lagg_if_setsadl(sc, lp->lp_lladdr);
+ }
+ }
- atomic_store_release(&ifp_port->if_lagg, (void *)lp);
SIMPLEQ_INSERT_TAIL(&sc->sc_ports, lp, lp_entry);
sc->sc_nports++;
+ lagg_capabilities_update(sc);
lagg_port_syncmulti(sc, lp);
lagg_port_syncvlan(sc, lp);
-
- IFNET_LOCK(ifp_port);
- ifp_port->if_output = lagg_port_output;
- if (stopped) {
- if (!ISSET(ifp_port->if_flags, IFF_RUNNING)) {
- error = if_init(ifp_port);
- if (error != 0)
- goto remove_port;
- }
- }
- IFNET_UNLOCK(ifp_port);
-
lagg_config_promisc(sc, lp);
+
lagg_proto_startport(sc, lp);
return 0;
-remove_port:
- SIMPLEQ_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entry);
- sc->sc_nports--;
+restore_ifp_port:
IFNET_LOCK(ifp_port);
- ifp_port->if_output = lp->lp_output;
- IFNET_UNLOCK(ifp_port);
- atomic_store_release(&ifp_port->if_lagg, NULL);
- pserialize_perform(sc->sc_psz);
- lagg_port_purgemulti(sc, lp);
- lagg_port_purgevlan(sc, lp);
+ if (stopped) {
+ if_stop(ifp_port, 0);
+ }
+free_port:
+ KASSERT(IFNET_LOCKED(ifp_port));
lagg_proto_freeport(sc, lp);
-
-teardown_lladdr:
- IFNET_LOCK(ifp_port);
- lagg_teardown_mtu(sc, lp);
- lagg_port_unsetsadl(lp);
- if (lp->lp_iftype == IFT_ETHER)
- lagg_teardown_lladdr(sc, lp);
-restore_ipv6lla:
+restore_mtu:
KASSERT(IFNET_LOCKED(ifp_port));
- lagg_in6_ifdetach(ifp_port);
+ if (ifp_port->if_mtu != lp->lp_mtu)
+ lagg_setmtu(ifp_port, lp->lp_mtu);
+restore_sadl:
+ KASSERT(IFNET_LOCKED(ifp_port));
+
+ /* restore if_type before changing sadl */
+ if_type = ifp_port->if_type;
+ ifp_port->if_type = lp->lp_iftype;
+
+ if (!SIMPLEQ_EMPTY(&sc->sc_ports)) {
+ lagg_port_setsadl(lp, lp->lp_lladdr);
+ } else {
+ if (ifp_port->if_type != if_type)
+ lagg_port_setsadl(lp, NULL);
+ }
+
+ lagg_in6_ifattach(ifp_port);
if (stopped) {
if (if_init(ifp_port) != 0) {
LAGG_LOG(sc, LOG_WARNING,
@@ -2413,10 +2290,10 @@ restore_ipv6lla:
ifp_port->if_xname);
}
}
- ifp_port->if_type = lp->lp_iftype;
- if (ifp_port->if_ioctl == lagg_port_ioctl)
- ifp_port->if_ioctl = lp->lp_ioctl;
+ ifp_port->if_ioctl = lp->lp_ioctl;
+ ifp_port->if_output = lp->lp_output;
+ atomic_store_release(&ifp_port->if_lagg, NULL);
IFNET_UNLOCK(ifp_port);
psref_target_destroy(&lp->lp_psref, lagg_port_psref_class);
@@ -2432,13 +2309,16 @@ static void
lagg_port_teardown(struct lagg_softc *sc, struct lagg_port *lp,
bool is_ifdetach)
{
- struct ifnet *ifp_port;
- bool stopped;
+ struct ifnet *ifp, *ifp_port;
+ bool stopped, is_1st_port, iftype_changed;
KASSERT(LAGG_LOCKED(sc));
+ ifp = &sc->sc_if;
ifp_port = lp->lp_ifp;
stopped = false;
+ is_1st_port =
+ SIMPLEQ_FIRST(&sc->sc_ports) == lp ? true : false;
ether_ifdetachhook_disestablish(ifp_port,
lp->lp_ifdetach_hook, &sc->sc_lock);
@@ -2448,56 +2328,92 @@ lagg_port_teardown(struct lagg_softc *sc
return;
}
+ if_linkstate_change_disestablish(ifp_port,
+ lp->lp_linkstate_hook, NULL);
+
lagg_proto_stopport(sc, lp);
+ lagg_port_purgemulti(sc, lp);
+ lagg_port_purgevlan(sc, lp);
+ if (is_ifdetach == false) {
+ lagg_unconfig_promisc(sc, lp);
+ lagg_setifcaps(lp, lp->lp_ifcapenable);
+ if (lp->lp_iftype == IFT_ETHER)
+ lagg_setethcaps(lp, lp->lp_eccapenable);
+ }
+
+ SIMPLEQ_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entry);
+ sc->sc_nports--;
+
+ if (is_1st_port) {
+ if (lp->lp_iftype == IFT_ETHER &&
+ lagg_lladdr_equal(lp->lp_lladdr,
+ CLLADDR(ifp->if_sadl))) {
+ struct lagg_port *lp0;
+ uint8_t *lla;
+
+ lp0 = SIMPLEQ_FIRST(&sc->sc_ports);
+ if (lp0 != NULL &&
+ lp0->lp_iftype == IFT_ETHER) {
+ lla = lp0->lp_lladdr;
+ } else {
+ lla = sc->sc_lladdr_rand;
+ }
+
+ lagg_if_setsadl(sc, lla);
+ }
+ }
+
IFNET_LOCK(ifp_port);
+ /* stop packet processing */
if (ISSET(ifp_port->if_flags, IFF_RUNNING) &&
ifp_port->if_init != NULL) {
if_stop(ifp_port, 0);
stopped = true;
}
- ifp_port->if_output = lp->lp_output;
- IFNET_UNLOCK(ifp_port);
-
- SIMPLEQ_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entry);
- sc->sc_nports--;
- atomic_store_release(&ifp_port->if_lagg, NULL);
- pserialize_perform(sc->sc_psz);
- if_linkstate_change_disestablish(ifp_port,
- lp->lp_linkstate_hook, NULL);
+ lagg_proto_freeport(sc, lp);
- psref_target_destroy(&lp->lp_psref, lagg_port_psref_class);
+ /* change if_type before set sadl */
+ iftype_changed = ifp_port->if_type != lp->lp_iftype ?
+ true : false;
+ ifp_port->if_type = lp->lp_iftype;
- lagg_port_purgemulti(sc, lp);
- lagg_port_purgevlan(sc, lp);
- lagg_teardown_lladdr(sc, lp);
+ if (is_ifdetach == false) {
+ if (iftype_changed &&
+ lagg_lladdr_equal(CLLADDR(ifp_port->if_sadl),
+ lp->lp_lladdr)) {
+ lagg_port_setsadl(lp, NULL);
+ }
+ lagg_port_setsadl(lp, lp->lp_lladdr);
+ lagg_in6_ifattach(ifp_port);
+ (void)lagg_setmtu(ifp_port, lp->lp_mtu);
+ }
- IFNET_LOCK(ifp_port);
- ifp_port->if_type = lp->lp_iftype;
+ ifp_port->if_output = lp->lp_output;
if (ifp_port->if_ioctl == lagg_port_ioctl)
ifp_port->if_ioctl = lp->lp_ioctl;
- lagg_teardown_mtu(sc, lp);
-
- if (stopped)
- if_init(ifp_port);
- IFNET_UNLOCK(ifp_port);
+ atomic_store_release(&ifp_port->if_lagg, NULL);
+ pserialize_perform(sc->sc_psz);
+ /* to assign ipv6 link local address */
if (is_ifdetach == false) {
- lagg_unconfig_promisc(sc, lp);
- lagg_setifcaps(lp, lp->lp_ifcapenable);
- if (lp->lp_iftype == IFT_ETHER)
- lagg_setethcaps(lp, lp->lp_eccapenable);
-
- IFNET_LOCK(ifp_port);
- lagg_port_unsetsadl(lp);
lagg_in6_ifattach(ifp_port);
- IFNET_UNLOCK(ifp_port);
}
- lagg_capabilities_update(sc);
+ /* restart packet processing */
+ if (stopped) {
+ int error;
+ error = if_init(ifp_port);
+ if (error != 0) {
+ LAGG_LOG(sc, LOG_WARNING,
+ "%s failed to if_init() on %d\n",
+ ifp_port->if_xname, error);
+ }
+ }
+ IFNET_UNLOCK(ifp_port);
- lagg_proto_freeport(sc, lp);
+ psref_target_destroy(&lp->lp_psref, lagg_port_psref_class);
kmem_free(lp, sizeof(*lp));
}
@@ -2505,17 +2421,13 @@ static int
lagg_addport(struct lagg_softc *sc, struct ifnet *ifp_port)
{
struct lagg_port *lp;
- uint8_t lladdr[ETHER_ADDR_LEN];
int error;
lp = kmem_zalloc(sizeof(*lp), KM_SLEEP);
lp->lp_ifp = ifp_port;
LAGG_LOCK(sc);
- lagg_lladdr_cpy(lladdr, sc->sc_lladdr);
error = lagg_port_setup(sc, lp, ifp_port);
- if (error == 0)
- lagg_sadl_update(sc, lladdr);
LAGG_UNLOCK(sc);
if (error != 0)
@@ -2528,7 +2440,6 @@ static int
lagg_delport(struct lagg_softc *sc, struct ifnet *ifp_port)
{
struct lagg_port *lp;
- uint8_t lladdr[ETHER_ADDR_LEN];
int error;
KASSERT(IFNET_LOCKED(&sc->sc_if));
@@ -2546,9 +2457,7 @@ lagg_delport(struct lagg_softc *sc, stru
goto out;
}
- lagg_lladdr_cpy(lladdr, sc->sc_lladdr);
lagg_port_teardown(sc, lp, false);
- lagg_sadl_update(sc, lladdr);
out:
LAGG_UNLOCK(sc);
@@ -2560,7 +2469,6 @@ static int
lagg_delport_all(struct lagg_softc *sc)
{
struct lagg_port *lp;
- uint8_t lladdr[ETHER_ADDR_LEN];
int error;
KASSERT(IFNET_LOCKED(&sc->sc_if));
@@ -2568,7 +2476,6 @@ lagg_delport_all(struct lagg_softc *sc)
error = 0;
LAGG_LOCK(sc);
- lagg_lladdr_cpy(lladdr, sc->sc_lladdr);
while ((lp = LAGG_PORTS_FIRST(sc)) != NULL) {
if (lp->lp_ifdetaching) {
error = EBUSY;
@@ -2578,7 +2485,6 @@ lagg_delport_all(struct lagg_softc *sc)
lagg_port_teardown(sc, lp, false);
}
- lagg_sadl_update(sc, lladdr);
LAGG_UNLOCK(sc);
return error;
@@ -2772,7 +2678,6 @@ lagg_ifdetach(void *xifp_port)
struct ifnet *ifp_port = xifp_port;
struct lagg_port *lp;
struct lagg_softc *sc;
- uint8_t lladdr[ETHER_ADDR_LEN];
int s;
IFNET_ASSERT_UNLOCKED(ifp_port);
@@ -2810,9 +2715,7 @@ lagg_ifdetach(void *xifp_port)
LAGG_LOCK(sc);
lp = ifp_port->if_lagg;
if (lp != NULL) {
- lagg_lladdr_cpy(lladdr, sc->sc_lladdr);
lagg_port_teardown(sc, lp, true);
- lagg_sadl_update(sc, lladdr);
}
LAGG_UNLOCK(sc);
IFNET_UNLOCK(&sc->sc_if);
@@ -2915,7 +2818,7 @@ lagg_workq_wait(struct workqueue *wq, st
}
static int
-lagg_chg_sadl(struct ifnet *ifp, uint8_t *lla, size_t lla_len)
+lagg_chg_sadl(struct ifnet *ifp, const uint8_t *lla, size_t lla_len)
{
struct psref psref_cur, psref_next;
struct ifaddr *ifa_cur, *ifa_next, *ifa_lla;
Index: src/sys/net/lagg/if_lagg_lacp.c
diff -u src/sys/net/lagg/if_lagg_lacp.c:1.21 src/sys/net/lagg/if_lagg_lacp.c:1.22
--- src/sys/net/lagg/if_lagg_lacp.c:1.21 Thu Mar 31 07:59:05 2022
+++ src/sys/net/lagg/if_lagg_lacp.c Fri Apr 1 07:26:51 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: if_lagg_lacp.c,v 1.21 2022/03/31 07:59:05 yamaguchi Exp $ */
+/* $NetBSD: if_lagg_lacp.c,v 1.22 2022/04/01 07:26:51 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.21 2022/03/31 07:59:05 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.22 2022/04/01 07:26:51 yamaguchi Exp $");
#ifdef _KERNEL_OPT
#include "opt_lagg.h"
@@ -667,11 +667,10 @@ lacp_allocport(struct lagg_proto_softc *
sc = lsc->lsc_softc;
KASSERT(LAGG_LOCKED(sc));
+ KASSERT(IFNET_LOCKED(lp->lp_ifp));
- IFNET_LOCK(lp->lp_ifp);
lacp_mcastaddr(&ifr, lp->lp_ifp->if_xname);
error = lp->lp_ioctl(lp->lp_ifp, SIOCADDMULTI, (void *)&ifr);
- IFNET_UNLOCK(lp->lp_ifp);
switch (error) {
case 0:
@@ -700,7 +699,6 @@ lacp_allocport(struct lagg_proto_softc *
lp->lp_proto_ctx = (void *)lacpp;
lp->lp_prio = ntohs(lacpp->lp_actor.lpi_portprio);
- lacp_linkstate(xlsc, lp);
return 0;
}
@@ -751,6 +749,7 @@ lacp_freeport(struct lagg_proto_softc *x
lacpp = lp->lp_proto_ctx;
KASSERT(LAGG_LOCKED(lsc->lsc_softc));
+ KASSERT(IFNET_LOCKED(lp->lp_ifp));
lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_smtx);
lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_marker);
@@ -758,9 +757,7 @@ lacp_freeport(struct lagg_proto_softc *x
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);
}
lp->lp_proto_ctx = NULL;