From a46d3b1d5493f74d028dc44259dfb01992664e22 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Sat, 16 Apr 2016 10:15:23 +0200 Subject: [PATCH 01/10] python: improve tx.py user-interface and documentation --- extra/python/README | 5 +++-- extra/python/tx.py | 28 ++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/extra/python/README b/extra/python/README index 452a258f4..c45530bd1 100644 --- a/extra/python/README +++ b/extra/python/README @@ -95,6 +95,7 @@ language. to see the available options. - (5.2) tx.py - An example packet generator using the lower level - Python netmap bindings. + (5.2) tx.py - An minimal packet generator using the lower level + Python netmap bindings, it is able to transmit + more than 20 Mpps. diff --git a/extra/python/tx.py b/extra/python/tx.py index 295d4032a..b48fc6a0c 100755 --- a/extra/python/tx.py +++ b/extra/python/tx.py @@ -1,9 +1,11 @@ #!/usr/bin/env python +# Copyright (C) 2013-2015, Vincenzo Maffione import netmap import time import struct import select +import argparse # program argument parsing def build_packet(): @@ -12,13 +14,28 @@ def build_packet(): ############################## MAIN ########################### + +parser = argparse.ArgumentParser(description = 'Minimal, high-performance packet '\ + 'generator written in Python using '\ + 'the netmap API', + epilog = 'Press Ctrl-C to stop') +parser.add_argument('-i', '--interface', help = 'the interface to register with netmap; ' + 'can be in the form or , where ' + 'OSNAME is the O.S. name for a network interface (e.g. "eth0"), ' + ' is a valid VALE port name (e.g. "vale18:2")', + default = 'vale0:0') + +args = parser.parse_args() + pkt = build_packet() +print("Opening interface %s" % (args.interface)) + # open the netmap device and register an interface nm = netmap.Netmap() nm.open() nfd = nm.getfd() -nm.if_name = 'vale:1' +nm.if_name = args.interface nm.register() time.sleep(1) @@ -29,6 +46,7 @@ def build_packet(): txr.slots[i].buf[0:len(pkt)] = pkt txr.slots[i].len = len(pkt) +print("Starting transmission, press Ctrl-C to stop") # transmit at maximum speed until Ctr-C is pressed cnt = 0 # packet counter @@ -58,6 +76,12 @@ def build_packet(): pass t_end = time.time() -print("\nPackets sent: %s, Avg rate %s Kpps" % (cnt, 0.001 * cnt / (t_end - t_start))) +rate = 0.001 * cnt / (t_end - t_start) +unit = 'K' +if rate > 1000: + rate /= 1000.0 + unit = 'M' + +print("\nPackets sent: %s, Avg rate %6.3f %spps" % (cnt, rate, unit)) nm.close() From 941f07a991b8a6b191e0a803160b2f4049640114 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Sat, 16 Apr 2016 10:43:30 +0200 Subject: [PATCH 02/10] python: add support for __enter__ and __exit__ method to NetmapDesc This makes it possible to use NetmapDesc class in the 'with' statement. --- extra/python/netmap_desc.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/extra/python/netmap_desc.c b/extra/python/netmap_desc.c index f25cc0efd..da901adfe 100644 --- a/extra/python/netmap_desc.c +++ b/extra/python/netmap_desc.c @@ -44,6 +44,7 @@ NetmapDesc_dealloc(NetmapDesc* self) if (self->nmd) { nm_close(self->nmd); + self->nmd = NULL; } self->ob_type->tp_free((PyObject*)self); } @@ -170,6 +171,24 @@ static PyGetSetDef NetmapDesc_getseters[] = { /*########################## NetmapDesc methods ########################*/ +static PyObject * +NetmapDesc_enter(NetmapDesc *self) +{ + Py_INCREF(self); + return (PyObject *)self; +} + +static PyObject * +NetmapDesc_exit(NetmapDesc *self, PyObject *args) +{ + if (self->nmd) { + nm_close(self->nmd); + self->nmd = NULL; + } + + Py_RETURN_NONE; +} + static PyObject * NetmapDesc_xxsync(NetmapDesc *self, int iocmd) { @@ -217,6 +236,12 @@ NetmapDesc_getflags(NetmapDesc *self) /* A container for the netmap methods. */ static PyMethodDef NetmapDesc_methods[] = { + {"__enter__", (PyCFunction)NetmapDesc_enter, METH_NOARGS, + "__enter__ implementation to support with statement" + }, + {"__exit__", (PyCFunction)NetmapDesc_exit, METH_VARARGS, + "__exit__ implementation to support with statement" + }, {"txsync", (PyCFunction)NetmapDesc_txsync, METH_NOARGS, "Do a txsync on the registered rings" }, From 25d44df3d53947983573e7e5cdccd1e3ab4e3389 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Tue, 19 Apr 2016 11:35:53 +0200 Subject: [PATCH 03/10] linux: i40e: clarify ix_crcstrip comment --- LINUX/i40e_netmap_linux.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LINUX/i40e_netmap_linux.h b/LINUX/i40e_netmap_linux.h index 9e8e62ba1..71d4fde72 100644 --- a/LINUX/i40e_netmap_linux.h +++ b/LINUX/i40e_netmap_linux.h @@ -60,7 +60,7 @@ extern int ix_rx_miss, ix_rx_miss_bufs, ix_crcstrip; /* * 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. @@ -69,9 +69,9 @@ extern int ix_rx_miss, ix_rx_miss_bufs, ix_crcstrip; * count packets that might be missed due to lost interrupts. */ SYSCTL_DECL(_dev_netmap); -int ix_rx_miss, ix_rx_miss_bufs, ix_crcstrip; +int ix_rx_miss = 0, ix_rx_miss_bufs = 0, ix_crcstrip = 0; SYSCTL_INT(_dev_netmap, OID_AUTO, ix_crcstrip, - CTLFLAG_RW, &ix_crcstrip, 1, "strip CRC on rx frames"); + CTLFLAG_RW, &ix_crcstrip, 0, "strip 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, From 6a5d94069ef626bf13967440df4bf5c1530965da Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Tue, 19 Apr 2016 13:43:25 +0200 Subject: [PATCH 04/10] linux: i40e: ix_crcstrip defaults to 1, similarly to FreeBSD --- LINUX/i40e_netmap_linux.h | 5 +++-- sys/dev/netmap/if_ixl_netmap.h | 4 ++-- sys/dev/netmap/ixgbe_netmap.h | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/LINUX/i40e_netmap_linux.h b/LINUX/i40e_netmap_linux.h index 71d4fde72..d275de920 100644 --- a/LINUX/i40e_netmap_linux.h +++ b/LINUX/i40e_netmap_linux.h @@ -64,14 +64,15 @@ extern int ix_rx_miss, ix_rx_miss_bufs, ix_crcstrip; * 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. + * The driver by default strips CRCs and we do not override it. * * ix_rx_miss, ix_rx_miss_bufs: * count packets that might be missed due to lost interrupts. */ SYSCTL_DECL(_dev_netmap); -int ix_rx_miss = 0, ix_rx_miss_bufs = 0, ix_crcstrip = 0; +int ix_rx_miss = 0, ix_rx_miss_bufs = 0, ix_crcstrip = 1; SYSCTL_INT(_dev_netmap, OID_AUTO, ix_crcstrip, - CTLFLAG_RW, &ix_crcstrip, 0, "strip CRC on rx frames"); + CTLFLAG_RW, &ix_crcstrip, 1, "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, diff --git a/sys/dev/netmap/if_ixl_netmap.h b/sys/dev/netmap/if_ixl_netmap.h index 9e15fcdc4..29a832dd3 100644 --- a/sys/dev/netmap/if_ixl_netmap.h +++ b/sys/dev/netmap/if_ixl_netmap.h @@ -59,7 +59,7 @@ extern int ixl_rx_miss, ixl_rx_miss_bufs, ixl_crcstrip; /* * 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 (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. @@ -74,7 +74,7 @@ SYSCTL_DECL(_dev_netmap); int ixl_rx_miss, ixl_rx_miss_bufs, ixl_crcstrip = 1; #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"); diff --git a/sys/dev/netmap/ixgbe_netmap.h b/sys/dev/netmap/ixgbe_netmap.h index d933e1e24..73b8e90de 100644 --- a/sys/dev/netmap/ixgbe_netmap.h +++ b/sys/dev/netmap/ixgbe_netmap.h @@ -52,7 +52,7 @@ /* * 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. @@ -64,7 +64,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, From 0e8968d8811c2c5e04e65c931963fc377ae4dbd5 Mon Sep 17 00:00:00 2001 From: Giuseppe Lettieri Date: Wed, 20 Apr 2016 15:10:28 +0200 Subject: [PATCH 05/10] ignore some more files --- .gitignore | 1 + apps/lb/.gitignore | 1 + apps/nmreplay/.gitignore | 1 + apps/tlem/.gitignore | 1 + 4 files changed, 4 insertions(+) create mode 100644 apps/lb/.gitignore create mode 100644 apps/nmreplay/.gitignore create mode 100644 apps/tlem/.gitignore diff --git a/.gitignore b/.gitignore index c27be5c00..975738eac 100644 --- a/.gitignore +++ b/.gitignore @@ -57,3 +57,4 @@ LINUX/veth.c *.sdf *.opensdf *~ +cscope.out diff --git a/apps/lb/.gitignore b/apps/lb/.gitignore new file mode 100644 index 000000000..aa1a077b9 --- /dev/null +++ b/apps/lb/.gitignore @@ -0,0 +1 @@ +lb diff --git a/apps/nmreplay/.gitignore b/apps/nmreplay/.gitignore new file mode 100644 index 000000000..fe5b10ed1 --- /dev/null +++ b/apps/nmreplay/.gitignore @@ -0,0 +1 @@ +nmreplay diff --git a/apps/tlem/.gitignore b/apps/tlem/.gitignore new file mode 100644 index 000000000..6daa2b960 --- /dev/null +++ b/apps/tlem/.gitignore @@ -0,0 +1 @@ +tlem From cc8bfeb5e0b9e3206d085363acffe99c52473e6b Mon Sep 17 00:00:00 2001 From: Giuseppe Lettieri Date: Wed, 20 Apr 2016 15:56:37 +0200 Subject: [PATCH 06/10] lb: fix: hash of next pkt was used for the current one --- apps/lb/lb.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/lb/lb.c b/apps/lb/lb.c index 416571b74..f26309ff3 100644 --- a/apps/lb/lb.c +++ b/apps/lb/lb.c @@ -561,16 +561,17 @@ int main(int argc, char **argv) while (!nm_ring_empty(rxring)) { struct overflow_queue *q; struct netmap_slot *rs = next_slot; - next_cur = nm_ring_next(rxring, next_cur); - next_slot = &rxring->slot[next_cur]; // CHOOSE THE CORRECT OUTPUT PIPE - next_buf = NETMAP_BUF(rxring, next_slot->buf_idx); - __builtin_prefetch(next_buf); - // 'B' is just a hashing seed uint32_t hash = pkt_hdr_hash((const unsigned char *)next_buf, 4, 'B'); if (hash == 0) non_ip++; // XXX ?? + // prefetch the buffer for the next round + next_cur = nm_ring_next(rxring, next_cur); + next_slot = &rxring->slot[next_cur]; + next_buf = NETMAP_BUF(rxring, next_slot->buf_idx); + __builtin_prefetch(next_buf); + // 'B' is just a hashing seed uint32_t output_port = hash % glob_arg.output_rings; struct port_des *port = &ports[output_port]; struct netmap_ring *ring = port->ring; From 1282841acde19eeb4018819b85b7dec4d209173e Mon Sep 17 00:00:00 2001 From: Giuseppe Lettieri Date: Thu, 21 Apr 2016 15:56:42 +0200 Subject: [PATCH 07/10] mem: do not increment active if allocation failed --- sys/dev/netmap/netmap_mem2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/dev/netmap/netmap_mem2.c b/sys/dev/netmap/netmap_mem2.c index 1cc5fe7dd..f053d2211 100644 --- a/sys/dev/netmap/netmap_mem2.c +++ b/sys/dev/netmap/netmap_mem2.c @@ -1481,8 +1481,9 @@ static int netmap_mem_private_finalize(struct netmap_mem_d *nmd) { int err; - nmd->active++; err = netmap_mem_finalize_all(nmd); + if (!err) + nmd->active++; return err; } From c4aaa2d1579357598e1cf0cf9b01369532ce8ec2 Mon Sep 17 00:00:00 2001 From: Giuseppe Lettieri Date: Thu, 21 Apr 2016 16:02:14 +0200 Subject: [PATCH 08/10] pkt-gen: don't abort on EINTR --- examples/ctrs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ctrs.h b/examples/ctrs.h index 784208eda..40c6b3dfb 100644 --- a/examples/ctrs.h +++ b/examples/ctrs.h @@ -95,7 +95,7 @@ wait_for_next_report(struct timeval *prev, struct timeval *cur, delta.tv_sec = report_interval/1000; delta.tv_usec = (report_interval%1000)*1000; - if (select(0, NULL, NULL, NULL, &delta) < 0) { + if (select(0, NULL, NULL, NULL, &delta) < 0 && errno != EINTR) { perror("select"); abort(); } From 18589737ebb135ee49e9f0db56e2c35e34f9499a Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Wed, 27 Apr 2016 21:28:16 +0200 Subject: [PATCH 09/10] linux: configure: fix typo Fixes #173. --- LINUX/configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LINUX/configure b/LINUX/configure index 6e4353466..a965a16e6 100755 --- a/LINUX/configure +++ b/LINUX/configure @@ -831,7 +831,7 @@ add_test 'have RX_HANDLER_RESULT' <<-EOF #include - static rx_handler_result_t dummy_rx_handler(struct sk_buf **pm) + static rx_handler_result_t dummy_rx_handler(struct sk_buff **pm) { (void)pm; return RX_HANDLER_PASS; From 325dfde8e0e15aa4df5fc8ce702f38e095207ada Mon Sep 17 00:00:00 2001 From: Giuseppe Lettieri Date: Thu, 28 Apr 2016 11:40:29 +0200 Subject: [PATCH 10/10] lb: remove the optimization that was causing reordering problems --- apps/lb/lb.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/apps/lb/lb.c b/apps/lb/lb.c index f26309ff3..25c57c93f 100644 --- a/apps/lb/lb.c +++ b/apps/lb/lb.c @@ -578,7 +578,6 @@ int main(int argc, char **argv) uint32_t free_buf; // Move the packet to the output pipe. - retry: if (nm_ring_space(ring)) { struct netmap_slot *ts = &ring->slot[ring->cur]; free_buf = ts->buf_idx; @@ -591,17 +590,6 @@ int main(int argc, char **argv) goto forward; } - /* try to push packets down to free some space - * in the pipe (no more than once per loop on - * the same pipe, to make sure that there is a - * reasonable amount of time between syncs) - */ - if (port->last_sync != iter) { - port->last_sync = iter; - ioctl(port->nmd->fd, NIOCTXSYNC, NULL); - goto retry; - } - /* use the overflow queue, if available */ if (!oq) { dropped++;