summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorVincenzo Maffione <vmaffione@FreeBSD.org>2020-11-22 09:20:08 +0000
committerVincenzo Maffione <vmaffione@FreeBSD.org>2020-11-22 09:20:08 +0000
commit4bfe1a4fe2f86000c643beac89f3a9e0a0df8ab7 (patch)
treedc5059236c26a416bb72f16c249039e3baaff824 /tools
parentecfd9756ced466e9a2af7167ddeb874fe41ae5c5 (diff)
downloadsrc-test2-4bfe1a4fe2f86000c643beac89f3a9e0a0df8ab7.tar.gz
src-test2-4bfe1a4fe2f86000c643beac89f3a9e0a0df8ab7.zip
netmap: pkt-gen: switch to libnetmap
Use the newer libnetmap (included in base) rather than the older nm_open()/nm_close() defined in netmap_user.h
Notes
Notes: svn path=/head/; revision=367932
Diffstat (limited to 'tools')
-rw-r--r--tools/tools/netmap/pkt-gen.c215
1 files changed, 120 insertions, 95 deletions
diff --git a/tools/tools/netmap/pkt-gen.c b/tools/tools/netmap/pkt-gen.c
index 56fbb57cdd9a..e6237b8ba281 100644
--- a/tools/tools/netmap/pkt-gen.c
+++ b/tools/tools/netmap/pkt-gen.c
@@ -38,35 +38,39 @@
*/
#define _GNU_SOURCE /* for CPU_SET() */
-#include <stdio.h>
-#define NETMAP_WITH_LIBS
-#include <net/netmap_user.h>
-
-#include <ctype.h> // isprint()
-#include <unistd.h> // sysconf()
-#include <sys/poll.h>
#include <arpa/inet.h> /* ntohs */
-#ifndef _WIN32
-#include <sys/sysctl.h> /* sysctl */
-#endif
+#include <assert.h>
+#include <ctype.h> // isprint()
+#include <errno.h>
+#include <fcntl.h>
#include <ifaddrs.h> /* getifaddrs */
+#include <libnetmap.h>
+#include <math.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
-#include <netinet/udp.h>
#include <netinet/ip6.h>
+#include <netinet/udp.h>
+#ifndef NO_PCAP
+#include <pcap/pcap.h>
+#endif
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#if !defined(_WIN32) && !defined(linux)
+#include <sys/sysctl.h> /* sysctl */
+#endif
+#include <sys/types.h>
+#include <unistd.h> // sysconf()
#ifdef linux
#define IPV6_VERSION 0x60
#define IPV6_DEFHLIM 64
#endif
-#include <assert.h>
-#include <math.h>
-
-#include <pthread.h>
-
-#ifndef NO_PCAP
-#include <pcap/pcap.h>
-#endif
#include "ctrs.h"
@@ -236,7 +240,8 @@ struct mac_range {
};
/* ifname can be netmap:foo-xxxx */
-#define MAX_IFNAMELEN 64 /* our buffer for ifname */
+#define MAX_IFNAMELEN 512 /* our buffer for ifname */
+//#define MAX_PKTSIZE 1536
#define MAX_PKTSIZE MAX_BODYSIZE /* XXX: + IP_HDR + ETH_HDR */
/* compact timestamp to fit into 60 byte packet. (enough to obtain RTT) */
@@ -288,7 +293,8 @@ struct glob_arg {
int affinity;
int main_fd;
- struct nm_desc *nmd;
+ struct nmport_d *nmd;
+ uint32_t orig_mode;
int report_interval; /* milliseconds between prints */
void *(*td_body)(void *);
int td_type;
@@ -322,7 +328,7 @@ struct targ {
int completed;
int cancel;
int fd;
- struct nm_desc *nmd;
+ struct nmport_d *nmd;
/* these ought to be volatile, but they are
* only sampled and errors should not accumulate
*/
@@ -515,16 +521,20 @@ extract_mac_range(struct mac_range *r)
static int
get_if_mtu(const struct glob_arg *g)
{
- char ifname[IFNAMSIZ];
struct ifreq ifreq;
int s, ret;
+ const char *ifname = g->nmd->hdr.nr_name;
+ size_t len;
+
+ if (!strncmp(g->ifname, "netmap:", 7) && !strchr(ifname, '{')
+ && !strchr(ifname, '}')) {
- if (!strncmp(g->ifname, "netmap:", 7) && !strchr(g->ifname, '{')
- && !strchr(g->ifname, '}')) {
- /* Parse the interface name and ask the kernel for the
- * MTU value. */
- strncpy(ifname, g->ifname+7, IFNAMSIZ-1);
- ifname[strcspn(ifname, "-*^{}/@")] = '\0';
+ len = strlen(ifname);
+
+ if (len > IFNAMSIZ) {
+ D("'%s' too long, cannot ask for MTU", ifname);
+ return -1;
+ }
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
@@ -533,13 +543,15 @@ get_if_mtu(const struct glob_arg *g)
}
memset(&ifreq, 0, sizeof(ifreq));
- strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);
+ memcpy(ifreq.ifr_name, ifname, len);
ret = ioctl(s, SIOCGIFMTU, &ifreq);
if (ret) {
D("ioctl(SIOCGIFMTU) failed: %s", strerror(errno));
}
+ close(s);
+
return ifreq.ifr_mtu;
}
@@ -620,7 +632,7 @@ system_ncpus(void)
* and #rx-rings.
*/
static int
-parse_nmr_config(const char* conf, struct nmreq *nmr)
+parse_nmr_config(const char* conf, struct nmreq_register *nmr)
{
char *w, *tok;
int i, v;
@@ -654,9 +666,7 @@ parse_nmr_config(const char* conf, struct nmreq *nmr)
nmr->nr_tx_rings, nmr->nr_tx_slots,
nmr->nr_rx_rings, nmr->nr_rx_slots);
free(w);
- return (nmr->nr_tx_rings || nmr->nr_tx_slots ||
- nmr->nr_rx_rings || nmr->nr_rx_slots) ?
- NM_OPEN_RING_CFG : 0;
+ return 0;
}
@@ -1108,20 +1118,22 @@ initialize_packet(struct targ *targ)
static void
get_vnet_hdr_len(struct glob_arg *g)
{
- struct nmreq req;
+ struct nmreq_header hdr;
+ struct nmreq_port_hdr ph;
int err;
- memset(&req, 0, sizeof(req));
- bcopy(g->nmd->req.nr_name, req.nr_name, sizeof(req.nr_name));
- req.nr_version = NETMAP_API;
- req.nr_cmd = NETMAP_VNET_HDR_GET;
- err = ioctl(g->main_fd, NIOCREGIF, &req);
+ hdr = g->nmd->hdr; /* copy name and version */
+ hdr.nr_reqtype = NETMAP_REQ_PORT_HDR_GET;
+ hdr.nr_options = 0;
+ memset(&ph, 0, sizeof(ph));
+ hdr.nr_body = (uintptr_t)&ph;
+ err = ioctl(g->main_fd, NIOCCTRL, &hdr);
if (err) {
D("Unable to get virtio-net header length");
return;
}
- g->virt_header = req.nr_arg1;
+ g->virt_header = ph.nr_hdr_len;
if (g->virt_header) {
D("Port requires virtio-net header, length = %d",
g->virt_header);
@@ -1132,17 +1144,18 @@ static void
set_vnet_hdr_len(struct glob_arg *g)
{
int err, l = g->virt_header;
- struct nmreq req;
+ struct nmreq_header hdr;
+ struct nmreq_port_hdr ph;
if (l == 0)
return;
- memset(&req, 0, sizeof(req));
- bcopy(g->nmd->req.nr_name, req.nr_name, sizeof(req.nr_name));
- req.nr_version = NETMAP_API;
- req.nr_cmd = NETMAP_BDG_VNET_HDR;
- req.nr_arg1 = l;
- err = ioctl(g->main_fd, NIOCREGIF, &req);
+ hdr = g->nmd->hdr; /* copy name and version */
+ hdr.nr_reqtype = NETMAP_REQ_PORT_HDR_SET;
+ hdr.nr_options = 0;
+ memset(&ph, 0, sizeof(ph));
+ hdr.nr_body = (uintptr_t)&ph;
+ err = ioctl(g->main_fd, NIOCCTRL, &hdr);
if (err) {
D("Unable to set virtio-net header length %d", l);
}
@@ -2480,7 +2493,7 @@ usage(int errcode)
exit(errcode);
}
-static void
+static int
start_threads(struct glob_arg *g) {
int i;
@@ -2500,31 +2513,43 @@ start_threads(struct glob_arg *g) {
memcpy(t->seed, &seed, sizeof(t->seed));
if (g->dev_type == DEV_NETMAP) {
- struct nm_desc nmd = *g->nmd; /* copy, we overwrite ringid */
- uint64_t nmd_flags = 0;
- nmd.self = &nmd;
+ int m = -1;
+
+ /*
+ * if the user wants both HW and SW rings, we need to
+ * know when to switch from NR_REG_ONE_NIC to NR_REG_ONE_SW
+ */
+ if (g->orig_mode == NR_REG_NIC_SW) {
+ m = (g->td_type == TD_TYPE_RECEIVER ?
+ g->nmd->reg.nr_rx_rings :
+ g->nmd->reg.nr_tx_rings);
+ }
if (i > 0) {
+ int j;
/* the first thread uses the fd opened by the main
* thread, the other threads re-open /dev/netmap
*/
- if (g->nthreads > 1) {
- nmd.req.nr_flags =
- g->nmd->req.nr_flags & ~NR_REG_MASK;
- nmd.req.nr_flags |= NR_REG_ONE_NIC;
- nmd.req.nr_ringid = i;
+ t->nmd = nmport_clone(g->nmd);
+ if (t->nmd == NULL)
+ return -1;
+
+ j = i;
+ if (m > 0 && j >= m) {
+ /* switch to the software rings */
+ t->nmd->reg.nr_mode = NR_REG_ONE_SW;
+ j -= m;
}
+ t->nmd->reg.nr_ringid = j & NETMAP_RING_MASK;
/* Only touch one of the rings (rx is already ok) */
if (g->td_type == TD_TYPE_RECEIVER)
- nmd_flags |= NETMAP_NO_TX_POLL;
+ t->nmd->reg.nr_flags |= NETMAP_NO_TX_POLL;
/* register interface. Override ifname and ringid etc. */
- t->nmd = nm_open(t->g->ifname, NULL, nmd_flags |
- NM_OPEN_IFNAME | NM_OPEN_NO_MMAP, &nmd);
- if (t->nmd == NULL) {
- D("Unable to open %s: %s",
- t->g->ifname, strerror(errno));
- continue;
+ if (nmport_open_desc(t->nmd) < 0) {
+ nmport_undo_prepare(t->nmd);
+ t->nmd = NULL;
+ return -1;
}
} else {
t->nmd = g->nmd;
@@ -2556,6 +2581,7 @@ start_threads(struct glob_arg *g) {
t->used = 0;
}
}
+ return 0;
}
static void
@@ -2655,7 +2681,7 @@ main_thread(struct glob_arg *g)
if (targs[i].used)
pthread_join(targs[i].thread, NULL); /* blocking */
if (g->dev_type == DEV_NETMAP) {
- nm_close(targs[i].nmd);
+ nmport_close(targs[i].nmd);
targs[i].nmd = NULL;
} else {
close(targs[i].fd);
@@ -3078,20 +3104,13 @@ main(int arc, char **argv)
} else if (g.dummy_send) { /* but DEV_NETMAP */
D("using a dummy send routine");
} else {
- struct nm_desc base_nmd;
- char errmsg[MAXERRMSG];
- u_int flags;
-
- bzero(&base_nmd, sizeof(base_nmd));
+ g.nmd = nmport_prepare(g.ifname);
+ if (g.nmd == NULL)
+ goto out;
- parse_nmr_config(g.nmr_config, &base_nmd.req);
+ parse_nmr_config(g.nmr_config, &g.nmd->reg);
- base_nmd.req.nr_flags |= NR_ACCEPT_VNET_HDR;
-
- if (nm_parse(g.ifname, &base_nmd, errmsg) < 0) {
- D("Invalid name '%s': %s", g.ifname, errmsg);
- goto out;
- }
+ g.nmd->reg.nr_flags |= NR_ACCEPT_VNET_HDR;
/*
* Open the netmap device using nm_open().
@@ -3100,20 +3119,25 @@ main(int arc, char **argv)
* which in turn may take some time for the PHY to
* reconfigure. We do the open here to have time to reset.
*/
- flags = NM_OPEN_IFNAME | NM_OPEN_ARG1 | NM_OPEN_ARG2 |
- NM_OPEN_ARG3 | NM_OPEN_RING_CFG;
+ g.orig_mode = g.nmd->reg.nr_mode;
if (g.nthreads > 1) {
- base_nmd.req.nr_flags &= ~NR_REG_MASK;
- base_nmd.req.nr_flags |= NR_REG_ONE_NIC;
- base_nmd.req.nr_ringid = 0;
+ switch (g.orig_mode) {
+ case NR_REG_ALL_NIC:
+ case NR_REG_NIC_SW:
+ g.nmd->reg.nr_mode = NR_REG_ONE_NIC;
+ break;
+ case NR_REG_SW:
+ g.nmd->reg.nr_mode = NR_REG_ONE_SW;
+ break;
+ default:
+ break;
+ }
+ g.nmd->reg.nr_ringid = 0;
}
- g.nmd = nm_open(g.ifname, NULL, flags, &base_nmd);
- if (g.nmd == NULL) {
- D("Unable to open %s: %s", g.ifname, strerror(errno));
+ if (nmport_open_desc(g.nmd) < 0)
goto out;
- }
g.main_fd = g.nmd->fd;
- D("mapped %luKB at %p", (unsigned long)(g.nmd->req.nr_memsize>>10),
+ ND("mapped %luKB at %p", (unsigned long)(g.nmd->req.nr_memsize>>10),
g.nmd->mem);
if (g.virt_header) {
@@ -3128,9 +3152,9 @@ main(int arc, char **argv)
/* get num of queues in tx or rx */
if (g.td_type == TD_TYPE_SENDER)
- devqueues = g.nmd->req.nr_tx_rings;
+ devqueues = g.nmd->reg.nr_tx_rings + g.nmd->reg.nr_host_tx_rings;
else
- devqueues = g.nmd->req.nr_rx_rings;
+ devqueues = g.nmd->reg.nr_rx_rings + g.nmd->reg.nr_host_rx_rings;
/* validate provided nthreads. */
if (g.nthreads < 1 || g.nthreads > devqueues) {
@@ -3150,17 +3174,17 @@ main(int arc, char **argv)
if (verbose) {
struct netmap_if *nifp = g.nmd->nifp;
- struct nmreq *req = &g.nmd->req;
+ struct nmreq_register *req = &g.nmd->reg;
- D("nifp at offset %d, %d tx %d rx region %d",
+ D("nifp at offset %"PRIu64", %d tx %d rx region %d",
req->nr_offset, req->nr_tx_rings, req->nr_rx_rings,
- req->nr_arg2);
- for (i = 0; i <= req->nr_tx_rings; i++) {
+ req->nr_mem_id);
+ for (i = 0; i < req->nr_tx_rings + req->nr_host_tx_rings; i++) {
struct netmap_ring *ring = NETMAP_TXRING(nifp, i);
D(" TX%d at 0x%p slots %d", i,
(void *)((char *)ring - (char *)nifp), ring->num_slots);
}
- for (i = 0; i <= req->nr_rx_rings; i++) {
+ for (i = 0; i < req->nr_rx_rings + req->nr_host_rx_rings; i++) {
struct netmap_ring *ring = NETMAP_RXRING(nifp, i);
D(" RX%d at 0x%p slots %d", i,
(void *)((char *)ring - (char *)nifp), ring->num_slots);
@@ -3230,7 +3254,8 @@ out:
if (pthread_sigmask(SIG_BLOCK, &ss, NULL) < 0) {
D("failed to block SIGINT: %s", strerror(errno));
}
- start_threads(&g);
+ if (start_threads(&g) < 0)
+ return 1;
/* Install the handler and re-enable SIGINT for the main thread */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sigint_h;