svn commit: r272547 - head/sys/net
Hiroki Sato
hrs at FreeBSD.org
Sun Oct 5 02:34:23 UTC 2014
Author: hrs
Date: Sun Oct 5 02:34:21 2014
New Revision: 272547
URL: https://svnweb.freebsd.org/changeset/base/272547
Log:
- Move L2 addr configuration for the primary port to a taskqueue. This fixes
LOR of softc rmlock in iflladdr_event handlers.
- Call if_delmulti_ifma() after LACP_UNLOCK(). This fixes another LOR.
- Fix a panic in lacp_transit_expire().
- Fix a panic in lagg_input() upon shutting down a port.
Modified:
head/sys/net/ieee8023ad_lacp.c
head/sys/net/if_lagg.c
head/sys/net/if_lagg.h
Modified: head/sys/net/ieee8023ad_lacp.c
==============================================================================
--- head/sys/net/ieee8023ad_lacp.c Sun Oct 5 02:16:53 2014 (r272546)
+++ head/sys/net/ieee8023ad_lacp.c Sun Oct 5 02:34:21 2014 (r272547)
@@ -579,12 +579,13 @@ lacp_port_destroy(struct lagg_port *lgp)
lacp_disable_distributing(lp);
lacp_unselect(lp);
+ LIST_REMOVE(lp, lp_next);
+ LACP_UNLOCK(lsc);
+
/* The address may have already been removed by if_purgemaddrs() */
if (!lgp->lp_detaching)
if_delmulti_ifma(lp->lp_ifma);
- LIST_REMOVE(lp, lp_next);
- LACP_UNLOCK(lsc);
free(lp, M_DEVBUF);
}
@@ -745,7 +746,9 @@ lacp_transit_expire(void *vp)
LACP_LOCK_ASSERT(lsc);
+ CURVNET_SET(lsc->lsc_softc->sc_ifp->if_vnet);
LACP_TRACE(NULL);
+ CURVNET_RESTORE();
lsc->lsc_suppress_distributing = FALSE;
}
Modified: head/sys/net/if_lagg.c
==============================================================================
--- head/sys/net/if_lagg.c Sun Oct 5 02:16:53 2014 (r272546)
+++ head/sys/net/if_lagg.c Sun Oct 5 02:34:21 2014 (r272547)
@@ -569,15 +569,15 @@ lagg_clone_destroy(struct ifnet *ifp)
static void
lagg_lladdr(struct lagg_softc *sc, uint8_t *lladdr)
{
- struct ifnet *ifp = sc->sc_ifp;
+ struct lagg_port lp;
- if (memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0)
- return;
+ LAGG_WLOCK_ASSERT(sc);
+
+ bzero(&lp, sizeof(lp));
+ lp.lp_ifp = sc->sc_ifp;
+ lp.lp_softc = sc;
- bcopy(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN);
- /* Let the protocol know the MAC has changed */
- lagg_proto_lladdr(sc);
- EVENTHANDLER_INVOKE(iflladdr_event, ifp);
+ lagg_port_lladdr(&lp, lladdr);
}
static void
@@ -648,6 +648,7 @@ lagg_port_lladdr(struct lagg_port *lp, u
/* Update the lladdr even if pending, it may have changed */
llq->llq_ifp = ifp;
+ llq->llq_primary = (sc->sc_primary->lp_ifp == ifp) ? 1 : 0;
bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN);
if (!pending)
@@ -680,14 +681,35 @@ lagg_port_setlladdr(void *arg, int pendi
for (llq = head; llq != NULL; llq = head) {
ifp = llq->llq_ifp;
- /* Set the link layer address */
CURVNET_SET(ifp->if_vnet);
- error = if_setlladdr(ifp, llq->llq_lladdr, ETHER_ADDR_LEN);
+ if (llq->llq_primary == 0) {
+ /*
+ * Set the link layer address on the laggport interface.
+ * if_setlladdr() triggers gratuitous ARPs for INET.
+ */
+ error = if_setlladdr(ifp, llq->llq_lladdr,
+ ETHER_ADDR_LEN);
+ if (error)
+ printf("%s: setlladdr failed on %s\n", __func__,
+ ifp->if_xname);
+ } else {
+ /*
+ * Set the link layer address on the lagg interface.
+ * lagg_proto_lladdr() notifies the MAC change to
+ * the aggregation protocol. iflladdr_event handler
+ * may trigger gratuitous ARPs for INET.
+ */
+ if (memcmp(llq->llq_lladdr, IF_LLADDR(ifp),
+ ETHER_ADDR_LEN) != 0) {
+ bcopy(llq->llq_lladdr, IF_LLADDR(ifp),
+ ETHER_ADDR_LEN);
+ LAGG_WLOCK(sc);
+ lagg_proto_lladdr(sc);
+ LAGG_WUNLOCK(sc);
+ EVENTHANDLER_INVOKE(iflladdr_event, ifp);
+ }
+ }
CURVNET_RESTORE();
- if (error)
- printf("%s: setlladdr failed on %s\n", __func__,
- ifp->if_xname);
-
head = SLIST_NEXT(llq, llq_entries);
free(llq, M_DEVBUF);
}
@@ -1639,7 +1661,7 @@ lagg_input(struct ifnet *ifp, struct mbu
ETHER_BPF_MTAP(scifp, m);
- m = lagg_proto_input(sc, lp, m);
+ m = (lp->lp_detaching == 0) ? lagg_proto_input(sc, lp, m) : NULL;
if (m != NULL) {
if (scifp->if_flags & IFF_MONITOR) {
Modified: head/sys/net/if_lagg.h
==============================================================================
--- head/sys/net/if_lagg.h Sun Oct 5 02:16:53 2014 (r272546)
+++ head/sys/net/if_lagg.h Sun Oct 5 02:34:21 2014 (r272547)
@@ -159,6 +159,9 @@ struct lagg_reqopts {
#define SIOCGLAGGOPTS _IOWR('i', 152, struct lagg_reqopts)
#define SIOCSLAGGOPTS _IOW('i', 153, struct lagg_reqopts)
+#define LAGG_OPT_BITS "\020\001USE_FLOWID\005LACP_STRICT" \
+ "\006LACP_TXTEST\007LACP_RXTEST"
+
#ifdef _KERNEL
/*
@@ -203,6 +206,7 @@ struct lagg_mc {
struct lagg_llq {
struct ifnet *llq_ifp;
uint8_t llq_lladdr[ETHER_ADDR_LEN];
+ uint8_t llq_primary;
SLIST_ENTRY(lagg_llq) llq_entries;
};
More information about the svn-src-head
mailing list