lacp: fix link state with multiple aggregators
When we have multiple aggregators, the link state should reflect the state of the active aggregator. This change was prompted by a script pruning 10GbE interfaces from an lacp bundle with 100GbE interfaces. Mixing speeds like this creates multiple aggregators. When the last 10GbE interface was removed, lagg0 would loose link because the current aggregator's port count would drop to 0, even though the 100GbE aggregator had active ports. This left the system in a hard to diagnose state where lagg0 reported "active", but all outgoing IP traffic was dropped, due to the RT_LINK_IS_UP() check noticing lagg0's if_link_state was marked as down. Reviewed by: zlei Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D56579
This commit is contained in:
@@ -682,6 +682,7 @@ static void
|
||||
lacp_disable_distributing(struct lacp_port *lp)
|
||||
{
|
||||
struct lacp_aggregator *la = lp->lp_aggregator;
|
||||
struct lacp_aggregator *la_active;
|
||||
struct lacp_softc *lsc = lp->lp_lsc;
|
||||
struct lagg_softc *sc = lsc->lsc_softc;
|
||||
char buf[LACP_LAGIDSTR_MAX+1];
|
||||
@@ -703,7 +704,6 @@ lacp_disable_distributing(struct lacp_port *lp)
|
||||
|
||||
TAILQ_REMOVE(&la->la_ports, lp, lp_dist_q);
|
||||
la->la_nports--;
|
||||
sc->sc_active = la->la_nports;
|
||||
|
||||
if (lsc->lsc_active_aggregator == la) {
|
||||
lacp_suppress_distributing(lsc, la);
|
||||
@@ -713,6 +713,8 @@ lacp_disable_distributing(struct lacp_port *lp)
|
||||
}
|
||||
|
||||
lp->lp_state &= ~LACP_STATE_DISTRIBUTING;
|
||||
la_active = lsc->lsc_active_aggregator;
|
||||
sc->sc_active = la_active != NULL ? la_active->la_nports : 0;
|
||||
if_link_state_change(sc->sc_ifp,
|
||||
sc->sc_active ? LINK_STATE_UP : LINK_STATE_DOWN);
|
||||
}
|
||||
@@ -721,6 +723,7 @@ static void
|
||||
lacp_enable_distributing(struct lacp_port *lp)
|
||||
{
|
||||
struct lacp_aggregator *la = lp->lp_aggregator;
|
||||
struct lacp_aggregator *la_active;
|
||||
struct lacp_softc *lsc = lp->lp_lsc;
|
||||
struct lagg_softc *sc = lsc->lsc_softc;
|
||||
char buf[LACP_LAGIDSTR_MAX+1];
|
||||
@@ -739,7 +742,6 @@ lacp_enable_distributing(struct lacp_port *lp)
|
||||
KASSERT(la->la_refcnt > la->la_nports, ("aggregator refcnt invalid"));
|
||||
TAILQ_INSERT_HEAD(&la->la_ports, lp, lp_dist_q);
|
||||
la->la_nports++;
|
||||
sc->sc_active = la->la_nports;
|
||||
|
||||
lp->lp_state |= LACP_STATE_DISTRIBUTING;
|
||||
|
||||
@@ -750,6 +752,8 @@ lacp_enable_distributing(struct lacp_port *lp)
|
||||
/* try to become the active aggregator */
|
||||
lacp_select_active_aggregator(lsc);
|
||||
|
||||
la_active = lsc->lsc_active_aggregator;
|
||||
sc->sc_active = la_active != NULL ? la_active->la_nports : 0;
|
||||
if_link_state_change(sc->sc_ifp,
|
||||
sc->sc_active ? LINK_STATE_UP : LINK_STATE_DOWN);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user