Page MenuHomeFreeBSD

D57023.id177902.diff
No OneTemporary

D57023.id177902.diff

diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c
--- a/sys/net/ieee8023ad_lacp.c
+++ b/sys/net/ieee8023ad_lacp.c
@@ -791,10 +791,6 @@
callout_init_mtx(&lsc->lsc_transit_callout, &lsc->lsc_mtx, 0);
callout_init_mtx(&lsc->lsc_callout, &lsc->lsc_mtx, 0);
-
- /* if the lagg is already up then do the same */
- if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
- lacp_init(sc);
}
void
diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h
--- a/sys/net/if_lagg.h
+++ b/sys/net/if_lagg.h
@@ -244,8 +244,9 @@
uint32_t sc_seq; /* sequence counter */
uint32_t sc_stride; /* stride for RR */
uint32_t sc_flags;
- int sc_destroying; /* destroying lagg */
-
+ int sc_state; /* lagg state, destroying etc. */
+#define LAGG_STATE_RUNNING 0x0001
+#define LAGG_STATE_DESTROYING 0x0002
CK_SLIST_HEAD(__tplhd, lagg_port) sc_ports; /* list of interfaces */
SLIST_ENTRY(lagg_softc) sc_entries;
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -87,6 +87,26 @@
#define LAGG_SUNLOCK(_sc) sx_sunlock(&(_sc)->sc_sx)
#define LAGG_SXLOCK_ASSERT(_sc) sx_assert(&(_sc)->sc_sx, SA_LOCKED)
+#define LAGG_SET_STATE(_sc, _state) \
+do { \
+ LAGG_XLOCK_ASSERT((_sc)); \
+ int _new = (_sc)->sc_state | (_state); \
+ atomic_store_rel_int(&(_sc)->sc_state, _new); \
+} while (0)
+
+#define LAGG_CLEAR_STATE(_sc, _state) \
+do { \
+ LAGG_XLOCK_ASSERT((_sc)); \
+ int _new = (_sc)->sc_state & ~(_state); \
+ atomic_store_rel_int(&(_sc)->sc_state, _new); \
+} while (0)
+
+#define LAGG_IS_RUNNING(_sc) \
+ ((atomic_load_acq_int(&(_sc)->sc_state) & LAGG_STATE_RUNNING) != 0)
+
+#define LAGG_IS_DESTROYING(_sc) \
+ ((atomic_load_acq_int(&(_sc)->sc_state) & LAGG_STATE_DESTROYING) != 0)
+
/* Special flags we should propagate to the lagg ports. */
static struct {
int flag;
@@ -622,7 +642,7 @@
struct lagg_port *lp;
LAGG_XLOCK(sc);
- sc->sc_destroying = 1;
+ LAGG_SET_STATE(sc, LAGG_STATE_DESTROYING);
lagg_stop(sc);
ifp->if_flags &= ~IFF_UP;
@@ -746,7 +766,7 @@
return (EINVAL);
}
- if (sc->sc_destroying == 1)
+ if (LAGG_IS_DESTROYING(sc))
return (ENXIO);
/* Limit the maximal number of lagg ports */
@@ -974,7 +994,7 @@
else
bcopy(lp0->lp_lladdr, lladdr, LAGG_ADDR_LEN);
sc->sc_primary = lp0;
- if (sc->sc_destroying == 0) {
+ if (! LAGG_IS_DESTROYING(sc)) {
bcopy(lladdr, IF_LLADDR(sc->sc_ifp), sc->sc_ifp->if_addrlen);
lagg_proto_lladdr(sc);
EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp);
@@ -1317,6 +1337,7 @@
mtx_unlock(&sc->sc_mtx);
}
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ LAGG_SET_STATE(sc, LAGG_STATE_RUNNING);
}
static void
@@ -1330,6 +1351,13 @@
return;
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ LAGG_CLEAR_STATE(sc, LAGG_STATE_RUNNING);
+ /*
+ * After a grace period has elapsed, threads running the
+ * data path will see the new state, then it is safe to
+ * handle protocol private data.
+ */
+ NET_EPOCH_WAIT();
lagg_proto_stop(sc);
@@ -1356,6 +1384,7 @@
struct thread *td = curthread;
char *buf, *outbuf;
int count, buflen, len, error = 0, oldmtu;
+ bool running;
bzero(&rpbuf, sizeof(rpbuf));
@@ -1402,8 +1431,17 @@
break;
}
LAGG_XLOCK(sc);
+ if (ra->ra_proto == sc->sc_proto) {
+ LAGG_XUNLOCK(sc);
+ break;
+ }
+ running = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0;
+ if (running)
+ lagg_stop(sc);
lagg_proto_detach(sc);
lagg_proto_attach(sc, ra->ra_proto);
+ if (running)
+ lagg_init_locked(sc);
LAGG_XUNLOCK(sc);
break;
case SIOCGLAGGOPTS:
@@ -2128,6 +2166,11 @@
if (m->m_pkthdr.csum_flags & CSUM_SND_TAG)
MPASS(m->m_pkthdr.snd_tag->ifp == ifp);
#endif
+ if (! LAGG_IS_RUNNING(sc)) {
+ m_freem(m);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ return (ENETDOWN);
+ }
/* We need at least one port */
if (sc->sc_count == 0) {
m_freem(m);
@@ -2150,6 +2193,11 @@
if (m->m_pkthdr.csum_flags & CSUM_SND_TAG)
MPASS(m->m_pkthdr.snd_tag->ifp == ifp);
#endif
+ if (! LAGG_IS_RUNNING(sc)) {
+ m_freem(m);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ return (ENETDOWN);
+ }
/* We need at least one port */
if (sc->sc_count == 0) {
m_freem(m);
@@ -2178,8 +2226,7 @@
struct ifnet *scifp = sc->sc_ifp;
NET_EPOCH_ASSERT();
- if ((scifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
- lp->lp_detaching != 0) {
+ if (! LAGG_IS_RUNNING(sc) || lp->lp_detaching != 0) {
m_freem(m);
return (NULL);
}
@@ -2212,8 +2259,7 @@
struct ifnet *scifp = sc->sc_ifp;
NET_EPOCH_ASSERT();
- if ((scifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
- lp->lp_detaching != 0) {
+ if (! LAGG_IS_RUNNING(sc) || lp->lp_detaching != 0) {
m_freem(m);
return (NULL);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Aug 7, 2:30 PM (6 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36181957
Default Alt Text
D57023.id177902.diff (4 KB)

Event Timeline