svn commit: r307394 - in head: share/man/man4 sys/conf sys/dev/netmap sys/modules/netmap sys/net tools/tools/netmap

Luigi Rizzo luigi at FreeBSD.org
Sun Oct 16 14:13:34 UTC 2016


Author: luigi
Date: Sun Oct 16 14:13:32 2016
New Revision: 307394
URL: https://svnweb.freebsd.org/changeset/base/307394

Log:
  Import the current version of netmap, aligned with the one on github.
  
  This commit, long overdue, contains contributions in the last 2 years
  from Stefano Garzarella, Giuseppe Lettieri, Vincenzo Maffione, including:
  + fixes on monitor ports
  + the 'ptnet' virtual device driver, and ptnetmap backend, for
    high speed virtual passthrough on VMs (bhyve fixes in an upcoming commit)
  + improved emulated netmap mode
  + more robust error handling
  + removal of stale code
  + various fixes to code and documentation (some mixup between RX and TX
    parameters, and private and public variables)
  
  We also include an additional tool, nmreplay, which is functionally
  equivalent to tcpreplay but operating on netmap ports.

Added:
  head/tools/tools/netmap/ctrs.h   (contents, props changed)
  head/tools/tools/netmap/nmreplay.8   (contents, props changed)
  head/tools/tools/netmap/nmreplay.c   (contents, props changed)
Modified:
  head/share/man/man4/netmap.4
  head/sys/conf/files
  head/sys/dev/netmap/if_ixl_netmap.h
  head/sys/dev/netmap/if_lem_netmap.h
  head/sys/dev/netmap/ixgbe_netmap.h
  head/sys/dev/netmap/netmap.c
  head/sys/dev/netmap/netmap_freebsd.c
  head/sys/dev/netmap/netmap_generic.c
  head/sys/dev/netmap/netmap_kern.h
  head/sys/dev/netmap/netmap_mbq.c
  head/sys/dev/netmap/netmap_mbq.h
  head/sys/dev/netmap/netmap_mem2.c
  head/sys/dev/netmap/netmap_mem2.h
  head/sys/dev/netmap/netmap_monitor.c
  head/sys/dev/netmap/netmap_offloadings.c
  head/sys/dev/netmap/netmap_pipe.c
  head/sys/dev/netmap/netmap_vale.c
  head/sys/modules/netmap/Makefile
  head/sys/net/netmap.h
  head/sys/net/netmap_user.h
  head/tools/tools/netmap/Makefile
  head/tools/tools/netmap/bridge.c
  head/tools/tools/netmap/pkt-gen.c
  head/tools/tools/netmap/vale-ctl.c

Modified: head/share/man/man4/netmap.4
==============================================================================
--- head/share/man/man4/netmap.4	Sun Oct 16 12:55:31 2016	(r307393)
+++ head/share/man/man4/netmap.4	Sun Oct 16 14:13:32 2016	(r307394)
@@ -33,10 +33,10 @@
 .Sh NAME
 .Nm netmap
 .Nd a framework for fast packet I/O
-.Pp
+.br
 .Nm VALE
 .Nd a fast VirtuAl Local Ethernet using the netmap API
-.Pp
+.br
 .Nm netmap pipes
 .Nd a shared memory packet transport channel
 .Sh SYNOPSIS
@@ -44,28 +44,49 @@
 .Sh DESCRIPTION
 .Nm
 is a framework for extremely fast and efficient packet I/O
-for both userspace and kernel clients.
+for userspace and kernel clients, and for Virtual Machines.
 It runs on
 .Fx
-and Linux, and includes
-.Nm VALE ,
-a very fast and modular in-kernel software switch/dataplane,
-and
-.Nm netmap pipes ,
-a shared memory packet transport channel.
-All these are accessed interchangeably with the same API.
+Linux and some versions of Windows, and supports a variety of
+.Nm netmap ports ,
+including
+.Bl -tag -width XXXX
+.It Nm physical NIC ports
+to access individual queues of network interfaces;
+.It Nm host ports
+to inject packets into the host stack;
+.It Nm VALE ports
+implementing a very fast and modular in-kernel software switch/dataplane;
+.It Nm netmap pipes
+a shared memory packet transport channel;
+.It Nm netmap monitors
+a mechanism similar to
+.Xr bpf
+to capture traffic
+.El
 .Pp
-.Nm ,
-.Nm VALE
-and
-.Nm netmap pipes
-are at least one order of magnitude faster than
+All these
+.Nm netmap ports
+are accessed interchangeably with the same API,
+and are at least one order of magnitude faster than
 standard OS mechanisms
-(sockets, bpf, tun/tap interfaces, native switches, pipes),
-reaching 14.88 million packets per second (Mpps)
-with much less than one core on a 10 Gbit NIC,
-about 20 Mpps per core for VALE ports,
-and over 100 Mpps for netmap pipes.
+(sockets, bpf, tun/tap interfaces, native switches, pipes).
+With suitably fast hardware (NICs, PCIe buses, CPUs),
+packet I/O using
+.Nm
+on supported NICs
+reaches 14.88 million packets per second (Mpps)
+with much less than one core on 10 Gbit/s NICs;
+35-40 Mpps on 40 Gbit/s NICs (limited by the hardware);
+about 20 Mpps per core for VALE ports;
+and over 100 Mpps for
+.Nm netmap pipes.
+NICs without native
+.Nm
+support can still use the API in emulated mode,
+which uses unmodified device drivers and is 3-5 times faster than
+.Xr bpf
+or raw sockets.
 .Pp
 Userspace clients can dynamically switch NICs into
 .Nm
@@ -73,8 +94,10 @@ mode and send and receive raw packets th
 memory mapped buffers.
 Similarly,
 .Nm VALE
-switch instances and ports, and
+switch instances and ports,
 .Nm netmap pipes
+and
+.Nm netmap monitors
 can be created dynamically,
 providing high speed packet I/O between processes,
 virtual machines, NICs and the host stack.
