socsvn commit: r288617 - in soc2015/stefano/ptnetmap/stable/10/sys: dev/netmap modules/netmap net

stefano at FreeBSD.org stefano at FreeBSD.org
Tue Jul 21 14:19:08 UTC 2015


Author: stefano
Date: Tue Jul 21 14:19:04 2015
New Revision: 288617
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=288617

Log:
  add netmap with ptnetmap support (virtio, e1000)
  
  - add netmap_virt.h (ex paravirt.h)
    contains:
          - CSB definition (shared memory between host/guest)
  	- ptnetmap functions declaration (host/guest)
          - ptnetmap-memdev ID, register and routines
  - add ptnetmap.c
    contains ptnetmap implementation - OS independent (FreeBSD/linux)

Added:
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_virt.h
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/ptnetmap.c
Modified:
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_em_netmap.h
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_igb_netmap.h
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_lem_netmap.h
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_re_netmap.h
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_vtnet_netmap.h
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/ixgbe_netmap.h
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap.c
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_freebsd.c
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_generic.c
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_kern.h
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_mem2.c
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_mem2.h
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_monitor.c
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_offloadings.c
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_pipe.c
  soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap_vale.c
  soc2015/stefano/ptnetmap/stable/10/sys/modules/netmap/Makefile
  soc2015/stefano/ptnetmap/stable/10/sys/net/netmap.h
  soc2015/stefano/ptnetmap/stable/10/sys/net/netmap_user.h

Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_em_netmap.h
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_em_netmap.h	Tue Jul 21 14:10:22 2015	(r288616)
+++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_em_netmap.h	Tue Jul 21 14:19:04 2015	(r288617)
@@ -24,7 +24,7 @@
  */
 
 /*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/netmap/if_em_netmap.h 238985 2012-08-02 11:59:43Z luigi $
  *
  * netmap support for: em.
  *
@@ -198,8 +198,6 @@
 		}
 	}
 
-	nm_txsync_finalize(kring);
-
 	return 0;
 }
 
@@ -217,7 +215,7 @@
 	u_int nic_i;	/* index into the NIC ring */
 	u_int n;
 	u_int const lim = kring->nkr_num_slots - 1;
-	u_int const head = nm_rxsync_prologue(kring);
+	u_int const head = kring->rhead;
 	int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
 
 	/* device-specific */
@@ -303,9 +301,6 @@
 		E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), nic_i);
 	}
 
-	/* tell userspace that there might be new packets */
-	nm_rxsync_finalize(kring);
-
 	return 0;
 
 ring_reset:

Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_igb_netmap.h
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_igb_netmap.h	Tue Jul 21 14:10:22 2015	(r288616)
+++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_igb_netmap.h	Tue Jul 21 14:19:04 2015	(r288617)
@@ -24,7 +24,7 @@
  */
 
 /*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/netmap/if_igb_netmap.h 256200 2013-10-09 17:32:52Z jfv $
  *
  * Netmap support for igb, partly contributed by Ahmed Kooli
  * For details on netmap support please see ixgbe_netmap.h
@@ -180,8 +180,6 @@
 		kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim);
 	}
 
-	nm_txsync_finalize(kring);
-
 	return 0;
 }
 
@@ -199,7 +197,7 @@
 	u_int nic_i;	/* index into the NIC ring */
 	u_int n;
 	u_int const lim = kring->nkr_num_slots - 1;
-	u_int const head = nm_rxsync_prologue(kring);
+	u_int const head = kring->rhead;
 	int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
 
 	/* device-specific */
@@ -283,9 +281,6 @@
 		E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), nic_i);
 	}
 
-	/* tell userspace that there might be new packets */
-	nm_rxsync_finalize(kring);
-
 	return 0;
 
 ring_reset:

Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_lem_netmap.h
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_lem_netmap.h	Tue Jul 21 14:10:22 2015	(r288616)
+++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_lem_netmap.h	Tue Jul 21 14:19:04 2015	(r288617)
@@ -25,7 +25,7 @@
 
 
 /*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/netmap/if_lem_netmap.h 271849 2014-09-19 03:51:26Z glebius $
  *
  * netmap support for: lem
  *
@@ -38,6 +38,7 @@
 #include <vm/vm.h>
 #include <vm/pmap.h>    /* vtophys ? */
 #include <dev/netmap/netmap_kern.h>
+#include <dev/netmap/netmap_virt.h>
 
 extern int netmap_adaptive_io;
 
@@ -302,8 +303,6 @@
 		kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim);
 	}
 
-	nm_txsync_finalize(kring);
-
 	return 0;
 }
 
@@ -321,7 +320,7 @@
 	u_int nic_i;	/* index into the NIC ring */
 	u_int n;
 	u_int const lim = kring->nkr_num_slots - 1;
-	u_int const head = nm_rxsync_prologue(kring);
+	u_int const head = kring->rhead;
 	int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
 
 	/* device-specific */
@@ -466,15 +465,262 @@
 		E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), nic_i);
 	}
 
