summaryrefslogtreecommitdiffstats
path: root/sys/net/if_ethersubr.c
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2005-06-05 03:13:13 +0000
committerthompsa <thompsa@FreeBSD.org>2005-06-05 03:13:13 +0000
commit6c5bdda300f45e4abacd6f3dbf4663bbfdfefa35 (patch)
tree352898b8dc193cd5970b2640defcbe72739413a7 /sys/net/if_ethersubr.c
parentdc83783f40a527cc3ecb6ae9c2c0277a18678b28 (diff)
downloadFreeBSD-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.c48
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)
OpenPOWER on IntegriCloud