@@ -89,17 +112,17 @@ and standard OS mechanisms such as
 .Xr epoll 2 ,
 and
 .Xr kqueue 2 .
-.Nm VALE
-and
-.Nm netmap pipes
+All types of
+.Nm netmap ports
+and the
+.Nm VALE switch
 are implemented by a single kernel module, which also emulates the
 .Nm
-API over standard drivers for devices without native
-.Nm
-support.
+API over standard drivers.
 For best performance,
 .Nm
-requires explicit support in device drivers.
+requires native support in device drivers.
+A list of such devices is at the end of this document.
 .Pp
 In the rest of this (long) manual page we document
 various aspects of the
@@ -116,7 +139,7 @@ which can be connected to a physical int
 to the host stack,
 or to a
 .Nm VALE
-switch).
+switch.
 Ports use preallocated circular queues of buffers
 .Em ( rings )
 residing in an mmapped region.
@@ -166,16 +189,18 @@ has multiple modes of operation controll
 .Vt struct nmreq
 argument.
 .Va arg.nr_name
-specifies the port name, as follows:
+specifies the netmap port name, as follows:
 .Bl -tag -width XXXX
 .It Dv OS network interface name (e.g. 'em0', 'eth1', ... )
 the data path of the NIC is disconnected from the host stack,
 and the file descriptor is bound to the NIC (one or all queues),
 or to the host stack;
-.It Dv valeXXX:YYY (arbitrary XXX and YYY)
-the file descriptor is bound to port YYY of a VALE switch called XXX,
-both dynamically created if necessary.
-The string cannot exceed IFNAMSIZ characters, and YYY cannot
+.It Dv valeSSS:PPP
+the file descriptor is bound to port PPP of VALE switch SSS.
+Switch instances and ports are dynamically created if necessary.
+.br
+Both SSS and PPP have the form [0-9a-zA-Z_]+ , the string
+cannot exceed IFNAMSIZ characters, and PPP cannot
 be the name of any existing OS network interface.
 .El
 .Pp
@@ -312,9 +337,6 @@ one slot is always kept empty.
 The ring size
 .Va ( num_slots )
 should not be assumed to be a power of two.
-.br
-(NOTE: older versions of netmap used head/count format to indicate
-the content of a ring).
 .Pp
 .Va head
 is the first slot available to userspace;
@@ -585,6 +607,15 @@ it from the host stack.
 Multiple file descriptors can be bound to the same port,
 with proper synchronization left to the user.
 .Pp
+The recommended way to bind a file descriptor to a port is
+to use function
+.Va nm_open(..)
+(see
+.Xr LIBRARIES )
+which parses names to access specific port types and
+enable features.
+In the following we document the main features.
+.Pp
 .Dv NIOCREGIF can also bind a file descriptor to one endpoint of a
 .Em netmap pipe ,
 consisting of two netmap ports with a crossover connection.
@@ -734,7 +765,7 @@ similar to
 binds a file descriptor to a port.
 .Bl -tag -width XX
 .It Va ifname
-is a port name, in the form "netmap:XXX" for a NIC and "valeXXX:YYY" for a
+is a port name, in the form "netmap:PPP" for a NIC and "valeSSS:PPP" for a
 .Nm VALE
 port.
 .It Va req
@@ -774,28 +805,39 @@ similar to pcap_next(), fetches the next
 natively supports the following devices:
 .Pp
 On FreeBSD:
+.Xr cxgbe 4 ,
 .Xr em 4 ,
 .Xr igb 4 ,
 .Xr ixgbe 4 ,
+.Xr ixl 4 ,
 .Xr lem 4 ,
 .Xr re 4 .
 .Pp
 On Linux
 .Xr e1000 4 ,
 .Xr e1000e 4 ,
+.Xr i40e 4 ,
 .Xr igb 4 ,
 .Xr ixgbe 4 ,
-.Xr mlx4 4 ,
-.Xr forcedeth 4 ,
 .Xr r8169 4 .
 .Pp
 NICs without native support can still be used in
 .Nm
 mode through emulation.
 Performance is inferior to native netmap
