|
|
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 |
|