Blob Blame History Raw
From 02c7610c3543e9190539efe944e1c90c3ebb5623 Mon Sep 17 00:00:00 2001
Message-Id: <02c7610c3543e9190539efe944e1c90c3ebb5623.1469118440.git.pabeni@redhat.com>
From: Paolo Abeni <pabeni@redhat.com>
Date: Thu, 21 Jul 2016 18:25:49 +0200
Subject: [PATCH] netsniff-ng: Skip duplicated packets on loopback device

Upstream commit: 81f8c546d90b7615e0e6a6777445b10b4263d598
---
 netsniff-ng.c | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/netsniff-ng.c b/netsniff-ng.c
index b238979..75b5ca0 100644
--- a/netsniff-ng.c
+++ b/netsniff-ng.c
@@ -54,7 +54,8 @@ enum dump_mode {
 
 struct ctx {
 	char *device_in, *device_out, *device_trans, *filter, *prefix;
-	int cpu, rfraw, dump, print_mode, dump_dir, packet_type, verbose;
+	int cpu, rfraw, dump, print_mode, dump_dir, packet_type, verbose,
+	    lo_ifindex;
 	unsigned long kpull, dump_interval, reserve_size, tx_bytes, tx_packets;
 	bool randomize, promiscuous, enforce, jumbo, dump_bpf;
 	enum pcap_ops_groups pcap;
@@ -346,6 +347,18 @@ static void pcap_to_xmit(struct ctx *ctx)
 	printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec);
 }
 
+static inline bool skip_packet(struct ctx *ctx, struct sockaddr_ll *sll)
+{
+	if (ctx->packet_type != -1)
+		return ctx->packet_type != sll->sll_pkttype;
+
+	/* when receving from the loopback device, each packet is seen twice,
+	 * so drop the outgoing ones to avoid duplicates
+	 */
+	return (sll->sll_ifindex == ctx->lo_ifindex) &&
+	       (sll->sll_pkttype == PACKET_OUTGOING);
+}
+
 static void receive_to_xmit(struct ctx *ctx)
 {
 	short ifflags = 0;
@@ -424,9 +437,8 @@ static void receive_to_xmit(struct ctx *ctx)
 
 			frame_count++;
 
-			if (ctx->packet_type != -1)
-				if (ctx->packet_type != hdr_in->s_ll.sll_pkttype)
-					goto next;
+			if (skip_packet(ctx, &hdr_in->s_ll))
+				goto next;
 
 			hdr_out = tx_ring.frames[it_out].iov_base;
 			out = ((uint8_t *) hdr_out) + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll);
@@ -835,9 +847,8 @@ static void walk_t3_block(struct block_desc *pbd, struct ctx *ctx,
 		__label__ next;
 		packet = ((uint8_t *) hdr + hdr->tp_mac);
 
-		if (ctx->packet_type != -1)
-			if (ctx->packet_type != sll->sll_pkttype)
-				goto next;
+		if (skip_packet(ctx, sll))
+			goto next;
 
 		(*frame_count)++;
 
@@ -1414,6 +1425,9 @@ int main(int argc, char **argv)
 	if (!ctx.device_in)
 		ctx.device_in = xstrdup("any");
 
+	if (!strcmp(ctx.device_in, "any") || !strcmp(ctx.device_in, "lo"))
+		ctx.lo_ifindex = device_ifindex("lo");
+
 	register_signal(SIGINT, signal_handler);
 	register_signal(SIGHUP, signal_handler);
 
-- 
1.8.3.1