socsvn commit: r287458 - soc2015/stefano/ptnetmap/head/sys/net

stefano at FreeBSD.org stefano at FreeBSD.org
Mon Jun 22 20:21:10 UTC 2015


Author: stefano
Date: Mon Jun 22 20:21:09 2015
New Revision: 287458
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=287458

Log:
  [ptnetmap] add new netmap headers

Modified:
  soc2015/stefano/ptnetmap/head/sys/net/netmap.h
  soc2015/stefano/ptnetmap/head/sys/net/netmap_user.h

Modified: soc2015/stefano/ptnetmap/head/sys/net/netmap.h
==============================================================================
--- soc2015/stefano/ptnetmap/head/sys/net/netmap.h	Mon Jun 22 20:05:26 2015	(r287457)
+++ soc2015/stefano/ptnetmap/head/sys/net/netmap.h	Mon Jun 22 20:21:09 2015	(r287458)
@@ -25,7 +25,7 @@
  */
 
 /*
- * $FreeBSD$
+ * $FreeBSD: head/sys/net/netmap.h 251139 2013-05-30 14:07:14Z luigi $
  *
  * Definitions of constants and the structures used by the netmap
  * framework, for the part visible to both kernel and userspace.
@@ -157,6 +157,11 @@
 	/*
 	 * must be set whenever buf_idx is changed (as it might be
 	 * necessary to recompute the physical address and mapping)
+	 *
+	 * It is also set by the kernel whenever the buf_idx is
+	 * changed internally (e.g., by pipes). Applications may
+	 * use this information to know when they can reuse the
+	 * contents of previously prepared buffers.
 	 */
 
 #define	NS_REPORT	0x0002	/* ask the hardware to report results */
@@ -491,6 +496,8 @@
 #define NETMAP_BDG_OFFSET	NETMAP_BDG_VNET_HDR	/* deprecated alias */
 #define NETMAP_BDG_NEWIF	6	/* create a virtual port */
 #define NETMAP_BDG_DELIF	7	/* destroy a virtual port */
+#define NETMAP_PT_HOST_CREATE	8	/* create ptnetmap kthreads */
+#define NETMAP_PT_HOST_DELETE	9	/* delete ptnetmap kthreads */
 	uint16_t	nr_arg1;	/* reserve extra rings in NIOCREGIF */
 #define NETMAP_BDG_HOST		1	/* attach the host stack on ATTACH */
 
@@ -513,7 +520,11 @@
 /* monitor uses the NR_REG to select the rings to monitor */
 #define NR_MONITOR_TX	0x100
 #define NR_MONITOR_RX	0x200
-
+#define NR_ZCOPY_MON	0x400
+/* request exclusive access to the selected rings */
+#define NR_EXCLUSIVE	0x800
+/* request netmap passthrough full support */
+#define NR_PASSTHROUGH_HOST	0x1000
 
 /*
  * FreeBSD uses the size value embedded in the _IOWR to determine
@@ -552,5 +563,4 @@
 	char nifr_name[IFNAMSIZ];
 	char data[NM_IFRDATA_LEN];
 };
-
 #endif /* _NET_NETMAP_H_ */

Modified: soc2015/stefano/ptnetmap/head/sys/net/netmap_user.h
==============================================================================
--- soc2015/stefano/ptnetmap/head/sys/net/netmap_user.h	Mon Jun 22 20:05:26 2015	(r287457)
+++ soc2015/stefano/ptnetmap/head/sys/net/netmap_user.h	Mon Jun 22 20:21:09 2015	(r287458)
@@ -284,6 +284,12 @@
  *		-NN		bind individual NIC ring pair
  *		{NN		bind master side of pipe NN
  *		}NN		bind slave side of pipe NN
+ *		a suffix starting with + and the following flags,
+ *		in any order:
+ *		x		exclusive access
+ *		z		zero copy monitor
+ *		t		monitor tx side
+ *		r		monitor rx side
  *
  * req		provides the initial values of nmreq before parsing ifname.
  *		Remember that the ifname parsing will override the ring
