Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 5 Aug 2016 13:54:56 GMT
From:      vincenzo@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r307219 - soc2016/vincenzo/head/usr.sbin/bhyve
Message-ID:  <201608051354.u75Dsuw1037808@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: vincenzo
Date: Fri Aug  5 13:54:55 2016
New Revision: 307219
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=307219

Log:
  ptnetmap: add backend-side support

Modified:
  soc2016/vincenzo/head/usr.sbin/bhyve/net_backends.c
  soc2016/vincenzo/head/usr.sbin/bhyve/net_backends.h

Modified: soc2016/vincenzo/head/usr.sbin/bhyve/net_backends.c
==============================================================================
--- soc2016/vincenzo/head/usr.sbin/bhyve/net_backends.c	Fri Aug  5 13:53:35 2016	(r307218)
+++ soc2016/vincenzo/head/usr.sbin/bhyve/net_backends.c	Fri Aug  5 13:54:55 2016	(r307219)
@@ -55,6 +55,7 @@
 #if (NETMAP_API < 11)
 #error "Netmap API version must be >= 11"
 #endif
+#include <dev/netmap/netmap_virt.h>
 
 /*
  * The API for network backends. This might need to be exposed
@@ -109,11 +110,6 @@
 	int (*set_features)(struct net_backend *be, uint64_t features,
 			    unsigned int vnet_hdr_len);
 
-	/*
-	 * Get ptnetmap_state if the backend support ptnetmap
-	 */
-	struct ptnetmap_state * (*get_ptnetmap)(struct net_backend *be);
-
 	struct pci_vtnet_softc *sc;
 	int fd;
 	unsigned int be_vnet_hdr_len;
@@ -171,12 +167,6 @@
 	return -1; /* never called, i believe */
 }
 
-static struct ptnetmap_state *
-netbe_null_get_ptnetmap(struct net_backend *be)
-{
-	return NULL;
-}
-
 static struct net_backend null_backend = {
 	.name = "null",
 	.init = netbe_null_init,
@@ -185,7 +175,6 @@
 	.recv = netbe_null_recv,
 	.get_features = netbe_null_get_features,
 	.set_features = netbe_null_set_features,
-	.get_ptnetmap = netbe_null_get_ptnetmap,
 };
 
 DATA_SET(net_backend_set, null_backend);
@@ -341,6 +330,8 @@
 
 #define NETMAP_POLLMASK (POLLIN | POLLRDNORM | POLLRDBAND)
 
+#define VNET_HDR_LEN	sizeof(struct virtio_net_rxhdr)
+
 struct netmap_priv {
 	char ifname[IFNAMSIZ];
 	struct nm_desc *nmd;
@@ -357,6 +348,8 @@
 	int rx_avail;
 	int rx_morefrag;
 	int rx_avail_slots;
+
+	struct ptnetmap_state ptnetmap;
 };
 
 static void *
@@ -405,10 +398,31 @@
 	return 0;
 }
 
+static int
+netmap_has_vnet_hdr_len(struct net_backend *be, unsigned vnet_hdr_len)
+{
+	int prev_hdr_len = be->be_vnet_hdr_len;
+	int ret;
+
+	if (vnet_hdr_len == prev_hdr_len) {
+		return 1;
+	}
+
+	ret = netmap_set_vnet_hdr_len(be, vnet_hdr_len);
+	if (ret) {
+		return 0;
+	}
+
+	netmap_set_vnet_hdr_len(be, prev_hdr_len);
+
+	return 1;
+}
+
 static uint64_t
 netmap_get_features(struct net_backend *be)
 {
-	return NETMAP_FEATURES;
+	return netmap_has_vnet_hdr_len(be, VNET_HDR_LEN) ?
+			NETMAP_FEATURES : 0;
 }
 
 static int
@@ -418,7 +432,125 @@
 	return netmap_set_vnet_hdr_len(be, vnet_hdr_len);
 }
 
