Allow to collect rx stats for multiple pcap mode, by storing
them in separated variables before switch to the next pcap file.

It allows to have the one approach when dump for single or multiple
pcap(s) mode.

Signed-off-by: Vadim Kochan <vadi...@gmail.com>
---
 netsniff-ng.c | 115 ++++++++++++++++++++++++++++++++++------------------------
 ring_rx.c     |  22 +----------
 ring_rx.h     |   2 +-
 3 files changed, 70 insertions(+), 69 deletions(-)

diff --git a/netsniff-ng.c b/netsniff-ng.c
index 57edc43..4b20d86 100644
--- a/netsniff-ng.c
+++ b/netsniff-ng.c
@@ -22,6 +22,7 @@
 #include <stdbool.h>
 #include <pthread.h>
 #include <fcntl.h>
+#include <inttypes.h>
 
 #include "ring_rx.h"
 #include "ring_tx.h"
@@ -64,6 +65,8 @@ struct ctx {
        gid_t gid;
        uint32_t link_type, magic;
        uint32_t fanout_group, fanout_type;
+       uint64_t pkts_seen, pkts_recvd, pkts_drops;
+       uint64_t pkts_recvd_last, pkts_drops_last;
 };
 
 static volatile sig_atomic_t sigint = 0, sighup = 0;
@@ -203,6 +206,35 @@ static inline void setup_rfmon_mac80211_dev(struct ctx 
*ctx, char **rfmon_dev)
        panic_handler_add(on_panic_del_rfmon, *rfmon_dev);
 }
 
