Page MenuHomeFreeBSD

D39015.diff
No OneTemporary

D39015.diff

diff --git a/share/man/man4/tap.4 b/share/man/man4/tap.4
--- a/share/man/man4/tap.4
+++ b/share/man/man4/tap.4
@@ -1,7 +1,7 @@
.\" $FreeBSD$
.\" Based on PR#2411
.\"
-.Dd January 13, 2020
+.Dd March 10, 2023
.Dt TAP 4
.Os
.Sh NAME
@@ -313,7 +313,16 @@
VMware
.Dv SIOCSIFFLAGS .
.El
+.Ss NETMAP
+.Xr netmap 4
+applications may open
+.Nm
+interfaces.
+Packets written to the interface are placed unmodified on the RX ring, and
+packets written to the host TX ring are handled exactly as if they had
+been written to the interface directly.
.Sh SEE ALSO
.Xr inet 4 ,
.Xr intro 4 ,
+.Xr netmap 4 ,
.Xr tun 4
diff --git a/share/man/man4/tun.4 b/share/man/man4/tun.4
--- a/share/man/man4/tun.4
+++ b/share/man/man4/tun.4
@@ -2,7 +2,7 @@
.\" $FreeBSD$
.\" Based on PR#2411
.\"
-.Dd March 17, 2020
+.Dd March 10, 2023
.Dt TUN 4
.Os
.Sh NAME
@@ -328,6 +328,31 @@
If the interface is up when the data device is not open
output packets are always thrown away rather than letting
them pile up.
+.Sh NETMAP
+.Nm
+interfaces can be opened by
+.Xr netmap 4
+applications.
+In this configuration,
+.Nm
+will insert fake Ethernet headers into received packets before they are
+handed to
+.Xr netmap 4 .
+The ethertype will be one of
+.Dv ETHERTYPE_IP
+or
+.Dv ETHERTYPE_IPV6
+depending on the type of packet written to the interface.
+The source MAC address will be
+.Dq 02:02:02:02:02:02
+and the destination MAC address will be
+.Dq 06:06:06:06:06:06 .
+.Pp
+When a
+.Xr netmap 4
+application submits a packet to the host ring, the ethertype is used to
+determine whether the packet is to be treated as an IPv4 or IPv6 packet,
+and the Ethernet header is stripped before any further processing is done.
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr read 2 ,
@@ -336,6 +361,7 @@
.Xr devname 3 ,
.Xr inet 4 ,
.Xr intro 4 ,
+.Xr netmap 4 ,
.Xr pty 4 ,
.Xr tap 4 ,
.Xr ifconfig 8
diff --git a/sys/net/if_tuntap.c b/sys/net/if_tuntap.c
--- a/sys/net/if_tuntap.c
+++ b/sys/net/if_tuntap.c
@@ -226,6 +226,7 @@
static void tunrename(void *arg, struct ifnet *ifp);
static int tunifioctl(struct ifnet *, u_long, caddr_t);
static void tuninit(struct ifnet *);
+static void tuninput(if_t ifp, struct mbuf *m);
static void tunifinit(void *xtp);
static int tuntapmodevent(module_t, int, void *);
static int tunoutput(struct ifnet *, struct mbuf *,
@@ -978,6 +979,7 @@
ifp->if_mtu = TUNMTU;
ifp->if_start = tunstart;
ifp->if_output = tunoutput;
+ ifp->if_input = tuninput;
ifp->if_snd.ifq_drv_maxlen = 0;
IFQ_SET_READY(&ifp->if_snd);
@@ -1369,6 +1371,48 @@
return (error);
}
+static void
+tuninput(if_t ifp, struct mbuf *m)
+{
+ struct ether_header *eh;
+ u_int proto;
+
+ KASSERT(if_getcapenable(ifp) & IFCAP_NETMAP,
+ ("%s: ifnet %s not in netmap mode", __func__, if_name(ifp)));
+ M_ASSERTPKTHDR(m);
+
+ if (__predict_false(m->m_len < ETHER_HDR_LEN)) {
+ m = m_pullup(m, ETHER_HDR_LEN);
+ if (m == NULL) {
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ return;
+ }
+ }
+
+ eh = mtod(m, struct ether_header *);
+ switch (ntohs(eh->ether_type)) {
+ case ETHERTYPE_IP:
+ proto = NETISR_IP;
+ break;
+ case ETHERTYPE_IPV6:
+ proto = NETISR_IPV6;
+ break;
+ default:
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ m_freem(m);
+ return;
+ }
+
+ m_adj(m, ETHER_HDR_LEN);
+ if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
+ if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
+
+ M_SETFIB(m, ifp->if_fib);
+ CURVNET_SET(ifp->if_vnet);
+ netisr_dispatch(proto, m);
+ CURVNET_RESTORE();
+}
+
/*
* tunoutput - queue packets from higher level ready to put out.
*/
@@ -1791,12 +1835,38 @@
return (0);
}
+#ifdef DEV_NETMAP
+/*
+ * Pass L3 packets to netmap. Create a dummy ethernet header for this purpose,
+ * with hard-coded source and destination addresses.
+ */
+static int
+tunwrite_netmap(if_t ifp, struct mbuf *m, int isr)
+{
+ struct ether_header *eh;
+
+ KASSERT(isr == NETISR_IP || isr == NETISR_IPV6,
+ ("%s: unexpected isr %d", __func__, isr));
+
+ M_PREPEND(m, ETHER_HDR_LEN, M_NOWAIT);
+ if (m == NULL)
+ return (ENOBUFS);
+
+ eh = mtod(m, struct ether_header *);
+ eh->ether_type = htons(isr == NETISR_IP ? ETHERTYPE_IP : ETHERTYPE_IPV6);
+ memcpy(eh->ether_shost, "\x02\x02\x02\x02\x02\x02", ETHER_ADDR_LEN);
+ memcpy(eh->ether_dhost, "\x06\x06\x06\x06\x06\x06", ETHER_ADDR_LEN);
+ if_input(ifp, m);
+ return (0);
+}
+#endif
+
static int
tunwrite_l3(struct tuntap_softc *tp, struct mbuf *m)
{
struct epoch_tracker et;
struct ifnet *ifp;
- int family, isr;
+ int error, family, isr;
ifp = TUN2IFP(tp);
/* Could be unlocked read? */
@@ -1835,11 +1905,18 @@
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
CURVNET_SET(ifp->if_vnet);
M_SETFIB(m, ifp->if_fib);
+
+ error = 0;
NET_EPOCH_ENTER(et);
- netisr_dispatch(isr, m);
+#ifdef DEV_NETMAP
+ if ((if_getcapenable(ifp) & IFCAP_NETMAP) != 0)
+ error = tunwrite_netmap(ifp, m, isr);
+ else
+#endif
+ netisr_dispatch(isr, m);
NET_EPOCH_EXIT(et);
CURVNET_RESTORE();
- return (0);
+ return (error);
}
/*

File Metadata

Mime Type
text/plain
Expires
Thu, Apr 2, 4:56 AM (9 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30705106
Default Alt Text
D39015.diff (4 KB)

Event Timeline