summaryrefslogtreecommitdiffstats
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r--sys/net/if_bridge.c70
1 files changed, 37 insertions, 33 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 3f0cabf..6c96cbb 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -243,7 +243,8 @@ static void bridge_enqueue(struct bridge_softc *, struct ifnet *,
struct mbuf *);
static void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp, int);
-static void bridge_forward(struct bridge_softc *, struct mbuf *m);
+static void bridge_forward(struct bridge_softc *, struct bridge_iflist *,
+ struct mbuf *m);
static void bridge_timer(void *);
@@ -1873,9 +1874,10 @@ bridge_start(struct ifnet *ifp)
* NOTE: Releases the lock on return.
*/
static void
-bridge_forward(struct bridge_softc *sc, struct mbuf *m)
+bridge_forward(struct bridge_softc *sc, struct bridge_iflist *sbif,
+ struct mbuf *m)
{
- struct bridge_iflist *bif;
+ struct bridge_iflist *dbif;
struct ifnet *src_if, *dst_if, *ifp;
struct ether_header *eh;
uint16_t vlan;
@@ -1887,19 +1889,8 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m)
sc->sc_ifp->if_ibytes += m->m_pkthdr.len;
vlan = VLANTAGOF(m);
- /*
- * Look up the bridge_iflist.
- */
- bif = bridge_lookup_member_if(sc, src_if);
- if (bif == NULL) {
- /* Interface is not a bridge member (anymore?) */
- BRIDGE_UNLOCK(sc);
- m_freem(m);
- return;
- }
-
- if ((bif->bif_flags & IFBIF_STP) &&
- bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) {
+ if ((sbif->bif_flags & IFBIF_STP) &&
+ sbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) {
BRIDGE_UNLOCK(sc);
m_freem(m);
return;
@@ -1912,7 +1903,7 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m)
* address is valid and not multicast, record
* the address.
*/
- if ((bif->bif_flags & IFBIF_LEARNING) != 0 &&
+ if ((sbif->bif_flags & IFBIF_LEARNING) != 0 &&
ETHER_IS_MULTICAST(eh->ether_shost) == 0 &&
(eh->ether_shost[0] == 0 &&
eh->ether_shost[1] == 0 &&
@@ -1921,11 +1912,11 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m)
eh->ether_shost[4] == 0 &&
eh->ether_shost[5] == 0) == 0) {
(void) bridge_rtupdate(sc, eh->ether_shost, vlan,
- bif, 0, IFBAF_DYNAMIC);
+ sbif, 0, IFBAF_DYNAMIC);
}
- if ((bif->bif_flags & IFBIF_STP) != 0 &&
- bif->bif_stp.bp_state == BSTP_IFSTATE_LEARNING) {
+ if ((sbif->bif_flags & IFBIF_STP) != 0 &&
+ sbif->bif_stp.bp_state == BSTP_IFSTATE_LEARNING) {
m_freem(m);
BRIDGE_UNLOCK(sc);
return;
@@ -1993,16 +1984,23 @@ bridge_forward(struct bridge_softc *sc, struct mbuf *m)
m_freem(m);
return;
}
- bif = bridge_lookup_member_if(sc, dst_if);
- if (bif == NULL) {
+ dbif = bridge_lookup_member_if(sc, dst_if);
+ if (dbif == NULL) {
/* Not a member of the bridge (anymore?) */
BRIDGE_UNLOCK(sc);
m_freem(m);
return;
}
- if ((bif->bif_flags & IFBIF_STP) &&
- bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) {
+ /* Private segments can not talk to each other */
+ if (sbif->bif_flags & dbif->bif_flags & IFBIF_PRIVATE) {
+ BRIDGE_UNLOCK(sc);
+ m_freem(m);
+ return;
+ }
+
+ if ((dbif->bif_flags & IFBIF_STP) &&
+ dbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) {
BRIDGE_UNLOCK(sc);
m_freem(m);
return;
@@ -2122,7 +2120,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
}
/* Perform the bridge forwarding function with the copy. */
- bridge_forward(sc, mc);
+ bridge_forward(sc, bif, mc);
/*
* Reinject the mbuf as arriving on the bridge so we have a
@@ -2210,7 +2208,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
#undef GRAB_OUR_PACKETS
/* Perform the bridge forwarding function. */
- bridge_forward(sc, m);
+ bridge_forward(sc, bif, m);
return (NULL);
}
@@ -2228,11 +2226,13 @@ static void
bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
struct mbuf *m, int runfilt)
{
- struct bridge_iflist *bif;
+ struct bridge_iflist *dbif, *sbif;
struct mbuf *mc;
struct ifnet *dst_if;
int error = 0, used = 0, i;
+ sbif = bridge_lookup_member_if(sc, src_if);
+
BRIDGE_LOCK2REF(sc, error);
if (error) {
m_freem(m);
@@ -2251,23 +2251,27 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
goto out;
}
- LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
- dst_if = bif->bif_ifp;
+ LIST_FOREACH(dbif, &sc->sc_iflist, bif_next) {
+ dst_if = dbif->bif_ifp;
if (dst_if == src_if)
continue;
- if ((bif->bif_flags & IFBIF_STP) &&
- bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
+ /* Private segments can not talk to each other */
+ if (sbif && (sbif->bif_flags & dbif->bif_flags & IFBIF_PRIVATE))
+ continue;
+
+ if ((dbif->bif_flags & IFBIF_STP) &&
+ dbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
continue;
- if ((bif->bif_flags & IFBIF_DISCOVER) == 0 &&
+ if ((dbif->bif_flags & IFBIF_DISCOVER) == 0 &&
(m->m_flags & (M_BCAST|M_MCAST)) == 0)
continue;
if ((dst_if->if_drv_flags & IFF_DRV_RUNNING) == 0)
continue;
- if (LIST_NEXT(bif, bif_next) == NULL) {
+ if (LIST_NEXT(dbif, bif_next) == NULL) {
mc = m;
used = 1;
} else {
OpenPOWER on IntegriCloud