+static void update_rx_stats(struct ctx *ctx, int sock, bool is_v3)
+{
+       uint64_t packets = 0, drops = 0;
+
+       get_rx_net_stats(sock, &packets, &drops, is_v3);
+
+       ctx->pkts_recvd += packets;
+       ctx->pkts_drops += drops;
+       ctx->pkts_recvd_last = packets;
+       ctx->pkts_drops_last = drops;
+}
+
+static void dump_rx_stats(struct ctx *ctx, int sock, bool is_v3)
+{
+       update_rx_stats(ctx, sock, is_v3);
+
+       printf("\r%12"PRIu64"  packets incoming (%"PRIu64" unread on exit)\n",
+                       is_v3 ? ctx->pkts_seen : ctx->pkts_recvd,
+                       is_v3 ? ctx->pkts_recvd - ctx->pkts_seen : 0);
+       printf("\r%12"PRIu64"  packets passed filter\n",
+                       ctx->pkts_recvd - ctx->pkts_drops);
+       printf("\r%12"PRIu64"  packets failed filter (out of space)\n",
+                       ctx->pkts_drops);
+
+       if (ctx->pkts_recvd  > 0)
+               printf("\r%12.4lf%% packet droprate\n",
+                       (1.0 * ctx->pkts_drops / ctx->pkts_recvd) * 100.0);
+}
+
 static void pcap_to_xmit(struct ctx *ctx)
 {
        uint8_t *out = NULL;
@@ -376,7 +408,6 @@ static void receive_to_xmit(struct ctx *ctx)
        int rx_sock, ifindex_in, ifindex_out, ret;
        size_t size_in, size_out;
        unsigned int it_in = 0, it_out = 0;
-       unsigned long frame_count = 0;
        struct frame_map *hdr_in, *hdr_out;
        struct ring tx_ring, rx_ring;
        struct pollfd rx_poll;
@@ -428,7 +459,7 @@ static void receive_to_xmit(struct ctx *ctx)
                        hdr_in = rx_ring.frames[it_in].iov_base;
                        in = ((uint8_t *) hdr_in) + hdr_in->tp_h.tp_mac;
 
-                       frame_count++;
+                       ctx->pkts_seen++;
 
                        if (ctx->packet_type != -1)
                                if (ctx->packet_type != 
hdr_in->s_ll.sll_pkttype)
@@ -465,14 +496,14 @@ static void receive_to_xmit(struct ctx *ctx)
 
                        show_frame_hdr(in, hdr_in->tp_h.tp_snaplen,
                                       ctx->link_type, hdr_in, ctx->print_mode,
-                                      frame_count);
+                                      ctx->pkts_seen);
 
                        dissector_entry_point(in, hdr_in->tp_h.tp_snaplen,
                                              ctx->link_type, ctx->print_mode,
                                              &hdr_in->s_ll);
 
                        if (frame_count_max != 0) {
-                               if (frame_count >= frame_count_max) {
+                               if (ctx->pkts_seen >= frame_count_max) {
                                        sigint = 1;
                                        break;
                                }
@@ -499,7 +530,7 @@ next:
 out:
        timer_purge();
 
-       sock_rx_net_stats(rx_sock, 0);
+       dump_rx_stats(ctx, rx_sock, false);
 
        bpf_release(&bpf_ops);
 
@@ -844,26 +875,8 @@ static int begin_single_pcap_file(struct ctx *ctx)
        return fd;
 }
 
-static void print_pcap_file_stats(int sock, struct ctx *ctx)
-{
-       int ret;
-       struct tpacket_stats kstats;
-       socklen_t slen = sizeof(kstats);
-
-       fmemset(&kstats, 0, sizeof(kstats));
-
-       ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen);
-       if (unlikely(ret))
-               panic("Cannot get packet statistics!\n");
-
-       if (ctx->print_mode == PRINT_NONE) {
-               printf(".(+%u/-%u)", kstats.tp_packets - kstats.tp_drops,
-                      kstats.tp_drops);
-               fflush(stdout);
-       }
-}
-
-static void update_pcap_next_dump(struct ctx *ctx, unsigned long snaplen, int 
*fd, int sock)
+static void update_pcap_next_dump(struct ctx *ctx, unsigned long snaplen,
+               int *fd, int sock, bool is_v3)
 {
        if (!dump_to_pcap(ctx))
                return;
@@ -888,14 +901,18 @@ static void update_pcap_next_dump(struct ctx *ctx, 
unsigned long snaplen, int *f
                *fd = next_multi_pcap_file(ctx, *fd);
                next_dump = false;
 
-               if (ctx->verbose)
-                       print_pcap_file_stats(sock, ctx);
+               update_rx_stats(ctx, sock, is_v3);
+
+               if (ctx->verbose && ctx->print_mode == PRINT_NONE)
+                       printf(".(+%lu/-%lu)",
+                               ctx->pkts_recvd_last - ctx->pkts_drops_last,
+                               ctx->pkts_drops_last);
        }
 }
 
 #ifdef HAVE_TPACKET3
 static void walk_t3_block(struct block_desc *pbd, struct ctx *ctx,
-                         int sock, int *fd, unsigned long *frame_count)
+                         int sock, int *fd)
 {
        int num_pkts = pbd->h1.num_pkts, i;
        struct tpacket3_hdr *hdr;
@@ -912,7 +929,7 @@ static void walk_t3_block(struct block_desc *pbd, struct 
ctx *ctx,
                        if (ctx->packet_type != sll->sll_pkttype)
                                goto next;
 
-               (*frame_count)++;
+               ctx->pkts_seen++;
 
                if (dump_to_pcap(ctx)) {
                        int ret;
@@ -926,7 +943,7 @@ static void walk_t3_block(struct block_desc *pbd, struct 
ctx *ctx,
                }
 
                __show_frame_hdr(packet, hdr->tp_snaplen, ctx->link_type, sll,
-                                hdr, ctx->print_mode, true, *frame_count);
+                                hdr, ctx->print_mode, true, ctx->pkts_seen);
 
                dissector_entry_point(packet, hdr->tp_snaplen, ctx->link_type,
                                      ctx->print_mode, sll);
@@ -935,13 +952,13 @@ next:
                sll = (void *) ((uint8_t *) hdr + TPACKET_ALIGN(sizeof(*hdr)));
 
                if (frame_count_max != 0) {
-                       if (unlikely(*frame_count >= frame_count_max)) {
+                       if (unlikely(ctx->pkts_seen >= frame_count_max)) {
                                sigint = 1;
                                break;
                        }
                }
 
-               update_pcap_next_dump(ctx, hdr->tp_snaplen, fd, sock);
+               update_pcap_next_dump(ctx, hdr->tp_snaplen, fd, sock, true);
        }
 }
 #endif /* HAVE_TPACKET3 */
@@ -956,7 +973,7 @@ static void recv_only_or_dump(struct ctx *ctx)
        struct pollfd rx_poll;
        struct sock_fprog bpf_ops;
        struct timeval start, end, diff;
-       unsigned long frame_count = 0;
+       bool is_v3 = is_defined(HAVE_TPACKET3);
 
        sock = pf_socket_type(ctx->link_type);
 
@@ -976,7 +993,7 @@ static void recv_only_or_dump(struct ctx *ctx)
                        printf("HW timestamping enabled\n");
        }
 
