From owner-svn-src-all@FreeBSD.ORG Thu May 3 15:37:06 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6A6C3106564A; Thu, 3 May 2012 15:37:06 +0000 (UTC) (envelope-from luigi@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 53B128FC15; Thu, 3 May 2012 15:37:06 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q43Fb6Sf049337; Thu, 3 May 2012 15:37:06 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q43Fb6Op049335; Thu, 3 May 2012 15:37:06 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <201205031537.q43Fb6Op049335@svn.freebsd.org> From: Luigi Rizzo Date: Thu, 3 May 2012 15:37:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r234956 - head/tools/tools/netmap X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 May 2012 15:37:06 -0000 Author: luigi Date: Thu May 3 15:37:05 2012 New Revision: 234956 URL: http://svn.freebsd.org/changeset/base/234956 Log: - add code to run pkt-gen on top of libpcap so we can see the difference from a native API - add some testing options, such as conditional prefetching and packet copy. Modified: head/tools/tools/netmap/pkt-gen.c Modified: head/tools/tools/netmap/pkt-gen.c ============================================================================== --- head/tools/tools/netmap/pkt-gen.c Thu May 3 15:34:44 2012 (r234955) +++ head/tools/tools/netmap/pkt-gen.c Thu May 3 15:37:05 2012 (r234956) @@ -25,7 +25,7 @@ /* * $FreeBSD$ - * $Id: pkt-gen.c 10637 2012-02-24 16:36:25Z luigi $ + * $Id: pkt-gen.c 10967 2012-05-03 11:29:23Z luigi $ * * Example program to show how to build a multithreaded packet * source/sink using the netmap device. @@ -90,6 +90,36 @@ int verbose = 0; #define SKIP_PAYLOAD 1 /* do not check payload. */ +inline void prefetch (const void *x) +{ + __asm volatile("prefetcht0 %0" :: "m" (*(const unsigned long *)x)); +} + +// XXX only for multiples of 32 bytes, non overlapped. +static inline void +pkt_copy(void *_src, void *_dst, int l) +{ + uint64_t *src = _src; + uint64_t *dst = _dst; +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + if (unlikely(l >= 1024)) { + bcopy(src, dst, l); + return; + } + for (; l > 0; l-=64) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + } +} + + #if EXPERIMENTAL /* Wrapper around `rdtsc' to take reliable timestamps flushing the pipeline */ #define netmap_rdtsc(t) \ @@ -140,6 +170,11 @@ struct glob_arg { int npackets; /* total packets to send */ int nthreads; int cpus; + int options; /* testing */ +#define OPT_PREFETCH 1 +#define OPT_ACCESS 2 +#define OPT_COPY 4 +#define OPT_MEMCPY 8 int use_pcap; pcap_t *p; }; @@ -394,19 +429,35 @@ check_payload(char *p, int psize) */ static int send_packets(struct netmap_ring *ring, struct pkt *pkt, - int size, u_int count, int fill_all) + int size, u_int count, int options) { u_int sent, cur = ring->cur; if (ring->avail < count) count = ring->avail; +#if 0 + if (options & (OPT_COPY | OPT_PREFETCH) ) { + for (sent = 0; sent < count; sent++) { + struct netmap_slot *slot = &ring->slot[cur]; + char *p = NETMAP_BUF(ring, slot->buf_idx); + + prefetch(p); + cur = NETMAP_RING_NEXT(ring, cur); + } + cur = ring->cur; + } +#endif for (sent = 0; sent < count; sent++) { struct netmap_slot *slot = &ring->slot[cur]; char *p = NETMAP_BUF(ring, slot->buf_idx); - if (fill_all) + if (options & OPT_COPY) + pkt_copy(pkt, p, size); + else if (options & OPT_MEMCPY) memcpy(p, pkt, size); + else if (options & OPT_PREFETCH) + prefetch(p); slot->len = size; if (sent == count - 1) @@ -428,8 +479,8 @@ sender_body(void *data) struct netmap_if *nifp = targ->nifp; struct netmap_ring *txring; int i, n = targ->g->npackets / targ->g->nthreads, sent = 0; - int fill_all = 1; - + int options = targ->g->options | OPT_COPY; +D("start"); if (setaffinity(targ->thread, targ->affinity)) goto quit; /* setup poll(2) mechanism. */ @@ -444,9 +495,13 @@ sender_body(void *data) void *pkt = &targ->pkt; pcap_t *p = targ->g->p; - for (; sent < n; sent++) { - if (pcap_inject(p, pkt, size) == -1) - break; + for (i = 0; sent < n; i++) { + if (pcap_inject(p, pkt, size) != -1) + sent++; + if (i > 10000) { + targ->count = sent; + i = 0; + } } } else { while (sent < n) { @@ -461,8 +516,8 @@ sender_body(void *data) /* * scan our queues and send on those with room */ - if (sent > 100000) - fill_all = 0; + if (sent > 100000 && !(targ->g->options & OPT_COPY) ) + options &= ~OPT_COPY; for (i = targ->qfirst; i < targ->qlast; i++) { int m, limit = MIN(n - sent, targ->g->burst); @@ -470,12 +525,12 @@ sender_body(void *data) if (txring->avail == 0) continue; m = send_packets(txring, &targ->pkt, targ->g->pkt_size, - limit, fill_all); + limit, options); sent += m; targ->count = sent; } } - /* Tell the interface that we have new packets. */ + /* flush any remaining packets */ ioctl(fds[0].fd, NIOCTXSYNC, NULL); /* final part: wait all the TX queues to be empty. */ @@ -672,6 +727,7 @@ int main(int arc, char **argv) { int i, fd; + char pcap_errbuf[PCAP_ERRBUF_SIZE]; struct glob_arg g; @@ -696,12 +752,15 @@ main(int arc, char **argv) g.cpus = 1; while ( (ch = getopt(arc, argv, - "i:t:r:l:d:s:D:S:b:c:p:T:w:v")) != -1) { + "i:t:r:l:d:s:D:S:b:c:o:p:PT:w:v")) != -1) { switch(ch) { default: D("bad option %c %s", ch, optarg); usage(); break; + case 'o': + g.options = atoi(optarg); + break; case 'i': /* interface */ ifname = optarg; break; @@ -775,6 +834,26 @@ main(int arc, char **argv) usage(); } + if (td_body == sender_body && g.src_mac == NULL) { + static char mybuf[20] = "ff:ff:ff:ff:ff:ff"; + /* retrieve source mac address. */ + if (source_hwaddr(ifname, mybuf) == -1) { + D("Unable to retrieve source mac"); + // continue, fail later + } + g.src_mac = mybuf; + } + + if (g.use_pcap) { + D("using pcap on %s", ifname); + g.p = pcap_open_live(ifname, 0, 1, 100, pcap_errbuf); + if (g.p == NULL) { + D("cannot open pcap on %s", ifname); + usage(); + } + mmap_addr = NULL; + fd = -1; + } else { bzero(&nmr, sizeof(nmr)); nmr.nr_version = NETMAP_API; /* @@ -811,16 +890,6 @@ main(int arc, char **argv) // continue, fail later } - if (td_body == sender_body && g.src_mac == NULL) { - static char mybuf[20] = "ff:ff:ff:ff:ff:ff"; - /* retrieve source mac address. */ - if (source_hwaddr(ifname, mybuf) == -1) { - D("Unable to retrieve source mac"); - // continue, fail later - } - g.src_mac = mybuf; - } - /* * Map the netmap shared memory: instead of issuing mmap() * inside the body of the threads, we prefer to keep this @@ -869,8 +938,15 @@ main(int arc, char **argv) D("aborting"); usage(); } + } - + if (g.options) { + D("special options:%s%s%s%s\n", + g.options & OPT_PREFETCH ? " prefetch" : "", + g.options & OPT_ACCESS ? " access" : "", + g.options & OPT_MEMCPY ? " memcpy" : "", + g.options & OPT_COPY ? " copy" : ""); + } /* Wait for PHY reset. */ D("Wait %d secs for phy reset", wait_link); sleep(wait_link); @@ -881,7 +957,12 @@ main(int arc, char **argv) signal(SIGINT, sigint_h); if (g.use_pcap) { - // XXX g.p = pcap_open_live(..); + g.p = pcap_open_live(ifname, 0, 1, 100, NULL); + if (g.p == NULL) { + D("cannot open pcap on %s", ifname); + usage(); + } else + D("using pcap %p on %s", g.p, ifname); } targs = calloc(g.nthreads, sizeof(*targs)); @@ -1018,9 +1099,11 @@ main(int arc, char **argv) rx_output(count, delta_t); } + if (g.use_pcap == 0) { ioctl(fd, NIOCUNREGIF, &nmr); munmap(mmap_addr, nmr.nr_memsize); close(fd); + } return (0); }