Blame SOURCES/0001-netsniff-ng-add-packet-fanout-support.patch

0a13d0
From 7d821344b6c147a55849e6f8e3652c412b08c80a Mon Sep 17 00:00:00 2001
0a13d0
From: =?UTF-8?q?Micha=C5=82=20Purzy=C5=84ski?= <michalpurzynski1@gmail.com>
0a13d0
Date: Tue, 21 Apr 2015 11:12:44 +0200
0a13d0
Subject: [PATCH 1/4] netsniff-ng: add packet fanout support
0a13d0
MIME-Version: 1.0
0a13d0
Content-Type: text/plain; charset=UTF-8
0a13d0
Content-Transfer-Encoding: 8bit
0a13d0
0a13d0
Upstream commit: f00d4d54f28c0374cc57e6ca07dd648d7684c69c
0a13d0
0a13d0
--
0a13d0
0a13d0
netsniff-ng: add packet fanout support
0a13d0
0a13d0
This work adds packet fanout support to netsniff-ng. Multiple netsniff-ng
0a13d0
instances can join the same fanout group with a particular id in order to
0a13d0
improve scaling.
0a13d0
0a13d0
Based on different fanout disciplines, e.g. distribute to fanout member
0a13d0
by packet hash, round-robin, by arrival cpu, by random, by socket rollover
0a13d0
(if one members socket queue is full, switch to next one, etc), by hardware
0a13d0
queue mapping, traffic can be distributed to one of the fanout members.
0a13d0
0a13d0
Moreover, we also allow the user to specify additional aux arguments, e.g.
0a13d0
whether to defrag incoming traffic for the fanout group or not, and whether
0a13d0
to roll over a socket in case other disciplines than socket rollover have
0a13d0
been used. All that is configurable via command line option.
0a13d0
0a13d0
Signed-off-by: Michał Purzyński <michalpurzynski1@gmail.com>
0a13d0
[ dbkm made some bigger changes to get this upstream ready ]
0a13d0
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
0a13d0
---
0a13d0
 netsniff-ng.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
0a13d0
 ring_rx.c     | 16 ++++++++++++++++
0a13d0
 ring_rx.h     | 34 ++++++++++++++++++++++++++++++++++
0a13d0
 3 files changed, 97 insertions(+), 3 deletions(-)
0a13d0
0a13d0
diff --git a/netsniff-ng.c b/netsniff-ng.c
0a13d0
index 0d9046c..b238979 100644
0a13d0
--- a/netsniff-ng.c
0a13d0
+++ b/netsniff-ng.c
0a13d0
@@ -57,14 +57,18 @@ struct ctx {
0a13d0
 	int cpu, rfraw, dump, print_mode, dump_dir, packet_type, verbose;
0a13d0
 	unsigned long kpull, dump_interval, reserve_size, tx_bytes, tx_packets;
0a13d0
 	bool randomize, promiscuous, enforce, jumbo, dump_bpf;
0a13d0
-	enum pcap_ops_groups pcap; enum dump_mode dump_mode;
0a13d0
-	uid_t uid; gid_t gid; uint32_t link_type, magic;
0a13d0
+	enum pcap_ops_groups pcap;
0a13d0
+	enum dump_mode dump_mode;
0a13d0
+	uid_t uid;
0a13d0
+	gid_t gid;
0a13d0
+	uint32_t link_type, magic;
0a13d0
+	uint32_t fanout_group, fanout_type;
0a13d0
 };
0a13d0
 
0a13d0
 static volatile sig_atomic_t sigint = 0;
0a13d0
 static volatile bool next_dump = false;
0a13d0
 
