diff options
author | luigi <luigi@FreeBSD.org> | 2012-05-03 15:34:44 +0000 |
---|---|---|
committer | luigi <luigi@FreeBSD.org> | 2012-05-03 15:34:44 +0000 |
commit | 5bceb861dc18e89e40f6c95ab9c10ce7bd87ed29 (patch) | |
tree | d964b403b5a6016c0d5b29feacb371a1c7cab42c /tools | |
parent | 48f59d28b651092680a3d14a183ef5b108f766c9 (diff) | |
download | FreeBSD-src-5bceb861dc18e89e40f6c95ab9c10ce7bd87ed29.zip FreeBSD-src-5bceb861dc18e89e40f6c95ab9c10ce7bd87ed29.tar.gz |
- correct a bug in pcap_dispatch(): a count of 0 means infinity.
- in pcap_dispatch(), issue a prefetch on the buffer before the
callback, this may save a little bit of time if the client
is very fast.
- in pcap_inject(), use a fast copy routine, which also helps
saving a few nanoseconds with fast clients.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/tools/netmap/pcap.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/tools/tools/netmap/pcap.c b/tools/tools/netmap/pcap.c index 06bb173..2479203 100644 --- a/tools/tools/netmap/pcap.c +++ b/tools/tools/netmap/pcap.c @@ -49,6 +49,34 @@ int verbose = 0; __FUNCTION__, __LINE__, ##__VA_ARGS__); \ } while (0) +inline void prefetch (const void *x) +{ + __asm volatile("prefetcht0 %0" :: "m" (*(const unsigned long *)x)); +} + +// XXX only for multiples of 64 bytes, non overlapped. +static inline void +pkt_copy(const void *_src, void *_dst, int l) +{ + const 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++; + } +} /* * We redefine here a number of structures that are in pcap.h @@ -479,21 +507,21 @@ pcap_setfilter(__unused pcap_t *p, __unused struct bpf_program *fp) int pcap_datalink(__unused pcap_t *p) { - D(""); + D("returns 1"); return 1; // ethernet } const char * pcap_datalink_val_to_name(int dlt) { - D("%d", dlt); + D("%d returns DLT_EN10MB", dlt); return "DLT_EN10MB"; } const char * pcap_datalink_val_to_description(int dlt) { - D("%d", dlt); + D("%d returns Ethernet link", dlt); return "Ethernet link"; } @@ -525,7 +553,8 @@ pcap_open_live(const char *device, __unused int snaplen, { struct my_ring *me; - D("request to open %s", device); + D("request to open %s snaplen %d promisc %d timeout %dms", + device, snaplen, promisc, to_ms); me = calloc(1, sizeof(*me)); if (me == NULL) { D("failed to allocate struct for %s", device); @@ -610,6 +639,8 @@ pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) u_int si; ND("cnt %d", cnt); + if (cnt == 0) + cnt = -1; /* scan all rings */ for (si = me->begin; si < me->end; si++) { struct netmap_ring *ring = NETMAP_RXRING(me->nifp, si); @@ -617,6 +648,10 @@ pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) if (ring->avail == 0) continue; me->hdr.ts = ring->ts; + /* + * XXX a proper prefetch should be done as + * prefetch(i); callback(i-1); ... + */ while ((cnt == -1 || cnt != got) && ring->avail > 0) { u_int i = ring->cur; u_int idx = ring->slot[i].buf_idx; @@ -626,6 +661,7 @@ pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) sleep(2); } u_char *buf = (u_char *)NETMAP_BUF(ring, idx); + prefetch(buf); me->hdr.len = me->hdr.caplen = ring->slot[i].len; // D("call %p len %d", p, me->hdr.len); callback(user, &me->hdr, buf); @@ -660,7 +696,7 @@ pcap_inject(pcap_t *p, const void *buf, size_t size) } u_char *dst = (u_char *)NETMAP_BUF(ring, idx); ring->slot[i].len = size; - bcopy(buf, dst, size); + pkt_copy(buf, dst, size); ring->cur = NETMAP_RING_NEXT(ring, i); ring->avail--; // if (ring->avail == 0) ioctl(me->fd, NIOCTXSYNC, NULL); |