-mode but still significantly higher than sockets, and approaching
+mode but still significantly higher than various raw socket types
+(bpf, PF_PACKET, etc.).
+Note that for slow devices (such as 1 Gbit/s and slower NICs,
+or several 10 Gbit/s NICs whose hardware is unable 
 that of in-kernel solutions such as Linux's
 .Xr pktgen .
+When emulation is in use, packet sniffer programs such as tcpdump
+could see received packets before they are diverted by netmap. This behaviour
+is not intentional, being just an artifact of the implementation of emulation.
+Note that in case the netmap application subsequently moves packets received
+from the emulated adapter onto the host RX ring, the sniffer will intercept
+those packets again, since the packets are injected to the host stack as they
+were received by the network interface.
 .Pp
 Emulation is also available for devices with native netmap support,
 which can be used for testing or performance comparison.
@@ -812,8 +854,12 @@ and module parameters on Linux
 .Bl -tag -width indent
 .It Va dev.netmap.admode: 0
 Controls the use of native or emulated adapter mode.
-0 uses the best available option, 1 forces native and
-fails if not available, 2 forces emulated hence never fails.
+.br
+0 uses the best available option;
+.br
+1 forces native mode and fails if not available;
+.br
+2 forces emulated hence never fails.
 .It Va dev.netmap.generic_ringsize: 1024
 Ring size used for emulated netmap mode
 .It Va dev.netmap.generic_mit: 100000
@@ -861,9 +907,9 @@ performance.
 uses
 .Xr select 2 ,
 .Xr poll 2 ,
-.Xr epoll
+.Xr epoll 2
 and
-.Xr kqueue
+.Xr kqueue 2
 to wake up processes when significant events occur, and
 .Xr mmap 2
 to map memory.
@@ -1015,8 +1061,8 @@ e.g. running the following in two differ
 .Dl pkt-gen -i vale1:b -f tx # sender
 The same example can be used to test netmap pipes, by simply
 changing port names, e.g.
-.Dl pkt-gen -i vale:x{3 -f rx # receiver on the master side
-.Dl pkt-gen -i vale:x}3 -f tx # sender on the slave side
+.Dl pkt-gen -i vale2:x{3 -f rx # receiver on the master side
+.Dl pkt-gen -i vale2:x}3 -f tx # sender on the slave side
 .Pp
 The following command attaches an interface and the host stack
 to a switch:

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Sun Oct 16 12:55:31 2016	(r307393)
+++ head/sys/conf/files	Sun Oct 16 14:13:32 2016	(r307394)
@@ -2187,6 +2187,7 @@ dev/nand/nfc_if.m		optional nand
 dev/ncr/ncr.c			optional ncr pci
 dev/ncv/ncr53c500.c		optional ncv
 dev/ncv/ncr53c500_pccard.c	optional ncv pccard
+dev/netmap/if_ptnet.c		optional netmap
 dev/netmap/netmap.c		optional netmap
 dev/netmap/netmap_freebsd.c	optional netmap
 dev/netmap/netmap_generic.c	optional netmap
@@ -2195,6 +2196,7 @@ dev/netmap/netmap_mem2.c	optional netmap
 dev/netmap/netmap_monitor.c	optional netmap
 dev/netmap/netmap_offloadings.c	optional netmap
 dev/netmap/netmap_pipe.c	optional netmap
+dev/netmap/netmap_pt.c		optional netmap
 dev/netmap/netmap_vale.c	optional netmap
 # compile-with "${NORMAL_C} -Wconversion -Wextra"
 dev/nfsmb/nfsmb.c		optional nfsmb pci

Modified: head/sys/dev/netmap/if_ixl_netmap.h
==============================================================================
--- head/sys/dev/netmap/if_ixl_netmap.h	Sun Oct 16 12:55:31 2016	(r307393)
+++ head/sys/dev/netmap/if_ixl_netmap.h	Sun Oct 16 14:13:32 2016	(r307394)
@@ -59,7 +59,7 @@ extern int ixl_rx_miss, ixl_rx_miss_bufs
 /*
  * device-specific sysctl variables:
  *
- * ixl_crcstrip: 0: keep CRC in rx frames (default), 1: strip it.
+ * ixl_crcstrip: 0: NIC keeps CRC in rx frames, 1: NIC strips it (default).
  *	During regular operations the CRC is stripped, but on some
  *	hardware reception of frames not multiple of 64 is slower,
  *	so using crcstrip=0 helps in benchmarks.
@@ -73,7 +73,7 @@ SYSCTL_DECL(_dev_netmap);
  */
 #if 0
 SYSCTL_INT(_dev_netmap, OID_AUTO, ixl_crcstrip,
-    CTLFLAG_RW, &ixl_crcstrip, 1, "strip CRC on rx frames");
+    CTLFLAG_RW, &ixl_crcstrip, 1, "NIC strips CRC on rx frames");
 #endif
 SYSCTL_INT(_dev_netmap, OID_AUTO, ixl_rx_miss,
     CTLFLAG_RW, &ixl_rx_miss, 0, "potentially missed rx intr");

Modified: head/sys/dev/netmap/if_lem_netmap.h
==============================================================================
--- head/sys/dev/netmap/if_lem_netmap.h	Sun Oct 16 12:55:31 2016	(r307393)
+++ head/sys/dev/netmap/if_lem_netmap.h	Sun Oct 16 14:13:32 2016	(r307394)
@@ -81,6 +81,22 @@ lem_netmap_reg(struct netmap_adapter *na
 }
 
 
+static void
+lem_netmap_intr(struct netmap_adapter *na, int onoff)
+{
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+
+	EM_CORE_LOCK(adapter);
+	if (onoff) {
+		lem_enable_intr(adapter);
+	} else {
+		lem_disable_intr(adapter);
+	}
+	EM_CORE_UNLOCK(adapter);
+}
+
+
 /*
  * Reconcile kernel and user view of the transmit ring.
  */
@@ -99,10 +115,6 @@ lem_netmap_txsync(struct netmap_kring *k
 
 	/* device-specific */
 	struct adapter *adapter = ifp->if_softc;
-#ifdef NIC_PARAVIRT
-	struct paravirt_csb *csb = adapter->csb;
-	uint64_t *csbd = (uint64_t *)(csb + 1);
-#endif /* NIC_PARAVIRT */
 
 	bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
 			BUS_DMASYNC_POSTREAD);
