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. Obtained from: pfSense MFC after: 2 weeks Sponsored by: Rubicon Communications, LLC (Netgate)
This commit is contained in:
parent
dba8901b07
commit
1f77bc5d5c
@ -550,12 +550,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);
|
||||
@ -564,7 +567,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);
|
||||
}
|
||||
@ -902,7 +904,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);
|
||||
@ -935,7 +937,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;
|
||||
@ -950,7 +953,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,
|
||||
@ -1129,7 +1132,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);
|
||||
}
|
||||
@ -1660,7 +1663,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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user