summaryrefslogtreecommitdiffstats
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2009-05-01 19:46:42 +0000
committerthompsa <thompsa@FreeBSD.org>2009-05-01 19:46:42 +0000
commite3d44e50bfc84fefdaf95052a5584a05e0014823 (patch)
tree573d4820154a81ca718009540b910fbd4ceb9569 /sys/net/if_bridge.c
parentc0a4585083af4b7e024799ba7e9153fb4b6f76ba (diff)
downloadFreeBSD-src-e3d44e50bfc84fefdaf95052a5584a05e0014823.zip
FreeBSD-src-e3d44e50bfc84fefdaf95052a5584a05e0014823.tar.gz
Reorder the bridge add and delete routines to avoid calling ifpromisc() with
the bridge lock held.
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r--sys/net/if_bridge.c69
1 files changed, 37 insertions, 32 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 70db614..276588b 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -893,29 +893,6 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
BRIDGE_LOCK_ASSERT(sc);
- if (!gone) {
- switch (ifs->if_type) {
- case IFT_ETHER:
- case IFT_L2VLAN:
- /*
- * Take the interface out of promiscuous mode.
- */
- (void) ifpromisc(ifs, 0);
- break;
-
- case IFT_GIF:
- break;
-
- default:
-#ifdef DIAGNOSTIC
- panic("bridge_delete_member: impossible");
-#endif
- break;
- }
- /* reneable any interface capabilities */
- bridge_set_ifcap(sc, bif, bif->bif_savedcaps);
- }
-
if (bif->bif_flags & IFBIF_STP)
bstp_disable(&bif->bif_stp);
@@ -948,6 +925,28 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
("%s: %d bridge routes referenced", __func__, bif->bif_addrcnt));
BRIDGE_UNLOCK(sc);
+ if (!gone) {
+ switch (ifs->if_type) {
+ case IFT_ETHER:
+ case IFT_L2VLAN:
+ /*
+ * Take the interface out of promiscuous mode.
+ */
+ (void) ifpromisc(ifs, 0);
+ break;
+
+ case IFT_GIF:
+ break;
+
+ default:
+#ifdef DIAGNOSTIC
+ panic("bridge_delete_member: impossible");
+#endif
+ break;
+ }
+ /* reneable any interface capabilities */
+ bridge_set_ifcap(sc, bif, bif->bif_savedcaps);
+ }
bstp_destroy(&bif->bif_stp); /* prepare to free */
BRIDGE_LOCK(sc);
free(bif, M_DEVBUF);
@@ -1017,17 +1016,9 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
switch (ifs->if_type) {
case IFT_ETHER:
case IFT_L2VLAN:
- /*
- * Place the interface into promiscuous mode.
- */
- error = ifpromisc(ifs, 1);
- if (error)
- goto out;
- break;
-
case IFT_GIF:
+ /* permitted interface types */
break;
-
default:
error = EINVAL;
goto out;
@@ -1055,6 +1046,20 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
/* Set interface capabilities to the intersection set of all members */
bridge_mutecaps(sc);
+
+ switch (ifs->if_type) {
+ case IFT_ETHER:
+ case IFT_L2VLAN:
+ /*
+ * Place the interface into promiscuous mode.
+ */
+ BRIDGE_UNLOCK(sc);
+ error = ifpromisc(ifs, 1);
+ BRIDGE_LOCK(sc);
+ break;
+ }
+ if (error)
+ bridge_delete_member(sc, bif, 0);
out:
if (error) {
if (bif != NULL)
OpenPOWER on IntegriCloud