Add a callback so we can notify the parent bridge that a port state change has

occured, we need to do this from a taskqueue to avoid a LOR with the if_bridge
mutex.
This commit is contained in:
Andrew Thompson 2006-08-02 02:47:27 +00:00
parent 3b234fcbab
commit 6f2abce0b3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=160899
2 changed files with 43 additions and 4 deletions

View File

@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/taskqueue.h>
#include <net/if.h>
#include <net/if_dl.h>
@ -112,6 +113,7 @@ static void bstp_make_forwarding(struct bstp_state *,
static void bstp_make_blocking(struct bstp_state *,
struct bstp_port *);
static void bstp_set_port_state(struct bstp_port *, uint8_t);
static void bstp_state_change(void *, int);
static void bstp_update_forward_transitions(struct bstp_port *);
#ifdef notused
static void bstp_set_bridge_priority(struct bstp_state *, uint64_t);
@ -520,7 +522,6 @@ bstp_make_blocking(struct bstp_state *bs, struct bstp_port *bp)
}
}
bstp_set_port_state(bp, BSTP_IFSTATE_BLOCKING);
/* XXX bridge_rtdelete(bs, bp->bp_ifp, IFBF_FLUSHDYN); */
bstp_timer_stop(&bp->bp_forward_delay_timer);
}
}
@ -529,6 +530,25 @@ static void
bstp_set_port_state(struct bstp_port *bp, uint8_t state)
{
bp->bp_state = state;
struct bstp_state *bs = bp->bp_bs;
/* notify the parent bridge */
if (bs->bs_state_cb != NULL)
taskqueue_enqueue(taskqueue_swi, &bp->bp_statetask);
}
/*
* Notify the bridge that a port state has changed, we need to do this from a
* taskqueue to avoid a LOR.
*/
static void
bstp_state_change(void *arg, int pending)
{
struct bstp_port *bp = (struct bstp_port *)arg;
struct bstp_state *bs = bp->bp_bs;
if (bp->bp_active == 1)
(*bs->bs_state_cb)(bp->bp_ifp, bp->bp_state);
}
static void
@ -910,7 +930,7 @@ static moduledata_t bstp_mod = {
DECLARE_MODULE(bridgestp, bstp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
void
bstp_attach(struct bstp_state *bs)
bstp_attach(struct bstp_state *bs, bstp_state_cb_t state_callback)
{
BSTP_LOCK_INIT(bs);
callout_init_mtx(&bs->bs_bstpcallout, &bs->bs_mtx, 0);
@ -921,6 +941,7 @@ bstp_attach(struct bstp_state *bs)
bs->bs_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY;
bs->bs_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
bs->bs_hold_time = BSTP_DEFAULT_HOLD_TIME;
bs->bs_state_cb = state_callback;
mtx_lock(&bstp_list_mtx);
LIST_INSERT_HEAD(&bstp_list, bs, bs_list);
@ -1007,7 +1028,6 @@ bstp_disable_port(struct bstp_state *bs, struct bstp_port *bp)
bstp_timer_stop(&bp->bp_forward_delay_timer);
bstp_configuration_update(bs);
bstp_port_state_selection(bs);
/* XXX bridge_rtdelete(bs, bp->bp_ifp, IFBF_FLUSHDYN); */
if (bstp_root_bridge(bs) && (root == 0)) {
bs->bs_max_age = bs->bs_bridge_max_age;
@ -1253,6 +1273,7 @@ bstp_add(struct bstp_state *bs, struct bstp_port *bp, struct ifnet *ifp)
bp->bp_path_cost = BSTP_DEFAULT_PATH_COST;
LIST_INSERT_HEAD(&bs->bs_bplist, bp, bp_next);
TASK_INIT(&bp->bp_statetask, 0, bstp_state_change, bp);
BSTP_UNLOCK(bs);
bstp_reinit(bs);
@ -1276,3 +1297,13 @@ bstp_delete(struct bstp_port *bp)
bstp_reinit(bs);
}
/*
* The bstp_port structure is about to be freed by the parent bridge.
*/
void
bstp_drain(struct bstp_port *bp)
{
KASSERT(bp->bp_active == 0, ("port is still attached"));
taskqueue_drain(taskqueue_swi, &bp->bp_statetask);
}

View File

@ -109,6 +109,11 @@
#define BSTP_TICK_VAL (1 * 256) /* in 256ths of a second */
#define BSTP_LINK_TIMER (BSTP_TICK_VAL * 30)
/*
* * Driver callbacks for STP state changes
* */
typedef void (*bstp_state_cb_t)(struct ifnet *, int);
/*
* Because BPDU's do not make nicely aligned structures, two different
* declarations are used: bstp_?bpdu (wire representation, packed) and
@ -202,6 +207,7 @@ struct bstp_port {
uint8_t bp_change_detection_enabled;
uint8_t bp_priority;
uint32_t bp_forward_transitions;
struct task bp_statetask;
};
/*
@ -232,6 +238,7 @@ struct bstp_state {
struct bstp_timer bs_link_timer;
struct timeval bs_last_tc_time;
LIST_HEAD(, bstp_port) bs_bplist;
bstp_state_cb_t bs_state_cb;
};
#define BSTP_LOCK_INIT(_bs) mtx_init(&(_bs)->bs_mtx, "bstp", \
@ -245,13 +252,14 @@ extern const uint8_t bstp_etheraddr[];
extern void (*bstp_linkstate_p)(struct ifnet *ifp, int state);
void bstp_attach(struct bstp_state *);
void bstp_attach(struct bstp_state *, bstp_state_cb_t);
void bstp_detach(struct bstp_state *);
void bstp_init(struct bstp_state *);
void bstp_reinit(struct bstp_state *);
void bstp_stop(struct bstp_state *);
int bstp_add(struct bstp_state *, struct bstp_port *, struct ifnet *);
void bstp_delete(struct bstp_port *);
void bstp_drain(struct bstp_port *);
void bstp_linkstate(struct ifnet *, int);
struct mbuf *bstp_input(struct bstp_port *, struct ifnet *, struct mbuf *);