-/* used by netmap and ptnetmap during the initialization */
+/* Store and return the features we agreed upon. */
+uint32_t
+ptnetmap_ack_features(struct ptnetmap_state *ptn, uint32_t wanted_features)
+{
+	ptn->acked_features = ptn->features & wanted_features;
+
+	return ptn->acked_features;
+}
+
+struct ptnetmap_state *
+get_ptnetmap(struct net_backend *be)
+{
+	struct netmap_priv *priv = be->priv;
+
+	/* Check that this is a netmap backend. */
+	if (be->set_features != netmap_set_features) {
+		return NULL;
+	}
+
+	return &priv->ptnetmap;
+}
+
+int
+ptnetmap_get_netmap_if(struct ptnetmap_state *ptn, struct netmap_if_info *nif)
+{
+	struct netmap_priv *priv = ptn->netmap_priv;
+
+	memset(nif, 0, sizeof(*nif));
+	if (priv->nmd == NULL) {
+		return EINVAL;
+	}
+
+	nif->nifp_offset = priv->nmd->req.nr_offset;
+	nif->num_tx_rings = priv->nmd->req.nr_tx_rings;
+	nif->num_rx_rings = priv->nmd->req.nr_rx_rings;
+	nif->num_tx_slots = priv->nmd->req.nr_tx_slots;
+	nif->num_rx_slots = priv->nmd->req.nr_rx_slots;
+
+	return 0;
+}
+
+int
+ptnetmap_get_host_memid(struct ptnetmap_state *ptn)
+{
+	struct netmap_priv *priv = ptn->netmap_priv;
+
+	if (priv->nmd == NULL) {
+		return EINVAL;
+	}
+
+	return priv->nmd->req.nr_arg2;
+}
+
+int
+ptnetmap_create(struct ptnetmap_state *ptn, struct ptnetmap_cfg *cfg)
+{
+	struct netmap_priv *priv = ptn->netmap_priv;
+	struct nmreq req;
+	int err;
+
+	if (!(ptn->acked_features & NET_PTN_FEATURES_BASE)) {
+		fprintf(stderr, "%s: ptnetmap features not acked\n",
+			__func__);
+		return EINVAL;
+	}
+
+	if (ptn->running) {
+		return 0;
+	}
+
+	/* XXX We should stop the netmap evloop here. */
+
+	/* Ask netmap to create kthreads for this interface. */
+	memset(&req, 0, sizeof(req));
+	strncpy(req.nr_name, priv->ifname, sizeof(req.nr_name));
+	req.nr_version = NETMAP_API;
+	ptnetmap_write_cfg(&req, cfg);
+	req.nr_cmd = NETMAP_PT_HOST_CREATE;
+	err = ioctl(priv->nmd->fd, NIOCREGIF, &req);
+	if (err) {
+		fprintf(stderr, "%s: Unable to create ptnetmap kthreads on "
+			"%s [errno=%d]", __func__, priv->ifname, errno);
+		return err;
+	}
+
+	ptn->running = 1;
+
+	return 0;
+}
+
+int
+ptnetmap_delete(struct ptnetmap_state *ptn)
+{
+	struct netmap_priv *priv = ptn->netmap_priv;
+	struct nmreq req;
+	int err;
+
+	if (!ptn->running) {
+		return 0;
+	}
+
+	/* Ask netmap to delete kthreads for this interface. */
+	memset(&req, 0, sizeof(req));
+	strncpy(req.nr_name, priv->ifname, sizeof(req.nr_name));
+	req.nr_version = NETMAP_API;
+	req.nr_cmd = NETMAP_PT_HOST_DELETE;
+	err = ioctl(priv->nmd->fd, NIOCREGIF, &req);
+	if (err) {
+		fprintf(stderr, "%s: Unable to create ptnetmap kthreads on "
+			"%s [errno=%d]", __func__, priv->ifname, errno);
+		return err;
+	}
+
+	ptn->running = 0;
+
+	return 0;
+}
+
+/* Used by netmap at initialization time. */
 static int
 netmap_common_init(struct net_backend *be, struct netmap_priv *priv,
 		   uint32_t nr_flags, const char *devname,
@@ -467,6 +599,7 @@
 	    net_backend_cb_t cb, void *param)
 {
 	struct netmap_priv *priv = NULL;
+	int ptnetmap = 0;
 
 	priv = calloc(1, sizeof(struct netmap_priv));
 	if (priv == NULL) {
@@ -474,10 +607,24 @@
 		return -1;
 	}
 
-	if (netmap_common_init(be, priv, 0, devname, cb, param)) {
+	if (netmap_common_init(be, priv, ptnetmap ? NR_PTNETMAP_HOST : 0,
+			       devname, cb, param)) {
 		goto err;
 	}
 
+	if (ptnetmap) {
+		priv->ptnetmap.netmap_priv = priv;
+		priv->ptnetmap.features = NET_PTN_FEATURES_BASE;
+		priv->ptnetmap.acked_features = 0;
+		priv->ptnetmap.running = 0;
+		if (netmap_has_vnet_hdr_len(be, VNET_HDR_LEN)) {
+			priv->ptnetmap.features |= NET_PTN_FEATURES_VNET_HDR;
+		}
+		/* XXX Call ptn_memdev_attach() here or in get_ptnetmap ? */
+		ptn_memdev_attach(priv->nmd->mem, priv->nmd->memsize,
+				  priv->nmd->req.nr_arg2);
+	}
+
 	be->priv = priv;
 
 	return 0;
@@ -494,6 +641,9 @@
 	struct netmap_priv *priv = be->priv;
 
 	if (be->priv) {
+		if (priv->ptnetmap.running) {
+			ptnetmap_delete(&priv->ptnetmap);
+		}
 		nm_close(priv->nmd);
 		free(be->priv);
 		be->priv = NULL;
@@ -741,11 +891,6 @@
 			be, be->name);
 		be->set_features = netbe_null_set_features;
 	}
-	if (be->get_ptnetmap == NULL) {
-		/*fprintf(stderr, "missing set_features for %p %s\n",
-			be, be->name);*/
-		be->get_ptnetmap = netbe_null_get_ptnetmap;
-	}
 }
 
 /*
@@ -836,9 +981,8 @@
 		return 0;
 
 	/* There are only three valid lengths. */
