diff options
author | glebius <glebius@FreeBSD.org> | 2004-10-12 10:33:42 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2004-10-12 10:33:42 +0000 |
commit | 30124ad8837dc84bb315a5a390b05d30636bada2 (patch) | |
tree | a5ded4c665031b36a0b508afb62b7435a0f6c875 /sys/net | |
parent | 13008687d43d8b904d17f862f9f9a7d2ffe7d5f9 (diff) | |
download | FreeBSD-src-30124ad8837dc84bb315a5a390b05d30636bada2.zip FreeBSD-src-30124ad8837dc84bb315a5a390b05d30636bada2.tar.gz |
Fix packet flow when both ng_ether(4) and bridge(4) are in use:
- push all bridge logic from if_ethersubr.c into bridge.c
make bridge_in() return mbuf pointer (or NULL).
- call only bridge_in() from ether_input(), after ng_ether_input()
was optinally called.
- call bridge_in() from ng_ether_rcv_upper().
Long description: http://lists.freebsd.org/mailman/htdig/freebsd-net/2004-May/003881.html
Reported by: Jian-Wei Wang <jwwang at FreeBSD.csie.NCTU.edu.tw>
Tested by: myself, Sergey Lyubka
Reviewed by: sam
Approved by: julian (mentor)
MFC after: 2 months
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/bridge.c | 33 | ||||
-rw-r--r-- | sys/net/bridge.h | 2 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 48 |
3 files changed, 32 insertions, 51 deletions
diff --git a/sys/net/bridge.c b/sys/net/bridge.c index 75f7c30..ddd0f0b 100644 --- a/sys/net/bridge.c +++ b/sys/net/bridge.c @@ -240,6 +240,7 @@ SYSCTL_INT(_net_link_ether_bridge, OID_AUTO, fw_count, CTLFLAG_RW, static int bdginit(void); static void parse_bdg_cfg(void); +static struct mbuf *bdg_forward(struct mbuf *, struct ifnet *); static int bdg_ipf; /* IPFilter enabled in bridge */ SYSCTL_INT(_net_link_ether_bridge, OID_AUTO, ipf, CTLFLAG_RW, @@ -760,13 +761,16 @@ bridge_dst_lookup(struct ether_header *eh, struct cluster_softc *c) * to fetch more of the packet, or simply drop it completely. */ -static struct ifnet * -bridge_in(struct ifnet *ifp, struct ether_header *eh) +static struct mbuf * +bridge_in(struct ifnet *ifp, struct mbuf *m) { - int index; + struct ether_header *eh; struct ifnet *dst, *old; bdg_hash_table *bt; /* location in hash table */ int dropit = BDG_MUTED(ifp); + int index; + + eh = mtod(m, struct ether_header *); /* * hash the source address @@ -856,7 +860,28 @@ bridge_in(struct ifnet *ifp, struct ether_header *eh) (dst <= BDG_FORWARD) ? bdg_dst_names[(uintptr_t)dst] : dst->if_xname)); - return dst; + switch ((uintptr_t)dst) { + case (uintptr_t)BDG_DROP: + m_freem(m); + return (NULL); + case (uintptr_t)BDG_LOCAL: + return (m); + case (uintptr_t)BDG_BCAST: + case (uintptr_t)BDG_MCAST: + m = bdg_forward(m, dst); +#ifdef DIAGNOSTIC /* glebius: am I right here? */ + if (m == NULL) { + if_printf(ifp, "bridge dropped %s packet\n", + dst == BDG_BCAST ? "broadcast" : "multicast"); + return (NULL); + } +#endif + return (m); + default: + m = bdg_forward(m, dst); + } + + return (NULL); /* not reached */ } /* diff --git a/sys/net/bridge.h b/sys/net/bridge.h index de30210..666c65d 100644 --- a/sys/net/bridge.h +++ b/sys/net/bridge.h @@ -101,7 +101,7 @@ struct bdg_stats { #define BDG_STAT(ifp, type) bdg_stats.s[ifp->if_index].p_in[(uintptr_t)type]++ #ifdef _KERNEL -typedef struct ifnet *bridge_in_t(struct ifnet *, struct ether_header *); +typedef struct mbuf *bridge_in_t(struct ifnet *, struct mbuf *); /* bdg_forward frees the mbuf if necessary, returning null */ typedef struct mbuf *bdg_forward_t(struct mbuf *, struct ifnet *); typedef void bdgtakeifaces_t(void); diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 2a5a030..e7a923b 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -566,53 +566,9 @@ ether_input(struct ifnet *ifp, struct mbuf *m) } /* Check for bridging mode */ - if (BDG_ACTIVE(ifp) ) { - struct ifnet *bif; - - /* - * Check with bridging code to see how the packet - * should be handled. Possibilities are: - * - * BDG_BCAST broadcast - * BDG_MCAST multicast - * BDG_LOCAL for local address, don't forward - * BDG_DROP discard - * ifp forward only to specified interface(s) - * - * Non-local destinations are handled by passing the - * packet back to the bridge code. - */ - bif = bridge_in_ptr(ifp, eh); - if (bif == BDG_DROP) { /* discard packet */ - m_freem(m); + if (BDG_ACTIVE(ifp) ) + if ((m = bridge_in_ptr(ifp, m)) == NULL) return; - } - if (bif != BDG_LOCAL) { /* non-local, forward */ - m = bdg_forward_ptr(m, bif); - /* - * The bridge may consume the packet if it's not - * supposed to be passed up or if a problem occurred - * while doing its job. This is reflected by it - * returning a NULL mbuf pointer. - */ - if (m == NULL) { - if (bif == BDG_BCAST || bif == BDG_MCAST) - if_printf(ifp, - "bridge dropped %s packet\n", - bif == BDG_BCAST ? "broadcast" : - "multicast"); - return; - } - /* - * But in some cases the bridge may return the - * packet for us to free; sigh. - */ - if (bif != BDG_BCAST && bif != BDG_MCAST) { - m_freem(m); - return; - } - } - } /* First chunk of an mbuf contains good entropy */ if (harvest.ethernet) |