@@ -323,6 +329,13 @@
 static int nm_close(struct nm_desc *);
 
 /*
+ * nm_mmap()    do mmap or inherit from parent if the nr_arg2
+ *              (memory block) matches.
+ */
+
+static int nm_mmap(struct nm_desc *, const struct nm_desc *);
+
+/*
  * nm_inject() is the same as pcap_inject()
  * nm_dispatch() is the same as pcap_dispatch()
  * nm_nextpkt() is the same as pcap_next()
@@ -338,7 +351,8 @@
  * An invalid netmap name will return errno = 0;
  * You can pass a pointer to a pre-filled nm_desc to add special
  * parameters. Flags is used as follows
- * NM_OPEN_NO_MMAP	use the memory from arg, only
+ * NM_OPEN_NO_MMAP	XXX: avoid mmap
+ *                      use the memory from arg, only
  *			if the nr_arg2 (memory block) matches.
  * NM_OPEN_ARG1		use req.nr_arg1 from arg
  * NM_OPEN_ARG2		use req.nr_arg2 from arg
@@ -351,9 +365,12 @@
 	struct nm_desc *d = NULL;
 	const struct nm_desc *parent = arg;
 	u_int namelen;
-	uint32_t nr_ringid = 0, nr_flags;
+	uint32_t nr_ringid = 0, nr_flags, nr_reg;
 	const char *port = NULL;
-	const char *errmsg = NULL;
+#define MAXERRMSG 80
+	char errmsg[MAXERRMSG] = "";
+	enum { P_START, P_RNGSFXOK, P_GETNUM, P_FLAGS, P_FLAGSOK } p_state;
+	long num;
 
 	if (strncmp(ifname, "netmap:", 7) && strncmp(ifname, "vale", 4)) {
 		errno = 0; /* name not recognised, not an error */
@@ -362,60 +379,112 @@
 	if (ifname[0] == 'n')
 		ifname += 7;
 	/* scan for a separator */
-	for (port = ifname; *port && !index("-*^{}", *port); port++)
+	for (port = ifname; *port && !index("-*^{}/", *port); port++)
 		;
 	namelen = port - ifname;
 	if (namelen >= sizeof(d->req.nr_name)) {
-		errmsg = "name too long";
+		snprintf(errmsg, MAXERRMSG, "name too long");
 		goto fail;
 	}