-	if (vnet_hdr_len && vnet_hdr_len != sizeof(struct virtio_net_rxhdr)
-		&& vnet_hdr_len != (sizeof(struct virtio_net_rxhdr) -
-				    sizeof(uint16_t)))
+	if (vnet_hdr_len && vnet_hdr_len != VNET_HDR_LEN
+		&& vnet_hdr_len != (VNET_HDR_LEN - sizeof(uint16_t)))
 		return -1;
 
 	be->fe_vnet_hdr_len = vnet_hdr_len;
@@ -919,7 +1063,7 @@
 		 */
 		memset(vh, 0, hlen);
 
-		if (hlen == sizeof(struct virtio_net_rxhdr)) {
+		if (hlen == VNET_HDR_LEN) {
 			vh->vrh_bufs = 1;
 		}
 	}

Modified: soc2016/vincenzo/head/usr.sbin/bhyve/net_backends.h
==============================================================================
--- soc2016/vincenzo/head/usr.sbin/bhyve/net_backends.h	Fri Aug  5 13:53:35 2016	(r307218)
+++ soc2016/vincenzo/head/usr.sbin/bhyve/net_backends.h	Fri Aug  5 13:54:55 2016	(r307219)
@@ -84,4 +84,33 @@
 	uint16_t	vrh_bufs;
 } __packed;
 
+/*
+ * ptnetmap definitions
+ */
+struct ptnetmap_state {
+	void		*netmap_priv;
+
+	/* True if ptnetmap kthreads are running. */
+	int		running;
+
+	/* Feature acknoweledgement support. */
+	unsigned long	features;
+	unsigned long	acked_features;
+
+	/* Info about netmap memory. */
+	uint32_t	memsize;
+	void		*mem;
+};
+
+/* Used to get read-only info. */
+struct netmap_if_info {
+	uint32_t nifp_offset;
+	uint16_t num_tx_rings;
+	uint16_t num_rx_rings;
+	uint16_t num_tx_slots;
+	uint16_t num_rx_slots;
+};
+
+int ptn_memdev_attach(void *mem_ptr, uint32_t mem_size, uint16_t mem_id);
+
 #endif /* __NET_BACKENDS_H__ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608051354.u75Dsuw1037808>