diff options
author | mav <mav@FreeBSD.org> | 2017-05-02 19:29:31 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2017-05-02 19:29:31 +0000 |
commit | 2b7fc1d0908bde2aeb232deaac7a7d01eb2bc0c9 (patch) | |
tree | 2f124760566c95968113b48990e4501e7f7d9b31 | |
parent | 90bc2e87022243695fdd4f0daf7c18f551fa3582 (diff) | |
download | FreeBSD-src-2b7fc1d0908bde2aeb232deaac7a7d01eb2bc0c9.zip FreeBSD-src-2b7fc1d0908bde2aeb232deaac7a7d01eb2bc0c9.tar.gz |
MFC r312979 (by loos):
Do not update the lagg link layer address when destroying a lagg clone.
This would enqueue an event to send the gratuitous arp on a dying lagg
interface without any physical ports attached to it.
Apart from that, the taskqueue_drain() on lagg_clone_destroy() runs too
late, when the ifp data structure is already freed. Fix that too.
-rw-r--r-- | sys/net/if_lagg.c | 17 | ||||
-rw-r--r-- | sys/net/if_lagg.h | 2 |
2 files changed, 12 insertions, 7 deletions
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 0a5fc15..095a891 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -539,12 +539,15 @@ lagg_clone_destroy(struct ifnet *ifp) EVENTHANDLER_DEREGISTER(vlan_unconfig, sc->vlan_detach); /* Shutdown and remove lagg ports */ - while ((lp = SLIST_FIRST(&sc->sc_ports)) != NULL) + while ((lp = SLIST_FIRST(&sc->sc_ports)) != NULL) { + lp->lp_detaching = LAGG_CLONE_DESTROY; lagg_port_destroy(lp, 1); + } /* Unhook the aggregation protocol */ lagg_proto_detach(sc); LAGG_UNLOCK_ASSERT(sc); + taskqueue_drain(taskqueue_swi, &sc->sc_lladdr_task); ifmedia_removeall(&sc->sc_media); ether_ifdetach(ifp); if_free(ifp); @@ -553,7 +556,6 @@ lagg_clone_destroy(struct ifnet *ifp) SLIST_REMOVE(&V_lagg_list, sc, lagg_softc, sc_entries); LAGG_LIST_UNLOCK(); - taskqueue_drain(taskqueue_swi, &sc->sc_lladdr_task); LAGG_LOCK_DESTROY(sc); free(sc, M_DEVBUF); } @@ -891,7 +893,7 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) * Remove multicast addresses and interface flags from this port and * reset the MAC address, skip if the interface is being detached. */ - if (!lp->lp_detaching) { + if (lp->lp_detaching == 0) { lagg_ether_cmdmulti(lp, 0); lagg_setflags(lp, 0); lagg_port_lladdr(lp, lp->lp_lladdr, LAGG_LLQTYPE_PHYS); @@ -924,7 +926,8 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) bcopy(lp0->lp_lladdr, lladdr, ETHER_ADDR_LEN); } - lagg_lladdr(sc, lladdr); + if (lp->lp_detaching != LAGG_CLONE_DESTROY) + lagg_lladdr(sc, lladdr); /* Mark lp0 as new primary */ sc->sc_primary = lp0; @@ -939,7 +942,7 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport) } /* Remove any pending lladdr changes from the queue */ - if (lp->lp_detaching) { + if (lp->lp_detaching != 0) { SLIST_FOREACH(llq, &sc->sc_llq_head, llq_entries) { if (llq->llq_ifp == ifp) { SLIST_REMOVE(&sc->sc_llq_head, llq, lagg_llq, @@ -1118,7 +1121,7 @@ lagg_port_ifdetach(void *arg __unused, struct ifnet *ifp) sc = lp->lp_softc; LAGG_WLOCK(sc); - lp->lp_detaching = 1; + lp->lp_detaching = LAGG_PORT_DETACH; lagg_port_destroy(lp, 1); LAGG_WUNLOCK(sc); } @@ -1603,7 +1606,7 @@ lagg_ether_cmdmulti(struct lagg_port *lp, int set) } else { while ((mc = SLIST_FIRST(&lp->lp_mc_head)) != NULL) { SLIST_REMOVE(&lp->lp_mc_head, mc, lagg_mc, mc_entries); - if (mc->mc_ifma && !lp->lp_detaching) + if (mc->mc_ifma && lp->lp_detaching == 0) if_delmulti_ifma(mc->mc_ifma); free(mc, M_DEVBUF); } diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h index 334995e..81eeeb8 100644 --- a/sys/net/if_lagg.h +++ b/sys/net/if_lagg.h @@ -261,6 +261,8 @@ struct lagg_port { void *lh_cookie; /* if state hook */ void *lp_psc; /* protocol data */ int lp_detaching; /* ifnet is detaching */ +#define LAGG_PORT_DETACH 0x01 /* detach lagg port */ +#define LAGG_CLONE_DESTROY 0x02 /* destroy lagg clone */ SLIST_HEAD(__mclhd, lagg_mc) lp_mc_head; /* multicast addresses */ |