diff options
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r-- | sys/net/if_bridge.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index cc97a56..b22e324 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -244,6 +244,7 @@ static void bridge_ifdetach(void *arg __unused, struct ifnet *); static void bridge_init(void *); static void bridge_dummynet(struct mbuf *, struct ifnet *); static void bridge_stop(struct ifnet *, int); +static void bridge_start(struct ifnet *); static int bridge_transmit(struct ifnet *, struct mbuf *); static void bridge_qflush(struct ifnet *); static struct mbuf *bridge_input(struct ifnet *, struct mbuf *); @@ -608,10 +609,13 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params) if_initname(ifp, bridge_name, unit); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = bridge_ioctl; + ifp->if_start = bridge_start; ifp->if_transmit = bridge_transmit; ifp->if_qflush = bridge_qflush; ifp->if_init = bridge_init; ifp->if_type = IFT_BRIDGE; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + IFQ_SET_READY(&ifp->if_snd); /* * Generate an ethernet address with a locally administered address. @@ -816,6 +820,8 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } BRIDGE_LOCK(sc); LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + if (bif->bif_ifp->if_type == IFT_GIF) + continue; if (bif->bif_ifp->if_mtu != ifr->ifr_mtu) { log(LOG_NOTICE, "%s: invalid MTU: %lu(%s)" " != %d\n", sc->sc_ifp->if_xname, @@ -1107,6 +1113,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) } #endif /* Allow the first Ethernet member to define the MTU */ + if (ifs->if_type != IFT_GIF) { if (LIST_EMPTY(&sc->sc_iflist)) sc->sc_ifp->if_mtu = ifs->if_mtu; else if (sc->sc_ifp->if_mtu != ifs->if_mtu) { @@ -1114,6 +1121,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) ifs->if_mtu, ifs->if_xname, sc->sc_ifp->if_mtu); return (EINVAL); } + } bif = malloc(sizeof(*bif), M_DEVBUF, M_NOWAIT|M_ZERO); if (bif == NULL) @@ -2073,6 +2081,47 @@ bridge_qflush(struct ifnet *ifp __unused) } /* + * bridge_start: + * + * Start output on a bridge. + * + */ +static void +bridge_start(struct ifnet *ifp) +{ + struct bridge_softc *sc; + struct mbuf *m; + struct ether_header *eh; + struct ifnet *dst_if; + + sc = ifp->if_softc; + + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + for (;;) { + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == 0) + break; + ETHER_BPF_MTAP(ifp, m); + + eh = mtod(m, struct ether_header *); + dst_if = NULL; + + BRIDGE_LOCK(sc); + if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) { + dst_if = bridge_rtlookup(sc, eh->ether_dhost, 1); + } + + if (dst_if == NULL) + bridge_broadcast(sc, ifp, m, 0); + else { + BRIDGE_UNLOCK(sc); + bridge_enqueue(sc, dst_if, m); + } + } + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; +} + +/* * bridge_forward: * * The forwarding function of the bridge. |