summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>2013-06-05 17:37:59 +0000
committerluigi <luigi@FreeBSD.org>2013-06-05 17:37:59 +0000
commit018a784d3f43677b1c8a81718f963490127f4b99 (patch)
tree9457b89bf83127b9f9169f6dbfdc466587aa846b /tools
parent1af0fc6f3bee18ed160a45d684b3eea28ca75e18 (diff)
downloadFreeBSD-src-018a784d3f43677b1c8a81718f963490127f4b99.zip
FreeBSD-src-018a784d3f43677b1c8a81718f963490127f4b99.tar.gz
new features (mostly for testing netmap capabilities)
+ pkt-gen -f rx now remains active even when traffic stops Previous behaviour (exit after 1 second of silence) can be restored with the -W option + the -X option does a hexdump of the content of a packet (both tx and rx). This can be useful to check what goes in and out. + the -I option instructs the sender to use indirect buffers (not really useful other than to test the kernel module in the VALE switch)
Diffstat (limited to 'tools')
-rw-r--r--tools/tools/netmap/pkt-gen.c101
1 files changed, 63 insertions, 38 deletions
diff --git a/tools/tools/netmap/pkt-gen.c b/tools/tools/netmap/pkt-gen.c
index e0a7d95..901175e 100644
--- a/tools/tools/netmap/pkt-gen.c
+++ b/tools/tools/netmap/pkt-gen.c
@@ -38,6 +38,8 @@
#include "nm_util.h"
+#include <ctype.h> // isprint()
+
const char *default_payload="netmap pkt-gen payload\n"
"http://info.iet.unipi.it/~luigi/netmap/ ";
@@ -86,6 +88,8 @@ struct glob_arg {
#define OPT_COPY 4
#define OPT_MEMCPY 8
#define OPT_TS 16 /* add a timestamp */
+#define OPT_INDIRECT 32 /* use indirect buffers, tx only */
+#define OPT_DUMP 64 /* dump rx/tx traffic */
int dev_type;
pcap_t *p;
@@ -346,6 +350,33 @@ wrapsum(u_int32_t sum)
return (htons(sum));
}
+/* Check the payload of the packet for errors (use it for debug).
+ * Look for consecutive ascii representations of the size of the packet.
+ */
+static void
+dump_payload(char *p, int len, struct netmap_ring *ring, int cur)
+{
+ char buf[128];
+ int i, j, i0;
+
+ /* 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);
+ /* hexdump routine */
+ for (i = 0; i < len; ) {
+ memset(buf, sizeof(buf), ' ');
+ sprintf(buf, "%5d: ", i);
+ i0 = i;
+ for (j=0; j < 16 && i < len; i++, j++)
+ sprintf(buf+7+j*3, "%02x ", (uint8_t)(p[i]));
+ i = i0;
+ for (j=0; j < 16 && i < len; i++, j++)
+ sprintf(buf+7+j + 48, "%c",
+ isprint(p[i]) ? p[i] : '.');
+ printf("%s\n", buf);
+ }
+}
+
/*
* Fill a packet with some payload.
* We create a UDP packet so the payload starts at
@@ -357,6 +388,7 @@ wrapsum(u_int32_t sum)
#define uh_ulen len
#define uh_sum check
#endif /* linux */
+
static void
initialize_packet(struct targ *targ)
{
@@ -365,11 +397,13 @@ initialize_packet(struct targ *targ)
struct ip *ip;
struct udphdr *udp;
uint16_t paylen = targ->g->pkt_size - sizeof(*eh) - sizeof(struct ip);
- int i, l, l0 = strlen(default_payload);
+ const char *payload = targ->g->options & OPT_INDIRECT ?
+ "XXXXXXXXXXXXXXXXXXXXXX" : default_payload;
+ int i, l, l0 = strlen(payload);
for (i = 0; i < paylen;) {
l = min(l0, paylen - i);
- bcopy(default_payload, pkt->body + i, l);
+ bcopy(payload, pkt->body + i, l);
i += l;
}
pkt->body[i-1] = '\0';
@@ -415,34 +449,9 @@ initialize_packet(struct targ *targ)
bcopy(&targ->g->src_mac.start, eh->ether_shost, 6);
bcopy(&targ->g->dst_mac.start, eh->ether_dhost, 6);
eh->ether_type = htons(ETHERTYPE_IP);
+ // dump_payload((void *)pkt, targ->g->pkt_size, NULL, 0);
}
-/* Check the payload of the packet for errors (use it for debug).
- * Look for consecutive ascii representations of the size of the packet.
- */
-static void
-check_payload(char *p, int psize)
-{
- char temp[64];
- int n_read, size, sizelen;
-
- /* get the length in ASCII of the length of the packet. */
- sizelen = sprintf(temp, "%d", psize) + 1; // include a whitespace
-
- /* dummy payload. */
- p += 14; /* skip packet header. */
- n_read = 14;
- while (psize - n_read >= sizelen) {
- sscanf(p, "%d", &size);
- if (size != psize) {
- D("Read %d instead of %d", size, psize);
- break;
- }
-
- p += sizelen;
- n_read += sizelen;
- }
-}
/*
@@ -475,7 +484,13 @@ send_packets(struct netmap_ring *ring, struct pkt *pkt,
struct netmap_slot *slot = &ring->slot[cur];
char *p = NETMAP_BUF(ring, slot->buf_idx);
- if (options & OPT_COPY)
+ 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)
pkt_copy(pkt, p, size);
else if (options & OPT_MEMCPY)
memcpy(p, pkt, size);
@@ -756,6 +771,7 @@ sender_body(void *data)
struct timespec tmptime, nexttime = { 0, 0}; // XXX silence compiler
int rate_limit = targ->g->tx_rate;
long long waited = 0;
+
D("start");
if (setaffinity(targ->thread, targ->affinity))
goto quit;
@@ -882,7 +898,7 @@ receive_pcap(u_char *user, const struct pcap_pkthdr * h,
}
static int
-receive_packets(struct netmap_ring *ring, u_int limit, int skip_payload)
+receive_packets(struct netmap_ring *ring, u_int limit, int dump)
{
u_int cur, rx;
@@ -893,8 +909,9 @@ receive_packets(struct netmap_ring *ring, u_int limit, int skip_payload)
struct netmap_slot *slot = &ring->slot[cur];
char *p = NETMAP_BUF(ring, slot->buf_idx);
- if (!skip_payload)
- check_payload(p, slot->len);
+ slot->flags = OPT_INDIRECT; // XXX
+ if (dump)
+ dump_payload(p, slot->len, ring, cur);
cur = NETMAP_RING_NEXT(ring, cur);
}
@@ -946,6 +963,7 @@ receiver_body(void *data)
targ->count++;
}
} else {
+ int dump = targ->g->options & OPT_DUMP;
while (!targ->cancel) {
/* Once we started to receive packets, wait at most 1 seconds
before quitting. */
@@ -962,8 +980,7 @@ receiver_body(void *data)
if (rxring->avail == 0)
continue;
- m = receive_packets(rxring, targ->g->burst,
- SKIP_PAYLOAD);
+ m = receive_packets(rxring, targ->g->burst, dump);
received += m;
}
targ->count = received;
@@ -1324,10 +1341,11 @@ main(int arc, char **argv)
g.burst = 512; // default
g.nthreads = 1;
g.cpus = 1;
+ g.forever = 1;
g.tx_rate = 0;
while ( (ch = getopt(arc, argv,
- "a:f:n:i:t:r:l:d:s:D:S:b:c:o:p:PT:w:WvR:")) != -1) {
+ "a:f:n:i:It:r:l:d:s:D:S:b:c:o:p:PT:w:WvR:X")) != -1) {
struct sf *fn;
switch(ch) {
@@ -1367,6 +1385,10 @@ main(int arc, char **argv)
g.dev_type = DEV_NETMAP;
break;
+ case 'I':
+ g.options |= OPT_INDIRECT; /* XXX use indirect buffer */
+ break;
+
case 't': /* send, deprecated */
D("-t deprecated, please use -f tx -n %s", optarg);
g.td_body = sender_body;
@@ -1399,8 +1421,8 @@ main(int arc, char **argv)
wait_link = atoi(optarg);
break;
- case 'W':
- g.forever = 1; /* do not exit rx even with no traffic */
+ case 'W': /* XXX changed default */
+ g.forever = 0; /* do not exit rx even with no traffic */
break;
case 'b': /* burst */
@@ -1430,6 +1452,8 @@ main(int arc, char **argv)
case 'R':
g.tx_rate = atoi(optarg);
break;
+ case 'X':
+ g.options |= OPT_DUMP;
}
}
@@ -1572,10 +1596,11 @@ main(int arc, char **argv)
}
if (g.options) {
- D("special options:%s%s%s%s\n",
+ D("--- SPECIAL OPTIONS:%s%s%s%s%s\n",
g.options & OPT_PREFETCH ? " prefetch" : "",
g.options & OPT_ACCESS ? " access" : "",
g.options & OPT_MEMCPY ? " memcpy" : "",
+ g.options & OPT_INDIRECT ? " indirect" : "",
g.options & OPT_COPY ? " copy" : "");
}
OpenPOWER on IntegriCloud