-       ring_rx_setup(&rx_ring, sock, size, ifindex, &rx_poll, 
is_defined(HAVE_TPACKET3), true,
+       ring_rx_setup(&rx_ring, sock, size, ifindex, &rx_poll, is_v3, true,
                      ctx->verbose, ctx->fanout_group, ctx->fanout_type);
 
        dissector_init_all(ctx->print_mode);
@@ -1023,7 +1040,7 @@ static void recv_only_or_dump(struct ctx *ctx)
                struct block_desc *pbd;
 
                while (user_may_pull_from_rx_block((pbd = 
rx_ring.frames[it].iov_base))) {
-                       walk_t3_block(pbd, ctx, sock, &fd, &frame_count);
+                       walk_t3_block(pbd, ctx, sock, &fd);
 
                        kernel_may_pull_from_rx_block(pbd);
                        it = (it + 1) % rx_ring.layout3.tp_block_nr;
@@ -1041,11 +1058,11 @@ static void recv_only_or_dump(struct ctx *ctx)
                                if (ctx->packet_type != hdr->s_ll.sll_pkttype)
                                        goto next;
 
-                       frame_count++;
+                       ctx->pkts_seen++;
 
                        if (unlikely(ring_frame_size(&rx_ring) < 
hdr->tp_h.tp_snaplen)) {
                                /* XXX: silently ignore for now. We used to
-                                * report them with sock_rx_net_stats()  */
+                                * report them with dump_rx_stats()  */
                                goto next;
                        }
 
@@ -1060,14 +1077,14 @@ static void recv_only_or_dump(struct ctx *ctx)
 
                        show_frame_hdr(packet, hdr->tp_h.tp_snaplen,
                                       ctx->link_type, hdr, ctx->print_mode,
-                                      frame_count);
+                                      ctx->pkts_seen);
 
                        dissector_entry_point(packet, hdr->tp_h.tp_snaplen,
                                              ctx->link_type, ctx->print_mode,
                                              &hdr->s_ll);
 
                        if (frame_count_max != 0) {
-                               if (unlikely(frame_count >= frame_count_max)) {
+                               if (unlikely(ctx->pkts_seen >= 
frame_count_max)) {
                                        sigint = 1;
                                        break;
                                }
@@ -1080,7 +1097,8 @@ next:
                        if (unlikely(sigint == 1))
                                break;
 
-                       update_pcap_next_dump(ctx, hdr->tp_h.tp_snaplen, &fd, 
sock);
+                       update_pcap_next_dump(ctx, hdr->tp_h.tp_snaplen, &fd,
+                                       sock, is_v3);
                }
 #endif /* HAVE_TPACKET3 */
 
@@ -1094,15 +1112,10 @@ next:
        bug_on(gettimeofday(&end, NULL));
        timersub(&end, &start, &diff);
 
-       if (!(ctx->dump_dir && ctx->print_mode == PRINT_NONE)) {
-               sock_rx_net_stats(sock, frame_count);
+       dump_rx_stats(ctx, sock, is_v3);
 
-               printf("\r%12lu  sec, %lu usec in total\n",
-                      diff.tv_sec, diff.tv_usec);
-       } else {
-               printf("\n\n");
-               fflush(stdout);
-       }
+       printf("\r%12lu  sec, %lu usec in total\n",
+                       diff.tv_sec, diff.tv_usec);
 
        bpf_release(&bpf_ops);
        dissector_cleanup_all();
@@ -1146,6 +1159,12 @@ static void init_ctx(struct ctx *ctx)
        ctx->promiscuous = true;
        ctx->randomize = false;
        ctx->hwtimestamp = true;
+
+       ctx->pkts_recvd = 0;
+       ctx->pkts_seen = 0;
+       ctx->pkts_drops = 0;
+       ctx->pkts_recvd_last = 0;
+       ctx->pkts_drops_last = 0;
 }
 
 static void destroy_ctx(struct ctx *ctx)
diff --git a/ring_rx.c b/ring_rx.c
index 32d3f6d..e8eb947 100644
--- a/ring_rx.c
+++ b/ring_rx.c
@@ -59,7 +59,7 @@ static inline size_t rx_ring_get_size(struct ring *ring, bool 
v3)
        return v3 ? ring->layout3.tp_block_size : ring->layout.tp_frame_size;
 }
 