-	/* tell userspace that there might be new packets */
-	nm_rxsync_finalize(kring);
-
 	return 0;
 
 ring_reset:
 	return netmap_ring_reinit(kring);
 }
 
+#if defined (NIC_PTNETMAP) && defined (WITH_PTNETMAP_GUEST)
+static uint32_t lem_netmap_ptctl(struct ifnet *, uint32_t);
+
+static int
+lem_ptnetmap_config(struct netmap_adapter *na,
+		u_int *txr, u_int *txd, u_int *rxr, u_int *rxd)
+{
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+	struct paravirt_csb *csb = adapter->csb;
+	int ret;
+
+	if (csb == NULL)
+		return EINVAL;
+
+	ret = lem_netmap_ptctl(ifp, NET_PARAVIRT_PTCTL_CONFIG);
+	if (ret)
+		return ret;
+
+	*txr = 1; //*txr = csb->num_tx_rings;
+	*rxr = 1; //*rxr = csb->num_rx_rings;
+	*txd = csb->num_tx_slots;
+	*rxd = csb->num_rx_slots;
+
+	D("txr %u rxr %u txd %u rxd %u",
+			*txr, *rxr, *txd, *rxd);
+
+	return 0;
+}
+
+static int
+lem_ptnetmap_txsync(struct netmap_kring *kring, int flags)
+{
+	struct netmap_adapter *na = kring->na;
+	//u_int ring_nr = kring->ring_id;
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+	struct paravirt_csb *csb = adapter->csb;
+	bool send_kick = false;
+
+	/* Disable notifications */
+	csb->guest_need_txkick = 0;
+
+	/*
+	 * First part: process new packets to send.
+	 */
+	kring->nr_hwcur = csb->tx_ring.hwcur;
+	ptnetmap_guest_write_kring_csb(&csb->tx_ring, kring->rcur, kring->rhead);
+	if (kring->rhead != kring->nr_hwcur) {
+		send_kick = true;
+	}
+
+	/* Send kick to the host if it needs them */
+	if ((send_kick && ACCESS_ONCE(csb->host_need_txkick)) || (flags & NAF_FORCE_RECLAIM)) {
+		csb->tx_ring.sync_flags = flags;
+		E1000_WRITE_REG(&adapter->hw, E1000_TDT(0), 0);
+	}
+
+	/*
+	 * Second part: reclaim buffers for completed transmissions.
+	 */
+	if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) {
+		ptnetmap_guest_read_kring_csb(&csb->tx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots);
+	}
+
+	/*
+	 * Ring full. The user thread will go to sleep and
+	 * we need a notification (interrupt) from the NIC,
+	 * whene there is free space.
+	 */
+	if (kring->rcur == kring->nr_hwtail) {
+		/* Reenable notifications. */
+		csb->guest_need_txkick = 1;
+		/* Double check */
+		ptnetmap_guest_read_kring_csb(&csb->tx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots);
+		/* If there is new free space, disable notifications */
+		if (kring->rcur != kring->nr_hwtail) {
+			csb->guest_need_txkick = 0;
+		}
+	}
+
+	ND("TX - CSB: head:%u cur:%u hwtail:%u - KRING: head:%u cur:%u",
+			csb->tx_ring.head, csb->tx_ring.cur, csb->tx_ring.hwtail, kring->rhead, kring->rcur);
+
+	return 0;
+}
+
+static int
+lem_ptnetmap_rxsync(struct netmap_kring *kring, int flags)
+{
+	struct netmap_adapter *na = kring->na;
+	//u_int ring_nr = kring->ring_id;
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+	struct paravirt_csb *csb = adapter->csb;
+
+	int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
+	uint32_t h_hwcur = kring->nr_hwcur, h_hwtail = kring->nr_hwtail;
+
+	/* Disable notifications */
+	csb->guest_need_rxkick = 0;
+
+	ptnetmap_guest_read_kring_csb(&csb->rx_ring, &h_hwcur, &h_hwtail, kring->nkr_num_slots);
+
+	/*
+	 * First part: import newly received packets.
+	 */
+	if (netmap_no_pendintr || force_update) {
+		kring->nr_hwtail = h_hwtail;
+		kring->nr_kflags &= ~NKR_PENDINTR;
+	}
+
+	/*
+	 * Second part: skip past packets that userspace has released.
+	 */
+	kring->nr_hwcur = h_hwcur;
+	if (kring->rhead != kring->nr_hwcur) {
+		ptnetmap_guest_write_kring_csb(&csb->rx_ring, kring->rcur, kring->rhead);
+		/* Send kick to the host if it needs them */
+		if (ACCESS_ONCE(csb->host_need_rxkick)) {
+			csb->rx_ring.sync_flags = flags;
+			E1000_WRITE_REG(&adapter->hw, E1000_RDT(0), 0);
+		}
+	}
+
+	/*
+	 * Ring empty. The user thread will go to sleep and
+	 * we need a notification (interrupt) from the NIC,
+	 * whene there are new packets.
+	 */
+	if (kring->rcur == kring->nr_hwtail) {
+		/* Reenable notifications. */
+		csb->guest_need_rxkick = 1;
+		/* Double check */
+		ptnetmap_guest_read_kring_csb(&csb->rx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots);
+		/* If there are new packets, disable notifications */
+		if (kring->rcur != kring->nr_hwtail) {
+			csb->guest_need_rxkick = 0;
+		}
+	}
+
+	ND("RX - CSB: head:%u cur:%u hwtail:%u - KRING: head:%u cur:%u",
+			csb->rx_ring.head, csb->rx_ring.cur, csb->rx_ring.hwtail, kring->rhead, kring->rcur);
+
+	return 0;
+
+
+}
+
+static int
+lem_ptnetmap_reg(struct netmap_adapter *na, int onoff)
+{
+	struct ifnet *ifp = na->ifp;
+	struct adapter *adapter = ifp->if_softc;
+	struct paravirt_csb *csb = adapter->csb;
+	struct netmap_kring *kring;
+	int ret;
+
+	if (onoff) {
+		ret = lem_netmap_ptctl(ifp, NET_PARAVIRT_PTCTL_REGIF);
+		if (ret)
+			return ret;
+
+		na->na_flags |= NAF_NETMAP_ON;
+		adapter->ptnetmap_enabled = 1;
+		/*
+		 * Init ring and kring pointers
+		 * After PARAVIRT_PTCTL_REGIF, the csb contains a snapshot of a
+		 * host kring pointers.
+		 * XXX This initialization is required, because we don't close the
+		 * host port on UNREGIF.
+		 */
+
+		// Init rx ring
+		kring = na->rx_rings;
+		kring->rhead = kring->ring->head = csb->rx_ring.head;
+		kring->rcur = kring->ring->cur = csb->rx_ring.cur;
+		kring->nr_hwcur = csb->rx_ring.hwcur;
+		kring->nr_hwtail = kring->rtail = kring->ring->tail = csb->rx_ring.hwtail;
+
+		// Init tx ring
+		kring = na->tx_rings;
+		kring->rhead = kring->ring->head = csb->tx_ring.head;
+		kring->rcur = kring->ring->cur = csb->tx_ring.cur;
+		kring->nr_hwcur = csb->tx_ring.hwcur;
+		kring->nr_hwtail = kring->rtail = kring->ring->tail = csb->tx_ring.hwtail;
+	} else {
+		na->na_flags &= ~NAF_NETMAP_ON;
+		adapter->ptnetmap_enabled = 0;
+		ret = lem_netmap_ptctl(ifp, NET_PARAVIRT_PTCTL_UNREGIF);
+	}
+
+	return lem_netmap_reg(na, onoff);
+}
+
+
+static int
+lem_ptnetmap_bdg_attach(const char *bdg_name, struct netmap_adapter *na)
+{
+	return EOPNOTSUPP;
+}
+
+static struct paravirt_csb *
+lem_netmap_getcsb(struct ifnet *ifp)
+{
+	struct adapter *adapter = ifp->if_softc;
+
+	return adapter->csb;
+}
+
+static uint32_t
+lem_netmap_ptctl(struct ifnet *ifp, uint32_t val)
+{
+	struct adapter *adapter = ifp->if_softc;
+	uint32_t ret;
+
+	E1000_WRITE_REG(&adapter->hw, E1000_PTCTL, val);
+	ret = E1000_READ_REG(&adapter->hw, E1000_PTSTS);
+	D("PTSTS = %u", ret);
+
+	return ret;
+}
+
+
+
+static uint32_t
+lem_ptnetmap_features(struct adapter *adapter)
+{
+	uint32_t features;
+	/* tell the device the features we support */
+	E1000_WRITE_REG(&adapter->hw, E1000_PTFEAT, NET_PTN_FEATURES_BASE);
+	/* get back the acknowledged features */
+	features = E1000_READ_REG(&adapter->hw, E1000_PTFEAT);
+	device_printf(adapter->dev, "netmap passthrough: %s\n",
+			(features & NET_PTN_FEATURES_BASE) ? "base" :
+			"none");
+	return features;
+}
+
+static struct netmap_pt_guest_ops lem_ptnetmap_ops = {
+	.nm_getcsb = lem_netmap_getcsb,
+	.nm_ptctl = lem_netmap_ptctl,
+};
+#elif defined (NIC_PTNETMAP)
+#warning "if_lem supports ptnetmap but netmap does not support it"
+#warning "(configure netmap with passthrough support)"
+#elif defined (WITH_PTNETMAP_GUEST)
+#warning "netmap supports ptnetmap but e1000 does not support it"
+#warning "(configure if_lem with passthrough support)"
+#endif /* NIC_PTNETMAP && WITH_PTNETMAP_GUEST */
 
 static void
 lem_netmap_attach(struct adapter *adapter)