-	switch (*port) {
-	default:  /* '\0', no suffix */
-		nr_flags = NR_REG_ALL_NIC;
-		break;
-	case '-': /* one NIC */
-		nr_flags = NR_REG_ONE_NIC;
-		nr_ringid = atoi(port + 1);
-		break;
-	case '*': /* NIC and SW, ignore port */
-		nr_flags = NR_REG_NIC_SW;
-		if (port[1]) {
-			errmsg = "invalid port for nic+sw";
-			goto fail;
+	p_state = P_START;
+	nr_flags = NR_REG_ALL_NIC; /* default for no suffix */
+	while (*port) {
+		switch (p_state) {
+		case P_START:
+			switch (*port) {
+			case '^': /* only SW ring */
+				nr_flags = NR_REG_SW;
+				p_state = P_RNGSFXOK;
+				break;
+			case '*': /* NIC and SW */
+				nr_flags = NR_REG_NIC_SW;
+				p_state = P_RNGSFXOK;
+				break;
+			case '-': /* one NIC ring pair */
+				nr_flags = NR_REG_ONE_NIC;
+				p_state = P_GETNUM;
+				break;
+			case '{': /* pipe (master endpoint) */
+				nr_flags = NR_REG_PIPE_MASTER;
+				p_state = P_GETNUM;
+				break;
+			case '}': /* pipe (slave endoint) */
+				nr_flags = NR_REG_PIPE_SLAVE;
+				p_state = P_GETNUM;
+				break;
+			case '/': /* start of flags */
+				p_state = P_FLAGS;
+				break;
+			default:
+				snprintf(errmsg, MAXERRMSG, "unknown modifier: '%c'", *port);
+				goto fail;
+			}
+			port++;
+			break;
+		case P_RNGSFXOK:
+			switch (*port) {
+			case '/':
+				p_state = P_FLAGS;
+				break;
+			default:
+				snprintf(errmsg, MAXERRMSG, "unexpected character: '%c'", *port);
+				goto fail;
+			}
+			port++;
+			break;
+		case P_GETNUM:
+			num = strtol(port, (char **)&port, 10);
+			if (num < 0 || num >= NETMAP_RING_MASK) {
+				snprintf(errmsg, MAXERRMSG, "'%ld' out of range [0, %d)",
+						num, NETMAP_RING_MASK);
+				goto fail;
+			}
+			nr_ringid = num & NETMAP_RING_MASK;
+			p_state = P_RNGSFXOK;
+			break;
+		case P_FLAGS:
+		case P_FLAGSOK:
+			switch (*port) {
+			case 'x':
+				nr_flags |= NR_EXCLUSIVE;
+				break;
+			case 'z':
+				nr_flags |= NR_ZCOPY_MON;
+				break;
+			case 't':
+				nr_flags |= NR_MONITOR_TX;
+				break;
+			case 'r':
+				nr_flags |= NR_MONITOR_RX;
+				break;
+			default:
+				snprintf(errmsg, MAXERRMSG, "unrecognized flag: '%c'", *port);
+				goto fail;
+			}
+			port++;
+			p_state = P_FLAGSOK;
+			break;
 		}
-		break;
-	case '^': /* only sw ring */
-		nr_flags = NR_REG_SW;
-		if (port[1]) {
-			errmsg = "invalid port for sw ring";
-			goto fail;
-		}
-		break;
-	case '{':
-		nr_flags = NR_REG_PIPE_MASTER;
-		nr_ringid = atoi(port + 1);
-		break;
-	case '}':
-		nr_flags = NR_REG_PIPE_SLAVE;
-		nr_ringid = atoi(port + 1);
-		break;
 	}
-
-	if (nr_ringid >= NETMAP_RING_MASK) {
-		errmsg = "invalid ringid";
+	if (p_state != P_START && p_state != P_RNGSFXOK && p_state != P_FLAGSOK) {
+		snprintf(errmsg, MAXERRMSG, "unexpected end of port name");
 		goto fail;
 	}
-
+	ND("flags: %s %s %s %s",
+			(nr_flags & NR_EXCLUSIVE) ? "EXCLUSIVE" : "",
+			(nr_flags & NR_ZCOPY_MON) ? "ZCOPY_MON" : "",
+			(nr_flags & NR_MONITOR_TX) ? "MONITOR_TX" : "",
+			(nr_flags & NR_MONITOR_RX) ? "MONITOR_RX" : "");
 	d = (struct nm_desc *)calloc(1, sizeof(*d));
 	if (d == NULL) {
-		errmsg = "nm_desc alloc failure";
+		snprintf(errmsg, MAXERRMSG, "nm_desc alloc failure");
 		errno = ENOMEM;
 		return NULL;
 	}
 	d->self = d;	/* set this early so nm_close() works */
 	d->fd = open("/dev/netmap", O_RDWR);
 	if (d->fd < 0) {
-		errmsg = "cannot open /dev/netmap";
+		snprintf(errmsg, MAXERRMSG, "cannot open /dev/netmap: %s", strerror(errno));
 		goto fail;
 	}
 
@@ -426,7 +495,7 @@
 
 	/* these fields are overridden by ifname and flags processing */
 	d->req.nr_ringid |= nr_ringid;
-	d->req.nr_flags = nr_flags;
+	d->req.nr_flags |= nr_flags;
 	memcpy(d->req.nr_name, ifname, namelen);
 	d->req.nr_name[namelen] = '\0';
 	/* optionally import info from parent */
@@ -464,51 +533,31 @@
 	d->req.nr_ringid |= new_flags & (NETMAP_NO_TX_POLL | NETMAP_DO_RX_POLL);
 
 	if (ioctl(d->fd, NIOCREGIF, &d->req)) {
-		errmsg = "NIOCREGIF failed";
+		snprintf(errmsg, MAXERRMSG, "NIOCREGIF failed: %s", strerror(errno));
 		goto fail;
 	}
 
-	if (IS_NETMAP_DESC(parent) && parent->mem &&
-	    parent->req.nr_arg2 == d->req.nr_arg2) {
-		/* do not mmap, inherit from parent */
-		d->memsize = parent->memsize;
-		d->mem = parent->mem;
-	} else {
-		/* XXX TODO: check if memsize is too large (or there is overflow) */
-		d->memsize = d->req.nr_memsize;
-		d->mem = mmap(0, d->memsize, PROT_WRITE | PROT_READ, MAP_SHARED,
-				d->fd, 0);
-		if (d->mem == MAP_FAILED) {
-			errmsg = "mmap failed";
-			goto fail;
-		}
-		d->done_mmap = 1;
+	if (!(new_flags & NM_OPEN_NO_MMAP) && nm_mmap(d, parent)) {
+	        snprintf(errmsg, MAXERRMSG, "mmap failed: %s", strerror(errno));
+		goto fail;
 	}
-	{
-		struct netmap_if *nifp = NETMAP_IF(d->mem, d->req.nr_offset);
-		struct netmap_ring *r = NETMAP_RXRING(nifp, );
 
-		*(struct netmap_if **)(uintptr_t)&(d->nifp) = nifp;
-		*(struct netmap_ring **)(uintptr_t)&d->some_ring = r;
-		*(void **)(uintptr_t)&d->buf_start = NETMAP_BUF(r, 0);
-		*(void **)(uintptr_t)&d->buf_end =
-			(char *)d->mem + d->memsize;
-	}
+	nr_reg = d->req.nr_flags & NR_REG_MASK;
 
-	if (d->req.nr_flags ==  NR_REG_SW) { /* host stack */
+	if (nr_reg ==  NR_REG_SW) { /* host stack */
 		d->first_tx_ring = d->last_tx_ring = d->req.nr_tx_rings;
 		d->first_rx_ring = d->last_rx_ring = d->req.nr_rx_rings;
-	} else if (d->req.nr_flags ==  NR_REG_ALL_NIC) { /* only nic */
+	} else if (nr_reg ==  NR_REG_ALL_NIC) { /* only nic */
 		d->first_tx_ring = 0;
 		d->first_rx_ring = 0;
 		d->last_tx_ring = d->req.nr_tx_rings - 1;
 		d->last_rx_ring = d->req.nr_rx_rings - 1;
-	} else if (d->req.nr_flags ==  NR_REG_NIC_SW) {
+	} else if (nr_reg ==  NR_REG_NIC_SW) {
 		d->first_tx_ring = 0;
 		d->first_rx_ring = 0;
 		d->last_tx_ring = d->req.nr_tx_rings;
 		d->last_rx_ring = d->req.nr_rx_rings;
-	} else if (d->req.nr_flags == NR_REG_ONE_NIC) {
+	} else if (nr_reg == NR_REG_ONE_NIC) {
 		/* XXX check validity */
 		d->first_tx_ring = d->last_tx_ring =
 		d->first_rx_ring = d->last_rx_ring = d->req.nr_ringid & NETMAP_RING_MASK;
@@ -541,7 +590,7 @@
 
 fail:
 	nm_close(d);
-	if (errmsg)
+	if (errmsg[0])
 		D("%s %s", errmsg, ifname);
 	if (errno == 0)
 		errno = EINVAL;
@@ -571,6 +620,44 @@
 }
 
 
+static int
+nm_mmap(struct nm_desc *d, const struct nm_desc *parent)
+{
+	//XXX TODO: check if mmap is already done
+
+	if (IS_NETMAP_DESC(parent) && parent->mem &&
+	    parent->req.nr_arg2 == d->req.nr_arg2) {
+		/* do not mmap, inherit from parent */
+		D("do not mmap, inherit from parent");
+		d->memsize = parent->memsize;
+		d->mem = parent->mem;
+	} else {
+		/* XXX TODO: check if memsize is too large (or there is overflow) */
+		d->memsize = d->req.nr_memsize;
+		d->mem = mmap(0, d->memsize, PROT_WRITE | PROT_READ, MAP_SHARED,
+				d->fd, 0);
+		if (d->mem == MAP_FAILED) {
+			goto fail;
+		}
+		d->done_mmap = 1;
+	}
+	{
+		struct netmap_if *nifp = NETMAP_IF(d->mem, d->req.nr_offset);
+		struct netmap_ring *r = NETMAP_RXRING(nifp, );
+
+		*(struct netmap_if **)(uintptr_t)&(d->nifp) = nifp;
+		*(struct netmap_ring **)(uintptr_t)&d->some_ring = r;
+		*(void **)(uintptr_t)&d->buf_start = NETMAP_BUF(r, 0);
+		*(void **)(uintptr_t)&d->buf_end =
+			(char *)d->mem + d->memsize;
+	}
+
+	return 0;
+
+fail:
+	return EINVAL;
+}
+
 /*
  * Same prototype as pcap_inject(), only need to cast.
  */


More information about the svn-soc-all mailing list