summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-06-03 23:24:18 +0200
committerDaniel Borkmann <dborkman@redhat.com>2013-06-03 23:26:45 +0200
commit3e071a78f2a5c7424340b4c8b446d51e82413c13 (patch)
tree2a411f35daeae48be99a8d325f88dcbd63bb0f2a
parentdc5f7a04f2b446b5224be356c2fc79e88a5d3e8f (diff)
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 <pkts>. 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 <dborkman@redhat.com>
-rw-r--r--netsniff-ng.c15
-rw-r--r--ring_rx.c25
-rw-r--r--ring_rx.h1
-rw-r--r--xutils.c22
-rw-r--r--xutils.h1
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);