0a13d0
-static const char *short_options = "d:i:o:rf:MJt:S:k:n:b:HQmcsqXlvhF:RGAP:Vu:g:T:DBU";
0a13d0
+static const char *short_options = "d:i:o:rf:MJt:S:k:n:b:HQmcsqXlvhF:RGAP:Vu:g:T:DBUC:K:L:";
0a13d0
 static const struct option long_options[] = {
0a13d0
 	{"dev",			required_argument,	NULL, 'd'},
0a13d0
 	{"in",			required_argument,	NULL, 'i'},
0a13d0
@@ -80,6 +84,9 @@ static const struct option long_options[] = {
0a13d0
 	{"user",		required_argument,	NULL, 'u'},
0a13d0
 	{"group",		required_argument,	NULL, 'g'},
0a13d0
 	{"magic",		required_argument,	NULL, 'T'},
0a13d0
+	{"fanout-group",	required_argument,	NULL, 'C'},
0a13d0
+	{"fanout-type",		required_argument,	NULL, 'K'},
0a13d0
+	{"fanout-opts",		required_argument,	NULL, 'L'},
0a13d0
 	{"rand",		no_argument,		NULL, 'r'},
0a13d0
 	{"rfraw",		no_argument,		NULL, 'R'},
0a13d0
 	{"mmap",		no_argument,		NULL, 'm'},
0a13d0
@@ -382,6 +389,7 @@ static void receive_to_xmit(struct ctx *ctx)
0a13d0
 	mmap_rx_ring(rx_sock, &rx_ring);
0a13d0
 	alloc_rx_ring_frames(rx_sock, &rx_ring);
0a13d0
 	bind_rx_ring(rx_sock, &rx_ring, ifindex_in);
0a13d0
+	join_fanout_group(rx_sock, ctx->fanout_group, ctx->fanout_type);
0a13d0
 	prepare_polling(rx_sock, &rx_poll);
0a13d0
 
0a13d0
 	set_packet_loss_discard(tx_sock);
0a13d0
@@ -924,6 +932,7 @@ static void recv_only_or_dump(struct ctx *ctx)
0a13d0
 	mmap_rx_ring(sock, &rx_ring);
0a13d0
 	alloc_rx_ring_frames(sock, &rx_ring);
0a13d0
 	bind_rx_ring(sock, &rx_ring, ifindex);
0a13d0
+	join_fanout_group(sock, ctx->fanout_group, ctx->fanout_type);
0a13d0
 
0a13d0
 	prepare_polling(sock, &rx_poll);
0a13d0
 	dissector_init_all(ctx->print_mode);
0a13d0
@@ -1021,12 +1030,15 @@ static void recv_only_or_dump(struct ctx *ctx)
0a13d0
 static void init_ctx(struct ctx *ctx)
0a13d0
 {
0a13d0
 	memset(ctx, 0, sizeof(*ctx));
0a13d0
+
0a13d0
 	ctx->uid = getuid();
0a13d0
 	ctx->uid = getgid();
0a13d0
 
0a13d0
 	ctx->cpu = -1;
0a13d0
 	ctx->packet_type = -1;
0a13d0
 
0a13d0
+	ctx->fanout_type = PACKET_FANOUT_ROLLOVER;
0a13d0
+
0a13d0
 	ctx->magic = ORIGINAL_TCPDUMP_MAGIC;
0a13d0
 	ctx->print_mode = PRINT_NORM;
0a13d0
 	ctx->pcap = PCAP_OPS_SG;
0a13d0
@@ -1055,6 +1067,9 @@ static void __noreturn help(void)
0a13d0
 	     "Options:\n"
0a13d0
 	     "  -i|-d|--dev|--in <dev|pcap|->  Input source as netdev, pcap or pcap stdin\n"
0a13d0
 	     "  -o|--out <dev|pcap|dir|cfg|->  Output sink as netdev, pcap, directory, trafgen, or stdout\n"
0a13d0
+	     "  -C|--fanout-group <id>         Join packet fanout group\n"
0a13d0
+	     "  -K|--fanout-type <type>        Apply fanout discipline: hash|lb|cpu|rnd|roll|qm\n"
0a13d0
+	     "  -L|--fanout-opts <opts>        Additional fanout options: defrag|roll\n"
0a13d0
 	     "  -f|--filter <bpf-file|expr>    Use BPF filter file from bpfc or tcpdump-like expression\n"
0a13d0
 	     "  -t|--type <type>               Filter for: host|broadcast|multicast|others|outgoing\n"
0a13d0
 	     "  -F|--interval <size|time>      Dump interval if -o is a dir: <num>KiB/MiB/GiB/s/sec/min/hrs\n"
0a13d0
@@ -1180,6 +1195,35 @@ int main(int argc, char **argv)
0a13d0
 			ctx.gid = strtoul(optarg, NULL, 0);
0a13d0
 			ctx.enforce = true;
0a13d0
 			break;
0a13d0
+		case 'C':
0a13d0
+			ctx.fanout_group = strtoul(optarg, NULL, 0);
0a13d0
+			if (ctx.fanout_group == 0)
0a13d0
+				panic("Non-zero fanout group id required!\n");
0a13d0
+			break;
0a13d0
+		case 'K':
0a13d0
+			if (!strncmp(optarg, "hash", strlen("hash")))
0a13d0
+				ctx.fanout_type = PACKET_FANOUT_HASH;
0a13d0
+			else if (!strncmp(optarg, "lb", strlen("lb")))
0a13d0
+				ctx.fanout_type = PACKET_FANOUT_LB;
0a13d0
+			else if (!strncmp(optarg, "cpu", strlen("cpu")))
0a13d0
+				ctx.fanout_type = PACKET_FANOUT_CPU;
0a13d0
+			else if (!strncmp(optarg, "rnd", strlen("rnd")))
0a13d0
+				ctx.fanout_type = PACKET_FANOUT_RND;
0a13d0
+			else if (!strncmp(optarg, "roll", strlen("roll")))
0a13d0
+				ctx.fanout_type = PACKET_FANOUT_ROLLOVER;
0a13d0
+			else if (!strncmp(optarg, "qm", strlen("qm")))
0a13d0
+				ctx.fanout_type = PACKET_FANOUT_QM;
0a13d0
+			else
0a13d0
+				panic("Unkown fanout type!\n");
0a13d0
+			break;
0a13d0
+		case 'L':
0a13d0
+			if (!strncmp(optarg, "defrag", strlen("defrag")))
0a13d0
+				ctx.fanout_type |= PACKET_FANOUT_FLAG_DEFRAG;
0a13d0
+			else if (!strncmp(optarg, "roll", strlen("roll")))
0a13d0
+				ctx.fanout_type |= PACKET_FANOUT_FLAG_ROLLOVER;
0a13d0
+			else
0a13d0
+				panic("Unkown fanout option!\n");
0a13d0
+			break;
0a13d0
 		case 't':
0a13d0
 			if (!strncmp(optarg, "host", strlen("host")))
0a13d0
 				ctx.packet_type = PACKET_HOST;
0a13d0
diff --git a/ring_rx.c b/ring_rx.c
0a13d0
index 3c701da..24a8c6d 100644
0a13d0
--- a/ring_rx.c
0a13d0
+++ b/ring_rx.c
0a13d0
@@ -131,6 +131,22 @@ void bind_rx_ring(int sock, struct ring *ring, int ifindex)
0a13d0
 	bind_ring_generic(sock, ring, ifindex);
0a13d0
 }
0a13d0
 
0a13d0
+void join_fanout_group(int sock, uint32_t fanout_group, uint32_t fanout_type)
0a13d0
+{
0a13d0
+	uint32_t fanout_opt = 0;
0a13d0
+	int ret;
0a13d0
+
0a13d0
+	if (fanout_group == 0)
0a13d0
+		return;
0a13d0
+
0a13d0
+	fanout_opt = (fanout_group & 0xffff) | (fanout_type << 16);
0a13d0
+
0a13d0
+	ret = setsockopt(sock, SOL_PACKET, PACKET_FANOUT, &fanout_opt,
0a13d0
+			 sizeof(fanout_opt));
0a13d0
+	if (ret < 0)
0a13d0
+		panic("Cannot set fanout ring mode!\n");
0a13d0
+}
0a13d0
+
0a13d0
 void sock_rx_net_stats(int sock, unsigned long seen)
0a13d0
 {
0a13d0
 	int ret;
0a13d0
diff --git a/ring_rx.h b/ring_rx.h
0a13d0
index 8bf439b..256984d 100644
0a13d0
--- a/ring_rx.h
0a13d0
+++ b/ring_rx.h
0a13d0
@@ -41,4 +41,38 @@ static inline void kernel_may_pull_from_rx_block(struct block_desc *pbd)
0a13d0
 	pbd->h1.block_status = TP_STATUS_KERNEL;
0a13d0
 }
0a13d0
 
0a13d0
+/* Fanout types. */
0a13d0
+
0a13d0
+#ifndef PACKET_FANOUT_HASH
0a13d0
+# define PACKET_FANOUT_HASH		0
0a13d0
+#endif
0a13d0
+
0a13d0
+#ifndef PACKET_FANOUT_LB
0a13d0
+# define PACKET_FANOUT_LB		1
0a13d0
+#endif
0a13d0
+
0a13d0
+#ifndef PACKET_FANOUT_CPU
0a13d0
+# define PACKET_FANOUT_CPU		2
0a13d0
+#endif
0a13d0
+
0a13d0
+#ifndef PACKET_FANOUT_ROLLOVER
0a13d0
+# define PACKET_FANOUT_ROLLOVER		3
0a13d0
+#endif
0a13d0
+
0a13d0
+#ifndef PACKET_FANOUT_RND
0a13d0
+# define PACKET_FANOUT_RND		4
0a13d0
+#endif
0a13d0
+
0a13d0
+#ifndef PACKET_FANOUT_QM
0a13d0
+# define PACKET_FANOUT_QM		5
0a13d0
+#endif
0a13d0
+
0a13d0
+#ifndef PACKET_FANOUT_FLAG_ROLLOVER
0a13d0
+# define PACKET_FANOUT_FLAG_ROLLOVER	0x1000
0a13d0
+#endif
0a13d0
+
0a13d0
+#ifndef PACKET_FANOUT_FLAG_DEFRAG
0a13d0
+# define PACKET_FANOUT_FLAG_DEFRAG	0x8000
0a13d0
+#endif
0a13d0
+
0a13d0
 #endif /* RX_RING_H */
0a13d0
-- 
0a13d0
2.5.5
0a13d0