diff options
author | luigi <luigi@FreeBSD.org> | 2001-02-02 00:18:00 +0000 |
---|---|---|
committer | luigi <luigi@FreeBSD.org> | 2001-02-02 00:18:00 +0000 |
commit | afaf9310f9d53654b62eec6d1e161a930b48ec6c (patch) | |
tree | 7883054a4e8cd6ddbdbfa3f02f94d51979d07a69 /sys/net | |
parent | e2f5e56cc5eb14305428986e66fcc781a0e712eb (diff) | |
download | FreeBSD-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.h | 49 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 33 |
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 |