From 66e558ed51ff7d3d7bebb5f5d56114df5eb77e96 Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Sat, 7 Nov 2015 16:55:16 +0200 Subject: trafgen: Allow to build packet from command line Craft packet directly from command line with same syntax as for conf file. It might be as first step to extend current syntax with specific proto fields. Signed-off-by: Vadim Kochan Signed-off-by: Tobias Klauser --- trafgen.8 | 8 +++++++- trafgen.c | 23 ++++++++++++++++++----- trafgen_conf.h | 1 + trafgen_parser.y | 25 +++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/trafgen.8 b/trafgen.8 index 84ef518..18b2b61 100644 --- a/trafgen.8 +++ b/trafgen.8 @@ -7,7 +7,7 @@ trafgen \- a fast, multithreaded network packet generator .PP .SH SYNOPSIS .PP -\fBtrafgen\fR [\fIoptions\fR] +\fBtrafgen\fR [\fIoptions\fR] [\fIpacket\fR] .PP .SH DESCRIPTION .PP @@ -197,6 +197,9 @@ enclosed by opening '{' and closing '}' braces, for example: { /* packet 1 content goes here ... */ } { /* packet 2 content goes here ... */ } .PP +Alternatively, packets can also be specified directly on the command line, using +the same syntax as used in the configuration files. +.PP When trafgen is started using multiple CPUs (default), then each of those packets will be scheduled for transmission on all CPUs by default. However, it is possible to tell trafgen to schedule a packet only on a particular CPU: @@ -397,6 +400,9 @@ Send out packets generated from the configuration file ''tcp_syn.cfg'' via the ''eth0'' networking device. After setting up the ring for transmission, drop credentials to the non-root user/group bob/bob. .PP +.SS trafgen --dev eth0 '{ fill(0xff, 6), 0x00, 0x02, 0xb3, rnd(3), c16(0x0800), fill(0xca, 64) }' -n 1 +Send out 1 invaid IPv4 packet built from command line to all hosts. +.PP .SH NOTE .PP trafgen can saturate a Gigabit Ethernet link without problems. As always, diff --git a/trafgen.c b/trafgen.c index 1da1897..0ee74ec 100644 --- a/trafgen.c +++ b/trafgen.c @@ -64,6 +64,7 @@ struct ctx { char *device, *device_trans, *rhost; struct timespec gap; struct sockaddr_in dest; + char *packet_str; }; struct cpu_stats { @@ -157,7 +158,7 @@ static void __noreturn help(void) { printf("trafgen %s, multithreaded zero-copy network packet generator\n", VERSION_STRING); puts("http://www.netsniff-ng.org\n\n" - "Usage: trafgen [options]\n" + "Usage: trafgen [options] [packet]\n" "Options:\n" " -i|-c|--in|--conf Packet configuration file/stdin\n" " -o|-d|--out|--dev Networking device i.e., eth0\n" @@ -189,7 +190,8 @@ static void __noreturn help(void) " trafgen --dev wlan0 --rfraw --conf beacon-test.txf -V --cpus 2\n" " trafgen --dev eth0 --conf frag_dos.cfg --rand --gap 1000us\n" " trafgen --dev eth0 --conf icmp.cfg --rand --num 1400000 -k1000\n" - " trafgen --dev eth0 --conf tcp_syn.cfg -u `id -u bob` -g `id -g bob`\n\n" + " trafgen --dev eth0 --conf tcp_syn.cfg -u `id -u bob` -g `id -g bob`\n" + " trafgen --dev eth0 '{ fill(0xff, 6), 0x00, 0x02, 0xb3, rnd(3), c16(0x0800), fill(0xca, 64) }'\n\n" "Arbitrary packet config examples (e.g. trafgen -e > trafgen.cfg):\n" " Run packet on all CPUs: { fill(0xff, 64) csum16(0, 64) }\n" " Run packet only on CPU1: cpu(1): { rnd(64), 0b11001100, 0xaa }\n" @@ -827,7 +829,11 @@ static void xmit_packet_precheck(struct ctx *ctx, unsigned int cpu) static void main_loop(struct ctx *ctx, char *confname, bool slow, unsigned int cpu, bool invoke_cpp, unsigned long orig_num) { - compile_packets(confname, ctx->verbose, cpu, invoke_cpp); + if (ctx->packet_str) + compile_packets_str(ctx->packet_str, ctx->verbose, cpu); + else + compile_packets(confname, ctx->verbose, cpu, invoke_cpp); + xmit_packet_precheck(ctx, cpu); if (cpu == 0) { @@ -891,6 +897,7 @@ int main(int argc, char **argv) unsigned long cpus_tmp, orig_num = 0; unsigned long long tx_packets, tx_bytes; struct ctx ctx; + int min_opts = 5; fmemset(&ctx, 0, sizeof(ctx)); ctx.cpus = get_number_cpus_online(); @@ -1067,11 +1074,16 @@ int main(int argc, char **argv) } } - if (argc < 5) + if (argc >= optind) { + min_opts = 4; + ctx.packet_str = argv2str(optind, argc, argv); + } + + if (argc < min_opts) help(); if (ctx.device == NULL) panic("No networking device given!\n"); - if (confname == NULL) + if (confname == NULL && !ctx.packet_str) panic("No configuration file given!\n"); if (device_mtu(ctx.device) == 0) panic("This is no networking device!\n"); @@ -1173,6 +1185,7 @@ thread_out: free(ctx.device_trans); free(ctx.rhost); free(confname); + free(ctx.packet_str); return 0; } diff --git a/trafgen_conf.h b/trafgen_conf.h index dddee8c..deadb7c 100644 --- a/trafgen_conf.h +++ b/trafgen_conf.h @@ -55,6 +55,7 @@ static inline bool packet_dyn_has_only_csums(struct packet_dyn *p) return (p->clen == 0 && p->rlen == 0 && p->slen); } +extern void compile_packets_str(char *str, bool verbose, unsigned int cpu); extern void compile_packets(char *file, bool verbose, unsigned int cpu, bool invoke_cpp); extern void cleanup_packets(void); diff --git a/trafgen_parser.y b/trafgen_parser.y index 88daf7a..1718f3d 100644 --- a/trafgen_parser.y +++ b/trafgen_parser.y @@ -34,6 +34,8 @@ extern FILE *yyin; extern int yylex(void); +extern void yy_scan_string(char *); +extern void yylex_destroy(); extern void yyerror(const char *); extern int yylineno; extern char *yytext; @@ -641,6 +643,29 @@ err: die(); } +void compile_packets_str(char *str, bool verbose, unsigned int cpu) +{ + int ret = 1; + + our_cpu = cpu; + realloc_packet(); + + yy_scan_string(str); + if (yyparse() != 0) + goto err; + + finalize_packet(); + if (our_cpu == 0 && verbose) + dump_conf(); + + ret = 0; +err: + yylex_destroy(); + + if (ret) + die(); +} + void yyerror(const char *err) { fprintf(stderr, "Syntax error at line %d, char '%s': %s\n", yylineno, yytext, err); -- cgit v1.2.3-54-g00ecf