diff options
-rw-r--r-- | sbin/ifconfig/ifbridge.c | 16 | ||||
-rw-r--r-- | sbin/ifconfig/ifconfig.8 | 10 | ||||
-rw-r--r-- | sys/net/if_bridge.c | 70 | ||||
-rw-r--r-- | sys/net/if_bridgevar.h | 4 |
4 files changed, 66 insertions, 34 deletions
diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c index 72fd491..d8176a8 100644 --- a/sbin/ifconfig/ifbridge.c +++ b/sbin/ifconfig/ifbridge.c @@ -665,6 +665,20 @@ setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp) err(1, "BRDGSTO %s", arg); } +static void +setbridge_private(const char *val, int d, int s, const struct afswtch *afp) +{ + + do_bridgeflag(s, val, IFBIF_PRIVATE, 1); +} + +static void +unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp) +{ + + do_bridgeflag(s, val, IFBIF_PRIVATE, 0); +} + static struct cmd bridge_cmds[] = { DEF_CMD_ARG("addm", setbridge_add), DEF_CMD_ARG("deletem", setbridge_delete), @@ -701,6 +715,8 @@ static struct cmd bridge_cmds[] = { DEF_CMD_ARG2("ifpriority", setbridge_ifpriority), DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost), DEF_CMD_ARG("timeout", setbridge_timeout), + DEF_CMD_ARG("private", setbridge_private), + DEF_CMD_ARG("-private", unsetbridge_private), }; static struct afswtch af_bridge = { .af_name = "af_bridge", diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index 79f0ce2..63b4317 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -1502,6 +1502,16 @@ address is seen on a different interface. Clear the .Dq sticky attribute on a member interface. +.It Cm private Ar interface +Mark an interface as a +.Dq private +interface. +A private interface does not forward any traffic to any other port that is also +a private interface. +.It Cm -private Ar interface +Clear the +.Dq private +attribute on a member interface. .It Cm span Ar interface Add the interface named by .Ar interface 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 { diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h index 8097cd9..ddd8ce7 100644 --- a/sys/net/if_bridgevar.h +++ b/sys/net/if_bridgevar.h @@ -142,9 +142,11 @@ struct ifbreq { #define IFBIF_BSTP_AUTOPTP 0x0100 /* member stp autoptp enabled */ #define IFBIF_BSTP_ADMEDGE 0x0200 /* member stp admin edge enabled */ #define IFBIF_BSTP_ADMCOST 0x0400 /* member stp admin path cost */ +#define IFBIF_PRIVATE 0x0800 /* if is a private segment */ #define IFBIFBITS "\020\001LEARNING\002DISCOVER\003STP\004SPAN" \ - "\005STICKY\006EDGE\007AUTOEDGE\010PTP\011AUTOPTP" + "\005STICKY\014PRIVATE\006EDGE\007AUTOEDGE\010PTP" \ + "\011AUTOPTP" #define IFBIFMASK ~(IFBIF_BSTP_EDGE|IFBIF_BSTP_AUTOEDGE|IFBIF_BSTP_PTP| \ IFBIF_BSTP_AUTOPTP|IFBIF_BSTP_ADMEDGE| \ IFBIF_BSTP_ADMCOST) /* not saved */ |