Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177452630
D59850.1794440392.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
4 KB
Referenced Files
None
Subscribers
None
D59850.1794440392.diff
View Options
diff --git a/sys/net/bridgestp.c b/sys/net/bridgestp.c
--- a/sys/net/bridgestp.c
+++ b/sys/net/bridgestp.c
@@ -460,12 +460,9 @@
struct bstp_tbpdu tpdu;
uint16_t len;
- if (bp->bp_active == 0) {
- m_freem(m);
- return;
- }
-
BSTP_LOCK(bs);
+ if (bp->bp_active == 0)
+ goto out;
eh = mtod(m, struct ether_header *);
@@ -1697,8 +1694,8 @@
BSTP_LOCK(bs);
if (set) {
bp->bp_flags |= BSTP_PORT_AUTOPTP;
- if (bp->bp_role != BSTP_ROLE_DISABLED)
- taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
+ if (bp->bp_active && bp->bp_role != BSTP_ROLE_DISABLED)
+ taskqueue_enqueue(taskqueue_thread, &bp->bp_mediatask);
} else
bp->bp_flags &= ~BSTP_PORT_AUTOPTP;
BSTP_UNLOCK(bs);
@@ -1792,31 +1789,41 @@
{
struct bstp_state *bs = bp->bp_bs;
- if (!bp->bp_active)
- return;
+ NET_EPOCH_ASSERT();
- bstp_ifupdstatus(bp, 0);
+ /* The caller holds the network epoch; the media ioctl may sleep. */
BSTP_LOCK(bs);
- bstp_update_state(bs, bp);
+ if (bp->bp_active)
+ taskqueue_enqueue(taskqueue_thread, &bp->bp_mediatask);
BSTP_UNLOCK(bs);
}
static void
bstp_ifupdstatus(void *arg, int pending)
{
+ struct epoch_tracker et;
struct bstp_port *bp = (struct bstp_port *)arg;
struct bstp_state *bs = bp->bp_bs;
struct ifnet *ifp = bp->bp_ifp;
struct ifmediareq ifmr;
int error, changed;
- if (!bp->bp_active)
+ BSTP_LOCK(bs);
+ if (!bp->bp_active) {
+ BSTP_UNLOCK(bs);
return;
+ }
+ BSTP_UNLOCK(bs);
+ CURVNET_SET(ifp->if_vnet);
bzero((char *)&ifmr, sizeof(ifmr));
error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
+ /* Updating the STP state may transmit BPDUs. */
+ NET_EPOCH_ENTER(et);
BSTP_LOCK(bs);
+ if (!bp->bp_active)
+ goto out;
changed = 0;
if ((error == 0) && (ifp->if_flags & IFF_UP)) {
if (ifmr.ifm_status & IFM_ACTIVE) {
@@ -1862,7 +1869,11 @@
}
if (changed)
bstp_assign_roles(bs);
+ bstp_update_state(bs, bp);
+out:
BSTP_UNLOCK(bs);
+ NET_EPOCH_EXIT(et);
+ CURVNET_RESTORE();
}
static void
@@ -1896,7 +1907,7 @@
if (bstp_timer_dectest(&bs->bs_link_timer)) {
LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
if (!(bp->bp_ifp->if_capabilities & IFCAP_LINKSTATE))
- taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
+ taskqueue_enqueue(taskqueue_thread, &bp->bp_mediatask);
}
bstp_timer_start(&bs->bs_link_timer, BSTP_LINK_TIMER);
}
@@ -2109,7 +2120,7 @@
LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
bp->bp_port_id = (bp->bp_priority << 8) |
(bp->bp_ifp->if_index & 0xfff);
- taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
+ taskqueue_enqueue(taskqueue_thread, &bp->bp_mediatask);
}
bstp_assign_roles(bs);
@@ -2181,6 +2192,10 @@
mtx_unlock(&bstp_list_mtx);
}
+/*
+ * The caller must destroy bs_mtx after a network epoch grace period.
+ * Input and link-state callbacks may still be checking inactive ports.
+ */
void
bstp_detach(struct bstp_state *bs)
{
@@ -2190,7 +2205,6 @@
LIST_REMOVE(bs, bs_list);
mtx_unlock(&bstp_list_mtx);
callout_drain(&bs->bs_bstpcallout);
- BSTP_LOCK_DESTROY(bs);
}
void
@@ -2292,11 +2306,19 @@
void
bstp_destroy(struct bstp_port *bp)
{
+ struct epoch_tracker et;
+ struct bstp_state *bs = bp->bp_bs;
+
KASSERT(bp->bp_active == 0, ("port is still attached"));
+ /* Media updates can enqueue state and route-age notifications. */
+ taskqueue_drain(taskqueue_thread, &bp->bp_mediatask);
taskqueue_drain(taskqueue_swi, &bp->bp_statetask);
taskqueue_drain(taskqueue_swi, &bp->bp_rtagetask);
- taskqueue_drain(taskqueue_swi, &bp->bp_mediatask);
- if (bp->bp_bs->bs_root_port == bp)
- bstp_assign_roles(bp->bp_bs);
+ NET_EPOCH_ENTER(et);
+ BSTP_LOCK(bs);
+ if (bs->bs_root_port == bp)
+ bstp_assign_roles(bs);
+ BSTP_UNLOCK(bs);
+ NET_EPOCH_EXIT(et);
}
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -920,6 +920,7 @@
sc = __containerof(ctx, struct bridge_softc, sc_epoch_ctx);
+ BSTP_LOCK_DESTROY(&sc->sc_stp);
BRIDGE_LOCK_DESTROY(sc);
free(sc, M_DEVBUF);
}
@@ -1253,6 +1254,8 @@
if (bif->bif_flags & IFBIF_STP)
bstp_disable(&bif->bif_stp);
+ /* Notifications may still need the member's bridge pointer. */
+ bstp_destroy(&bif->bif_stp);
ifs->if_bridge = NULL;
CK_LIST_REMOVE(bif, bif_next);
@@ -1313,8 +1316,6 @@
/* Re-enable any interface capabilities */
bridge_set_ifcap(sc, bif, bif->bif_savedcaps);
}
- bstp_destroy(&bif->bif_stp); /* prepare to free */
-
NET_EPOCH_CALL(bridge_delete_member_cb, &bif->bif_epoch_ctx);
}
@@ -1515,11 +1516,11 @@
EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp);
}
+ bstp_create(&sc->sc_stp, &bif->bif_stp, bif->bif_ifp);
ifs->if_bridge = bif;
ifs->if_bridge_output = bridge_output;
ifs->if_bridge_input = bridge_input;
ifs->if_bridge_linkstate = bridge_linkstate;
- bstp_create(&sc->sc_stp, &bif->bif_stp, bif->bif_ifp);
/*
* XXX: XLOCK HERE!?!
*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 11, 11:39 PM (8 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41667509
Default Alt Text
D59850.1794440392.diff (4 KB)
Attached To
Mode
D59850: bridgestp: Defer media queries outside the network epoch
Attached
Detach File
Event Timeline