summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>2001-02-02 00:18:00 +0000
committerluigi <luigi@FreeBSD.org>2001-02-02 00:18:00 +0000
commitafaf9310f9d53654b62eec6d1e161a930b48ec6c (patch)
tree7883054a4e8cd6ddbdbfa3f02f94d51979d07a69 /sys/net
parente2f5e56cc5eb14305428986e66fcc781a0e712eb (diff)
downloadFreeBSD-src-afaf9310f9d53654b62eec6d1e161a930b48ec6c.zip
FreeBSD-src-afaf9310f9d53654b62eec6d1e161a930b48ec6c.tar.gz
MFS: bridge/ipfw/dummynet fixes (bridge.c will be committed separately)
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/bridge.h49
-rw-r--r--sys/net/if_ethersubr.c33
2 files changed, 66 insertions, 16 deletions
diff --git a/sys/net/bridge.h b/sys/net/bridge.h
index 246bb87..4f81ebe 100644
--- a/sys/net/bridge.h
+++ b/sys/net/bridge.h
@@ -37,8 +37,43 @@ typedef struct hash_table {
extern bdg_hash_table *bdg_table ;
+/*
+ * We need additional info for the bridge. The bdg_ifp2sc[] array
+ * provides a pointer to this struct using the if_index.
+ * bdg_softc has a backpointer to the struct ifnet, the bridge
+ * flags, and a cluster (bridging occurs only between port of the
+ * same cluster).
+ */
+struct bdg_softc {
+ struct ifnet *ifp ;
+ /* also ((struct arpcom *)ifp)->ac_enaddr is the eth. addr */
+ int flags ;
+#define IFF_BDG_PROMISC 0x0001 /* set promisc mode on this if. */
+#define IFF_MUTE 0x0002 /* mute this if for bridging. */
+#define IFF_USED 0x0004 /* use this if for bridging. */
+ short cluster_id ; /* in network format */
+ u_long magic;
+} ;
+
+extern struct bdg_softc *ifp2sc;
+
+#define BDG_USED(ifp) (ifp2sc[ifp->if_index].flags & IFF_USED)
+#define BDG_MUTED(ifp) (ifp2sc[ifp->if_index].flags & IFF_MUTE)
+#define BDG_MUTE(ifp) ifp2sc[ifp->if_index].flags |= IFF_MUTE
+#define BDG_UNMUTE(ifp) ifp2sc[ifp->if_index].flags &= ~IFF_MUTE
+#define BDG_CLUSTER(ifp) (ifp2sc[ifp->if_index].cluster_id)
+#define BDG_EH(ifp) ((struct arpcom *)ifp)->ac_enaddr
+
+#define BDG_SAMECLUSTER(ifp,src) \
+ (src == NULL || BDG_CLUSTER(ifp) == BDG_CLUSTER(src) )
+
+
#define BDG_MAX_PORTS 128
-extern unsigned char bdg_addresses[6*BDG_MAX_PORTS];
+typedef struct _bdg_addr {
+ unsigned char etheraddr[6] ;
+ short cluster_id ;
+} bdg_addr ;
+extern bdg_addr bdg_addresses[BDG_MAX_PORTS];
extern int bdg_ports ;
extern void bdgtakeifaces(void);
@@ -53,7 +88,7 @@ extern void bdgtakeifaces(void);
struct ifnet *bridge_in(struct ifnet *ifp, struct ether_header *eh);
/* bdg_forward frees the mbuf if necessary, returning null */
-int bdg_forward(struct mbuf **m0, struct ether_header *eh, struct ifnet *dst);
+struct mbuf *bdg_forward(struct mbuf *m0, struct ether_header *eh, struct ifnet *dst);
#ifdef __i386__
#define BDG_MATCH(a,b) ( \
@@ -108,6 +143,9 @@ struct bdg_stats {
* BDG_LOCAL is for a local address
* BDG_DROP must be dropped
* other ifp of the dest. interface (incl.self)
+ *
+ * We assume this is only called for interfaces for which bridging
+ * is enabled, i.e. BDG_USED(ifp) is true.
*/
static __inline
struct ifnet *
@@ -115,7 +153,7 @@ bridge_dst_lookup(struct ether_header *eh)
{
struct ifnet *dst ;
int index ;
- u_char *eth_addr = bdg_addresses ;
+ bdg_addr *p ;
if (IS_ETHER_BROADCAST(eh->ether_dhost))
return BDG_BCAST ;
@@ -124,9 +162,8 @@ bridge_dst_lookup(struct ether_header *eh)
/*
* Lookup local addresses in case one matches.
*/
- for (index = bdg_ports, eth_addr = bdg_addresses ;
- index ; index--, eth_addr += 6 )
- if (BDG_MATCH(eth_addr, eh->ether_dhost) )
+ for (index = bdg_ports, p = bdg_addresses ; index ; index--, p++ )
+ if (BDG_MATCH(p->etheraddr, eh->ether_dhost) )
return BDG_LOCAL ;
/*
* Look for a possible destination in table
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 0bbb2c3..ed7fa57 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -362,14 +362,18 @@ ether_output_frame(ifp, m)
int error = 0;
#ifdef BRIDGE
- if (do_bridge) {
- struct ether_header hdr;
+ if (do_bridge && BDG_USED(ifp) ) {
+ struct ether_header *eh; /* a ptr suffices */
+ struct ifnet *oifp = ifp ;
m->m_pkthdr.rcvif = NULL;
- bcopy(mtod(m, struct ether_header *), &hdr, ETHER_HDR_LEN);
+ eh = mtod(m, struct ether_header *);
m_adj(m, ETHER_HDR_LEN);
- ifp = bridge_dst_lookup(&hdr);
- bdg_forward(&m, &hdr, ifp);
+ ifp = bridge_dst_lookup(eh);
+ if (ifp > BDG_FORWARD && !BDG_SAMECLUSTER(ifp, oifp)) {
+ printf("ether_out_frame: bad output if\n");
+ }
+ m = bdg_forward(m, eh, ifp);
if (m != NULL)
m_freem(m);
return (0);
@@ -408,6 +412,7 @@ ether_input(ifp, eh, m)
struct ether_header *eh;
struct mbuf *m;
{
+ struct ether_header save_eh;
/* Check for a BPF tap */
if (ifp->if_bpf != NULL) {
@@ -429,7 +434,7 @@ ether_input(ifp, eh, m)
#ifdef BRIDGE
/* Check for bridging mode */
- if (do_bridge) {
+ if (do_bridge && BDG_USED(ifp) ) {
struct ifnet *bif;
/* Check with bridging code */
@@ -438,14 +443,22 @@ ether_input(ifp, eh, m)
return;
}
if (bif != BDG_LOCAL) {
- bdg_forward(&m, eh, bif); /* needs forwarding */
+ struct mbuf *oldm = m ;
+
+ save_eh = *eh ; /* because it might change */
+ m = bdg_forward(&m, eh, bif); /* needs forwarding */
/*
* Do not continue if bdg_forward() processed our
* packet (and cleared the mbuf pointer m) or if
* it dropped (m_free'd) the packet itself.
*/
- if (m == NULL)
- return;
+ if (m == NULL) {
+ if (bif == BDG_BCAST || bif == BDG_MCAST)
+ printf("bdg_forward drop MULTICAST PKT\n");
+ return;
+ }
+ if (m != oldm) /* m changed! */
+ eh = &save_eh ;
}
if (bif == BDG_LOCAL
|| bif == BDG_BCAST
@@ -454,7 +467,7 @@ ether_input(ifp, eh, m)
/* If not local and not multicast, just drop it */
if (m != NULL)
- m_freem(m);
+ m_freem(m);
return;
}
#endif
OpenPOWER on IntegriCloud