diff options
author | Vadim Kochan <vadim4j@gmail.com> | 2015-08-24 21:37:03 +0300 |
---|---|---|
committer | Tobias Klauser <tklauser@distanz.ch> | 2015-08-25 11:14:42 +0200 |
commit | 5f94671f31c040f7cb78e56ac2524e84f703769c (patch) | |
tree | 8134a0da6d94405449fdb223d11d97184e269a11 | |
parent | d84a6b7139f3c6d0eb70615543cf368350000e5b (diff) |
netsniff-ng: Show total rx stats for multi pcap mode
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 <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r-- | netsniff-ng.c | 118 | ||||
-rw-r--r-- | ring_rx.c | 23 | ||||
-rw-r--r-- | ring_rx.h | 2 |
3 files changed, 77 insertions, 66 deletions
diff --git a/netsniff-ng.c b/netsniff-ng.c index 57edc43..3b69c8f 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,41 @@ static inline void setup_rfmon_mac80211_dev(struct ctx *ctx, char **rfmon_dev) panic_handler_add(on_panic_del_rfmon, *rfmon_dev); } +static int update_rx_stats(struct ctx *ctx, int sock, bool is_v3) +{ + uint64_t packets, drops; + int ret; + + ret = get_rx_net_stats(sock, &packets, &drops, is_v3); + if (ret) + return ret; + + ctx->pkts_recvd += packets; + ctx->pkts_drops += drops; + ctx->pkts_recvd_last = packets; + ctx->pkts_drops_last = drops; + + return 0; +} + +static void dump_rx_stats(struct ctx *ctx, int sock, bool is_v3) +{ + if (update_rx_stats(ctx, sock, is_v3)) + return; + + 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 +414,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 +465,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 +502,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 +536,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 +881,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 +907,19 @@ 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); + if (update_rx_stats(ctx, sock, is_v3)) + return; + + 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 +936,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 +950,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 +959,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 +980,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 +1000,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 +1047,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 +1065,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 +1084,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 +1104,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,14 +1119,11 @@ 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); + if (ctx->print_mode != PRINT_NONE) { + 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); } bpf_release(&bpf_ops); @@ -1146,6 +1168,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) @@ -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,8 @@ 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 __maybe_unused) { int ret; struct tpacket_stats stats; @@ -238,21 +239,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); - } -} @@ -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) { |