Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150432824
D39015.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D39015.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D39015: tuntap: Add netmap support for both tap(4) and tun(4) interfaces
Attached
Detach File
Event Timeline
Log In to Comment