--- //depot/vendor/freebsd/src/sys/conf/NOTES 2005/02/07 23:20:45 +++ //depot/user/andy_fud/if_bridge/sys/conf/NOTES 2005/02/22 00:17:42 @@ -604,6 +604,7 @@ device tun #Tunnel driver (ppp(8), nos-tun(8)) device sl #Serial Line IP device gre #IP over IP tunneling +device bridge_ng #Bridge interface device pf #PF OpenBSD packet-filter firewall device pflog #logging support interface for PF device pfsync #synchronization interface for PF --- //depot/vendor/freebsd/src/sys/conf/files 2005/02/14 06:00:55 +++ //depot/user/andy_fud/if_bridge/sys/conf/files 2005/02/22 00:17:42 @@ -1263,10 +1263,12 @@ net/bpf_filter.c optional bpf net/bpf_filter.c optional netgraph_bpf net/bridge.c optional bridge +net/bridgestp.c optional bridge_ng net/bsd_comp.c optional ppp_bsdcomp net/if.c standard net/if_arcsubr.c optional arcnet net/if_atmsubr.c optional atm +net/if_bridge.c optional bridge_ng net/if_clone.c standard net/if_disc.c optional disc net/if_ef.c optional ef --- //depot/vendor/freebsd/src/sys/i386/conf/GENERIC 2005/01/05 05:25:33 +++ //depot/user/andy_fud/if_bridge/sys/i386/conf/GENERIC 2005/01/12 01:48:56 @@ -250,6 +250,7 @@ device io # I/O device device random # Entropy device device ether # Ethernet support +device bridge_ng # Bridge Interface device sl # Kernel SLIP device ppp # Kernel PPP device tun # Packet tunnel. --- //depot/vendor/freebsd/src/sys/net/if.c 2005/02/14 05:37:07 +++ //depot/user/andy_fud/if_bridge/sys/net/if.c 2005/02/22 00:17:42 @@ -322,6 +322,7 @@ case IFT_XETHER: case IFT_ISO88025: case IFT_L2VLAN: + case IFT_BRIDGE: snprintf(eaddr, 18, "%6D", IFP2AC(ifp)->ac_enaddr, ":"); break; default: @@ -1860,6 +1861,7 @@ 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), --- //depot/vendor/freebsd/src/sys/net/if.h 2005/01/07 01:45:46 +++ //depot/user/andy_fud/if_bridge/sys/net/if.h 2005/01/12 01:48:56 @@ -281,6 +281,13 @@ 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 --- //depot/vendor/freebsd/src/sys/net/if_ethersubr.c 2005/02/18 22:35:19 +++ //depot/user/andy_fud/if_bridge/sys/net/if_ethersubr.c 2005/02/22 00:17:42 @@ -109,6 +109,10 @@ 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 }; @@ -278,6 +282,14 @@ (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. @@ -505,6 +517,7 @@ return; } eh = mtod(m, struct ether_header *); + etype = ntohs(eh->ether_type); if (m->m_pkthdr.len > ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) { @@ -566,6 +579,42 @@ 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!")); + /* clear M_PROMISC, in case the packets comes from a vlan */ + //m->m_flags &= ~M_PROMISC; + + /* 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) --- //depot/vendor/freebsd/src/sys/net/if_llc.h 2005/01/07 01:45:46 +++ //depot/user/andy_fud/if_bridge/sys/net/if_llc.h 2005/01/12 01:48:56 @@ -149,6 +149,7 @@ /* * 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 --- //depot/vendor/freebsd/src/sys/net/if_types.h 2005/01/07 01:52:23 +++ //depot/user/andy_fud/if_bridge/sys/net/if_types.h 2005/01/12 01:48:56 @@ -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 */ --- //depot/vendor/freebsd/src/sys/net/if_var.h 2005/01/07 01:52:23 +++ //depot/user/andy_fud/if_bridge/sys/net/if_var.h 2005/01/12 01:48:56 @@ -183,6 +183,8 @@ 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 */ --- //depot/vendor/freebsd/src/sys/netinet/if_ether.c 2005/01/07 01:52:23 +++ //depot/user/andy_fud/if_bridge/sys/netinet/if_ether.c 2005/01/12 01:48:56 @@ -547,6 +547,10 @@ struct in_addr isaddr, itaddr, myaddr; int op, rif_len; int req_len; + int bridged = 0; + + 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) { @@ -565,11 +569,11 @@ * when we have clusters of interfaces). */ 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; 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; /* @@ -584,7 +588,7 @@ /* * 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: myaddr = ia->ia_addr.sin_addr; @@ -615,7 +619,7 @@ 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) { if (log_arp_wrong_iface) log(LOG_ERR, "arp: %s is on %s but got reply from %*D on %s\n", inet_ntoa(isaddr),