From 7d1ba2b499fcd904bdea7a965688ab7ffd3e390e Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Thu, 12 Dec 2013 13:41:51 +0100 Subject: 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 --- built_in.h | 4 ++++ sock.c | 18 ++++++++++++++++++ sock.h | 1 + trafgen.8 | 6 ++++++ trafgen.c | 13 +++++++++++-- 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 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; -- cgit v1.2.3-54-g00ecf