@@ -491,7 +737,19 @@
 	na.nm_rxsync = lem_netmap_rxsync;
 	na.nm_register = lem_netmap_reg;
 	na.num_tx_rings = na.num_rx_rings = 1;
-	netmap_attach(&na);
+#if defined (NIC_PTNETMAP) && defined (WITH_PTNETMAP_GUEST)
+        /* XXX: check if the device support ptnetmap (now we use PARA_SUBDEV) */
+	if ((adapter->hw.subsystem_device_id == E1000_PARA_SUBDEV) &&
+		(lem_ptnetmap_features(adapter) & NET_PTN_FEATURES_BASE)) {
+		na.nm_config = lem_ptnetmap_config;
+		na.nm_register = lem_ptnetmap_reg;
+		na.nm_txsync = lem_ptnetmap_txsync;
+		na.nm_rxsync = lem_ptnetmap_rxsync;
+		na.nm_bdg_attach = lem_ptnetmap_bdg_attach; /* XXX */
+		netmap_pt_guest_attach(&na, &lem_ptnetmap_ops);
+	} else
+#endif /* NIC_PTNETMAP && defined WITH_PTNETMAP_GUEST */
+		netmap_attach(&na);
 }
 
 /* end of file */

Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_re_netmap.h
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_re_netmap.h	Tue Jul 21 14:10:22 2015	(r288616)
+++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_re_netmap.h	Tue Jul 21 14:19:04 2015	(r288617)
@@ -24,7 +24,7 @@
  */
 
 /*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/netmap/if_re_netmap.h 234225 2012-04-13 15:33:12Z luigi $
  *
  * netmap support for: re
  *
@@ -159,8 +159,6 @@
 		}
 	}
 
-	nm_txsync_finalize(kring);
-
 	return 0;
 }
 
@@ -178,7 +176,7 @@
 	u_int nic_i;	/* index into the NIC ring */
 	u_int n;
 	u_int const lim = kring->nkr_num_slots - 1;
