Page MenuHomeFreeBSD

D38066.id118432.diff
No OneTemporary

D38066.id118432.diff

diff --git a/share/man/man4/bridge.4 b/share/man/man4/bridge.4
--- a/share/man/man4/bridge.4
+++ b/share/man/man4/bridge.4
@@ -35,7 +35,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 7, 2022
+.Dd March 6, 2023
.Dt IF_BRIDGE 4
.Os
.Sh NAME
@@ -412,6 +412,29 @@
Enabling
.Va net.link.bridge.pfil_local_phys
will let you do the additional filtering on the physical interface.
+.Sh NETMAP
+.Xr netmap 4
+applications may open a bridge interface in emulated mode.
+The netmap application will receive all packets which arrive from member
+interfaces.
+In particular, packets which would otherwise be forwarded to another
+member interface will be received by the netmap application.
+.Pp
+When the
+.Xr netmap 4
+application transmits a packet to the host stack via the bridge interface,
+.Nm
+receive it and attempts to determine its
+.Ql source
+interface by looking up the source MAC address in the interface's learning
+tables.
+Packets for which no matching source interface is found are dropped and the
+input error counter is incremented.
+If a matching source interface is found,
+.Nm
+treats the packet as though it was received from the corresponding interface
+and handles it normally without passing the packet back to
+.Xr netmap 4 .
.Sh EXAMPLES
The following when placed in the file
.Pa /etc/rc.conf
@@ -486,6 +509,7 @@
.Xr gif 4 ,
.Xr ipf 4 ,
.Xr ipfw 4 ,
+.Xr netmap 4 ,
.Xr pf 4 ,
.Xr ifconfig 8
.Sh HISTORY
diff --git a/sys/net/ethernet.h b/sys/net/ethernet.h
--- a/sys/net/ethernet.h
+++ b/sys/net/ethernet.h
@@ -43,6 +43,7 @@
* Ethernet-specific mbuf flags.
*/
#define M_HASFCS M_PROTO5 /* FCS included at end of frame */
+#define M_BRIDGE_INJECT M_PROTO6 /* if_bridge-injected frame */
/*
* Ethernet CRC32 polynomials (big- and little-endian versions).
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -267,6 +267,7 @@
uint32_t sc_brtexceeded; /* # of cache drops */
struct ifnet *sc_ifaddr; /* member mac copied from */
struct ether_addr sc_defaddr; /* Default MAC address */
+ if_input_fn_t sc_if_input; /* Saved copy of if_input */
struct epoch_context sc_epoch_ctx;
};
@@ -298,6 +299,7 @@
#endif
static void bridge_qflush(struct ifnet *);
static struct mbuf *bridge_input(struct ifnet *, struct mbuf *);
+static void bridge_inject(struct ifnet *, struct mbuf *);
static int bridge_output(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
static int bridge_enqueue(struct bridge_softc *, struct ifnet *,
@@ -753,6 +755,14 @@
#ifdef VIMAGE
ifp->if_reassign = bridge_reassign;
#endif
+ sc->sc_if_input = ifp->if_input;
+ ifp->if_input = bridge_inject;
+
+ /*
+ * Allow BRIDGE_INPUT() to pass in packets originating from the bridge
+ * itself. This is required for netmap but otherwise has no effect.
+ */
+ ifp->if_bridge_input = bridge_input;
BRIDGE_LIST_LOCK();
LIST_INSERT_HEAD(&V_bridge_list, sc, sc_list);
@@ -2317,10 +2327,6 @@
if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
vlan = VLANTAGOF(m);
- if ((sbif->bif_flags & IFBIF_STP) &&
- sbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
- goto drop;
-
eh = mtod(m, struct ether_header *);
dst = eh->ether_dhost;
@@ -2340,6 +2346,20 @@
sbif->bif_stp.bp_state == BSTP_IFSTATE_LEARNING)
goto drop;
+#ifdef DEV_NETMAP
+ /*
+ * If the packet wasn't injected by netmap itself, and the netmap
+ * application opted into receiving forwarded packets by putting the
+ * interface into promiscuous mode, pass it down.
+ */
+ if ((m->m_flags & M_BRIDGE_INJECT) == 0 &&
+ (if_getcapenable(ifp) & IFCAP_NETMAP) != 0) {
+ ifp->if_input(ifp, m);
+ return;
+ }
+ m->m_flags &= ~M_BRIDGE_INJECT;
+#endif
+
/*
* At this point, the port either doesn't participate
* in spanning tree or it is in the forwarding state.
@@ -2446,7 +2466,7 @@
static struct mbuf *
bridge_input(struct ifnet *ifp, struct mbuf *m)
{
- struct bridge_softc *sc = ifp->if_bridge;
+ struct bridge_softc *sc;
struct bridge_iflist *bif, *bif2;
struct ifnet *bifp;
struct ether_header *eh;
@@ -2456,11 +2476,31 @@
NET_EPOCH_ASSERT();
- if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return (m);
+ eh = mtod(m, struct ether_header *);
+ vlan = VLANTAGOF(m);
+ sc = ifp->if_bridge;
+ if (sc == NULL) {
+ /*
+ * This packet originated from the bridge itself, so it must
+ * have been transmitted by netmap. Derive the "source"
+ * interface from the source address and drop the packet if the
+ * source address isn't known.
+ */
+ KASSERT((m->m_flags & M_BRIDGE_INJECT) != 0,
+ ("%s: ifnet %p missing a bridge softc", __func__, ifp));
+ sc = if_getsoftc(ifp);
+ ifp = bridge_rtlookup(sc, eh->ether_shost, vlan);
+ if (ifp == NULL) {
+ if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1);
+ m_freem(m);
+ return (NULL);
+ }
+ m->m_pkthdr.rcvif = ifp;
+ }
bifp = sc->sc_ifp;
- vlan = VLANTAGOF(m);
+ if ((bifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return (m);
/*
* Implement support for bridge monitoring. If this flag has been
@@ -2481,8 +2521,6 @@
return (m);
}
- eh = mtod(m, struct ether_header *);
-
bridge_span(sc, m);
if (m->m_flags & (M_BCAST|M_MCAST)) {
@@ -2527,7 +2565,8 @@
}
if (mc2 != NULL) {
mc2->m_pkthdr.rcvif = bifp;
- (*bifp->if_input)(bifp, mc2);
+ mc2->m_flags &= ~M_BRIDGE_INJECT;
+ sc->sc_if_input(bifp, mc2);
}
/* Return the original packet for local processing. */
@@ -2555,6 +2594,18 @@
#define PFIL_HOOKED_INET6 false
#endif
+#ifdef DEV_NETMAP
+#define GRAB_FOR_NETMAP(ifp, m) do { \
+ if ((if_getcapenable(ifp) & IFCAP_NETMAP) != 0 && \
+ ((m)->m_flags & M_BRIDGE_INJECT) == 0) { \
+ (ifp)->if_input(ifp, m); \
+ return (NULL); \
+ } \
+} while (0)
+#else
+#define GRAB_FOR_NETMAP(ifp, m)
+#endif
+
#define GRAB_OUR_PACKETS(iface) \
if ((iface)->if_type == IFT_GIF) \
continue; \
@@ -2577,7 +2628,9 @@
/* It's passing over or to the bridge, locally. */ \
ETHER_BPF_MTAP(bifp, m); \
if_inc_counter(bifp, IFCOUNTER_IPACKETS, 1); \
- if_inc_counter(bifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); \
+ if_inc_counter(bifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);\
+ /* Hand the packet over to netmap if necessary. */ \
+ GRAB_FOR_NETMAP(bifp, m); \
/* Filter on the physical interface. */ \
if (V_pfil_local_phys && (PFIL_HOOKED_IN(V_inet_pfil_head) || \
PFIL_HOOKED_INET6)) { \
@@ -2620,6 +2673,7 @@
#undef CARP_CHECK_WE_ARE_DST
#undef CARP_CHECK_WE_ARE_SRC
#undef PFIL_HOOKED_INET6
+#undef GRAB_FOR_NETMAP
#undef GRAB_OUR_PACKETS
/* Perform the bridge forwarding function. */
@@ -2628,6 +2682,28 @@
return (NULL);
}
+/*
+ * Inject a packet back into the host ethernet stack. This will generally only
+ * be used by netmap when an application writes to the host TX ring. The
+ * M_BRIDGE_INJECT flag ensures that the packet is re-routed to the bridge
+ * interface after ethernet processing.
+ */
+static void
+bridge_inject(struct ifnet *ifp, struct mbuf *m)
+{
+ struct bridge_softc *sc;
+
+#ifdef DEV_NETMAP
+ if ((if_getcapenable(ifp) & IFCAP_NETMAP) != 0) {
+ KASSERT((m->m_flags & M_BRIDGE_INJECT) == 0,
+ ("%s: mbuf %p has M_BRIDGE_INJECT set", __func__, m));
+ m->m_flags |= M_BRIDGE_INJECT;
+ }
+#endif
+ sc = if_getsoftc(ifp);
+ sc->sc_if_input(ifp, m);
+}
+
/*
* bridge_broadcast:
*
diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h
--- a/sys/net/if_bridgevar.h
+++ b/sys/net/if_bridgevar.h
@@ -309,8 +309,10 @@
KASSERT((_ifp)->if_bridge_input != NULL, \
("%s: if_bridge not loaded!", __func__)); \
_m = (*(_ifp)->if_bridge_input)(_ifp, _m); \
- if (_m != NULL) \
+ if (_m != NULL) { \
_ifp = _m->m_pkthdr.rcvif; \
+ m->m_flags &= ~M_BRIDGE_INJECT; \
+ } \
} while (0)
#define BRIDGE_OUTPUT(_ifp, _m, _err) do { \
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -670,7 +670,7 @@
* The BRIDGE_INPUT() macro will update ifp if the bridge changed it
* and the frame should be delivered locally.
*/
- if (ifp->if_bridge != NULL) {
+ if (ifp->if_bridge != NULL || (m->m_flags & M_BRIDGE_INJECT) != 0) {
m->m_flags &= ~M_PROMISC;
BRIDGE_INPUT(ifp, m);
if (m == NULL) {

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 18, 1:02 AM (3 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14687847
Default Alt Text
D38066.id118432.diff (8 KB)

Event Timeline