summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--sys/net/if.c8
-rw-r--r--sys/net/if.h7
-rw-r--r--sys/net/if_ethersubr.c48
-rw-r--r--sys/net/if_llc.h1
-rw-r--r--sys/net/if_types.h1
-rw-r--r--sys/net/if_var.h2
-rw-r--r--sys/netinet/if_ether.c12
-rw-r--r--sys/sys/sockio.h5
8 files changed, 80 insertions, 4 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index a39b2ac..d244f4e 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -93,6 +93,7 @@ SYSCTL_INT(_net_link, OID_AUTO, log_link_state_change, CTLFLAG_RW,
&log_link_state_change, 0,
"log interface link state change events");
+void (*bstp_linkstate_p)(struct ifnet *ifp, int state);
void (*ng_ether_link_state_p)(struct ifnet *ifp, int state);
struct mbuf *(*tbr_dequeue_ptr)(struct ifaltq *, int) = NULL;
@@ -337,6 +338,7 @@ if_findindex(struct ifnet *ifp)
case IFT_XETHER:
case IFT_ISO88025:
case IFT_L2VLAN:
+ case IFT_BRIDGE:
snprintf(eaddr, 18, "%6D", IFP2AC(ifp)->ac_enaddr, ":");
break;
default:
@@ -1049,6 +1051,11 @@ do_link_state_change(void *arg, int pending)
if (ifp->if_carp)
carp_carpdev_state(ifp->if_carp);
#endif
+ if (ifp->if_bridge) {
+ KASSERT(bstp_linkstate_p != NULL,("if_bridge bstp not loaded!"));
+ (*bstp_linkstate_p)(ifp, link_state);
+ }
+
if (pending > 1)
if_printf(ifp, "%d link states coalesced\n", pending);
if (log_link_state_change)
@@ -1932,6 +1939,7 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
case IFT_XETHER:
case IFT_ISO88025:
case IFT_L2VLAN:
+ case IFT_BRIDGE:
bcopy(lladdr, IFP2AC(ifp)->ac_enaddr, len);
/*
* XXX We also need to store the lladdr in LLADDR(sdl),
diff --git a/sys/net/if.h b/sys/net/if.h
index b4d5bdb..39bff63 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -281,6 +281,13 @@ struct ifmediareq {
int *ifm_ulist; /* media words */
};
+struct ifdrv {
+ char ifd_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ unsigned long ifd_cmd;
+ size_t ifd_len;
+ void *ifd_data;
+};
+
/*
* Structure used to retrieve aux status data from interfaces.
* Kernel suppliers to this interface should respect the formatting
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)
diff --git a/sys/net/if_llc.h b/sys/net/if_llc.h
index afdcda8..8d96686 100644
--- a/sys/net/if_llc.h
+++ b/sys/net/if_llc.h
@@ -149,6 +149,7 @@ struct frmrinfo {
/*
* ISO PDTR 10178 contains among others
*/
+#define LLC_8021D_LSAP 0x42
#define LLC_X25_LSAP 0x7e
#define LLC_SNAP_LSAP 0xaa
#define LLC_ISO_LSAP 0xfe
diff --git a/sys/net/if_types.h b/sys/net/if_types.h
index e60b65d..1dff5c2 100644
--- a/sys/net/if_types.h
+++ b/sys/net/if_types.h
@@ -238,6 +238,7 @@
#define IFT_ATMVCIENDPT 0xc2 /* ATM VCI End Point */
#define IFT_OPTICALCHANNEL 0xc3 /* Optical Channel */
#define IFT_OPTICALTRANSPORT 0xc4 /* Optical Transport */
+#define IFT_BRIDGE 0xd1 /* Transparent bridge interface */
#define IFT_STF 0xd7 /* 6to4 interface */
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 6a17905..b189a70 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -184,6 +184,8 @@ struct ifnet {
struct ifaltq if_snd; /* output queue (includes altq) */
const u_int8_t *if_broadcastaddr; /* linklevel broadcast bytestring */
+ void *if_bridge; /* bridge glue */
+
struct lltable *lltables; /* list of L3-L2 resolution tables */
struct label *if_label; /* interface MAC label */
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 56d411d..83e5449 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -553,10 +553,14 @@ in_arpinput(m)
u_int8_t *enaddr = NULL;
int op, rif_len;
int req_len;
+ int bridged = 0;
#ifdef DEV_CARP
int carp_match = 0;
#endif
+ if (do_bridge || ifp->if_bridge)
+ bridged = 1;
+
req_len = arphdr_len2(ifp->if_addrlen, sizeof(struct in_addr));
if (m->m_len < req_len && (m = m_pullup(m, req_len)) == NULL) {
log(LOG_ERR, "in_arp: runt packet -- m_pullup failed\n");
@@ -578,7 +582,7 @@ in_arpinput(m)
* XXX: This is really ugly!
*/
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) {
- if ((do_bridge || (ia->ia_ifp == ifp)) &&
+ if ((bridged || (ia->ia_ifp == ifp)) &&
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
goto match;
#ifdef DEV_CARP
@@ -591,7 +595,7 @@ in_arpinput(m)
#endif
}
LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash)
- if ((do_bridge || (ia->ia_ifp == ifp)) &&
+ if ((bridged || (ia->ia_ifp == ifp)) &&
isaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
goto match;
/*
@@ -606,7 +610,7 @@ in_arpinput(m)
/*
* If bridging, fall back to using any inet address.
*/
- if (!do_bridge || (ia = TAILQ_FIRST(&in_ifaddrhead)) == NULL)
+ if (!bridged || (ia = TAILQ_FIRST(&in_ifaddrhead)) == NULL)
goto drop;
match:
if (!enaddr)
@@ -639,7 +643,7 @@ match:
la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);
if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
/* the following is not an error when doing bridging */
- if (!do_bridge && rt->rt_ifp != ifp
+ if (!bridged && rt->rt_ifp != ifp
#ifdef DEV_CARP
&& (ifp->if_type != IFT_CARP || !carp_match)
#endif
diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h
index 4c064e2..82059a4 100644
--- a/sys/sys/sockio.h
+++ b/sys/sys/sockio.h
@@ -105,6 +105,11 @@
#define SIOCGPRIVATE_0 _IOWR('i', 80, struct ifreq) /* device private 0 */
#define SIOCGPRIVATE_1 _IOWR('i', 81, struct ifreq) /* device private 1 */
+#define SIOCSDRVSPEC _IOW('i', 123, struct ifdrv) /* set driver-specific
+ parameters */
+#define SIOCGDRVSPEC _IOWR('i', 123, struct ifdrv) /* get driver-specific
+ parameters */
+
#define SIOCIFCREATE _IOWR('i', 122, struct ifreq) /* create clone if */
#define SIOCIFDESTROY _IOW('i', 121, struct ifreq) /* destroy clone if */
#define SIOCIFGCLONERS _IOWR('i', 120, struct if_clonereq) /* get cloners */
OpenPOWER on IntegriCloud