Page MenuHomeFreeBSD

D59850.id.diff
No OneTemporary

D59850.id.diff

Index: sys/net/bridgestp.c
===================================================================
--- sys/net/bridgestp.c
+++ 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 *);
@@ -1700,8 +1697,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);
@@ -1795,31 +1792,39 @@
{
struct bstp_state *bs = bp->bp_bs;
- if (!bp->bp_active)
- return;
-
- 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) {
@@ -1865,7 +1870,11 @@
}
if (changed)
bstp_assign_roles(bs);
+ bstp_update_state(bs, bp);
+out:
BSTP_UNLOCK(bs);
+ NET_EPOCH_EXIT(et);
+ CURVNET_RESTORE();
}
static void
@@ -1899,7 +1908,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);
}
@@ -2112,7 +2121,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);
@@ -2193,6 +2202,8 @@
LIST_REMOVE(bs, bs_list);
mtx_unlock(&bstp_list_mtx);
callout_drain(&bs->bs_bstpcallout);
+ /* Link callbacks may still be checking inactive ports under bs_mtx. */
+ NET_EPOCH_WAIT();
BSTP_LOCK_DESTROY(bs);
}
@@ -2295,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);
}
Index: sys/net/if_bridge.c
===================================================================
--- sys/net/if_bridge.c
+++ sys/net/if_bridge.c
@@ -1253,6 +1253,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 +1315,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 +1515,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

Mime Type
text/plain
Expires
Fri, Sep 25, 4:44 AM (5 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39575526
Default Alt Text
D59850.id.diff (4 KB)

Event Timeline