summaryrefslogtreecommitdiff
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
authorCamiel Dobbelaar <camield@cvs.openbsd.org>2012-10-05 17:17:05 +0000
committerCamiel Dobbelaar <camield@cvs.openbsd.org>2012-10-05 17:17:05 +0000
commit97f361f45ba615c51d5ed3d199661695056d69fd (patch)
treed587043476b3011e4b9d407ae8f76b924f697564 /sys/net/if_bridge.c
parentf9456dc1995e86224b952c3e98063ed528245036 (diff)
Point an interface directly to its bridgeport configuration, instead
of to the bridge itself. This is ok, since an interface can only be part of one bridge, and the parent bridge is easy to find from the bridgeport. This way we can get rid of a lot of list walks, improving performance and shortening the code. ok henning stsp sthen reyk
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r--sys/net/if_bridge.c190
1 files changed, 64 insertions, 126 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 54503a16dc6..72e244b9f48 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.196 2012/09/20 14:10:18 mpf Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.197 2012/10/05 17:17:04 camield Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -273,7 +273,7 @@ bridge_delete(struct bridge_softc *sc, struct bridge_iflist *p)
if (p->bif_flags & IFBIF_STP)
bstp_delete(p->bif_stp);
- p->ifp->if_bridge = NULL;
+ p->ifp->if_bridgeport = NULL;
error = ifpromisc(p->ifp, 0);
LIST_REMOVE(p, next);
@@ -310,11 +310,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = ENOENT;
break;
}
- if (ifs->if_bridge == (caddr_t)sc) {
- error = EEXIST;
- break;
- }
- if (ifs->if_bridge != NULL) {
+ if (ifs->if_bridgeport != NULL) {
error = EBUSY;
break;
}
@@ -384,28 +380,28 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
}
+ p->bridge_sc = sc;
p->ifp = ifs;
p->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
SIMPLEQ_INIT(&p->bif_brlin);
SIMPLEQ_INIT(&p->bif_brlout);
- ifs->if_bridge = (caddr_t)sc;
+ ifs->if_bridgeport = (caddr_t)p;
LIST_INSERT_HEAD(&sc->sc_iflist, p, next);
break;
case SIOCBRDGDEL:
if ((error = suser(curproc, 0)) != 0)
break;
-
- LIST_FOREACH(p, &sc->sc_iflist, next) {
- if (strncmp(p->ifp->if_xname, req->ifbr_ifsname,
- sizeof(p->ifp->if_xname)) == 0) {
- error = bridge_delete(sc, p);
- break;
- }
- }
- if (p == LIST_END(&sc->sc_iflist)) {
+ ifs = ifunit(req->ifbr_ifsname);
+ if (ifs == NULL) {
error = ENOENT;
break;
}
+ p = (struct bridge_iflist *)ifs->if_bridgeport;
+ if (p == NULL || p->bridge_sc != sc) {
+ error = ESRCH;
+ break;
+ }
+ error = bridge_delete(sc, p);
break;
case SIOCBRDGIFS:
error = bridge_bifconf(sc, (struct ifbifconf *)data);
@@ -418,11 +414,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = ENOENT;
break;
}
- if (ifs->if_bridge == (caddr_t)sc) {
- error = EEXIST;
- break;
- }
- if (ifs->if_bridge != NULL) {
+ if (ifs->if_bridgeport != NULL) {
error = EBUSY;
break;
}
@@ -467,15 +459,8 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = ENOENT;
break;
}
- if ((caddr_t)sc != ifs->if_bridge) {
- error = ESRCH;
- break;
- }
- LIST_FOREACH(p, &sc->sc_iflist, next) {
- if (p->ifp == ifs)
- break;
- }
- if (p == LIST_END(&sc->sc_iflist)) {
+ p = (struct bridge_iflist *)ifs->if_bridgeport;
+ if (p == NULL || p->bridge_sc != sc) {
error = ESRCH;
break;
}
@@ -515,15 +500,8 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = ENOENT;
break;
}
- if ((caddr_t)sc != ifs->if_bridge) {
- error = ESRCH;
- break;
- }
- LIST_FOREACH(p, &sc->sc_iflist, next) {
- if (p->ifp == ifs)
- break;
- }
- if (p == LIST_END(&sc->sc_iflist)) {
+ p = (struct bridge_iflist *)ifs->if_bridgeport;
+ if (p == NULL || p->bridge_sc != sc) {
error = ESRCH;
break;
}
@@ -561,15 +539,13 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCBRDGSADDR:
if ((error = suser(curproc, 0)) != 0)
break;
-
ifs = ifunit(bareq->ifba_ifsname);
if (ifs == NULL) { /* no such interface */
error = ENOENT;
break;
}
-
- if (ifs->if_bridge == NULL ||
- ifs->if_bridge != (caddr_t)sc) {
+ p = (struct bridge_iflist *)ifs->if_bridgeport;
+ if (p == NULL || p->bridge_sc != sc) {
error = ESRCH;
break;
}
@@ -626,16 +602,8 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = ENOENT;
break;
}
- if (ifs->if_bridge == NULL ||
- ifs->if_bridge != (caddr_t)sc) {
- error = ESRCH;
- break;
- }
- LIST_FOREACH(p, &sc->sc_iflist, next) {
- if (p->ifp == ifs)
- break;
- }
- if (p == LIST_END(&sc->sc_iflist)) {
+ p = (struct bridge_iflist *)ifs->if_bridgeport;
+ if (p == NULL || p->bridge_sc != sc) {
error = ESRCH;
break;
}
@@ -664,16 +632,8 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = ENOENT;
break;
}
- if (ifs->if_bridge == NULL ||
- ifs->if_bridge != (caddr_t)sc) {
- error = ESRCH;
- break;
- }
- LIST_FOREACH(p, &sc->sc_iflist, next) {
- if (p->ifp == ifs)
- break;
- }
- if (p == LIST_END(&sc->sc_iflist)) {
+ p = (struct bridge_iflist *)ifs->if_bridgeport;
+ if (p == NULL || p->bridge_sc != sc) {
error = ESRCH;
break;
}
@@ -731,51 +691,49 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
void
bridge_ifdetach(struct ifnet *ifp)
{
- struct bridge_softc *sc = (struct bridge_softc *)ifp->if_bridge;
+ struct bridge_softc *sc;
struct bridge_iflist *bif;
- LIST_FOREACH(bif, &sc->sc_iflist, next)
- if (bif->ifp == ifp) {
- bridge_delete(sc, bif);
- break;
- }
+ bif = (struct bridge_iflist *)ifp->if_bridgeport;
+ sc = bif->bridge_sc;
+
+ bridge_delete(sc, bif);
}
void
bridge_update(struct ifnet *ifp, struct ether_addr *ea, int delete)
{
- struct bridge_softc *sc = (struct bridge_softc *)ifp->if_bridge;
+ struct bridge_softc *sc;
struct bridge_iflist *bif;
u_int8_t *addr;
addr = (u_int8_t *)ea;
- LIST_FOREACH(bif, &sc->sc_iflist, next)
- if (bif->ifp == ifp) {
- /*
- * Update the bridge interface if it is in
- * the learning state.
- */
- if ((bif->bif_flags & IFBIF_LEARNING) &&
- (ETHER_IS_MULTICAST(addr) == 0) &&
- !(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 &&
- addr[3] == 0 && addr[4] == 0 && addr[5] == 0)) {
- /* Care must be taken with spanning tree */
- if ((bif->bif_flags & IFBIF_STP) &&
- (bif->bif_state == BSTP_IFSTATE_DISCARDING))
- return;
+ bif = (struct bridge_iflist *)ifp->if_bridgeport;
+ sc = bif->bridge_sc;
- /* Delete the address from the bridge */
- bridge_rtdaddr(sc, ea);
-
- if (!delete) {
- /* Update the bridge table */
- bridge_rtupdate(sc, ea, ifp, 0,
- IFBAF_DYNAMIC);
- }
- }
+ /*
+ * Update the bridge interface if it is in
+ * the learning state.
+ */
+ if ((bif->bif_flags & IFBIF_LEARNING) &&
+ (ETHER_IS_MULTICAST(addr) == 0) &&
+ !(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 &&
+ addr[3] == 0 && addr[4] == 0 && addr[5] == 0)) {
+ /* Care must be taken with spanning tree */
+ if ((bif->bif_flags & IFBIF_STP) &&
+ (bif->bif_state == BSTP_IFSTATE_DISCARDING))
return;
+
+ /* Delete the address from the bridge */
+ bridge_rtdaddr(sc, ea);
+
+ if (!delete) {
+ /* Update the bridge table */
+ bridge_rtupdate(sc, ea, ifp, 0, IFBAF_DYNAMIC);
}
+ }
+ return;
}
int
@@ -879,13 +837,8 @@ bridge_brlconf(struct bridge_softc *sc, struct ifbrlconf *bc)
ifp = ifunit(bc->ifbrl_ifsname);
if (ifp == NULL)
return (ENOENT);
- if (ifp->if_bridge == NULL || ifp->if_bridge != (caddr_t)sc)
- return (ESRCH);
- LIST_FOREACH(ifl, &sc->sc_iflist, next) {
- if (ifl->ifp == ifp)
- break;
- }
- if (ifl == LIST_END(&sc->sc_iflist))
+ ifl = (struct bridge_iflist *)ifp->if_bridgeport;
+ if (ifl == NULL || ifl->bridge_sc != sc)
return (ESRCH);
SIMPLEQ_FOREACH(n, &ifl->bif_brlin, brl_next) {
@@ -1005,11 +958,11 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
#endif /* IPSEC */
/* ifp must be a member interface of the bridge. */
- sc = (struct bridge_softc *)ifp->if_bridge;
- if (sc == NULL) {
+ if (ifp->if_bridgeport == NULL) {
m_freem(m);
return (EINVAL);
}
+ sc = ((struct bridge_iflist *)ifp->if_bridgeport)->bridge_sc;
if (m->m_len < sizeof(*eh)) {
m = m_pullup(m, sizeof(*eh));
@@ -1207,11 +1160,8 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m)
sc->sc_if.if_ipackets++;
sc->sc_if.if_ibytes += m->m_pkthdr.len;
- LIST_FOREACH(ifl, &sc->sc_iflist, next)
- if (ifl->ifp == src_if)
- break;
-
- if (ifl == LIST_END(&sc->sc_iflist)) {
+ ifl = (struct bridge_iflist *)src_if->if_bridgeport;
+ if (ifl == NULL) {
m_freem(m);
return;
}
@@ -1327,14 +1277,7 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m)
m_freem(m);
return;
}
- LIST_FOREACH(ifl, &sc->sc_iflist, next) {
- if (ifl->ifp == dst_if)
- break;
- }
- if (ifl == LIST_END(&sc->sc_iflist)) {
- m_freem(m);
- return;
- }
+ ifl = (struct bridge_iflist *)dst_if->if_bridgeport;
if ((ifl->bif_flags & IFBIF_STP) &&
(ifl->bif_state == BSTP_IFSTATE_DISCARDING)) {
m_freem(m);
@@ -1379,7 +1322,7 @@ bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
/*
* Make sure this interface is a bridge member.
*/
- if (ifp == NULL || ifp->if_bridge == NULL || m == NULL)
+ if (ifp == NULL || ifp->if_bridgeport == NULL || m == NULL)
return (m);
if ((m->m_flags & M_PKTHDR) == 0)
@@ -1387,17 +1330,11 @@ bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
m->m_flags &= ~M_PROTO1; /* Loop prevention */
- sc = (struct bridge_softc *)ifp->if_bridge;
+ ifl = (struct bridge_iflist *)ifp->if_bridgeport;
+ sc = ifl->bridge_sc;
if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
return (m);
- LIST_FOREACH(ifl, &sc->sc_iflist, next) {
- if (ifl->ifp == ifp)
- break;
- }
- if (ifl == LIST_END(&sc->sc_iflist))
- return (m);
-
#if NBPFILTER > 0
if (sc->sc_if.if_bpf)
bpf_mtap_hdr(sc->sc_if.if_bpf, (caddr_t)eh,
@@ -2000,10 +1937,11 @@ bridge_rtage(struct bridge_softc *sc)
void
bridge_rtagenode(struct ifnet *ifp, int age)
{
- struct bridge_softc *sc = (struct bridge_softc *)ifp->if_bridge;
+ struct bridge_softc *sc;
struct bridge_rtnode *n;
int i;
+ sc = ((struct bridge_iflist *)ifp->if_bridgeport)->bridge_sc;
if (sc == NULL)
return;