From 3e071a78f2a5c7424340b4c8b446d51e82413c13 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 3 Jun 2013 23:24:18 +0200 Subject: netsniff-ng: v3: fix packet accounting on --num We need to carry frame_count through multiple calls of walk function to account correctly for --num . Also, move socket stats printing into rx ring, since it belongs there. Todo: the kernel socket seems to have a different count that what we see. This needs to be fixed one way or the other. Not yet sure what's causing this. Signed-off-by: Daniel Borkmann --- netsniff-ng.c | 15 ++++++++------- ring_rx.c | 25 +++++++++++++++++++++++++ ring_rx.h | 1 + xutils.c | 22 ---------------------- xutils.h | 1 - 5 files changed, 34 insertions(+), 30 deletions(-) diff --git a/netsniff-ng.c b/netsniff-ng.c index 899a148..b61dec9 100644 --- a/netsniff-ng.c +++ b/netsniff-ng.c @@ -476,7 +476,7 @@ static void receive_to_xmit(struct ctx *ctx) timer_purge(); - sock_print_net_stats(rx_sock); + sock_rx_net_stats(rx_sock); bpf_release(&bpf_ops); @@ -809,11 +809,10 @@ static void print_pcap_file_stats(int sock, struct ctx *ctx) } static void walk_t3_block(struct block_desc *pbd, struct ctx *ctx, - int sock, int fd) + int sock, int fd, unsigned long *frame_count) { uint8_t *packet; int num_pkts = pbd->h1.num_pkts, i, ret; - unsigned long frame_count = 0; struct tpacket3_hdr *hdr; pcap_pkthdr_t phdr; struct sockaddr_ll *sll; @@ -824,12 +823,13 @@ static void walk_t3_block(struct block_desc *pbd, struct ctx *ctx, for (i = 0; i < num_pkts && likely(sigint == 0); ++i) { __label__ next; packet = ((uint8_t *) hdr + hdr->tp_mac); - frame_count++; if (ctx->packet_type != -1) if (ctx->packet_type != sll->sll_pkttype) goto next; + (*frame_count)++; + if (dump_to_pcap(ctx)) { tpacket3_hdr_to_pcap_pkthdr(hdr, sll, &phdr, ctx->magic); @@ -849,7 +849,7 @@ static void walk_t3_block(struct block_desc *pbd, struct ctx *ctx, sll = (void *) ((uint8_t *) hdr + TPACKET_ALIGN(sizeof(*hdr))); if (frame_count_max != 0) { - if (frame_count >= frame_count_max) { + if (unlikely(*frame_count >= frame_count_max)) { sigint = 1; break; } @@ -885,6 +885,7 @@ static void recv_only_or_dump(struct ctx *ctx) struct sock_fprog bpf_ops; struct timeval start, end, diff; struct block_desc *pbd; + unsigned long frame_count = 0; sock = pf_socket(); @@ -967,7 +968,7 @@ static void recv_only_or_dump(struct ctx *ctx) while (likely(sigint == 0)) { while (user_may_pull_from_rx_block((pbd = (void *) rx_ring.frames[it].iov_base))) { - walk_t3_block(pbd, ctx, sock, fd); + walk_t3_block(pbd, ctx, sock, fd, &frame_count); kernel_may_pull_from_rx_block(pbd); it = (it + 1) % rx_ring.layout3.tp_block_nr; @@ -983,7 +984,7 @@ static void recv_only_or_dump(struct ctx *ctx) timersub(&end, &start, &diff); if (!(ctx->dump_dir && ctx->print_mode == PRINT_NONE)) { - sock_print_net_stats(sock); + sock_rx_net_stats(sock); printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec); diff --git a/ring_rx.c b/ring_rx.c index 28ecaf4..c674332 100644 --- a/ring_rx.c +++ b/ring_rx.c @@ -130,3 +130,28 @@ void bind_rx_ring(int sock, struct ring *ring, int ifindex) { bind_ring_generic(sock, ring, ifindex); } + +void sock_rx_net_stats(int sock) +{ + int ret; + bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3; + union { + struct tpacket_stats k2; + struct tpacket_stats_v3 k3; + } stats; + socklen_t slen = v3 ? sizeof(stats.k3) : sizeof(stats.k2); + + memset(&stats, 0, sizeof(stats)); + ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &stats, &slen); + if (ret > -1) { + 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 passed filter\n", packets - drops); + printf("\r%12ld packets failed filter (out of space)\n", drops); + if (stats.k3.tp_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 9c72cda..43b4020 100644 --- a/ring_rx.h +++ b/ring_rx.h @@ -17,6 +17,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); static inline int user_may_pull_from_rx(struct tpacket2_hdr *hdr) { diff --git a/xutils.c b/xutils.c index a5fbb3c..eea258c 100644 --- a/xutils.c +++ b/xutils.c @@ -608,28 +608,6 @@ void device_set_flags(const char *ifname, const short flags) close(sock); } -void sock_print_net_stats(int sock) -{ - int ret; - struct tpacket_stats kstats; - - socklen_t slen = sizeof(kstats); - - memset(&kstats, 0, sizeof(kstats)); - ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &kstats, &slen); - if (ret > -1) { - uint64_t packets = kstats.tp_packets; - uint64_t drops = kstats.tp_drops; - - printf("\r%12ld packets incoming\n", packets); - printf("\r%12ld packets passed filter\n", packets - drops); - printf("\r%12ld packets failed filter (out of space)\n", drops); - if (kstats.tp_packets > 0) - printf("\r%12.4lf%\% packet droprate\n", - (1.0 * drops / packets) * 100.0); - } -} - void register_signal(int signal, void (*handler)(int)) { sigset_t block_mask; diff --git a/xutils.h b/xutils.h index 28a307b..ce8ee75 100644 --- a/xutils.h +++ b/xutils.h @@ -36,7 +36,6 @@ extern int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf); extern int ethtool_link(const char *ifname); extern int device_mtu(const char *ifname); extern int device_address(const char *ifname, int af, struct sockaddr_storage *ss); -extern void sock_print_net_stats(int sock); extern int device_ifindex(const char *ifname); extern short device_get_flags(const char *ifname); extern void device_set_flags(const char *ifname, const short flags); -- cgit v1.2.3-54-g00ecf