From f3c3677c5dd67d7edda5bee5b316e014be231337 Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Tue, 26 Jan 2016 22:25:04 +0200 Subject: trafgen: parser: Add syntax to generate Ethernet header fields Add function 'eth()' to support generating Ethernet header fields from the trafgen configuration language. Supported fields: da|daddr destination address, default: 00:00:00:00:00:00 sa|saddr source address, default: device MAC prot|proto protocol number, default: 0x0000 Example usage: { eth(prot=0x0800, da=11:22:33:44:55:66), fill(0xff, 60) } { eth(prot=0x0800) } { eth() } It is important that proto_init is called before fields will be filled to initialize the specified proto with header fields. Signed-off-by: Vadim Kochan [tk: document supported keywords in commit message] Signed-off-by: Tobias Klauser --- trafgen_lexer.l | 15 +++++++++++++++ trafgen_parser.y | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/trafgen_lexer.l b/trafgen_lexer.l index 6c27b0c..d209116 100644 --- a/trafgen_lexer.l +++ b/trafgen_lexer.l @@ -19,6 +19,7 @@ #include "trafgen_parser.tab.h" #include "xmalloc.h" #include "built_in.h" +#include "str.h" extern void yyerror(const char *); @@ -75,6 +76,9 @@ number_bin ([0]?[b][0-1]+) number_dec (([0])|([1-9][0-9]*)) number_ascii ([a-zA-Z]) +mac_hex ([a-fA-F0-9]+) +mac ({mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}:{mac_hex}) + %% "cpu" { return K_CPU; } @@ -99,6 +103,12 @@ number_ascii ([a-zA-Z]) "const32"|"c32" { return K_CONST32; } "const64"|"c64" { return K_CONST64; } +"daddr"|"da" { return K_DADDR; } +"saddr"|"sa" { return K_SADDR; } +"prot"[o]? { return K_PROT; } + +"eth" { return K_ETH; } + [ ]*"-"[ ]* { return '-'; } [ ]*"+"[ ]* { return '+'; } [ ]*"*"[ ]* { return '*'; } @@ -117,6 +127,7 @@ number_ascii ([a-zA-Z]) "]" { return ']'; } "," { return ','; } ":" { return ':'; } +"=" { return '='; } "\n" { yylineno++; } @@ -146,6 +157,10 @@ number_ascii ([a-zA-Z]) {number_ascii} { yylval.number = (uint8_t) (*yytext); return number; } +{mac} { if (str2mac(yytext, yylval.bytes, 256)) + panic("Failed to parse MAC address %s\n", yytext); + return mac; } + "'\\x"[a-fA-F0-9]{2}"'" { yylval.number = strtol(yytext + 3, NULL, 16); return number; } diff --git a/trafgen_parser.y b/trafgen_parser.y index 4725f7c..df1b1a6 100644 --- a/trafgen_parser.y +++ b/trafgen_parser.y @@ -21,6 +21,8 @@ #include "xmalloc.h" #include "trafgen_parser.tab.h" #include "trafgen_conf.h" +#include "trafgen_proto.h" +#include "trafgen_l2.h" #include "built_in.h" #include "die.h" #include "str.h" @@ -59,6 +61,8 @@ extern size_t dlen; static int our_cpu, min_cpu = -1, max_cpu = -1; +static struct proto_hdr *hdr; + static inline int test_ignore(void) { if (min_cpu < 0 && max_cpu < 0) @@ -324,22 +328,33 @@ static void set_dynamic_incdec(uint8_t start, uint8_t stop, uint8_t stepping, __setup_new_counter(&pktd->cnt[packetdc_last], start, stop, stepping, type); } +static void proto_add(enum proto_id pid) +{ + proto_header_init(pid); + hdr = proto_current_header(); +} + %} %union { long long int number; + uint8_t bytes[256]; char *str; } %token K_COMMENT K_FILL K_RND K_SEQINC K_SEQDEC K_DRND K_DINC K_DDEC K_WHITE %token K_CPU K_CSUMIP K_CSUMUDP K_CSUMTCP K_CSUMUDP6 K_CSUMTCP6 K_CONST8 K_CONST16 K_CONST32 K_CONST64 +%token K_DADDR K_SADDR K_PROT +%token K_ETH + %token ',' '{' '}' '(' ')' '[' ']' ':' '-' '+' '*' '/' '%' '&' '|' '<' '>' '^' -%token number string +%token number string mac %type number expression %type string +%type mac %left '-' '+' '*' '/' '%' '&' '|' '<' '>' '^' @@ -372,9 +387,16 @@ noenforce_white | delimiter_nowhite { } ; +skip_white + : { } + | K_WHITE { } + ; packet : '{' noenforce_white payload noenforce_white '}' { min_cpu = max_cpu = -1; + + proto_packet_finish(); + realloc_packet(); } | K_CPU '(' number cpu_delim number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' { @@ -388,10 +410,15 @@ packet max_cpu = tmp; } + proto_packet_finish(); + realloc_packet(); } | K_CPU '(' number ')' ':' noenforce_white '{' noenforce_white payload noenforce_white '}' { min_cpu = max_cpu = $3; + + proto_packet_finish(); + realloc_packet(); } ; @@ -422,6 +449,7 @@ elem | ddec { } | csum { } | const { } + | proto { proto_header_finish(hdr); } | inline_comment { } ; @@ -536,6 +564,33 @@ ddec { set_dynamic_incdec($3, $5, $7, TYPE_DEC); } ; +proto + : eth_proto { } + ; + +eth_proto + : eth '(' eth_param_list ')' { } + ; + +eth + : K_ETH { proto_add(PROTO_ETH); } + ; + +eth_param_list + : { } + | eth_field { } + | eth_field delimiter eth_param_list { } + ; + +eth_field + : K_DADDR skip_white '=' skip_white mac + { proto_field_set_bytes(hdr, ETH_DST_ADDR, $5); } + | K_SADDR skip_white '=' skip_white mac + { proto_field_set_bytes(hdr, ETH_SRC_ADDR, $5); } + | K_PROT skip_white '=' skip_white number + { proto_field_set_be16(hdr, ETH_PROTO_ID, $5); } + ; + %% static void finalize_packet(void) -- cgit v1.2.3-54-g00ecf