Change from a callback in if_ethersubr to using EVENTHANDLER in order to detach
span ports when they disappear. The span port does not have a pointer to the softc so revert r1.31 and bring back the softc linked-list. MFC after: 2 weeks
This commit is contained in:
parent
8615fd8696
commit
e0a87e8acd
@ -170,6 +170,9 @@ __FBSDID("$FreeBSD$");
|
||||
#define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60)
|
||||
#endif
|
||||
|
||||
static struct mtx bridge_list_mtx;
|
||||
eventhandler_tag bridge_detach_cookie = NULL;
|
||||
|
||||
int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
|
||||
|
||||
uma_zone_t bridge_rtnode_zone;
|
||||
@ -178,7 +181,7 @@ static int bridge_clone_create(struct if_clone *, int);
|
||||
static void bridge_clone_destroy(struct ifnet *);
|
||||
|
||||
static int bridge_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void bridge_ifdetach(struct ifnet *);
|
||||
static void bridge_ifdetach(void *arg __unused, struct ifnet *);
|
||||
static void bridge_init(void *);
|
||||
static void bridge_dummynet(struct mbuf *, struct ifnet *);
|
||||
static void bridge_stop(struct ifnet *, int);
|
||||
@ -219,6 +222,8 @@ static struct bridge_iflist *bridge_lookup_member_if(struct bridge_softc *,
|
||||
struct ifnet *ifp);
|
||||
static void bridge_delete_member(struct bridge_softc *,
|
||||
struct bridge_iflist *, int);
|
||||
static void bridge_delete_span(struct bridge_softc *,
|
||||
struct bridge_iflist *);
|
||||
|
||||
static int bridge_ioctl_add(struct bridge_softc *, void *);
|
||||
static int bridge_ioctl_del(struct bridge_softc *, void *);
|
||||
@ -345,6 +350,8 @@ const int bridge_control_table_size =
|
||||
static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
LIST_HEAD(, bridge_softc) bridge_list;
|
||||
|
||||
IFC_SIMPLE_DECLARE(bridge, 0);
|
||||
|
||||
static int
|
||||
@ -353,24 +360,30 @@ bridge_modevent(module_t mod, int type, void *data)
|
||||
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
mtx_init(&bridge_list_mtx, "if_bridge list", NULL, MTX_DEF);
|
||||
if_clone_attach(&bridge_cloner);
|
||||
bridge_rtnode_zone = uma_zcreate("bridge_rtnode",
|
||||
sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL,
|
||||
UMA_ALIGN_PTR, 0);
|
||||
LIST_INIT(&bridge_list);
|
||||
bridge_input_p = bridge_input;
|
||||
bridge_output_p = bridge_output;
|
||||
bridge_dn_p = bridge_dummynet;
|
||||
bridge_detach_p = bridge_ifdetach;
|
||||
bstp_linkstate_p = bstp_linkstate;
|
||||
bridge_detach_cookie = EVENTHANDLER_REGISTER(
|
||||
ifnet_departure_event, bridge_ifdetach, NULL,
|
||||
EVENTHANDLER_PRI_ANY);
|
||||
break;
|
||||
case MOD_UNLOAD:
|
||||
EVENTHANDLER_DEREGISTER(ifnet_departure_event,
|
||||
bridge_detach_cookie);
|
||||
if_clone_detach(&bridge_cloner);
|
||||
uma_zdestroy(bridge_rtnode_zone);
|
||||
bridge_input_p = NULL;
|
||||
bridge_output_p = NULL;
|
||||
bridge_dn_p = NULL;
|
||||
bridge_detach_p = NULL;
|
||||
bstp_linkstate_p = NULL;
|
||||
mtx_destroy(&bridge_list_mtx);
|
||||
break;
|
||||
default:
|
||||
return EOPNOTSUPP;
|
||||
@ -481,6 +494,10 @@ bridge_clone_create(struct if_clone *ifc, int unit)
|
||||
ifp->if_baudrate = 0;
|
||||
ifp->if_type = IFT_BRIDGE;
|
||||
|
||||
mtx_lock(&bridge_list_mtx);
|
||||
LIST_INSERT_HEAD(&bridge_list, sc, sc_list);
|
||||
mtx_unlock(&bridge_list_mtx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -504,8 +521,7 @@ bridge_clone_destroy(struct ifnet *ifp)
|
||||
bridge_delete_member(sc, bif, 0);
|
||||
|
||||
while ((bif = LIST_FIRST(&sc->sc_spanlist)) != NULL) {
|
||||
LIST_REMOVE(bif, bif_next);
|
||||
free(bif, M_DEVBUF);
|
||||
bridge_delete_span(sc, bif);
|
||||
}
|
||||
|
||||
BRIDGE_UNLOCK(sc);
|
||||
@ -513,6 +529,10 @@ bridge_clone_destroy(struct ifnet *ifp)
|
||||
callout_drain(&sc->sc_brcallout);
|
||||
callout_drain(&sc->sc_bstpcallout);
|
||||
|
||||
mtx_lock(&bridge_list_mtx);
|
||||
LIST_REMOVE(sc, sc_list);
|
||||
mtx_unlock(&bridge_list_mtx);
|
||||
|
||||
ether_ifdetach(ifp);
|
||||
if_free_type(ifp, IFT_ETHER);
|
||||
|
||||
@ -724,6 +744,23 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
|
||||
bstp_initialization(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* bridge_delete_span:
|
||||
*
|
||||
* Delete the specified span interface.
|
||||
*/
|
||||
static void
|
||||
bridge_delete_span(struct bridge_softc *sc, struct bridge_iflist *bif)
|
||||
{
|
||||
BRIDGE_LOCK_ASSERT(sc);
|
||||
|
||||
KASSERT(bif->bif_ifp->if_bridge == NULL,
|
||||
("%s: not a span interface", __func__));
|
||||
|
||||
LIST_REMOVE(bif, bif_next);
|
||||
free(bif, M_DEVBUF);
|
||||
}
|
||||
|
||||
static int
|
||||
bridge_ioctl_add(struct bridge_softc *sc, void *arg)
|
||||
{
|
||||
@ -1285,8 +1322,7 @@ bridge_ioctl_delspan(struct bridge_softc *sc, void *arg)
|
||||
if (bif == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
LIST_REMOVE(bif, bif_next);
|
||||
free(bif, M_DEVBUF);
|
||||
bridge_delete_span(sc, bif);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -1298,20 +1334,37 @@ bridge_ioctl_delspan(struct bridge_softc *sc, void *arg)
|
||||
* interface is detaching.
|
||||
*/
|
||||
static void
|
||||
bridge_ifdetach(struct ifnet *ifp)
|
||||
bridge_ifdetach(void *arg __unused, struct ifnet *ifp)
|
||||
{
|
||||
struct bridge_softc *sc = ifp->if_bridge;
|
||||
struct bridge_iflist *bif;
|
||||
|
||||
BRIDGE_LOCK(sc);
|
||||
/* Check if the interface is a bridge member */
|
||||
if (sc != NULL) {
|
||||
BRIDGE_LOCK(sc);
|
||||
|
||||
bif = bridge_lookup_member_if(sc, ifp);
|
||||
if (bif == NULL)
|
||||
bif = bridge_lookup_member_if(sc, ifp);
|
||||
if (bif != NULL)
|
||||
bridge_delete_member(sc, bif, 1);
|
||||
|
||||
|
||||
BRIDGE_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
bridge_delete_member(sc, bif, 1);
|
||||
/* Check if the interface is a span port */
|
||||
mtx_lock(&bridge_list_mtx);
|
||||
LIST_FOREACH(sc, &bridge_list, sc_list) {
|
||||
BRIDGE_LOCK(sc);
|
||||
LIST_FOREACH(bif, &sc->sc_spanlist, bif_next)
|
||||
if (ifp == bif->bif_ifp) {
|
||||
bridge_delete_span(sc, bif);
|
||||
break;
|
||||
}
|
||||
|
||||
BRIDGE_UNLOCK(sc);
|
||||
BRIDGE_UNLOCK(sc);
|
||||
}
|
||||
mtx_unlock(&bridge_list_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -267,6 +267,7 @@ struct bridge_rtnode {
|
||||
*/
|
||||
struct bridge_softc {
|
||||
struct ifnet *sc_ifp; /* make this an interface */
|
||||
LIST_ENTRY(bridge_softc) sc_list;
|
||||
struct mtx sc_mtx;
|
||||
struct cv sc_cv;
|
||||
uint64_t sc_designated_root;
|
||||
@ -362,7 +363,6 @@ extern struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *);
|
||||
extern int (*bridge_output_p)(struct ifnet *, struct mbuf *,
|
||||
struct sockaddr *, struct rtentry *);
|
||||
extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *);
|
||||
extern void (*bridge_detach_p)(struct ifnet *);
|
||||
extern void (*bstp_linkstate_p)(struct ifnet *ifp, int state);
|
||||
|
||||
void bstp_initialization(struct bridge_softc *);
|
||||
|
@ -111,7 +111,6 @@ struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *);
|
||||
int (*bridge_output_p)(struct ifnet *, struct mbuf *,
|
||||
struct sockaddr *, struct rtentry *);
|
||||
void (*bridge_dn_p)(struct mbuf *, struct ifnet *);
|
||||
void (*bridge_detach_p)(struct ifnet *ifp);
|
||||
|
||||
static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
@ -899,12 +898,6 @@ ether_ifdetach(struct ifnet *ifp)
|
||||
(*ng_ether_detach_p)(ifp);
|
||||
}
|
||||
|
||||
if (ifp->if_bridge) {
|
||||
KASSERT(bridge_detach_p != NULL,
|
||||
("bridge_detach_p is NULL"));
|
||||
(*bridge_detach_p)(ifp);
|
||||
}
|
||||
|
||||
bpfdetach(ifp);
|
||||
if_detach(ifp);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user