-	u_int const head = nm_rxsync_prologue(kring);
+	u_int const head = kring->rhead;
 	int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
 
 	/* device-specific */
@@ -273,9 +271,6 @@
 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 	}
 
-	/* tell userspace that there might be new packets */
-	nm_rxsync_finalize(kring);
-
 	return 0;
 
 ring_reset:

Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_vtnet_netmap.h
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_vtnet_netmap.h	Tue Jul 21 14:10:22 2015	(r288616)
+++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/if_vtnet_netmap.h	Tue Jul 21 14:19:04 2015	(r288617)
@@ -24,7 +24,7 @@
  */
 
 /*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/netmap/if_vtnet_netmap.h 270097 2014-08-17 10:25:27Z luigi $
  */
 
 #include <net/netmap.h>
@@ -32,6 +32,13 @@
 #include <vm/vm.h>
 #include <vm/pmap.h>    /* vtophys ? */
 #include <dev/netmap/netmap_kern.h>
+#ifdef WITH_PTNETMAP_GUEST
+#include <dev/netmap/netmap_virt.h>
+static int vtnet_ptnetmap_txsync(struct netmap_kring *kring, int flags);
+#define VTNET_PTNETMAP_ON(_na)        ((nm_netmap_on(_na)) && ((_na)->nm_txsync == vtnet_ptnetmap_txsync))
+#else   /* !WITH_PTNETMAP_GUEST */
+#define VTNET_PTNETMAP_ON(_na)        0
+#endif  /* WITH_PTNETMAP_GUEST */
 
 
 #define SOFTC_T	vtnet_softc
@@ -214,9 +221,6 @@
 		virtqueue_postpone_intr(vq, VQ_POSTPONE_SHORT);
 	}
 
-//out:
-	nm_txsync_finalize(kring);
-
         return 0;
 }
 
@@ -278,7 +282,7 @@
 	// u_int nic_i;	/* index into the NIC ring */
 	u_int n;
 	u_int const lim = kring->nkr_num_slots - 1;
-	u_int const head = nm_rxsync_prologue(kring);
+	u_int const head = kring->rhead;
 	int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
 
 	/* device-specific */
@@ -340,9 +344,6 @@
         	vtnet_rxq_enable_intr(rxq);
 	}
 
-	/* tell userspace that there might be new packets. */
-	nm_rxsync_finalize(kring);
-
         ND("[C] h %d c %d t %d hwcur %d hwtail %d",
 		ring->head, ring->cur, ring->tail,
 		kring->nr_hwcur, kring->nr_hwtail);
@@ -359,6 +360,9 @@
 	struct netmap_adapter* na = NA(ifp);
 	unsigned int r;
 
+	/* if ptnetmap is enabled we must not init netmap buffers */
+	if (VTNET_PTNETMAP_ON(na))
+		return 1;
 	if (!nm_native_on(na))
 		return 0;
 	for (r = 0; r < na->num_rx_rings; r++) {
@@ -409,6 +413,367 @@
 	return 0;
 }
 
