summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesper Dangaard Brouer <brouer@redhat.com>2013-12-12 13:41:51 +0100
committerJesper Dangaard Brouer <brouer@redhat.com>2013-12-12 13:41:51 +0100
commit7d1ba2b499fcd904bdea7a965688ab7ffd3e390e (patch)
tree22e6ce832be46bc0cbffeb8b15d352d4e2b8ba9e
parentc3602a995b21e8133c7f4fd1fb1e7e21b6a844f1 (diff)
trafgen: take advantage of PACKET_QDISC_BYPASS sock option
Since Linux 3.14, the kernel supports a socket option PACKET_QDISC_BYPASS, which trafgen enables by default. That allow us to bypass the kernels normal qdisc (traffic control) layer. An option -q, --qdisc-path is added to allow enabling the qdisc path explicity, useful for testing purposes. This will be avail in kernels >= 3.14 via commit d346a3fae3 (packet: introduce PACKET_QDISC_BYPASS socket option). Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
-rw-r--r--built_in.h4
-rw-r--r--sock.c18
-rw-r--r--sock.h1
-rw-r--r--trafgen.86
-rw-r--r--trafgen.c13
5 files changed, 40 insertions, 2 deletions
diff --git a/built_in.h b/built_in.h
index 6f6625e..20d7317 100644
--- a/built_in.h
+++ b/built_in.h
@@ -370,6 +370,10 @@ static inline u64 cpu_to_le64(u64 val)
# define TP_STATUS_TS_RAW_HARDWARE (1 << 31)
#endif
+#ifndef PACKET_QDISC_BYPASS
+# define PACKET_QDISC_BYPASS 20
+#endif
+
#ifndef POLLRDNORM
# define POLLRDNORM 0x0040
#endif
diff --git a/sock.c b/sock.c
index a8b4f82..e5f6eac 100644
--- a/sock.c
+++ b/sock.c
@@ -42,6 +42,24 @@ int pf_tx_socket(void)
return sock;
}
+/* Avail in kernel >= 3.14
+ * in commit d346a3fae3 (packet: introduce PACKET_QDISC_BYPASS socket option)
+ */
+void set_sock_qdisc_bypass(int fd, int verbose)
+{
+ int ret, val = 1;
+
+ ret = setsockopt(fd, SOL_PACKET, PACKET_QDISC_BYPASS, &val, sizeof(val));
+ if (ret < 0) {
+ if (errno == ENOPROTOOPT) {
+ if (verbose)
+ printf("No kernel support for PACKET_QDISC_BYPASS"
+ " (kernel < 3.14?)\n");
+ } else
+ perror("Cannot set PACKET_QDISC_BYPASS");
+ } else
+ if (verbose) printf("Enabled kernel qdisc bypass\n");
+}
void set_sock_prio(int fd, int prio)
{
diff --git a/sock.h b/sock.h
index 75be501..0e680ef 100644
--- a/sock.h
+++ b/sock.h
@@ -7,6 +7,7 @@ extern int pf_tx_socket(void);
extern void set_nonblocking(int fd);
extern int set_nonblocking_sloppy(int fd);
extern int set_reuseaddr(int fd);
+extern void set_sock_qdisc_bypass(int fd, int verbose);
extern void set_sock_prio(int fd, int prio);
extern void set_tcp_nodelay(int fd);
extern void set_socket_keepalive(int fd);
diff --git a/trafgen.8 b/trafgen.8
index 6a49fd0..72c2575 100644
--- a/trafgen.8
+++ b/trafgen.8
@@ -161,6 +161,12 @@ threads.
.SS -Q, --notouch-irq
Do not reassign the NIC's IRQ CPU affinity settings.
.PP
+.SS -q, --qdisc-path
+Since Linux 3.14, the kernel supports a socket option PACKET_QDISC_BYPASS,
+which trafgen enables by default. This options disables the qdisc bypass,
+and uses the normal send path through the kernel's qdisc (traffic control)
+layer, which can be usefully for testing the qdisc path.
+.PP
.SS -V, --verbose
Let trafgen be more talkative and let it print the parsed configuration and
some ring buffer statistics.
diff --git a/trafgen.c b/trafgen.c
index e69fcb5..6f19677 100644
--- a/trafgen.c
+++ b/trafgen.c
@@ -55,7 +55,7 @@
#include "csum.h"
struct ctx {
- bool rand, rfraw, jumbo_support, verbose, smoke_test, enforce;
+ bool rand, rfraw, jumbo_support, verbose, smoke_test, enforce, qdisc_path;
unsigned long kpull, num, reserve_size;
unsigned int cpus;
uid_t uid; gid_t gid;
@@ -80,7 +80,7 @@ size_t plen = 0;
struct packet_dyn *packet_dyn = NULL;
size_t dlen = 0;
-static const char *short_options = "d:c:n:t:vJhS:rk:i:o:VRs:P:eE:pu:g:CHQ";
+static const char *short_options = "d:c:n:t:vJhS:rk:i:o:VRs:P:eE:pu:g:CHQq";
static const struct option long_options[] = {
{"dev", required_argument, NULL, 'd'},
{"out", required_argument, NULL, 'o'},
@@ -97,6 +97,7 @@ static const struct option long_options[] = {
{"group", required_argument, NULL, 'g'},
{"prio-high", no_argument, NULL, 'H'},
{"notouch-irq", no_argument, NULL, 'Q'},
+ {"qdisc-path", no_argument, NULL, 'q'},
{"jumbo-support", no_argument, NULL, 'J'},
{"no-cpu-stats", no_argument, NULL, 'C'},
{"cpp", no_argument, NULL, 'p'},
@@ -193,6 +194,7 @@ static void __noreturn help(void)
" -g|--group <groupid> Drop privileges and change to groupid\n"
" -H|--prio-high Make this high priority process\n"
" -Q|--notouch-irq Do not touch IRQ CPU affinity of NIC\n"
+ " -q|--qdisc-path Enabled qdisc kernel path (default off since 3.14)\n"
" -V|--verbose Be more verbose\n"
" -C|--no-cpu-stats Do not print CPU time statistics on exit\n"
" -v|--version Show version and exit\n"
@@ -856,6 +858,9 @@ static void main_loop(struct ctx *ctx, char *confname, bool slow,
sock = pf_tx_socket();
+ if (ctx->qdisc_path == false)
+ set_sock_qdisc_bypass(sock, ctx->verbose);
+
if (slow)
xmit_slowpath_or_die(ctx, cpu, orig_num);
else
@@ -897,6 +902,7 @@ int main(int argc, char **argv)
ctx.cpus = get_number_cpus_online();
ctx.uid = getuid();
ctx.gid = getgid();
+ ctx.qdisc_path = false;
while ((c = getopt_long(argc, argv, short_options, long_options,
&opt_index)) != EOF) {
@@ -934,6 +940,9 @@ int main(int argc, char **argv)
case 'Q':
set_irq_aff = false;
break;
+ case 'q':
+ ctx.qdisc_path = true;
+ break;
case 'r':
ctx.rand = true;
break;