-static int get_rx_net_stats(int sock, uint64_t *packets, uint64_t *drops, bool 
v3)
+int get_rx_net_stats(int sock, uint64_t *packets, uint64_t *drops, bool v3)
 {
        int ret;
        union {
@@ -101,7 +101,7 @@ static inline size_t rx_ring_get_size(struct ring *ring, 
bool v3 __maybe_unused)
        return ring->layout.tp_frame_size;
 }
 
-static int get_rx_net_stats(int sock, uint64_t *packets, uint64_t *drops, bool 
v3 __maybe_unused)
+int get_rx_net_stats(int sock, uint64_t *packets, uint64_t *drops, bool v3)
 {
        int ret;
        struct tpacket_stats stats;
@@ -238,21 +238,3 @@ void ring_rx_setup(struct ring *ring, int sock, size_t 
size, int ifindex,
        join_fanout_group(sock, fanout_group, fanout_type);
        prepare_polling(sock, poll);
 }
-
-void sock_rx_net_stats(int sock, unsigned long seen)
-{
-       int ret;
-       uint64_t packets, drops;
-       bool v3 = is_tpacket_v3(sock);
-
-       ret = get_rx_net_stats(sock, &packets, &drops, v3);
-       if (ret == 0) {
-               printf("\r%12"PRIu64"  packets incoming (%"PRIu64" unread on 
exit)\n",
-                      v3 ? (uint64_t)seen : packets, v3 ? packets - seen : 0);
-               printf("\r%12"PRIu64"  packets passed filter\n", packets - 
drops);
-               printf("\r%12"PRIu64"  packets failed filter (out of space)\n", 
drops);
-               if (packets > 0)
-                       printf("\r%12.4lf%% packet droprate\n",
-                              (1.0 * drops / packets) * 100.0);
-       }
-}
diff --git a/ring_rx.h b/ring_rx.h
index 1f33018..67ddc03 100644
--- a/ring_rx.h
+++ b/ring_rx.h
@@ -15,7 +15,7 @@ extern void ring_rx_setup(struct ring *ring, int sock, size_t 
size, int ifindex,
                          struct pollfd *poll, bool v3, bool jumbo_support,
                          bool verbose, uint32_t fanout_group, uint32_t 
fanout_type);
 extern void destroy_rx_ring(int sock, struct ring *ring);
-extern void sock_rx_net_stats(int sock, unsigned long seen);
+extern int get_rx_net_stats(int sock, uint64_t *packets, uint64_t *drops, bool 
v3);
 
 static inline int user_may_pull_from_rx(struct tpacket2_hdr *hdr)
 {
-- 
2.4.2

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to