+#ifdef WITH_PTNETMAP_GUEST
+/* ptnetmap virtio register BASE */
+#define PTNETMAP_VIRTIO_IO_BASE         sizeof(struct virtio_net_config)
+
+#ifndef VIRTIO_NET_F_PTNETMAP
+#define VIRTIO_NET_F_PTNETMAP   0x1000000  /* linux/qeum  24 */
+#endif /* VIRTIO_NET_F_PTNETMAP */
+
+static void inline
+vtnet_ptnetmap_iowrite4(device_t dev, uint32_t addr, uint32_t val)
+{
+	int i;
+	/* virtio_pci config_set use multiple iowrite8, we need to split the call and reverse the order */
+	for (i = 3; i >= 0; i--) {
+		virtio_write_dev_config_1(dev, PTNETMAP_VIRTIO_IO_BASE + addr + i, *(((uint8_t *)&val) + i));
+	}
+}
+
+static uint32_t inline
+vtnet_ptnetmap_ioread4(device_t dev, uint32_t addr)
+{
+	uint32_t val;
+	int i;
+
+	for (i = 0; i <= 3; i++) {
+		*(((uint8_t *)&val) + i) = virtio_read_dev_config_1(dev, PTNETMAP_VIRTIO_IO_BASE + addr + i);
+	}
+	return val;
+}
+
+static int
+vtnet_ptnetmap_alloc_csb(struct SOFTC_T *sc)
+{
+	device_t dev = sc->vtnet_dev;
+	struct ifnet *ifp = sc->vtnet_ifp;
+	struct netmap_pt_guest_adapter* ptna = (struct netmap_pt_guest_adapter *)NA(ifp);
+
+	vm_paddr_t csb_phyaddr;
+
+	if (ptna->csb)
+		return 0;
+
+	ptna->csb = contigmalloc(NET_PARAVIRT_CSB_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO,
+			(size_t)0, -1UL, PAGE_SIZE, 0);
+	if (!ptna->csb) {
+		D("Communication Status Block allocation failed!");
+		return ENOMEM;
+	}
+
+	csb_phyaddr = vtophys(ptna->csb);
+
+	ptna->csb->guest_csb_on = 1;
+
+	/* Tell the device the CSB physical address. */
+	vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_CSBBAH, (uint32_t)(csb_phyaddr >> 32));
+	vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_CSBBAL, (uint32_t)(csb_phyaddr));
+
+	return 0;
+}
+
+static void
+vtnet_ptnetmap_free_csb(struct SOFTC_T *sc)
+{
+	device_t dev = sc->vtnet_dev;
+	struct ifnet *ifp = sc->vtnet_ifp;
+	struct netmap_pt_guest_adapter* ptna = (struct netmap_pt_guest_adapter *)NA(ifp);
+
+	if (ptna->csb) {
+		/* CSB deallocation protocol. */
+		vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_CSBBAH, 0x0ULL);
+		vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_CSBBAL, 0x0ULL);
+
+		contigfree(ptna->csb, NET_PARAVIRT_CSB_SIZE, M_DEVBUF);
+		ptna->csb = NULL;
+	}
+}
+
+static uint32_t vtnet_ptnetmap_ptctl(struct ifnet *, uint32_t);
+static int
+vtnet_ptnetmap_config(struct netmap_adapter *na,
+		u_int *txr, u_int *txd, u_int *rxr, u_int *rxd)
+{
+	struct netmap_pt_guest_adapter *ptna = (struct netmap_pt_guest_adapter *)na;
+	struct paravirt_csb *csb = ptna->csb;
+	int ret;
+
+	if (csb == NULL)
+		return EINVAL;
+
+	ret = vtnet_ptnetmap_ptctl(na->ifp, NET_PARAVIRT_PTCTL_CONFIG);
+	if (ret)
+		return ret;
+
+	*txr = 1; //*txr = csb->num_tx_rings;
+	*rxr = 1; //*rxr = csb->num_rx_rings;
+	*txd = csb->num_tx_slots;
+	*rxd = csb->num_rx_slots;
+
+	D("txr %u rxr %u txd %u rxd %u",
+			*txr, *rxr, *txd, *rxd);
+	return 0;
+}
+
+static int
+vtnet_ptnetmap_txsync(struct netmap_kring *kring, int flags)
+{
+	struct netmap_adapter *na = kring->na;
+	struct netmap_pt_guest_adapter *ptna = (struct netmap_pt_guest_adapter *)na;
+        struct ifnet *ifp = na->ifp;
+	u_int ring_nr = kring->ring_id;
+
+	/* device-specific */
+	struct SOFTC_T *sc = ifp->if_softc;
+	struct vtnet_txq *txq = &sc->vtnet_txqs[ring_nr];
+	struct virtqueue *vq = txq->vtntx_vq;
+	struct paravirt_csb *csb = ptna->csb;
+	bool send_kick = false;
+
+	/* Disable notifications */
+	csb->guest_need_txkick = 0;
+
+	/*
+	 * First part: process new packets to send.
+	 */
+	kring->nr_hwcur = csb->tx_ring.hwcur;
+	ptnetmap_guest_write_kring_csb(&csb->tx_ring, kring->rcur, kring->rhead);
+	if (kring->rhead != kring->nr_hwcur) {
+		send_kick = true;
+	}
+
+        /* Send kick to the host if it needs them */
+	if ((send_kick && ACCESS_ONCE(csb->host_need_txkick)) || (flags & NAF_FORCE_RECLAIM)) {
+		csb->tx_ring.sync_flags = flags;
+		virtqueue_notify(vq);
+	}
+
+	/*
+	 * Second part: reclaim buffers for completed transmissions.
+	 */
+	if (flags & NAF_FORCE_RECLAIM || nm_kr_txempty(kring)) {
+                ptnetmap_guest_read_kring_csb(&csb->tx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots);
+	}
+
+        /*
+         * Ring full. The user thread will go to sleep and
+         * we need a notification (interrupt) from the NIC,
+         * whene there is free space.
+         */
+	if (kring->rcur == kring->nr_hwtail) {
+		/* Reenable notifications. */
+		csb->guest_need_txkick = 1;
+                /* Double check */
+                ptnetmap_guest_read_kring_csb(&csb->tx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots);
+                /* If there is new free space, disable notifications */
+		if (kring->rcur != kring->nr_hwtail) {
+			csb->guest_need_txkick = 0;
+		}
+	}
+
+
+	ND(1,"TX - CSB: head:%u cur:%u hwtail:%u - KRING: head:%u cur:%u tail: %u",
+			csb->tx_ring.head, csb->tx_ring.cur, csb->tx_ring.hwtail, kring->rhead, kring->rcur, kring->nr_hwtail);
+	ND("TX - vq_index: %d", vq->index);
+
+	return 0;
+}
+
+static int
+vtnet_ptnetmap_rxsync(struct netmap_kring *kring, int flags)
+{
+	struct netmap_adapter *na = kring->na;
+	struct netmap_pt_guest_adapter *ptna = (struct netmap_pt_guest_adapter *)na;
+        struct ifnet *ifp = na->ifp;
+	u_int ring_nr = kring->ring_id;
+
+	/* device-specific */
+	struct SOFTC_T *sc = ifp->if_softc;
+	struct vtnet_rxq *rxq = &sc->vtnet_rxqs[ring_nr];
+	struct virtqueue *vq = rxq->vtnrx_vq;
+	struct paravirt_csb *csb = ptna->csb;
+
+	int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
+	uint32_t h_hwcur = kring->nr_hwcur, h_hwtail = kring->nr_hwtail;
+
+        /* Disable notifications */
+	csb->guest_need_rxkick = 0;
+
+        ptnetmap_guest_read_kring_csb(&csb->rx_ring, &h_hwcur, &h_hwtail, kring->nkr_num_slots);
+
+	/*
+	 * First part: import newly received packets.
+	 */
+	if (netmap_no_pendintr || force_update) {
+		kring->nr_hwtail = h_hwtail;
+		kring->nr_kflags &= ~NKR_PENDINTR;
+	}
+
+	/*
+	 * Second part: skip past packets that userspace has released.
+	 */
+	kring->nr_hwcur = h_hwcur;
+	if (kring->rhead != kring->nr_hwcur) {
+		ptnetmap_guest_write_kring_csb(&csb->rx_ring, kring->rcur, kring->rhead);
+                /* Send kick to the host if it needs them */
+		if (ACCESS_ONCE(csb->host_need_rxkick)) {
+			csb->rx_ring.sync_flags = flags;
+			virtqueue_notify(vq);
+		}
+	}
+
+        /*
+         * Ring empty. The user thread will go to sleep and
+         * we need a notification (interrupt) from the NIC,
+         * whene there are new packets.
+         */
+        if (kring->rcur == kring->nr_hwtail) {
+		/* Reenable notifications. */
+                csb->guest_need_rxkick = 1;
+                /* Double check */
+                ptnetmap_guest_read_kring_csb(&csb->rx_ring, &kring->nr_hwcur, &kring->nr_hwtail, kring->nkr_num_slots);
+                /* If there are new packets, disable notifications */
+                if (kring->rcur != kring->nr_hwtail) {
+                        csb->guest_need_rxkick = 0;
+                }
+        }
+
+	ND("RX - CSB: head:%u cur:%u hwtail:%u - KRING: head:%u cur:%u",
+			csb->rx_ring.head, csb->rx_ring.cur, csb->rx_ring.hwtail, kring->rhead, kring->rcur);
+	ND("RX - vq_index: %d", vq->index);
+
+	return 0;
+}
+
+static int
+vtnet_ptnetmap_reg(struct netmap_adapter *na, int onoff)
+{
+	struct netmap_pt_guest_adapter *ptna = (struct netmap_pt_guest_adapter *)na;
+
+	/* device-specific */
+        struct ifnet *ifp = na->ifp;
+	struct SOFTC_T *sc = ifp->if_softc;
+	struct paravirt_csb *csb = ptna->csb;
+	struct netmap_kring *kring;
+	int ret = 0;
+
+	if (na == NULL)
+		return EINVAL;
+
+	VTNET_CORE_LOCK(sc);
+	/* enable or disable flags and callbacks in na and ifp */
+	if (onoff) {
+	        int i;
+		nm_set_native_flags(na);
+                /* push fake-elem in the tx queues to enable interrupts */
+                for (i = 0; i < sc->vtnet_max_vq_pairs; i++) {
+			struct vtnet_txq *txq = &sc->vtnet_txqs[i];
+			struct mbuf *m0;
+			m0 = m_gethdr(M_NOWAIT, MT_DATA);
+			m0->m_len = 64;
+
+			if (m0) {
+				ret = vtnet_txq_encap(txq, &m0);
+			}
+		}
+		ret = vtnet_ptnetmap_ptctl(na->ifp, NET_PARAVIRT_PTCTL_REGIF);
+		if (ret) {
+			//na->na_flags &= ~NAF_NETMAP_ON;
+			nm_clear_native_flags(na);
+			goto out;
+		}
+		/*
+		 * Init ring and kring pointers
+		 * After PARAVIRT_PTCTL_REGIF, the csb contains a snapshot of a
+		 * host kring pointers.
+		 * XXX This initialization is required, because we don't close the
+		 * host port on UNREGIF.
+		 */
+		// Init rx ring
+		kring = na->rx_rings;
+		kring->rhead = kring->ring->head = csb->rx_ring.head;
+		kring->rcur = kring->ring->cur = csb->rx_ring.cur;
+		kring->nr_hwcur = csb->rx_ring.hwcur;
+		kring->nr_hwtail = kring->rtail = kring->ring->tail = csb->rx_ring.hwtail;
+
+		// Init tx ring
+		kring = na->tx_rings;
+		kring->rhead = kring->ring->head = csb->tx_ring.head;
+		kring->rcur = kring->ring->cur = csb->tx_ring.cur;
+		kring->nr_hwcur = csb->tx_ring.hwcur;
+		kring->nr_hwtail = kring->rtail = kring->ring->tail = csb->tx_ring.hwtail;
+	} else {
+		ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+		//na->na_flags &= ~NAF_NETMAP_ON;
+		nm_clear_native_flags(na);
+		ret = vtnet_ptnetmap_ptctl(na->ifp, NET_PARAVIRT_PTCTL_UNREGIF);
+		vtnet_init_locked(sc);       /* also enable intr */
+	}
+out:
+        VTNET_CORE_UNLOCK(sc);
+        return (ifp->if_drv_flags & IFF_DRV_RUNNING ? ret : 1);
+}
+
+static int
+vtnet_ptnetmap_bdg_attach(const char *bdg_name, struct netmap_adapter *na)
+{
+	return EOPNOTSUPP;
+}
+
+static struct paravirt_csb *
+vtnet_ptnetmap_getcsb(struct ifnet *ifp)
+{
+	struct netmap_pt_guest_adapter *ptna = (struct netmap_pt_guest_adapter *)NA(ifp);
+
+	return ptna->csb;
+}
+
+static uint32_t
+vtnet_ptnetmap_ptctl(struct ifnet *ifp, uint32_t val)
+{
+	struct SOFTC_T *sc = ifp->if_softc;
+	device_t dev = sc->vtnet_dev;
+	uint32_t ret;
+
+        D("PTCTL = %u", val);
+	vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_PTCTL, val);
+        ret = vtnet_ptnetmap_ioread4(dev, PTNETMAP_VIRTIO_IO_PTSTS);
+	D("PTSTS = %u", ret);
+
+	return ret;
+}
+
+static uint32_t
+vtnet_ptnetmap_features(struct SOFTC_T *sc)
+{
+	device_t dev = sc->vtnet_dev;
+	uint32_t features;
+	/* tell the device the features we support */
+	vtnet_ptnetmap_iowrite4(dev, PTNETMAP_VIRTIO_IO_PTFEAT, NET_PTN_FEATURES_BASE);
+	/* get back the acknowledged features */
+	features = vtnet_ptnetmap_ioread4(dev, PTNETMAP_VIRTIO_IO_PTFEAT);
+	D("netmap passthrough: %s\n",
+			(features & NET_PTN_FEATURES_BASE) ? "base" :
+			"none");
+	return features;
+}
+
+static void
+vtnet_ptnetmap_dtor(struct netmap_adapter *na)
+{
+        struct ifnet *ifp = na->ifp;
+	struct SOFTC_T *sc = ifp->if_softc;
+
+        vtnet_ptnetmap_free_csb(sc);
+}
+
+static struct netmap_pt_guest_ops vtnet_ptnetmap_ops = {
+    .nm_getcsb = vtnet_ptnetmap_getcsb, /* TODO: remove */
+    .nm_ptctl = vtnet_ptnetmap_ptctl,
+};
+#endif /* WITH_PTNETMAP_GUEST */
+
 static void
 vtnet_netmap_attach(struct SOFTC_T *sc)
 {
@@ -425,6 +790,21 @@
 	na.nm_config = vtnet_netmap_config;
 	na.num_tx_rings = na.num_rx_rings = sc->vtnet_max_vq_pairs;
 	D("max rings %d", sc->vtnet_max_vq_pairs);
+#ifdef WITH_PTNETMAP_GUEST
+	D("check ptnetmap support");
+	if (virtio_with_feature(sc->vtnet_dev, VIRTIO_NET_F_PTNETMAP) &&
+			(vtnet_ptnetmap_features(sc) & NET_PTN_FEATURES_BASE)) {
+		D("ptnetmap supported");
+		na.nm_config = vtnet_ptnetmap_config;
+		na.nm_register = vtnet_ptnetmap_reg;
+		na.nm_txsync = vtnet_ptnetmap_txsync;
+		na.nm_rxsync = vtnet_ptnetmap_rxsync;
+		na.nm_dtor = vtnet_ptnetmap_dtor;
+		na.nm_bdg_attach = vtnet_ptnetmap_bdg_attach; /* XXX */
+		netmap_pt_guest_attach(&na, &vtnet_ptnetmap_ops);
+		vtnet_ptnetmap_alloc_csb(sc);
+	} else
+#endif /* WITH_PTNETMAP_GUEST */
 	netmap_attach(&na);
 
         D("virtio attached txq=%d, txd=%d rxq=%d, rxd=%d",

Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/ixgbe_netmap.h
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/ixgbe_netmap.h	Tue Jul 21 14:10:22 2015	(r288616)
+++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/ixgbe_netmap.h	Tue Jul 21 14:19:04 2015	(r288617)
@@ -24,7 +24,7 @@
  */
 
 /*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/netmap/ixgbe_netmap.h 244514 2012-12-20 22:26:03Z luigi $
  *
  * netmap support for: ixgbe
  *
@@ -61,7 +61,8 @@
  *	count packets that might be missed due to lost interrupts.
  */
 SYSCTL_DECL(_dev_netmap);
-static int ix_rx_miss, ix_rx_miss_bufs, ix_crcstrip;
+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");
 SYSCTL_INT(_dev_netmap, OID_AUTO, ix_rx_miss,
@@ -321,8 +322,6 @@
 		}
 	}
 
-	nm_txsync_finalize(kring);
-
 	return 0;
 }
 
