From 72fadc94c648e53283e45102233d04abe35fe19f Mon Sep 17 00:00:00 2001 From: mpi Date: Tue, 23 Jun 2015 09:42:23 +0000 Subject: [PATCH] Adapt bridge(4) to the new if_input() framework. Move bridge_input() outside of ether_input() in order to duplicate packets flowing through a bridge port before applying any transformation on mbufs. This saves a various m_adj(9)/M_PREPEND(9) dances and remove the bridge(4) hack from vlan(4). Tested by mxb and kettenis@ ok bluhm@ --- sys/net/if.c | 11 ++++++- sys/net/if_bridge.c | 69 ++++++++++++------------------------------ sys/net/if_bridge.h | 5 ++- sys/net/if_ethersubr.c | 24 +-------------- sys/net/if_vlan.c | 15 +-------- sys/netinet/ip_ether.c | 20 ++---------- 6 files changed, 37 insertions(+), 107 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index a9180400ba3..453c43e0a07 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.340 2015/06/16 11:09:39 mpi Exp $ */ +/* $OpenBSD: if.c,v 1.341 2015/06/23 09:42:23 mpi Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -530,6 +530,15 @@ if_input_process(void *xmq) continue; } +#if NBRIDGE > 0 + if (ifp->if_bridgeport && (m->m_flags & M_PROTO1) == 0) { + m = bridge_input(m); + if (m == NULL) + continue; + } + m->m_flags &= ~M_PROTO1; /* Loop prevention */ +#endif + /* * Pass this mbuf to all input handlers of its * interface until it is consumed. diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 15d77b216cc..9bf5fda2476 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.244 2015/06/16 11:09:39 mpi Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.245 2015/06/23 09:42:23 mpi Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -116,8 +116,6 @@ void bridge_broadcast(struct bridge_softc *, struct ifnet *, void bridge_localbroadcast(struct bridge_softc *, struct ifnet *, struct ether_header *, struct mbuf *); void bridge_span(struct bridge_softc *, struct mbuf *); -struct mbuf *bridge_dispatch(struct bridge_iflist *, struct ifnet *, - struct mbuf *); void bridge_stop(struct bridge_softc *); void bridge_init(struct bridge_softc *); int bridge_bifconf(struct bridge_softc *, struct ifbifconf *); @@ -1198,7 +1196,7 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m) * If packet is unicast, destined for someone on "this" * side of the bridge, drop it. */ - if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) { + if (!ETHER_IS_MULTICAST(eh.ether_dhost)) { if ((dst_p = bridge_rtlookup(sc, dst)) != NULL) dst_if = dst_p->brt_if; else @@ -1207,8 +1205,14 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m) m_freem(m); return; } - } else + } else { + if (memcmp(etherbroadcastaddr, eh.ether_dhost, + sizeof(etherbroadcastaddr)) == 0) + m->m_flags |= M_BCAST; + else + m->m_flags |= M_MCAST; dst_if = NULL; + } /* * Multicast packets get handled a little differently: @@ -1302,37 +1306,31 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m) * not for us, and schedule an interrupt. */ struct mbuf * -bridge_input(struct ifnet *ifp, struct ether_header *eh0, struct mbuf *m) +bridge_input(struct mbuf *m) { + struct ifnet *ifp; struct bridge_softc *sc; struct bridge_iflist *ifl; + struct bridge_iflist *srcifl; struct ether_header *eh; -#if NVLAN > 0 - uint16_t etype = ntohs(eh0->ether_type); -#endif /* NVLAN > 0 */ + struct arpcom *ac; + struct mbuf_list ml = MBUF_LIST_INITIALIZER(); + struct mbuf *mc; + int s; - /* - * Make sure this interface is a bridge member. - */ - if (ifp == NULL || ifp->if_bridgeport == NULL || m == NULL) + ifp = if_get(m->m_pkthdr.ph_ifidx); + KASSERT(ifp != NULL); + if (((ifp->if_flags & IFF_UP) == 0) || (ifp->if_bridgeport == NULL)) return (m); if ((m->m_flags & M_PKTHDR) == 0) panic("bridge_input(): no HDR"); - m->m_flags &= ~M_PROTO1; /* Loop prevention */ - ifl = (struct bridge_iflist *)ifp->if_bridgeport; sc = ifl->bridge_sc; if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) return (m); - M_PREPEND(m, sizeof(*eh), M_DONTWAIT); - if (m == NULL) - return (NULL); - eh = mtod(m, struct ether_header *); - memmove(eh, eh0, sizeof(*eh)); - #if NBPFILTER > 0 if (sc->sc_if.if_bpf) bpf_mtap_ether(sc->sc_if.if_bpf, m, BPF_DIRECTION_IN); @@ -1340,35 +1338,8 @@ bridge_input(struct ifnet *ifp, struct ether_header *eh0, struct mbuf *m) bridge_span(sc, m); - m = bridge_dispatch(ifl, ifp, m); - -#if NVLAN > 0 - if ((m != NULL) && ((m->m_flags & M_VLANTAG) || - etype == ETHERTYPE_VLAN || etype == ETHERTYPE_QINQ)) { - /* The bridge did not want the vlan frame either, drop it. */ - ifp->if_noproto++; - m_freem(m); - m = NULL; - } -#endif /* NVLAN > 0 */ - - return (m); -} - -struct mbuf * -bridge_dispatch(struct bridge_iflist *ifl, struct ifnet *ifp, struct mbuf *m) -{ - struct bridge_softc *sc = ifl->bridge_sc; - struct bridge_iflist *srcifl; - struct ether_header *eh; - struct arpcom *ac; - struct mbuf_list ml = MBUF_LIST_INITIALIZER(); - struct mbuf *mc; - int s; - eh = mtod(m, struct ether_header *); - - if (m->m_flags & (M_BCAST | M_MCAST)) { + if (ETHER_IS_MULTICAST(eh->ether_dhost)) { /* * Reserved destination MAC addresses (01:80:C2:00:00:0x) * should not be forwarded to bridge members according to diff --git a/sys/net/if_bridge.h b/sys/net/if_bridge.h index 6dbdb0dc0d9..3a373825295 100644 --- a/sys/net/if_bridge.h +++ b/sys/net/if_bridge.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.h,v 1.42 2015/04/12 09:57:54 dlg Exp $ */ +/* $OpenBSD: if_bridge.h,v 1.43 2015/06/23 09:42:23 mpi Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -437,8 +437,7 @@ struct bridge_softc { extern const u_int8_t bstp_etheraddr[]; void bridge_ifdetach(struct ifnet *); -struct mbuf *bridge_input(struct ifnet *, struct ether_header *, - struct mbuf *); +struct mbuf *bridge_input(struct mbuf *); int bridge_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); void bridge_update(struct ifnet *, struct ether_addr *, int); diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index c6ae0229045..94d7370a57f 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ethersubr.c,v 1.205 2015/06/16 11:09:39 mpi Exp $ */ +/* $OpenBSD: if_ethersubr.c,v 1.206 2015/06/23 09:42:23 mpi Exp $ */ /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ /* @@ -379,28 +379,6 @@ ether_input(struct mbuf *m) etype = ntohs(eh->ether_type); -#if NBRIDGE > 0 - /* - * Tap the packet off here for a bridge, if configured and - * active for this interface. bridge_input returns - * NULL if it has consumed the packet, otherwise, it - * gets processed as normal. - */ - if (ifp->if_bridgeport) { - if (m->m_flags & M_PROTO1) - m->m_flags &= ~M_PROTO1; - else { - m = bridge_input(ifp, eh, m); - if (m == NULL) - return (1); - /* The bridge has determined it's for us. */ - ifp = if_get(m->m_pkthdr.ph_ifidx); - KASSERT(ifp != NULL); - m_adj(m, ETHER_HDR_LEN); - } - } -#endif - ac = (struct arpcom *)ifp; /* diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 6371b96536b..8c359fde4e9 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vlan.c,v 1.129 2015/06/16 11:09:39 mpi Exp $ */ +/* $OpenBSD: if_vlan.c,v 1.130 2015/06/23 09:42:23 mpi Exp $ */ /* * Copyright 1998 Massachusetts Institute of Technology @@ -70,11 +70,6 @@ #include #endif -#include "bridge.h" -#if NBRIDGE > 0 -#include -#endif - u_long vlan_tagmask, svlan_tagmask; #define TAG_HASH_SIZE 32 @@ -304,14 +299,6 @@ vlan_input(struct mbuf *m) } if (ifv == NULL) { -#if NBRIDGE > 0 - /* - * If the packet hasn't been through its bridge(4) give - * it a chance. - */ - if (ifp->if_bridgeport && (m->m_flags & M_PROTO1) == 0) - return (0); -#endif ifp->if_noproto++; m_freem(m); return (1); diff --git a/sys/netinet/ip_ether.c b/sys/netinet/ip_ether.c index f581082c6a1..78bf0cbc083 100644 --- a/sys/netinet/ip_ether.c +++ b/sys/netinet/ip_ether.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ether.c,v 1.72 2015/06/16 11:09:40 mpi Exp $ */ +/* $OpenBSD: ip_ether.c,v 1.73 2015/06/23 09:42:23 mpi Exp $ */ /* * The author of this code is Angelos D. Keromytis (kermit@adk.gr) * @@ -162,7 +162,6 @@ etherip_input6(struct mbuf **m, int *offp, int proto) void etherip_decap(struct mbuf *m, int iphlen) { - struct ether_header eh; struct etherip_header eip; struct gif_softc *sc; int s; @@ -229,27 +228,14 @@ etherip_decap(struct mbuf *m, int iphlen) /* Statistics */ etheripstat.etherip_ibytes += m->m_pkthdr.len; - /* Copy ethernet header */ - m_copydata(m, 0, sizeof(eh), (void *) &eh); - /* Reset the flags based on the inner packet */ - m->m_flags &= ~(M_BCAST|M_MCAST|M_AUTH|M_CONF); - if (eh.ether_dhost[0] & 1) { - if (memcmp(etherbroadcastaddr, eh.ether_dhost, - sizeof(etherbroadcastaddr)) == 0) - m->m_flags |= M_BCAST; - else - m->m_flags |= M_MCAST; - } + m->m_flags &= ~(M_BCAST|M_MCAST|M_AUTH|M_CONF|M_PROTO1); #if NBPFILTER > 0 if (sc->gif_if.if_bpf) bpf_mtap_af(sc->gif_if.if_bpf, AF_LINK, m, BPF_DIRECTION_IN); #endif - /* Trim the beginning of the mbuf, to remove the ethernet header. */ - m_adj(m, sizeof(struct ether_header)); - /* * Tap the packet off here for a bridge. bridge_input() returns * NULL if it has consumed the packet. In the case of gif's, @@ -264,7 +250,7 @@ etherip_decap(struct mbuf *m, int iphlen) sc->gif_if.if_imcasts++; s = splnet(); - m = bridge_input(&sc->gif_if, &eh, m); + m = bridge_input(m); splx(s); if (m == NULL) return; -- 2.20.1