Adapt bridge(4) to the new if_input() framework.
authormpi <mpi@openbsd.org>
Tue, 23 Jun 2015 09:42:23 +0000 (09:42 +0000)
committermpi <mpi@openbsd.org>
Tue, 23 Jun 2015 09:42:23 +0000 (09:42 +0000)
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 <mxb AT alumni DOT chalmers DOT se> and kettenis@

ok bluhm@

sys/net/if.c
sys/net/if_bridge.c
sys/net/if_bridge.h
sys/net/if_ethersubr.c
sys/net/if_vlan.c
sys/netinet/ip_ether.c

index a918040..453c43e 100644 (file)
@@ -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.
index 15d77b2..9bf5fda 100644 (file)
@@ -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
index 6dbdb0d..3a37382 100644 (file)
@@ -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);
index c6ae022..94d7370 100644 (file)
@@ -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;
 
        /*
index 6371b96..8c359fd 100644 (file)
@@ -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
 #include <net/bpf.h>
 #endif
 
-#include "bridge.h"
-#if NBRIDGE > 0
-#include <net/if_bridge.h>
-#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);
index f581082..78bf0cb 100644 (file)
@@ -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;