@@ -350,7 +349,7 @@
 	u_int nic_i;	/* index into the NIC ring */
 	u_int n;
 	u_int const lim = kring->nkr_num_slots - 1;
-	u_int const head = nm_rxsync_prologue(kring);
+	u_int const head = kring->rhead;
 	int force_update = (flags & NAF_FORCE_READ) || kring->nr_kflags & NKR_PENDINTR;
 
 	/* device-specific */
@@ -457,9 +456,6 @@
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_RDT(rxr->me), nic_i);
 	}
 
-	/* tell userspace that there might be new packets */
-	nm_rxsync_finalize(kring);
-
 	return 0;
 
 ring_reset:

Modified: soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap.c
==============================================================================
--- soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap.c	Tue Jul 21 14:10:22 2015	(r288616)
+++ soc2015/stefano/ptnetmap/stable/10/sys/dev/netmap/netmap.c	Tue Jul 21 14:19:04 2015	(r288617)
@@ -293,7 +293,7 @@
  *                kring->nm_sync() == DEVICE_netmap_rxsync()
  *           2) device interrupt handler
  *                na->nm_notify()  == netmap_notify()
- *    - tx from host stack
+ *    - rx from host stack
  *       concurrently:
  *           1) host stack
  *                netmap_transmit()
