summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>2013-11-01 21:21:14 +0000
committerluigi <luigi@FreeBSD.org>2013-11-01 21:21:14 +0000
commit41bc3f25be2a8772bd195ab5284f20c73a6cfe54 (patch)
tree62d07ffe9208f3098d5f67c47dd66e29212478b5 /tools
parent42bc4565bed9b35c5ce0004b8e9bcfab2bf04b8d (diff)
downloadFreeBSD-src-41bc3f25be2a8772bd195ab5284f20c73a6cfe54.zip
FreeBSD-src-41bc3f25be2a8772bd195ab5284f20c73a6cfe54.tar.gz
update to the latest netmap snapshot.
This includes the following: - use separate memory regions for VALE ports - locking fixes - some simplifications in the NIC-specific routines - performance improvements for the VALE switch - some new features in the pkt-gen test program - documentation updates There are small API changes that require programs to be recompiled (NETMAP_API has been bumped so you will detect old binaries at runtime). In particular: - struct netmap_slot now is 16 bytes to support an extra pointer, which may save one data copy when using VALE ports or VMs; - the struct netmap_if has two extra fields; MFC after: 3 days
Diffstat (limited to 'tools')
-rw-r--r--tools/tools/netmap/nm_util.c12
-rw-r--r--tools/tools/netmap/pkt-gen.c394
2 files changed, 283 insertions, 123 deletions
diff --git a/tools/tools/netmap/nm_util.c b/tools/tools/netmap/nm_util.c
index 6153603..195b687 100644
--- a/tools/tools/netmap/nm_util.c
+++ b/tools/tools/netmap/nm_util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Luigi Rizzo. All rights reserved.
+ * Copyright (C) 2012-2013 Luigi Rizzo. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -130,20 +130,14 @@ netmap_open(struct my_ring *me, int ringid, int promisc)
req.nr_version = NETMAP_API;
strncpy(req.nr_name, me->ifname, sizeof(req.nr_name));
req.nr_ringid = ringid;
- err = ioctl(fd, NIOCGINFO, &req);
+ err = ioctl(fd, NIOCREGIF, &req);
if (err) {
- D("cannot get info on %s, errno %d ver %d",
- me->ifname, errno, req.nr_version);
+ D("Unable to register %s", me->ifname);
goto error;
}
me->memsize = l = req.nr_memsize;
if (verbose)
D("memsize is %d MB", l>>20);
- err = ioctl(fd, NIOCREGIF, &req);
- if (err) {
- D("Unable to register %s", me->ifname);
- goto error;
- }
if (me->mem == NULL) {
me->mem = mmap(0, l, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
diff --git a/tools/tools/netmap/pkt-gen.c b/tools/tools/netmap/pkt-gen.c
index 901175e..7203eba 100644
--- a/tools/tools/netmap/pkt-gen.c
+++ b/tools/tools/netmap/pkt-gen.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Matteo Landi, Luigi Rizzo. All rights reserved.
+ * Copyright (C) 2011-2013 Matteo Landi, Luigi Rizzo. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,7 +25,7 @@
/*
* $FreeBSD$
- * $Id$
+ * $Id: pkt-gen.c 12346 2013-06-12 17:36:25Z luigi $
*
* Example program to show how to build a multithreaded packet
* source/sink using the netmap device.
@@ -40,7 +40,10 @@
#include <ctype.h> // isprint()
-const char *default_payload="netmap pkt-gen payload\n"
+const char *default_payload="netmap pkt-gen DIRECT payload\n"
+ "http://info.iet.unipi.it/~luigi/netmap/ ";
+
+const char *indirect_payload="netmap pkt-gen indirect payload\n"
"http://info.iet.unipi.it/~luigi/netmap/ ";
int time_second; // support for RD() debugging macro
@@ -58,8 +61,8 @@ struct pkt {
struct ip_range {
char *name;
- struct in_addr start, end, cur;
- uint16_t port0, port1, cur_p;
+ uint32_t start, end; /* same as struct in_addr */
+ uint16_t port0, port1;
};
struct mac_range {
@@ -80,6 +83,7 @@ struct glob_arg {
int burst;
int forever;
int npackets; /* total packets to send */
+ int frags; /* fragments per packet */
int nthreads;
int cpus;
int options; /* testing */
@@ -103,6 +107,8 @@ struct glob_arg {
void *mmap_addr;
int mmap_size;
char *ifname;
+ char *nmr_config;
+ int dummy_send;
};
enum dev_type { DEV_NONE, DEV_NETMAP, DEV_PCAP, DEV_TAP };
@@ -137,45 +143,58 @@ struct targ {
static void
extract_ip_range(struct ip_range *r)
{
- char *p_lo, *p_hi;
- char buf1[16]; // one ip address
+ char *ap, *pp;
+ struct in_addr a;
D("extract IP range from %s", r->name);
- p_lo = index(r->name, ':'); /* do we have ports ? */
- if (p_lo) {
- D(" found ports at %s", p_lo);
- *p_lo++ = '\0';
- p_hi = index(p_lo, '-');
- if (p_hi)
- *p_hi++ = '\0';
- else
- p_hi = p_lo;
- r->port0 = strtol(p_lo, NULL, 0);
- r->port1 = strtol(p_hi, NULL, 0);
- if (r->port1 < r->port0) {
- r->cur_p = r->port0;
- r->port0 = r->port1;
- r->port1 = r->cur_p;
+ r->port0 = r->port1 = 0;
+ r->start = r->end = 0;
+
+ /* the first - splits start/end of range */
+ ap = index(r->name, '-'); /* do we have ports ? */
+ if (ap) {
+ *ap++ = '\0';
+ }
+ /* grab the initial values (mandatory) */
+ pp = index(r->name, ':');
+ if (pp) {
+ *pp++ = '\0';
+ r->port0 = r->port1 = strtol(pp, NULL, 0);
+ };
+ inet_aton(r->name, &a);
+ r->start = r->end = ntohl(a.s_addr);
+ if (ap) {
+ pp = index(ap, ':');
+ if (pp) {
+ *pp++ = '\0';
+ if (*pp)
+ r->port1 = strtol(pp, NULL, 0);
}
- r->cur_p = r->port0;
- D("ports are %d to %d", r->port0, r->port1);
+ if (*ap) {
+ inet_aton(ap, &a);
+ r->end = ntohl(a.s_addr);
+ }
+ }
+ if (r->port0 > r->port1) {
+ uint16_t tmp = r->port0;
+ r->port0 = r->port1;
+ r->port1 = tmp;
}
- p_hi = index(r->name, '-'); /* do we have upper ip ? */
- if (p_hi) {
- *p_hi++ = '\0';
- } else
- p_hi = r->name;
- inet_aton(r->name, &r->start);
- inet_aton(p_hi, &r->end);
- if (r->start.s_addr > r->end.s_addr) {
- r->cur = r->start;
+ if (r->start > r->end) {
+ uint32_t tmp = r->start;
r->start = r->end;
- r->end = r->cur;
+ r->end = tmp;
+ }
+ {
+ struct in_addr a;
+ char buf1[16]; // one ip address
+
+ a.s_addr = htonl(r->end);
+ strncpy(buf1, inet_ntoa(a), sizeof(buf1));
+ a.s_addr = htonl(r->start);
+ D("range is %s:%d to %s:%d",
+ inet_ntoa(a), r->port0, buf1, r->port1);
}
- r->cur = r->start;
- strncpy(buf1, inet_ntoa(r->end), sizeof(buf1));
- D("range is %s %d to %s %d", inet_ntoa(r->start), r->port0,
- buf1, r->port1);
}
static void
@@ -256,6 +275,53 @@ system_ncpus(void)
/*
+ * parse the vale configuration in conf and put it in nmr.
+ * The configuration may consist of 0 to 4 numbers separated
+ * by commas: #tx-slots,#rx-slots,#tx-rinzgs,#rx-rings.
+ * Missing numbers or zeroes stand for default values.
+ * As an additional convenience, if exactly one number
+ * is specified, then this is assigned to bot #tx-slots and #rx-slots.
+ * If there is no 4th number, then the 3rd is assigned to bot #tx-rings
+ * and #rx-rings.
+ */
+void parse_nmr_config(const char* conf, struct nmreq *nmr)
+{
+ char *w, *tok;
+ int i, v;
+
+ nmr->nr_tx_rings = nmr->nr_rx_rings = 0;
+ nmr->nr_tx_slots = nmr->nr_rx_slots = 0;
+ if (conf == NULL || ! *conf)
+ return;
+ w = strdup(conf);
+ for (i = 0, tok = strtok(w, ","); tok; i++, tok = strtok(NULL, ",")) {
+ v = atoi(tok);
+ switch (i) {
+ case 0:
+ nmr->nr_tx_slots = nmr->nr_rx_slots = v;
+ break;
+ case 1:
+ nmr->nr_rx_slots = v;
+ break;
+ case 2:
+ nmr->nr_tx_rings = nmr->nr_rx_rings = v;
+ break;
+ case 3:
+ nmr->nr_rx_rings = v;
+ break;
+ default:
+ D("ignored config: %s", tok);
+ break;
+ }
+ }
+ D("txr %d txd %d rxr %d rxd %d",
+ nmr->nr_tx_rings, nmr->nr_tx_slots,
+ nmr->nr_rx_rings, nmr->nr_rx_slots);
+ free(w);
+}
+
+
+/*
* locate the src mac address for our interface, put it
* into the user-supplied buffer. return 0 if ok, -1 on error.
*/
@@ -361,7 +427,9 @@ dump_payload(char *p, int len, struct netmap_ring *ring, int cur)
/* get the length in ASCII of the length of the packet. */
- printf("ring %p cur %5d len %5d buf %p\n", ring, cur, len, p);
+ printf("ring %p cur %5d [buf %6d flags 0x%04x len %5d]\n",
+ ring, cur, ring->slot[cur].buf_idx,
+ ring->slot[cur].flags, len);
/* hexdump routine */
for (i = 0; i < len; ) {
memset(buf, sizeof(buf), ' ');
@@ -389,6 +457,54 @@ dump_payload(char *p, int len, struct netmap_ring *ring, int cur)
#define uh_sum check
#endif /* linux */
+/*
+ * increment the addressed in the packet,
+ * starting from the least significant field.
+ * DST_IP DST_PORT SRC_IP SRC_PORT
+ */
+static void
+update_addresses(struct pkt *pkt, struct glob_arg *g)
+{
+ uint32_t a;
+ uint16_t p;
+ struct ip *ip = &pkt->ip;
+ struct udphdr *udp = &pkt->udp;
+
+ p = ntohs(udp->uh_sport);
+ if (p < g->src_ip.port1) { /* just inc, no wrap */
+ udp->uh_sport = htons(p + 1);
+ return;
+ }
+ udp->uh_sport = htons(g->src_ip.port0);
+
+ a = ntohl(ip->ip_src.s_addr);
+ if (a < g->src_ip.end) { /* just inc, no wrap */
+ ip->ip_src.s_addr = htonl(a + 1);
+ return;
+ }
+ ip->ip_src.s_addr = htonl(g->src_ip.start);
+
+ udp->uh_sport = htons(g->src_ip.port0);
+ p = ntohs(udp->uh_dport);
+ if (p < g->dst_ip.port1) { /* just inc, no wrap */
+ udp->uh_dport = htons(p + 1);
+ return;
+ }
+ udp->uh_dport = htons(g->dst_ip.port0);
+
+ a = ntohl(ip->ip_dst.s_addr);
+ if (a < g->dst_ip.end) { /* just inc, no wrap */
+ ip->ip_dst.s_addr = htonl(a + 1);
+ return;
+ }
+ ip->ip_dst.s_addr = htonl(g->dst_ip.start);
+
+}
+
+/*
+ * initialize one packet and prepare for the next one.
+ * The copy could be done better instead of repeating it each time.
+ */
static void
initialize_packet(struct targ *targ)
{
@@ -398,9 +514,10 @@ initialize_packet(struct targ *targ)
struct udphdr *udp;
uint16_t paylen = targ->g->pkt_size - sizeof(*eh) - sizeof(struct ip);
const char *payload = targ->g->options & OPT_INDIRECT ?
- "XXXXXXXXXXXXXXXXXXXXXX" : default_payload;
+ indirect_payload : default_payload;
int i, l, l0 = strlen(payload);
+ /* create a nice NUL-terminated string */
for (i = 0; i < paylen;) {
l = min(l0, paylen - i);
bcopy(payload, pkt->body + i, l);
@@ -409,6 +526,7 @@ initialize_packet(struct targ *targ)
pkt->body[i-1] = '\0';
ip = &pkt->ip;
+ /* prepare the headers */
ip->ip_v = IPVERSION;
ip->ip_hl = 5;
ip->ip_id = 0;
@@ -418,22 +536,14 @@ initialize_packet(struct targ *targ)
ip->ip_off = htons(IP_DF); /* Don't fragment */
ip->ip_ttl = IPDEFTTL;
ip->ip_p = IPPROTO_UDP;
- ip->ip_dst.s_addr = targ->g->dst_ip.cur.s_addr;
- if (++targ->g->dst_ip.cur.s_addr > targ->g->dst_ip.end.s_addr)
- targ->g->dst_ip.cur.s_addr = targ->g->dst_ip.start.s_addr;
- ip->ip_src.s_addr = targ->g->src_ip.cur.s_addr;
- if (++targ->g->src_ip.cur.s_addr > targ->g->src_ip.end.s_addr)
- targ->g->src_ip.cur.s_addr = targ->g->src_ip.start.s_addr;
+ ip->ip_dst.s_addr = htonl(targ->g->dst_ip.start);
+ ip->ip_src.s_addr = htonl(targ->g->src_ip.start);
ip->ip_sum = wrapsum(checksum(ip, sizeof(*ip), 0));
udp = &pkt->udp;
- udp->uh_sport = htons(targ->g->src_ip.cur_p);
- if (++targ->g->src_ip.cur_p > targ->g->src_ip.port1)
- targ->g->src_ip.cur_p = targ->g->src_ip.port0;
- udp->uh_dport = htons(targ->g->dst_ip.cur_p);
- if (++targ->g->dst_ip.cur_p > targ->g->dst_ip.port1)
- targ->g->dst_ip.cur_p = targ->g->dst_ip.port0;
+ udp->uh_sport = htons(targ->g->src_ip.port0);
+ udp->uh_dport = htons(targ->g->dst_ip.port0);
udp->uh_ulen = htons(paylen);
/* Magic: taken from sbin/dhclient/packet.c */
udp->uh_sum = wrapsum(checksum(udp, sizeof(*udp),
@@ -461,13 +571,18 @@ initialize_packet(struct targ *targ)
*/
static int
send_packets(struct netmap_ring *ring, struct pkt *pkt,
- int size, u_int count, int options)
+ struct glob_arg *g, u_int count, int options, u_int nfrags)
{
u_int sent, cur = ring->cur;
+ int fcnt;
+ int size = g->pkt_size;
if (ring->avail < count)
count = ring->avail;
-
+ if (count < nfrags) {
+ D("truncating packet, no room for frags %d %d",
+ count, nfrags);
+ }
#if 0
if (options & (OPT_COPY | OPT_PREFETCH) ) {
for (sent = 0; sent < count; sent++) {
@@ -480,25 +595,36 @@ send_packets(struct netmap_ring *ring, struct pkt *pkt,
cur = ring->cur;
}
#endif
- for (sent = 0; sent < count; sent++) {
+ for (fcnt = nfrags, sent = 0; sent < count; sent++) {
struct netmap_slot *slot = &ring->slot[cur];
char *p = NETMAP_BUF(ring, slot->buf_idx);
slot->flags = 0;
- if (options & OPT_DUMP)
- dump_payload(p, size, ring, cur);
if (options & OPT_INDIRECT) {
slot->flags |= NS_INDIRECT;
- *((struct pkt **)(void *)p) = pkt;
- } else if (options & OPT_COPY)
+ slot->ptr = (uint64_t)pkt;
+ } else if (options & OPT_COPY) {
pkt_copy(pkt, p, size);
- else if (options & OPT_MEMCPY)
+ if (fcnt == 1)
+ update_addresses(pkt, g);
+ } else if (options & OPT_MEMCPY) {
memcpy(p, pkt, size);
- else if (options & OPT_PREFETCH)
+ if (fcnt == 1)
+ update_addresses(pkt, g);
+ } else if (options & OPT_PREFETCH) {
prefetch(p);
+ }
+ if (options & OPT_DUMP)
+ dump_payload(p, size, ring, cur);
slot->len = size;
- if (sent == count - 1)
+ if (--fcnt > 0)
+ slot->flags |= NS_MOREFRAG;
+ else
+ fcnt = nfrags;
+ if (sent == count - 1) {
+ slot->flags &= ~NS_MOREFRAG;
slot->flags |= NS_REPORT;
+ }
cur = NETMAP_RING_NEXT(ring, cur);
}
ring->avail -= sent;
@@ -801,6 +927,7 @@ sender_body(void *data)
for (i = 0; !targ->cancel && (n == 0 || sent < n); i++) {
if (pcap_inject(p, pkt, size) != -1)
sent++;
+ update_addresses(pkt, targ->g);
if (i > 10000) {
targ->count = sent;
i = 0;
@@ -814,6 +941,7 @@ sender_body(void *data)
for (i = 0; !targ->cancel && (n == 0 || sent < n); i++) {
if (write(targ->g->main_fd, pkt, size) != -1)
sent++;
+ update_addresses(pkt, targ->g);
if (i > 10000) {
targ->count = sent;
i = 0;
@@ -821,6 +949,8 @@ sender_body(void *data)
}
} else {
int tosend = 0;
+ int frags = targ->g->frags;
+
while (!targ->cancel && (n == 0 || sent < n)) {
if (rate_limit && tosend <= 0) {
@@ -855,11 +985,20 @@ sender_body(void *data)
txring = NETMAP_TXRING(nifp, i);
if (txring->avail == 0)
continue;
- m = send_packets(txring, &targ->pkt, targ->g->pkt_size,
- limit, options);
+ if (frags > 1)
+ limit = ((limit + frags - 1) / frags) * frags;
+
+ m = send_packets(txring, &targ->pkt, targ->g,
+ limit, options, frags);
+ ND("limit %d avail %d frags %d m %d",
+ limit, txring->avail, frags, m);
sent += m;
- tosend -= m;
targ->count = sent;
+ if (rate_limit) {
+ tosend -= m;
+ if (tosend <= 0)
+ break;
+ }
}
}
/* flush any remaining packets */
@@ -909,7 +1048,6 @@ receive_packets(struct netmap_ring *ring, u_int limit, int dump)
struct netmap_slot *slot = &ring->slot[cur];
char *p = NETMAP_BUF(ring, slot->buf_idx);
- slot->flags = OPT_INDIRECT; // XXX
if (dump)
dump_payload(p, slot->len, ring, cur);
@@ -1063,18 +1201,20 @@ usage(void)
"\t-n count number of iterations (can be 0)\n"
"\t-t pkts_to_send also forces tx mode\n"
"\t-r pkts_to_receive also forces rx mode\n"
- "\t-l pkts_size in bytes excluding CRC\n"
- "\t-d dst-ip end with %%n to sweep n addresses\n"
- "\t-s src-ip end with %%n to sweep n addresses\n"
- "\t-D dst-mac end with %%n to sweep n addresses\n"
- "\t-S src-mac end with %%n to sweep n addresses\n"
+ "\t-l pkt_size in bytes excluding CRC\n"
+ "\t-d dst_ip[:port[-dst_ip:port]] single or range\n"
+ "\t-s src_ip[:port[-src_ip:port]] single or range\n"
+ "\t-D dst-mac\n"
+ "\t-S src-mac\n"
"\t-a cpu_id use setaffinity\n"
"\t-b burst size testing, mostly\n"
"\t-c cores cores to use\n"
"\t-p threads processes/threads to use\n"
"\t-T report_ms milliseconds between reports\n"
- "\t-P use libpcap instead of netmap\n"
+ "\t-P use libpcap instead of netmap\n"
"\t-w wait_for_link_time in seconds\n"
+ "\t-R rate in packets per second\n"
+ "\t-X dump payload\n"
"",
cmd);
@@ -1112,6 +1252,7 @@ start_threads(struct glob_arg *g)
strncpy(tifreq.nr_name, g->ifname, sizeof(tifreq.nr_name));
tifreq.nr_version = NETMAP_API;
tifreq.nr_ringid = (g->nthreads > 1) ? (i | NETMAP_HW_RING) : 0;
+ parse_nmr_config(g->nmr_config, &tifreq);
/*
* if we are acting as a receiver only, do not touch the transmit ring.
@@ -1126,8 +1267,10 @@ start_threads(struct glob_arg *g)
D("Unable to register %s", g->ifname);
continue;
}
+ D("memsize is %d MB", tifreq.nr_memsize >> 20);
targs[i].nmr = tifreq;
targs[i].nifp = NETMAP_IF(g->mmap_addr, tifreq.nr_offset);
+ D("nifp flags 0x%x", targs[i].nifp->ni_flags);
/* start threads. */
targs[i].qfirst = (g->nthreads > 1) ? i : 0;
targs[i].qlast = (g->nthreads > 1) ? i+1 :
@@ -1343,9 +1486,11 @@ main(int arc, char **argv)
g.cpus = 1;
g.forever = 1;
g.tx_rate = 0;
+ g.frags = 1;
+ g.nmr_config = "";
while ( (ch = getopt(arc, argv,
- "a:f:n:i:It:r:l:d:s:D:S:b:c:o:p:PT:w:WvR:X")) != -1) {
+ "a:f:F:n:i:It:r:l:d:s:D:S:b:c:o:p:PT:w:WvR:XC:")) != -1) {
struct sf *fn;
switch(ch) {
@@ -1358,6 +1503,15 @@ main(int arc, char **argv)
g.npackets = atoi(optarg);
break;
+ case 'F':
+ i = atoi(optarg);
+ if (i < 1 || i > 63) {
+ D("invalid frags %d [1..63], ignore", i);
+ break;
+ }
+ g.frags = i;
+ break;
+
case 'f':
for (fn = func; fn->key; fn++) {
if (!strcmp(fn->key, optarg))
@@ -1383,6 +1537,8 @@ main(int arc, char **argv)
g.dev_type = DEV_TAP;
else
g.dev_type = DEV_NETMAP;
+ if (!strcmp(g.ifname, "null"))
+ g.dummy_send = 1;
break;
case 'I':
@@ -1454,6 +1610,9 @@ main(int arc, char **argv)
break;
case 'X':
g.options |= OPT_DUMP;
+ break;
+ case 'C':
+ g.nmr_config = strdup(optarg);
}
}
@@ -1507,6 +1666,8 @@ main(int arc, char **argv)
D("cannot open pcap on %s", g.ifname);
usage();
}
+ } else if (g.dummy_send) {
+ D("using a dummy send routine");
} else {
bzero(&nmr, sizeof(nmr));
nmr.nr_version = NETMAP_API;
@@ -1523,20 +1684,36 @@ main(int arc, char **argv)
if (g.main_fd == -1) {
D("Unable to open /dev/netmap");
// fail later
- } else {
- if ((ioctl(g.main_fd, NIOCGINFO, &nmr)) == -1) {
- D("Unable to get if info without name");
- } else {
- D("map size is %d Kb", nmr.nr_memsize >> 10);
- }
- bzero(&nmr, sizeof(nmr));
- nmr.nr_version = NETMAP_API;
- strncpy(nmr.nr_name, g.ifname, sizeof(nmr.nr_name));
- if ((ioctl(g.main_fd, NIOCGINFO, &nmr)) == -1) {
- D("Unable to get if info for %s", g.ifname);
- }
- devqueues = nmr.nr_rx_rings;
}
+ /*
+ * Register the interface on the netmap device: from now on,
+ * we can operate on the network interface without any
+ * interference from the legacy network stack.
+ *
+ * We decide to put the first interface registration here to
+ * give time to cards that take a long time to reset the PHY.
+ */
+ bzero(&nmr, sizeof(nmr));
+ nmr.nr_version = NETMAP_API;
+ strncpy(nmr.nr_name, g.ifname, sizeof(nmr.nr_name));
+ nmr.nr_version = NETMAP_API;
+ parse_nmr_config(g.nmr_config, &nmr);
+ if (ioctl(g.main_fd, NIOCREGIF, &nmr) == -1) {
+ D("Unable to register interface %s", g.ifname);
+ //continue, fail later
+ }
+ ND("%s: txr %d txd %d rxr %d rxd %d", g.ifname,
+ nmr.nr_tx_rings, nmr.nr_tx_slots,
+ nmr.nr_rx_rings, nmr.nr_rx_slots);
+ //if ((ioctl(g.main_fd, NIOCGINFO, &nmr)) == -1) {
+ // D("Unable to get if info without name");
+ //} else {
+ // D("map size is %d Kb", nmr.nr_memsize >> 10);
+ //}
+ if ((ioctl(g.main_fd, NIOCGINFO, &nmr)) == -1) {
+ D("Unable to get if info for %s", g.ifname);
+ }
+ devqueues = nmr.nr_rx_rings;
/* validate provided nthreads. */
if (g.nthreads < 1 || g.nthreads > devqueues) {
@@ -1559,19 +1736,6 @@ main(int arc, char **argv)
// continue, fail later
}
- /*
- * Register the interface on the netmap device: from now on,
- * we can operate on the network interface without any
- * interference from the legacy network stack.
- *
- * We decide to put the first interface registration here to
- * give time to cards that take a long time to reset the PHY.
- */
- nmr.nr_version = NETMAP_API;
- if (ioctl(g.main_fd, NIOCREGIF, &nmr) == -1) {
- D("Unable to register interface %s", g.ifname);
- //continue, fail later
- }
/* Print some debug information. */
@@ -1595,6 +1759,7 @@ main(int arc, char **argv)
}
}
+
if (g.options) {
D("--- SPECIAL OPTIONS:%s%s%s%s%s\n",
g.options & OPT_PREFETCH ? " prefetch" : "",
@@ -1603,23 +1768,24 @@ main(int arc, char **argv)
g.options & OPT_INDIRECT ? " indirect" : "",
g.options & OPT_COPY ? " copy" : "");
}
-
- if (g.tx_rate == 0) {
- g.tx_period.tv_sec = 0;
- g.tx_period.tv_nsec = 0;
- } else if (g.tx_rate == 1) {
- g.tx_period.tv_sec = 1;
- g.tx_period.tv_nsec = 0;
- } else {
- g.tx_period.tv_sec = 0;
+
+ g.tx_period.tv_sec = g.tx_period.tv_nsec = 0;
+ if (g.tx_rate > 0) {
+ /* try to have at least something every second,
+ * reducing the burst size to 0.5s worth of data
+ * (but no less than one full set of fragments)
+ */
+ if (g.burst > g.tx_rate/2)
+ g.burst = g.tx_rate/2;
+ if (g.burst < g.frags)
+ g.burst = g.frags;
g.tx_period.tv_nsec = (1e9 / g.tx_rate) * g.burst;
- if (g.tx_period.tv_nsec > 1000000000) {
- g.tx_period.tv_sec = g.tx_period.tv_nsec / 1000000000;
- g.tx_period.tv_nsec = g.tx_period.tv_nsec % 1000000000;
- }
+ g.tx_period.tv_sec = g.tx_period.tv_nsec / 1000000000;
+ g.tx_period.tv_nsec = g.tx_period.tv_nsec % 1000000000;
}
- D("Sending %d packets every %d.%09d ns",
- g.burst, (int)g.tx_period.tv_sec, (int)g.tx_period.tv_nsec);
+ if (g.td_body == sender_body)
+ D("Sending %d packets every %ld.%09ld s",
+ g.burst, g.tx_period.tv_sec, g.tx_period.tv_nsec);
/* Wait for PHY reset. */
D("Wait %d secs for phy reset", wait_link);
sleep(wait_link);
OpenPOWER on IntegriCloud