diff options
author | thompsa <thompsa@FreeBSD.org> | 2005-06-05 03:13:13 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2005-06-05 03:13:13 +0000 |
commit | 6c5bdda300f45e4abacd6f3dbf4663bbfdfefa35 (patch) | |
tree | 352898b8dc193cd5970b2640defcbe72739413a7 /sys/net/if_ethersubr.c | |
parent | dc83783f40a527cc3ecb6ae9c2c0277a18678b28 (diff) | |
download | FreeBSD-src-6c5bdda300f45e4abacd6f3dbf4663bbfdfefa35.zip FreeBSD-src-6c5bdda300f45e4abacd6f3dbf4663bbfdfefa35.tar.gz |
Add hooks into the networking layer to support if_bridge. This changes struct
ifnet so a buildworld is necessary.
Approved by: mlaier (mentor)
Obtained from: NetBSD
Diffstat (limited to 'sys/net/if_ethersubr.c')
-rw-r--r-- | sys/net/if_ethersubr.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 7f4b1ce..7c62f37 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -114,6 +114,10 @@ bdg_forward_t *bdg_forward_ptr; bdgtakeifaces_t *bdgtakeifaces_ptr; struct bdg_softc *ifp2sc; +struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *); +int (*bridge_output_p)(struct ifnet *, struct mbuf *, + struct sockaddr *, struct rtentry *); + static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -283,6 +287,15 @@ ether_output(struct ifnet *ifp, struct mbuf *m, (void)memcpy(eh->ether_shost, IFP2AC(ifp)->ac_enaddr, sizeof(eh->ether_shost)); + /* + * Bridges require special output handling. + */ + if (ifp->if_bridge) { + KASSERT(bridge_output_p != NULL, + ("ether_input: if_bridge not loaded!")); + return ((*bridge_output_p)(ifp, m, NULL, NULL)); + } + /* * If a simplex interface, and the packet is being sent to our * Ethernet address or a broadcast address, loopback a copy. @@ -577,6 +590,41 @@ ether_input(struct ifnet *ifp, struct mbuf *m) return; } + /* + * Tap the packet off here for a bridge. bridge_input() + * will return NULL if it has consumed the packet, otherwise + * it gets processed as normal. Note that bridge_input() + * will always return the original packet if we need to + * process it locally. + */ + if (ifp->if_bridge) { + KASSERT(bridge_input_p != NULL, + ("ether_input: if_bridge not loaded!")); + + /* Mark the packet as broadcast or multicast. This is also set + * further down the code in ether_demux() but since the bridge + * input routine rarely returns a mbuf for further processing, + * it is an acceptable duplication. + */ + if (ETHER_IS_MULTICAST(eh->ether_dhost)) { + if (bcmp(etherbroadcastaddr, eh->ether_dhost, + sizeof(etherbroadcastaddr)) == 0) + m->m_flags |= M_BCAST; + else + m->m_flags |= M_MCAST; + } + + m = (*bridge_input_p)(ifp, m); + if (m == NULL) + return; + /* + * Bridge has determined that the packet is for us. + * Update our interface pointer -- we may have had + * to "bridge" the packet locally. + */ + ifp = m->m_pkthdr.rcvif; + } + /* Check for bridging mode */ if (BDG_ACTIVE(ifp) ) if ((m = bridge_in_ptr(ifp, m)) == NULL) |