@@ -313,31 +313,113 @@
  *
  *               -= SYSTEM DEVICE WITH GENERIC SUPPORT =-
  *
+ *    na == NA(ifp) == generic_netmap_adapter created in generic_netmap_attach()
  *
- *
- *                           -= VALE PORT =-
- *
- *
- *
- *                           -= NETMAP PIPE =-
- *
- *
- *
- *  -= SYSTEM DEVICE WITH NATIVE SUPPORT, CONNECTED TO VALE, NO HOST RINGS =-
- *
- *
- *
- *  -= SYSTEM DEVICE WITH NATIVE SUPPORT, CONNECTED TO VALE, WITH HOST RINGS =-
- *
- *
- *
- *  -= SYSTEM DEVICE WITH GENERIC SUPPORT, CONNECTED TO VALE, NO HOST RINGS =-
- *
+ *    - tx from netmap userspace:
+ *       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
+ *           2) generic_mbuf_destructor()
+ *                   na->nm_notify() == netmap_notify()
+ *    - rx from netmap userspace:
+ *           1) ioctl(NIOCRXSYNC)/netmap_poll() in process context
+ *               kring->nm_sync() == generic_netmap_rxsync()
+ *                   mbq_safe_dequeue()
+ *           2) device driver
+ *               generic_rx_handler()
+ *                   mbq_safe_enqueue()
+ *                   na->nm_notify() == netmap_notify()
+ *    - rx from host stack:
+ *        concurrently:

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


More information about the svn-soc-all mailing list