@@ -113,19 +125,6 @@ lem_netmap_txsync(struct netmap_kring *k
 
 	nm_i = kring->nr_hwcur;
 	if (nm_i != head) {	/* we have new packets to send */
-#ifdef NIC_PARAVIRT
-		int do_kick = 0;
-		uint64_t t = 0; // timestamp
-		int n = head - nm_i;
-		if (n < 0)
-			n += lim + 1;
-		if (csb) {
-			t = rdtsc(); /* last timestamp */
-			csbd[16] += t - csbd[0]; /* total Wg */
-			csbd[17] += n;		/* Wg count */
-			csbd[0] = t;
-		}
-#endif /* NIC_PARAVIRT */
 		nic_i = netmap_idx_k2n(kring, nm_i);
 		while (nm_i != head) {
 			struct netmap_slot *slot = &ring->slot[nm_i];
@@ -166,38 +165,8 @@ lem_netmap_txsync(struct netmap_kring *k
 		bus_dmamap_sync(adapter->txdma.dma_tag, adapter->txdma.dma_map,
 			BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 
-#ifdef NIC_PARAVIRT
-		/* set unconditionally, then also kick if needed */
-		if (csb) {
-			t = rdtsc();
-			if (csb->host_need_txkick == 2) {
-				/* can compute an update of delta */
-				int64_t delta = t - csbd[3];
-				if (delta < 0)
-					delta = -delta;
-				if (csbd[8] == 0 || delta < csbd[8]) {
-					csbd[8] = delta;
-					csbd[9]++;
-				}
-				csbd[10]++;
-			}
-			csb->guest_tdt = nic_i;
-			csbd[18] += t - csbd[0]; // total wp
-			csbd[19] += n;
-		}
-		if (!csb || !csb->guest_csb_on || (csb->host_need_txkick & 1))
-			do_kick = 1;
-		if (do_kick)
-#endif /* NIC_PARAVIRT */
 		/* (re)start the tx unit up to slot nic_i (excluded) */
 		E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), nic_i);
-#ifdef NIC_PARAVIRT
-		if (do_kick) {
-			uint64_t t1 = rdtsc();
-			csbd[20] += t1 - t; // total Np
-			csbd[21]++;
-		}
-#endif /* NIC_PARAVIRT */
 	}
 
 	/*
@@ -206,93 +175,6 @@ lem_netmap_txsync(struct netmap_kring *k
 	if (ticks != kring->last_reclaim || flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) {
 		kring->last_reclaim = ticks;
 		/* record completed transmissions using TDH */
-#ifdef NIC_PARAVIRT
-		/* host updates tdh unconditionally, and we have
-		 * no side effects on reads, so we can read from there
-		 * instead of exiting.
-		 */
-		if (csb) {
-		    static int drain = 0, nodrain=0, good = 0, bad = 0, fail = 0;
-		    u_int x = adapter->next_tx_to_clean;
-		    csbd[19]++; // XXX count reclaims
-		    nic_i = csb->host_tdh;
-		    if (csb->guest_csb_on) {
-			if (nic_i == x) {
-			    bad++;
-		    	    csbd[24]++; // failed reclaims
-			    /* no progress, request kick and retry */
-			    csb->guest_need_txkick = 1;
-			    mb(); // XXX barrier
-		    	    nic_i = csb->host_tdh;
-			} else {
-			    good++;
-			}
-			if (nic_i != x) {
-			    csb->guest_need_txkick = 2;
-			    if (nic_i == csb->guest_tdt)
-				drain++;
-			    else
-				nodrain++;
-#if 1
-			if (netmap_adaptive_io) {
-			    /* new mechanism: last half ring (or so)
-			     * released one slot at a time.
-			     * This effectively makes the system spin.
-			     *
-			     * Take next_to_clean + 1 as a reference.
-			     * tdh must be ahead or equal
-			     * On entry, the logical order is
-			     *		x < tdh = nic_i
-			     * We first push tdh up to avoid wraps.
-			     * The limit is tdh-ll (half ring).
-			     * if tdh-256 < x we report x;
-			     * else we report tdh-256
-			     */
-			    u_int tdh = nic_i;
-			    u_int ll = csbd[15];
-			    u_int delta = lim/8;
-			    if (netmap_adaptive_io == 2 || ll > delta)
-				csbd[15] = ll = delta;
-			    else if (netmap_adaptive_io == 1 && ll > 1) {
-				csbd[15]--;
-			    }
-
-			    if (nic_i >= kring->nkr_num_slots) {
-				RD(5, "bad nic_i %d on input", nic_i);
-			    }
-			    x = nm_next(x, lim);
-			    if (tdh < x)
-				tdh += lim + 1;
-			    if (tdh <= x + ll) {
-				nic_i = x;
-				csbd[25]++; //report n + 1;
-			    } else {
-				tdh = nic_i;
-				if (tdh < ll)
-				    tdh += lim + 1;
-				nic_i = tdh - ll;
-				csbd[26]++; // report tdh - ll
-			    }
-			}
-#endif
-			} else {
-			    /* we stop, count whether we are idle or not */
-			    int bh_active = csb->host_need_txkick & 2 ? 4 : 0;
-			    csbd[27+ csb->host_need_txkick]++;
-			    if (netmap_adaptive_io == 1) {
-				if (bh_active && csbd[15] > 1)
-				    csbd[15]--;
-				else if (!bh_active && csbd[15] < lim/2)
-				    csbd[15]++;
-			    }
-			    bad--;
-			    fail++;
-			}
-		    }
-		    RD(1, "drain %d nodrain %d good %d retry %d fail %d",
-			drain, nodrain, good, bad, fail);
-		} else
-#endif /* !NIC_PARAVIRT */
 		nic_i = E1000_READ_REG(&adapter->hw, E1000_TDH(0));
 		if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */
 			D("TDH wrap %d", nic_i);
@@ -324,21 +206,10 @@ lem_netmap_rxsync(struct netmap_kring *k
 
 	/* device-specific */
 	struct adapter *adapter = ifp->if_softc;
-#ifdef NIC_PARAVIRT
-	struct paravirt_csb *csb = adapter->csb;
-	uint32_t csb_mode = csb && csb->guest_csb_on;
-	uint32_t do_host_rxkick = 0;
-#endif /* NIC_PARAVIRT */
 
 	if (head > lim)
 		return netmap_ring_reinit(kring);
 
-#ifdef NIC_PARAVIRT
-	if (csb_mode) {
-		force_update = 1;
-		csb->guest_need_rxkick = 0;
-	}
-#endif /* NIC_PARAVIRT */
 	/* XXX check sync modes */
 	bus_dmamap_sync(adapter->rxdma.dma_tag, adapter->rxdma.dma_map,
 			BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
@@ -357,23 +228,6 @@ lem_netmap_rxsync(struct netmap_kring *k
 			uint32_t staterr = le32toh(curr->status);
 			int len;
 
-#ifdef NIC_PARAVIRT
-			if (csb_mode) {
-			    if ((staterr & E1000_RXD_STAT_DD) == 0) {
-				/* don't bother to retry if more than 1 pkt */
-				if (n > 1)
-				    break;
-				csb->guest_need_rxkick = 1;
-				wmb();
-				staterr = le32toh(curr->status);
-				if ((staterr & E1000_RXD_STAT_DD) == 0) {
-				    break;
-				} else { /* we are good */
-				   csb->guest_need_rxkick = 0;
-				}
-			    }
-			} else
-#endif /* NIC_PARAVIRT */
 			if ((staterr & E1000_RXD_STAT_DD) == 0)
 				break;
 			len = le16toh(curr->length) - 4; // CRC
@@ -390,18 +244,6 @@ lem_netmap_rxsync(struct netmap_kring *k
 			nic_i = nm_next(nic_i, lim);
 		}
 		if (n) { /* update the state variables */
-#ifdef NIC_PARAVIRT
-			if (csb_mode) {
-			    if (n > 1) {
-				/* leave one spare buffer so we avoid rxkicks */
-				nm_i = nm_prev(nm_i, lim);
-				nic_i = nm_prev(nic_i, lim);
-				n--;
-			    } else {
-				csb->guest_need_rxkick = 1;
-			    }
-			}
-#endif /* NIC_PARAVIRT */
 			ND("%d new packets at nic %d nm %d tail %d",
 				n,
 				adapter->next_rx_desc_to_check,
@@ -440,10 +282,6 @@ lem_netmap_rxsync(struct netmap_kring *k
 			curr->status = 0;
 			bus_dmamap_sync(adapter->rxtag, rxbuf->map,
 			    BUS_DMASYNC_PREREAD);
-#ifdef NIC_PARAVIRT
-			if (csb_mode && csb->host_rxkick_at == nic_i)
-				do_host_rxkick = 1;
-#endif /* NIC_PARAVIRT */
 			nm_i = nm_next(nm_i, lim);
 			nic_i = nm_next(nic_i, lim);
 		}
@@ -455,12 +293,6 @@ lem_netmap_rxsync(struct netmap_kring *k
 		 * so move nic_i back by one unit
 		 */
 		nic_i = nm_prev(nic_i, lim);
-#ifdef NIC_PARAVIRT
-		/* set unconditionally, then also kick if needed */
-		if (csb)
-			csb->guest_rdt = nic_i;
-		if (!csb_mode || do_host_rxkick)
-#endif /* NIC_PARAVIRT */
 		E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), nic_i);
 	}
 
@@ -486,6 +318,7 @@ lem_netmap_attach(struct adapter *adapte
 	na.nm_rxsync = lem_netmap_rxsync;
 	na.nm_register = lem_netmap_reg;
 	na.num_tx_rings = na.num_rx_rings = 1;
+	na.nm_intr = lem_netmap_intr;
 	netmap_attach(&na);
 }
 

Modified: head/sys/dev/netmap/ixgbe_netmap.h
==============================================================================
--- head/sys/dev/netmap/ixgbe_netmap.h	Sun Oct 16 12:55:31 2016	(r307393)
+++ head/sys/dev/netmap/ixgbe_netmap.h	Sun Oct 16 14:13:32 2016	(r307394)
@@ -53,7 +53,7 @@ void ixgbe_netmap_attach(struct adapter 
 /*
  * device-specific sysctl variables:
  *
- * ix_crcstrip: 0: keep CRC in rx frames (default), 1: strip it.
+ * ix_crcstrip: 0: NIC keeps CRC in rx frames (default), 1: NIC strips it.
  *	During regular operations the CRC is stripped, but on some
  *	hardware reception of frames not multiple of 64 is slower,
  *	so using crcstrip=0 helps in benchmarks.
@@ -65,7 +65,7 @@ SYSCTL_DECL(_dev_netmap);
 static int ix_rx_miss, ix_rx_miss_bufs;
 int ix_crcstrip;
 SYSCTL_INT(_dev_netmap, OID_AUTO, ix_crcstrip,
-    CTLFLAG_RW, &ix_crcstrip, 0, "strip CRC on rx frames");
+    CTLFLAG_RW, &ix_crcstrip, 0, "NIC strips CRC on rx frames");
 SYSCTL_INT(_dev_netmap, OID_AUTO, ix_rx_miss,
     CTLFLAG_RW, &ix_rx_miss, 0, "potentially missed rx intr");
 SYSCTL_INT(_dev_netmap, OID_AUTO, ix_rx_miss_bufs,
@@ -109,6 +109,20 @@ set_crcstrip(struct ixgbe_hw *hw, int on
 	IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rxc);
 }
 
+static void
+ixgbe_netmap_intr(struct netmap_adapter *na, int onoff)
+{
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+
+	IXGBE_CORE_LOCK(adapter);
+	if (onoff) {
+		ixgbe_enable_intr(adapter); // XXX maybe ixgbe_stop ?
+	} else {
+		ixgbe_disable_intr(adapter); // XXX maybe ixgbe_stop ?
+	}
+	IXGBE_CORE_UNLOCK(adapter);
+}
 
 /*
  * Register/unregister. We are already under netmap lock.
@@ -311,7 +325,7 @@ ixgbe_netmap_txsync(struct netmap_kring 
 		 * good way.
 		 */
 		nic_i = IXGBE_READ_REG(&adapter->hw, IXGBE_IS_VF(adapter) ?
-				       IXGBE_VFTDH(kring->ring_id) : IXGBE_TDH(kring->ring_id));
+				IXGBE_VFTDH(kring->ring_id) : IXGBE_TDH(kring->ring_id));
 		if (nic_i >= kring->nkr_num_slots) { /* XXX can it happen ? */
 			D("TDH wrap %d", nic_i);
 			nic_i -= kring->nkr_num_slots;
@@ -486,6 +500,7 @@ ixgbe_netmap_attach(struct adapter *adap
 	na.nm_rxsync = ixgbe_netmap_rxsync;
 	na.nm_register = ixgbe_netmap_reg;
 	na.num_tx_rings = na.num_rx_rings = adapter->num_queues;
+	na.nm_intr = ixgbe_netmap_intr;
 	netmap_attach(&na);
 }
 

Modified: head/sys/dev/netmap/netmap.c
==============================================================================
--- head/sys/dev/netmap/netmap.c	Sun Oct 16 12:55:31 2016	(r307393)
+++ head/sys/dev/netmap/netmap.c	Sun Oct 16 14:13:32 2016	(r307394)
@@ -1,5 +1,9 @@
 /*
- * Copyright (C) 2011-2014 Matteo Landi, Luigi Rizzo. All rights reserved.
+ * Copyright (C) 2011-2014 Matteo Landi
+ * Copyright (C) 2011-2016 Luigi Rizzo
+ * Copyright (C) 2011-2016 Giuseppe Lettieri
+ * Copyright (C) 2011-2016 Vincenzo Maffione
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -133,13 +137,12 @@ ports attached to the switch)
  * >    select()able file descriptor on which events are reported.
  *
  *  	Internally, we allocate a netmap_priv_d structure, that will be
- *  	initialized on ioctl(NIOCREGIF).
+ *  	initialized on ioctl(NIOCREGIF). There is one netmap_priv_d
+ *  	structure for each open().
  *
  *      os-specific:
- *  	    FreeBSD: netmap_open (netmap_freebsd.c). The priv is
- *  		     per-thread.
- *  	    linux:   linux_netmap_open (netmap_linux.c). The priv is
- *  		     per-open.
+ *  	    FreeBSD: see netmap_open() (netmap_freebsd.c)
+ *  	    linux:   see linux_netmap_open() (netmap_linux.c)
  *
  * > 2. on each descriptor, the process issues an ioctl() to identify
  * >    the interface that should report events to the file descriptor.
@@ -299,18 +302,17 @@ ports attached to the switch)
  *                netmap_transmit()
  *                  na->nm_notify  == netmap_notify()
  *           2) ioctl(NIOCRXSYNC)/netmap_poll() in process context
- *                kring->nm_sync() == netmap_rxsync_from_host_compat
+ *                kring->nm_sync() == netmap_rxsync_from_host
  *                  netmap_rxsync_from_host(na, NULL, NULL)
  *    - tx to host stack
  *           ioctl(NIOCTXSYNC)/netmap_poll() in process context
- *             kring->nm_sync() == netmap_txsync_to_host_compat
+ *             kring->nm_sync() == netmap_txsync_to_host
  *               netmap_txsync_to_host(na)
- *                 NM_SEND_UP()
- *                   FreeBSD: na->if_input() == ?? XXX
+ *                 nm_os_send_up()
+ *                   FreeBSD: na->if_input() == ether_input()
  *                   linux: netif_rx() with NM_MAGIC_PRIORITY_RX
  *
  *
- *
  *               -= SYSTEM DEVICE WITH GENERIC SUPPORT =-
  *
  *    na == NA(ifp) == generic_netmap_adapter created in generic_netmap_attach()
@@ -319,10 +321,11 @@ ports attached to the switch)
  *       concurrently:
  *           1) ioctl(NIOCTXSYNC)/netmap_poll() in process context
  *               kring->nm_sync() == generic_netmap_txsync()
- *                   linux:   dev_queue_xmit() with NM_MAGIC_PRIORITY_TX
- *                       generic_ndo_start_xmit()
- *                           orig. dev. start_xmit
- *                   FreeBSD: na->if_transmit() == orig. dev if_transmit
+ *                   nm_os_generic_xmit_frame()
+ *                       linux:   dev_queue_xmit() with NM_MAGIC_PRIORITY_TX
+ *                           ifp->ndo_start_xmit == generic_ndo_start_xmit()
+ *                               gna->save_start_xmit == orig. dev. start_xmit
+ *                       FreeBSD: na->if_transmit() == orig. dev if_transmit
  *           2) generic_mbuf_destructor()
  *                   na->nm_notify() == netmap_notify()
  *    - rx from netmap userspace:
@@ -333,24 +336,15 @@ ports attached to the switch)
  *               generic_rx_handler()
  *                   mbq_safe_enqueue()
  *                   na->nm_notify() == netmap_notify()
- *    - rx from host stack:
- *        concurrently:
+ *    - rx from host stack
+ *        FreeBSD: same as native
+ *        Linux: same as native except:
  *           1) host stack
- *               linux: generic_ndo_start_xmit()
- *                   netmap_transmit()
- *               FreeBSD: ifp->if_input() == netmap_transmit
- *               both:
- *                       na->nm_notify() == netmap_notify()
- *           2) ioctl(NIOCRXSYNC)/netmap_poll() in process context
- *                kring->nm_sync() == netmap_rxsync_from_host_compat
- *                  netmap_rxsync_from_host(na, NULL, NULL)
- *    - tx to host stack:
- *           ioctl(NIOCTXSYNC)/netmap_poll() in process context
- *             kring->nm_sync() == netmap_txsync_to_host_compat
- *               netmap_txsync_to_host(na)
- *                 NM_SEND_UP()
- *                   FreeBSD: na->if_input() == ??? XXX
- *                   linux: netif_rx() with NM_MAGIC_PRIORITY_RX
+ *               dev_queue_xmit() without NM_MAGIC_PRIORITY_TX
+ *                   ifp->ndo_start_xmit == generic_ndo_start_xmit()
+ *                       netmap_transmit()
+ *                           na->nm_notify() == netmap_notify()
+ *    - tx to host stack (same as native):
  *
  *
  *                           -= VALE =-
@@ -371,7 +365,7 @@ ports attached to the switch)
  *         from host stack:
  *             netmap_transmit()
  *                na->nm_notify() == netmap_bwrap_intr_notify(ring_nr == host ring)
- *                     kring->nm_sync() == netmap_rxsync_from_host_compat()
+ *                     kring->nm_sync() == netmap_rxsync_from_host()
  *                     netmap_vp_txsync()
  *
  *      - system device with generic support:
@@ -384,7 +378,7 @@ ports attached to the switch)
  *         from host stack:
  *            netmap_transmit()
  *                na->nm_notify() == netmap_bwrap_intr_notify(ring_nr == host ring)
- *                     kring->nm_sync() == netmap_rxsync_from_host_compat()
+ *                     kring->nm_sync() == netmap_rxsync_from_host()
  *                     netmap_vp_txsync()
  *
  *   (all cases) --> nm_bdg_flush()
@@ -407,7 +401,7 @@ ports attached to the switch)
  *                 netmap_vp_rxsync()
  *          to host stack:
  *                 netmap_vp_rxsync()
- *                 kring->nm_sync() == netmap_txsync_to_host_compat
+ *                 kring->nm_sync() == netmap_txsync_to_host
  *                 netmap_vp_rxsync_locked()
  *
  *      - system device with generic adapter:
@@ -418,7 +412,7 @@ ports attached to the switch)
  *                 netmap_vp_rxsync()
  *          to host stack:
  *                 netmap_vp_rxsync()
- *                 kring->nm_sync() == netmap_txsync_to_host_compat
+ *                 kring->nm_sync() == netmap_txsync_to_host
  *                 netmap_vp_rxsync()
  *
  */
@@ -455,29 +449,19 @@ ports attached to the switch)
 #include <sys/refcount.h>
 
 
-/* reduce conditional code */
-// linux API, use for the knlist in FreeBSD
-/* use a private mutex for the knlist */
-#define init_waitqueue_head(x) do {			\
-	struct mtx *m = &(x)->m;			\
-	mtx_init(m, "nm_kn_lock", NULL, MTX_DEF);	\
-	knlist_init_mtx(&(x)->si.si_note, m);		\
-    } while (0)
-
-#define OS_selrecord(a, b)	selrecord(a, &((b)->si))
-#define OS_selwakeup(a, b)	freebsd_selwakeup(a, b)
-
 #elif defined(linux)
 
 #include "bsd_glue.h"
 
-
-
 #elif defined(__APPLE__)
 
 #warning OSX support is only partial
 #include "osx_glue.h"
 
+#elif defined (_WIN32)
+
+#include "win_glue.h"
+
 #else
 
 #error	Unsupported platform
@@ -492,47 +476,72 @@ ports attached to the switch)
 #include <dev/netmap/netmap_mem2.h>
 
 
-MALLOC_DEFINE(M_NETMAP, "netmap", "Network memory map");
-
 /* user-controlled variables */
 int netmap_verbose;
 
 static int netmap_no_timestamp; /* don't timestamp on rxsync */
-
-SYSCTL_NODE(_dev, OID_AUTO, netmap, CTLFLAG_RW, 0, "Netmap args");
-SYSCTL_INT(_dev_netmap, OID_AUTO, verbose,
-    CTLFLAG_RW, &netmap_verbose, 0, "Verbose mode");
-SYSCTL_INT(_dev_netmap, OID_AUTO, no_timestamp,
-    CTLFLAG_RW, &netmap_no_timestamp, 0, "no_timestamp");
 int netmap_mitigate = 1;
-SYSCTL_INT(_dev_netmap, OID_AUTO, mitigate, CTLFLAG_RW, &netmap_mitigate, 0, "");
 int netmap_no_pendintr = 1;
-SYSCTL_INT(_dev_netmap, OID_AUTO, no_pendintr,
-    CTLFLAG_RW, &netmap_no_pendintr, 0, "Always look for new received packets.");
 int netmap_txsync_retry = 2;
-SYSCTL_INT(_dev_netmap, OID_AUTO, txsync_retry, CTLFLAG_RW,
-    &netmap_txsync_retry, 0 , "Number of txsync loops in bridge's flush.");
-
 int netmap_adaptive_io = 0;
-SYSCTL_INT(_dev_netmap, OID_AUTO, adaptive_io, CTLFLAG_RW,
-    &netmap_adaptive_io, 0 , "Adaptive I/O on paravirt");
-
 int netmap_flags = 0;	/* debug flags */
-int netmap_fwd = 0;	/* force transparent mode */
+static int netmap_fwd = 0;	/* force transparent mode */
 
 /*
  * netmap_admode selects the netmap mode to use.
  * Invalid values are reset to NETMAP_ADMODE_BEST
  */
-enum { NETMAP_ADMODE_BEST = 0,	/* use native, fallback to generic */
+enum {	NETMAP_ADMODE_BEST = 0,	/* use native, fallback to generic */
 	NETMAP_ADMODE_NATIVE,	/* either native or none */
 	NETMAP_ADMODE_GENERIC,	/* force generic */
 	NETMAP_ADMODE_LAST };
 static int netmap_admode = NETMAP_ADMODE_BEST;
 
-int netmap_generic_mit = 100*1000;   /* Generic mitigation interval in nanoseconds. */
-int netmap_generic_ringsize = 1024;   /* Generic ringsize. */
-int netmap_generic_rings = 1;   /* number of queues in generic. */
+/* netmap_generic_mit controls mitigation of RX notifications for
+ * the generic netmap adapter. The value is a time interval in
+ * nanoseconds. */
+int netmap_generic_mit = 100*1000;
+
+/* We use by default netmap-aware qdiscs with generic netmap adapters,
+ * even if there can be a little performance hit with hardware NICs.
+ * However, using the qdisc is the safer approach, for two reasons:
+ * 1) it prevents non-fifo qdiscs to break the TX notification
+ *    scheme, which is based on mbuf destructors when txqdisc is
+ *    not used.
+ * 2) it makes it possible to transmit over software devices that
+ *    change skb->dev, like bridge, veth, ...
+ *
+ * Anyway users looking for the best performance should
+ * use native adapters.
+ */
+int netmap_generic_txqdisc = 1;
+
+/* Default number of slots and queues for generic adapters. */
+int netmap_generic_ringsize = 1024;
+int netmap_generic_rings = 1;
+
+/* Non-zero if ptnet devices are allowed to use virtio-net headers. */
+int ptnet_vnet_hdr = 1;
+
+/*
+ * SYSCTL calls are grouped between SYSBEGIN and SYSEND to be emulated
+ * in some other operating systems
+ */
+SYSBEGIN(main_init);
+
+SYSCTL_DECL(_dev_netmap);
+SYSCTL_NODE(_dev, OID_AUTO, netmap, CTLFLAG_RW, 0, "Netmap args");
+SYSCTL_INT(_dev_netmap, OID_AUTO, verbose,
+    CTLFLAG_RW, &netmap_verbose, 0, "Verbose mode");
+SYSCTL_INT(_dev_netmap, OID_AUTO, no_timestamp,
+    CTLFLAG_RW, &netmap_no_timestamp, 0, "no_timestamp");
+SYSCTL_INT(_dev_netmap, OID_AUTO, mitigate, CTLFLAG_RW, &netmap_mitigate, 0, "");
+SYSCTL_INT(_dev_netmap, OID_AUTO, no_pendintr,
+    CTLFLAG_RW, &netmap_no_pendintr, 0, "Always look for new received packets.");
+SYSCTL_INT(_dev_netmap, OID_AUTO, txsync_retry, CTLFLAG_RW,
+    &netmap_txsync_retry, 0 , "Number of txsync loops in bridge's flush.");
+SYSCTL_INT(_dev_netmap, OID_AUTO, adaptive_io, CTLFLAG_RW,
+    &netmap_adaptive_io, 0 , "Adaptive I/O on paravirt");
 
 SYSCTL_INT(_dev_netmap, OID_AUTO, flags, CTLFLAG_RW, &netmap_flags, 0 , "");
 SYSCTL_INT(_dev_netmap, OID_AUTO, fwd, CTLFLAG_RW, &netmap_fwd, 0 , "");
@@ -540,19 +549,24 @@ SYSCTL_INT(_dev_netmap, OID_AUTO, admode
 SYSCTL_INT(_dev_netmap, OID_AUTO, generic_mit, CTLFLAG_RW, &netmap_generic_mit, 0 , "");
 SYSCTL_INT(_dev_netmap, OID_AUTO, generic_ringsize, CTLFLAG_RW, &netmap_generic_ringsize, 0 , "");
 SYSCTL_INT(_dev_netmap, OID_AUTO, generic_rings, CTLFLAG_RW, &netmap_generic_rings, 0 , "");
+SYSCTL_INT(_dev_netmap, OID_AUTO, generic_txqdisc, CTLFLAG_RW, &netmap_generic_txqdisc, 0 , "");
+SYSCTL_INT(_dev_netmap, OID_AUTO, ptnet_vnet_hdr, CTLFLAG_RW, &ptnet_vnet_hdr, 0 , "");
+
+SYSEND;
 
 NMG_LOCK_T	netmap_global_lock;
-int netmap_use_count = 0; /* number of active netmap instances */
 
 /*
  * mark the ring as stopped, and run through the locks
  * to make sure other users get to see it.
+ * stopped must be either NR_KR_STOPPED (for unbounded stop)
+ * of NR_KR_LOCKED (brief stop for mutual exclusion purposes)
  */
 static void
-netmap_disable_ring(struct netmap_kring *kr)
+netmap_disable_ring(struct netmap_kring *kr, int stopped)
 {
-	kr->nkr_stopped = 1;
-	nm_kr_get(kr);
+	nm_kr_stop(kr, stopped);
+	// XXX check if nm_kr_stop is sufficient
 	mtx_lock(&kr->q_lock);
 	mtx_unlock(&kr->q_lock);
 	nm_kr_put(kr);
@@ -563,7 +577,7 @@ void
 netmap_set_ring(struct netmap_adapter *na, u_int ring_id, enum txrx t, int stopped)
 {
 	if (stopped)
-		netmap_disable_ring(NMR(na, t) + ring_id);
+		netmap_disable_ring(NMR(na, t) + ring_id, stopped);
 	else
 		NMR(na, t)[ring_id].nkr_stopped = 0;
 }
@@ -590,13 +604,14 @@ netmap_set_all_rings(struct netmap_adapt
  * Convenience function used in drivers.  Waits for current txsync()s/rxsync()s
  * to finish and prevents any new one from starting.  Call this before turning
  * netmap mode off, or before removing the hardware rings (e.g., on module
- * onload).  As a rule of thumb for linux drivers, this should be placed near
- * each napi_disable().
+ * onload).
  */
 void
 netmap_disable_all_rings(struct ifnet *ifp)
 {
-	netmap_set_all_rings(NA(ifp), 1 /* stopped */);
+	if (NM_NA_VALID(ifp)) {
+		netmap_set_all_rings(NA(ifp), NM_KR_STOPPED);
+	}
 }
 
 /*
@@ -607,9 +622,34 @@ netmap_disable_all_rings(struct ifnet *i
 void
 netmap_enable_all_rings(struct ifnet *ifp)
 {
-	netmap_set_all_rings(NA(ifp), 0 /* enabled */);
+	if (NM_NA_VALID(ifp)) {
+		netmap_set_all_rings(NA(ifp), 0 /* enabled */);
+	}
 }
 
+void
+netmap_make_zombie(struct ifnet *ifp)
+{
+	if (NM_NA_VALID(ifp)) {
+		struct netmap_adapter *na = NA(ifp);
+		netmap_set_all_rings(na, NM_KR_LOCKED);
+		na->na_flags |= NAF_ZOMBIE;
+		netmap_set_all_rings(na, 0);
+	}
+}
+
+void
+netmap_undo_zombie(struct ifnet *ifp)
+{
+	if (NM_NA_VALID(ifp)) {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list