netsniff-ng: tpacketv3: 'fix' packet accounting output
authorDaniel Borkmann <dborkman@redhat.com>
Tue, 25 Jun 2013 10:30:58 +0000 (25 12:30 +0200)
committerDaniel Borkmann <dborkman@redhat.com>
Tue, 25 Jun 2013 10:30:58 +0000 (25 12:30 +0200)
In netsniff-ng, we use tpacketv3 for capturing-only mode. The issue
observed lately is that when using f.e. -n10 or capturing a pcap and
then quitting, the pcap or actually seen number of packets are less
than what the statistics tell us from getsockopt(2).

This is due to the fact that tpacketv3 divides its ring buffer into
blocks of frames. Meaning, while we are traversing block n, the kernel
already fills up block n+1 and following if new packets arrive. While
doing so, it increments packet counters. Thus, when we ^C, we haven't
seen those blocks, so the stats tell us mostly a slightly higher
result. Fix this by adjusting socket stats printing to this fact.

Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
netsniff-ng.c
ring_rx.c
ring_rx.h

index c5570fc..19d4db3 100644 (file)
@@ -479,7 +479,7 @@ static void receive_to_xmit(struct ctx *ctx)
 
        timer_purge();
 
-       sock_rx_net_stats(rx_sock);
+       sock_rx_net_stats(rx_sock, 0);
 
        bpf_release(&bpf_ops);
 
@@ -989,7 +989,7 @@ static void recv_only_or_dump(struct ctx *ctx)
        timersub(&end, &start, &diff);
 
        if (!(ctx->dump_dir && ctx->print_mode == PRINT_NONE)) {
-               sock_rx_net_stats(sock);
+               sock_rx_net_stats(sock, frame_count);
 
                printf("\r%12lu  sec, %lu usec in total\n",
                       diff.tv_sec, diff.tv_usec);
index c674332..96101be 100644 (file)
--- a/ring_rx.c
+++ b/ring_rx.c
@@ -131,7 +131,7 @@ void bind_rx_ring(int sock, struct ring *ring, int ifindex)
        bind_ring_generic(sock, ring, ifindex);
 }
 
-void sock_rx_net_stats(int sock)
+void sock_rx_net_stats(int sock, unsigned long seen)
 {
        int ret;
        bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3;
@@ -147,7 +147,8 @@ void sock_rx_net_stats(int sock)
                uint64_t packets = stats.k3.tp_packets;
                uint64_t drops = stats.k3.tp_drops;
 
-               printf("\r%12ld  packets incoming\n", packets);
+               printf("\r%12ld  packets incoming (%ld unread on exit)\n",
+                      v3 ? seen : packets, v3 ? packets - seen : 0);
                printf("\r%12ld  packets passed filter\n", packets - drops);
                printf("\r%12ld  packets failed filter (out of space)\n", drops);
                if (stats.k3.tp_packets > 0)
index 6f3cdab..8bf439b 100644 (file)
--- a/ring_rx.h
+++ b/ring_rx.h
@@ -19,7 +19,7 @@ extern void alloc_rx_ring_frames(int sock, struct ring *ring);
 extern void bind_rx_ring(int sock, struct ring *ring, int ifindex);
 extern void setup_rx_ring_layout(int sock, struct ring *ring,
                                 unsigned int size, bool jumbo_support, bool v3);
-extern void sock_rx_net_stats(int sock);
+extern void sock_rx_net_stats(int sock, unsigned long seen);
 
 static inline int user_may_pull_from_rx(struct tpacket2_hdr *hdr)
 {