summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2017-05-02 19:29:31 +0000
committermav <mav@FreeBSD.org>2017-05-02 19:29:31 +0000
commit2b7fc1d0908bde2aeb232deaac7a7d01eb2bc0c9 (patch)
tree2f124760566c95968113b48990e4501e7f7d9b31
parent90bc2e87022243695fdd4f0daf7c18f551fa3582 (diff)
downloadFreeBSD-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.c17
-rw-r--r--sys/net/if_lagg.h2
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 */
OpenPOWER on IntegriCloud