From 4c553c5a5b40c21ba67bd82455e79678b204cd07 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Thu, 27 Dec 2018 14:26:11 +0100 Subject: Filter refactoring: dropped the recursion from the interpreter This is a major change of how the filters are interpreted. If everything works how it should, it should not affect you unless you are hacking the filters themselves. Anyway, this change should make a huge improvement in the filter performance as previous benchmarks showed that our major problem lies in the recursion itself. There are also some changes in nest and protocols, related mostly to spreading const declarations throughout the whole BIRD and also to refactored dynamic attribute definitions. The need of these came up during the whole work and it is too difficult to split out these not-so-related changes. --- proto/static/config.Y | 7 +++++-- proto/static/static.c | 2 +- proto/static/static.h | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'proto/static') diff --git a/proto/static/config.Y b/proto/static/config.Y index d7a02961..56caef24 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -14,7 +14,7 @@ CF_DEFINES #define STATIC_CFG ((struct static_config *) this_proto) static struct static_route *this_srt, *this_snh; -static struct f_inst **this_srt_last_cmd; +static struct f_inst *this_srt_cmds, **this_srt_last_cmd; static struct static_route * static_nexthop_new(void) @@ -39,6 +39,8 @@ static_route_finish(void) { if (net_type_match(this_srt->net, NB_DEST) == !this_srt->dest) cf_error("Unexpected or missing nexthop/type"); + + this_srt->cmds = f_postfixify(this_srt_cmds); } CF_DECLS @@ -108,7 +110,8 @@ stat_route0: ROUTE net_any { this_srt = cfg_allocz(sizeof(struct static_route)); add_tail(&STATIC_CFG->routes, &this_srt->n); this_srt->net = $2; - this_srt_last_cmd = &(this_srt->cmds); + this_srt_cmds = NULL; + this_srt_last_cmd = &this_srt_cmds; this_srt->mp_next = NULL; this_snh = NULL; } diff --git a/proto/static/static.c b/proto/static/static.c index 75a74ad0..2fa687eb 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -308,7 +308,7 @@ static inline int static_same_rte(struct static_route *or, struct static_route *nr) { /* Note that i_same() requires arguments in (new, old) order */ - return static_same_dest(or, nr) && i_same(nr->cmds, or->cmds); + return static_same_dest(or, nr) && f_same(nr->cmds, or->cmds); } static void diff --git a/proto/static/static.h b/proto/static/static.h index a3c30b87..f736996c 100644 --- a/proto/static/static.h +++ b/proto/static/static.h @@ -39,7 +39,7 @@ struct static_route { struct static_route *chain; /* Next for the same neighbor */ struct static_route *mp_head; /* First nexthop of this route */ struct static_route *mp_next; /* Nexthops for multipath routes */ - struct f_inst *cmds; /* List of commands for setting attributes */ + struct f_line *cmds; /* List of commands for setting attributes */ byte dest; /* Destination type (RTD_*) */ byte state; /* State of route announcement (SRS_*) */ byte active; /* Next hop is active (nbr/iface/BFD available) */ -- cgit v1.2.3 From 9b46748d5b50d1e8c242a571e80fe1f9f33aeb73 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Mon, 21 Jan 2019 09:17:54 +0100 Subject: Filter: refactoring of instruction constructors --- conf/conf.h | 2 +- conf/confbase.Y | 4 + filter/Makefile | 10 +- filter/config.Y | 343 +++++++++++++++++++++----------------------------- filter/dump.m4 | 4 +- filter/f-inst.c | 101 ++++++++++----- filter/f-inst.h | 124 ++++++++++++++++++ filter/f-util.c | 98 ++++++++------- filter/filter.c | 30 ++--- filter/filter.h | 222 ++++++++++++++++---------------- filter/interpret.m4 | 11 +- filter/line-size.m4 | 14 ++- filter/new.m4 | 84 +++++++++++++ filter/postfixify.m4 | 39 +++--- filter/same.m4 | 4 +- filter/struct.m4 | 67 ++++++++++ nest/attrs.h | 2 +- proto/static/config.Y | 12 +- 18 files changed, 744 insertions(+), 427 deletions(-) create mode 100644 filter/f-inst.h create mode 100644 filter/new.m4 create mode 100644 filter/struct.m4 (limited to 'proto/static') diff --git a/conf/conf.h b/conf/conf.h index 427569fd..6138ccec 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -107,7 +107,7 @@ struct symbol { struct sym_scope *scope; int class; int aux; - void *aux2; + uint aux2; void *def; char name[1]; }; diff --git a/conf/confbase.Y b/conf/confbase.Y index 492ecd08..13f6aade 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -49,6 +49,10 @@ CF_DECLS struct rtable_config *r; struct channel_config *cc; struct f_inst *x; + struct f_inst *xp[2]; + struct { struct f_inst *inst; uint count; } xc; + enum filter_return fret; + enum ec_subtype ecs; struct f_dynamic_attr fda; struct f_static_attr fsa; struct filter *f; diff --git a/filter/Makefile b/filter/Makefile index c74ba2f3..15f2c3d0 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -1,4 +1,4 @@ -src := filter.c f-util.c tree.c trie.c +src := filter.c f-util.c tree.c trie.c f-inst-new.c obj := $(src-o-files) $(all-daemon) $(cf-local) @@ -17,10 +17,16 @@ $(o)f-inst-interpret.c: $(s)interpret.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(o)f-inst-same.c: $(s)same.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(M4) $(M4FLAGS_FILTERS) -P $^ >$@ +$(o)f-inst-struct.h: $(s)struct.m4 $(s)f-inst.c $(objdir)/.dir-stamp + $(M4) $(M4FLAGS_FILTERS) -P $^ >$@ + +$(o)f-inst-new.c: $(s)new.m4 $(s)f-inst.c $(objdir)/.dir-stamp + $(M4) $(M4FLAGS_FILTERS) -P $^ >$@ + $(o)f-inst-dump.c: $(s)dump.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(M4) $(M4FLAGS_FILTERS) -P $^ >$@ -$(o)filter.o: $(o)f-inst-interpret.c $(o)f-inst-line-size.c $(o)f-inst-postfixify.c $(o)f-inst-same.c $(o)f-inst-dump.c +$(o)filter.o: $(o)f-inst-interpret.c $(o)f-inst-line-size.c $(o)f-inst-postfixify.c $(o)f-inst-same.c $(o)f-inst-dump.c $(o)f-inst-struct.h tests_src := tree_test.c filter_test.c trie_test.c tests_targets := $(tests_targets) $(tests-target-files) diff --git a/filter/config.Y b/filter/config.Y index a79b1582..607f534e 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -16,6 +16,8 @@ static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; } static inline u32 pair_a(u32 p) { return p >> 16; } static inline u32 pair_b(u32 p) { return p & 0xFFFF; } +#define f_generate_complex(fi_code, da, arg) \ + f_new_inst(FI_EA_SET, da, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg)) /* * Sets and their items are during parsing handled as lists, linked @@ -158,30 +160,29 @@ f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3, u32 t3) static inline struct f_inst * f_generate_empty(struct f_dynamic_attr dyn) { - struct f_inst *e = f_new_inst(FI_CONSTANT); + struct f_val empty; switch (dyn.type & EAF_TYPE_MASK) { case EAF_TYPE_AS_PATH: - e->val = f_const_empty_path; + empty = f_const_empty_path; break; case EAF_TYPE_INT_SET: - e->val = f_const_empty_clist; + empty = f_const_empty_clist; break; case EAF_TYPE_EC_SET: - e->val = f_const_empty_eclist; + empty = f_const_empty_eclist; break; case EAF_TYPE_LC_SET: - e->val = f_const_empty_lclist; + empty = f_const_empty_lclist; break; default: cf_error("Can't empty that attribute"); } - struct f_inst *s = f_new_inst_da(FI_EA_SET, dyn); - s->a[0].p = e; - return s; + return f_new_inst(FI_EA_SET, dyn, f_new_inst(FI_CONSTANT, empty)); } +#if 0 static inline struct f_inst * f_generate_dpair(struct f_inst *t1, struct f_inst *t2) @@ -332,6 +333,8 @@ f_generate_path_mask(struct f_inst *t) return pmc; } +#endif + /* * Remove all new lines and doubled whitespaces * and convert all tabulators to spaces @@ -380,21 +383,10 @@ assert_copy_expr(const char *start, size_t len) static struct f_inst * assert_done(struct f_inst *expr, const char *start, const char *end) { - struct f_inst *i; - i = f_new_inst(FI_ASSERT); - i->a[0].p = expr; - - if (end >= start) - { - i->a[1].p = assert_copy_expr(start, end - start + 1); - } - else - { - /* this is a break of lexer buffer */ - i->a[1].p = "???"; - } - - return i; + return f_new_inst(FI_ASSERT, expr, + (end >= start) ? + assert_copy_expr(start, end - start + 1) + : "???"); } CF_DECLS @@ -420,17 +412,20 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, %nonassoc THEN %nonassoc ELSE -%type term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn function_call symbol bgp_path_expr bgp_path bgp_path_tail +%type function_params declsn +%type cmds_int function_body +%type term block cmd cmds constant constructor print_one print_list var_list var_listn function_call symbol bgp_path_expr bgp_path bgp_path_tail one_decl decls %type dynamic_attr %type static_attr %type filter filter_body where_filter -%type type break_command ec_kind +%type type +%type ec_kind +%type break_command %type cnum %type pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body %type fprefix_set %type set_atom switch_atom fipa %type fprefix -%type decls declsn one_decl function_params %type get_cf_position CF_GRAMMAR @@ -515,8 +510,7 @@ one_decl: val->type = T_VOID; $2 = cf_define_symbol($2, SYM_VARIABLE | $1, val); DBG( "New variable %s type %x\n", $2->name, $1 ); - $2->aux2 = NULL; - $$=$2; + $$ = f_new_inst(FI_SET, NULL, $2); } ; @@ -524,24 +518,29 @@ one_decl: decls: /* EMPTY */ { $$ = NULL; } | one_decl ';' decls { $$ = $1; - $$->aux2 = $3; + f_inst_next($$, $3); } ; -/* Declarations that have no ';' at the end. */ -declsn: one_decl { $$ = $1; } +/* Declarations that have no ';' at the end. Beware; these are reversed. */ +declsn: one_decl { $$.inst = $1; $$.count = 1; } | one_decl ';' declsn { - $$ = $1; - $$->aux2 = $3; + $$ = $3; + $$.count++; + f_inst_next($$.inst, $1); } ; filter_body: function_body { - struct filter *f = cfg_alloc(sizeof(struct filter)); - f->name = NULL; - f->root = f_postfixify($1); - $$ = f; + $$ = cfg_alloc(sizeof(struct filter)); + $$->name = NULL; + if ($1[0]) { + const struct f_inst *inst[2] = { $1[0], $1[1] }; + $$->root = f_postfixify_concat(inst, 2); + } + else + $$->root = f_postfixify($1[1]); } ; @@ -556,42 +555,19 @@ filter: where_filter: WHERE term { /* Construct 'IF term THEN { ACCEPT; } ELSE { REJECT; }' */ - struct filter *f = cfg_alloc(sizeof(struct filter)); - struct f_inst acc = { - .fi_code = FI_PRINT_AND_DIE, - .a = { { .p = NULL }, { .i = F_ACCEPT } }, - .lineno = ifs->lino, - }; - struct f_inst rej = { - .fi_code = FI_PRINT_AND_DIE, - .a = { { .p = NULL }, { .i = F_REJECT } }, - .lineno = ifs->lino, - }; - struct f_inst i = { - .fi_code = FI_CONDITION, - .a = { { .p = $2 }, { .p = &acc }, { .p = &rej } }, - .lineno = ifs->lino, - }; - f->name = NULL; - f->root = f_postfixify(&i); - $$ = f; + $$ = f_new_where($2); } ; function_params: - '(' declsn ')' { DBG( "Have function parameters\n" ); $$=$2; } - | '(' ')' { $$=NULL; } + '(' declsn ')' { $$ = $2; } + | '(' ')' { $$.inst = NULL; $$.count = 0; } ; function_body: decls '{' cmds '}' { - if ($1) { - /* Prepend instruction to clear local variables */ - $$ = f_new_inst(FI_CLEAR_LOCAL_VARS); - $$->a[0].p = $1; - $$->next = $3; - } else - $$ = $3; + $$[0] = $1 ? f_clear_local_vars($1) : NULL; + $$[1] = $3; } ; @@ -601,10 +577,26 @@ function_def: $2 = cf_define_symbol($2, SYM_FUNCTION, NULL); cf_push_scope($2); } function_params function_body { - struct f_inst *vc = f_new_inst(FI_CONSTANT); - vc->val = (struct f_val) { .type = T_VOID }; - $2->def = f_postfixify_concat($5, vc, NULL); - $2->aux2 = $4; + const struct f_inst *catlist[4]; + uint count = 0; + + /* Argument setters */ + if ($4.inst) + catlist[count++] = $4.inst; + + /* Local var clearers */ + if ($5[0]) + catlist[count++] = $5[0]; + + /* Return void if no return is needed */ + catlist[count++] = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID }); + + /* Function body itself */ + if ($5[1]) + catlist[count++] = $5[1]; + + $2->def = f_postfixify_concat(catlist, count); + $2->aux2 = $4.count; DBG("Hmm, we've got one function here - %s\n", $2->name); cf_pop_scope(); } @@ -612,15 +604,12 @@ function_def: /* Programs */ -/* Hack: $$ of cmds_int is the last node. - $$->next of cmds_int is temporary used for the first node */ - cmds: /* EMPTY */ { $$ = NULL; } - | cmds_int { $$ = $1->next; $1->next = NULL; } + | cmds_int { $$ = $1[0]; } ; -cmds_int: cmd { $$ = $1; $1->next = $1; } - | cmds_int cmd { $$ = $2; $2->next = $1->next ; $1->next = $2; } +cmds_int: cmd { $$[0] = $$[1] = $1; } + | cmds_int cmd { $$[1] = $2; f_inst_next($1[1], $2); $$[0] = $1[0]; } ; block: @@ -784,37 +773,36 @@ bgp_path: ; bgp_path_tail: - NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT); $$->next = $2; $$->val = (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .asn = $1, .kind = PM_ASN, }, }; } - | NUM DDOT NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT); $$->next = $4; $$->val = (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .from = $1, .to = $3, .kind = PM_ASN_RANGE }, }; } - | '*' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT); $$->next = $2; $$->val = (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_ASTERISK }, }; } - | '?' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT); $$->next = $2; $$->val = (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_QUESTION }, }; } - | bgp_path_expr bgp_path_tail { $$ = $1; $$->next = $2; } + NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .asn = $1, .kind = PM_ASN, }, }); f_inst_next($$, $2); } + | NUM DDOT NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .from = $1, .to = $3, .kind = PM_ASN_RANGE }, }); f_inst_next($$, $4); } + | '*' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_ASTERISK }, }); f_inst_next($$, $2); } + | '?' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_QUESTION }, }); f_inst_next($$, $2); } + | bgp_path_expr bgp_path_tail { $$ = $1; f_inst_next($$, $2); } | { $$ = NULL; } ; constant: - NUM { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_INT, .val.i = $1, }; } - | TRUE { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_BOOL, .val.i = 1, }; } - | FALSE { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_BOOL, .val.i = 0, }; } - | TEXT { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_STRING, .val.s = $1, }; } - | fipa { $$ = f_new_inst(FI_CONSTANT); $$->val = $1; } - | VPN_RD { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_RD, .val.ec = $1, }; } - | net_ { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_NET, .val.net = $1, }; } + NUM { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = $1, }); } + | TRUE { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 1, }); } + | FALSE { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 0, }); } + | TEXT { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_STRING, .val.s = $1, }); } + | fipa { $$ = f_new_inst(FI_CONSTANT, $1); } + | VPN_RD { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_RD, .val.ec = $1, }); } + | net_ { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_NET, .val.net = $1, }); } | '[' set_items ']' { DBG( "We've got a set here..." ); - $$ = f_new_inst(FI_CONSTANT); - $$->val = (struct f_val) { .type = T_SET, .val.t = build_tree($2), }; + $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_SET, .val.t = build_tree($2), }); DBG( "ook\n" ); } - | '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = T_PREFIX_SET, .val.ti = $2, }; } - | ENUM { $$ = f_new_inst(FI_CONSTANT); $$->val = (struct f_val) { .type = $1 >> 16, .val.i = $1 & 0xffff, }; } + | '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PREFIX_SET, .val.ti = $2, }); } + | ENUM { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = $1 >> 16, .val.i = $1 & 0xffff, }); } ; constructor: - '(' term ',' term ')' { $$ = f_generate_dpair($2, $4); } - | '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); } - | '(' term ',' term ',' term ')' { $$ = f_generate_lc($2, $4, $6); } - | bgp_path { $$ = f_generate_path_mask($1); } + '(' term ',' term ')' { $$ = f_new_inst(FI_PAIR_CONSTRUCT, $2, $4); } + | '(' ec_kind ',' term ',' term ')' { $$ = f_new_inst(FI_EC_CONSTRUCT, $4, $6, $2); } + | '(' term ',' term ',' term ')' { $$ = f_new_inst(FI_LC_CONSTRUCT, $2, $4, $6); } + | bgp_path { $$ = f_new_inst(FI_PATHMASK_CONSTRUCT, $1, 0); } ; @@ -823,23 +811,7 @@ rtadot: /* EMPTY, we are not permitted RTA. prefix */ function_call: SYM '(' var_list ')' { - struct symbol *sym; - struct f_inst *inst = $3; - if ($1->class != SYM_FUNCTION) - cf_error("You can't call something which is not a function. Really."); - DBG("You are calling function %s\n", $1->name); - $$ = f_new_inst(FI_CALL); - $$->a[0].p = inst; - $$->a[1].p = $1->def; - sym = $1->aux2; - while (sym || inst) { - if (!sym || !inst) - cf_error("Wrong number of arguments for function %s.", $1->name); - DBG( "You should pass parameter called %s\n", sym->name); - inst->a[0].p = sym; - sym = sym->aux2; - inst = inst->next; - } + $$ = f_new_inst(FI_CALL, $1, $3); } ; @@ -847,15 +819,13 @@ symbol: SYM { switch ($1->class & 0xffff) { case SYM_CONSTANT_RANGE: - $$ = f_new_inst(FI_CONSTANT_INDIRECT); - $$->a[0].p = $1; + $$ = f_new_inst(FI_CONSTANT_INDIRECT, $1->def); break; case SYM_VARIABLE_RANGE: - $$ = f_new_inst(FI_VARIABLE); - $$->a[0].p = $1; + $$ = f_new_inst(FI_VARIABLE, $1); break; case SYM_ATTRIBUTE: - $$ = f_new_inst_da(FI_EA_GET, *((struct f_dynamic_attr *) $1->def)); + $$ = f_new_inst(FI_EA_GET, *((struct f_dynamic_attr *) $1->def)); break; default: cf_error("%s: variable expected.", $1->name); @@ -876,22 +846,22 @@ static_attr: term: '(' term ')' { $$ = $2; } - | term '+' term { $$ = f_new_inst(FI_ADD); $$->a[0].p = $1; $$->a[1].p = $3; } - | term '-' term { $$ = f_new_inst(FI_SUBTRACT); $$->a[0].p = $1; $$->a[1].p = $3; } - | term '*' term { $$ = f_new_inst(FI_MULTIPLY); $$->a[0].p = $1; $$->a[1].p = $3; } - | term '/' term { $$ = f_new_inst(FI_DIVIDE); $$->a[0].p = $1; $$->a[1].p = $3; } - | term AND term { $$ = f_new_inst(FI_AND); $$->a[0].p = $1; $$->a[1].p = $3; } - | term OR term { $$ = f_new_inst(FI_OR); $$->a[0].p = $1; $$->a[1].p = $3; } - | term '=' term { $$ = f_new_inst(FI_EQ); $$->a[0].p = $1; $$->a[1].p = $3; } - | term NEQ term { $$ = f_new_inst(FI_NEQ); $$->a[0].p = $1; $$->a[1].p = $3; } - | term '<' term { $$ = f_new_inst(FI_LT); $$->a[0].p = $1; $$->a[1].p = $3; } - | term LEQ term { $$ = f_new_inst(FI_LTE); $$->a[0].p = $1; $$->a[1].p = $3; } - | term '>' term { $$ = f_new_inst(FI_LT); $$->a[0].p = $3; $$->a[1].p = $1; } - | term GEQ term { $$ = f_new_inst(FI_LTE); $$->a[0].p = $3; $$->a[1].p = $1; } - | term '~' term { $$ = f_new_inst(FI_MATCH); $$->a[0].p = $1; $$->a[1].p = $3; } - | term NMA term { $$ = f_new_inst(FI_NOT_MATCH);$$->a[0].p = $1; $$->a[1].p = $3; } - | '!' term { $$ = f_new_inst(FI_NOT); $$->a[0].p = $2; } - | DEFINED '(' term ')' { $$ = f_new_inst(FI_DEFINED); $$->a[0].p = $3; } + | term '+' term { $$ = f_new_inst(FI_ADD, $1, $3); } + | term '-' term { $$ = f_new_inst(FI_SUBTRACT, $1, $3); } + | term '*' term { $$ = f_new_inst(FI_MULTIPLY, $1, $3); } + | term '/' term { $$ = f_new_inst(FI_DIVIDE, $1, $3); } + | term AND term { $$ = f_new_inst(FI_AND, $1, $3); } + | term OR term { $$ = f_new_inst(FI_OR, $1, $3); } + | term '=' term { $$ = f_new_inst(FI_EQ, $1, $3); } + | term NEQ term { $$ = f_new_inst(FI_NEQ, $1, $3); } + | term '<' term { $$ = f_new_inst(FI_LT, $1, $3); } + | term LEQ term { $$ = f_new_inst(FI_LTE, $1, $3); } + | term '>' term { $$ = f_new_inst(FI_LT, $3, $1); } + | term GEQ term { $$ = f_new_inst(FI_LTE, $3, $1); } + | term '~' term { $$ = f_new_inst(FI_MATCH, $1, $3); } + | term NMA term { $$ = f_new_inst(FI_NOT_MATCH, $1, $3); } + | '!' term { $$ = f_new_inst(FI_NOT, $2); } + | DEFINED '(' term ')' { $$ = f_new_inst(FI_DEFINED, $3); } | symbol { $$ = $1; } | constant { $$ = $1; } @@ -899,22 +869,22 @@ term: | PREFERENCE { $$ = f_new_inst(FI_PREF_GET); } - | rtadot static_attr { $$ = f_new_inst_sa(FI_RTA_GET, $2); } + | rtadot static_attr { $$ = f_new_inst(FI_RTA_GET, $2); } - | rtadot dynamic_attr { $$ = f_new_inst_da(FI_EA_GET, $2); } + | rtadot dynamic_attr { $$ = f_new_inst(FI_EA_GET, $2); } - | term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4); $$->a[0].p = $1; } - | term '.' TYPE { $$ = f_new_inst(FI_TYPE); $$->a[0].p = $1; } - | term '.' IP { $$ = f_new_inst(FI_IP); $$->a[0].p = $1; $$->aux = T_IP; } - | term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER); $$->a[0].p = $1; $$->aux = T_RD; } - | term '.' LEN { $$ = f_new_inst(FI_LENGTH); $$->a[0].p = $1; } - | term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN); $$->a[0].p = $1; } - | term '.' ASN { $$ = f_new_inst(FI_ROA_ASN); $$->a[0].p = $1; } - | term '.' SRC { $$ = f_new_inst(FI_SADR_SRC); $$->a[0].p = $1; } - | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK); $$->a[0].p = $1; $$->a[1].p = $5; } - | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST); $$->a[0].p = $1; } - | term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST); $$->a[0].p = $1; } - | term '.' LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG); $$->a[0].p = $1; } + | term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4, $1); } + | term '.' TYPE { $$ = f_new_inst(FI_TYPE, $1); } + | term '.' IP { $$ = f_new_inst(FI_IP, $1); } + | term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER, $1); } + | term '.' LEN { $$ = f_new_inst(FI_LENGTH, $1); } + | term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN, $1); } + | term '.' ASN { $$ = f_new_inst(FI_ROA_ASN, $1); } + | term '.' SRC { $$ = f_new_inst(FI_SADR_SRC, $1); } + | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK, $1, $5); } + | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST, $1); } + | term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST, $1); } + | term '.' LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG, $1); } /* Communities */ /* This causes one shift/reduce conflict @@ -924,19 +894,19 @@ term: | rtadot dynamic_attr '.' RESET{ } */ - | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT); $$->val = f_const_empty_path; } - | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT); $$->val = f_const_empty_clist; } - | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT); $$->val = f_const_empty_eclist; } - | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT); $$->val = f_const_empty_lclist; } - | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND); $$->a[0].p = $3; $$->a[1].p = $5; } - | ADD '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD); $$->a[0].p = $3; $$->a[1].p = $5; } - | DELETE '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_DEL); $$->a[0].p = $3; $$->a[1].p = $5; } - | FILTER '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_FILTER); $$->a[0].p = $3; $$->a[1].p = $5; } + | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_path); } + | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_clist); } + | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_eclist); } + | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_lclist); } + | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND, $3, $5); } + | ADD '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD, $3, $5); } + | DELETE '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_DEL, $3, $5); } + | FILTER '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_FILTER, $3, $5); } - | ROA_CHECK '(' rtable ')' { $$ = f_new_inst(FI_ROA_CHECK_IMPLICIT); $$->a[0].rtc = $3; } - | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_new_inst(FI_ROA_CHECK_EXPLICIT); $$->a[2].rtc = $3; $$->a[0].p = $5; $$->a[1].p = $7; } + | ROA_CHECK '(' rtable ')' { $$ = f_new_inst(FI_ROA_CHECK_IMPLICIT, $3); } + | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_new_inst(FI_ROA_CHECK_EXPLICIT, $5, $7, $3); } - | FORMAT '(' term ')' { $$ = f_new_inst(FI_FORMAT); $$->a[0].p = $3; } + | FORMAT '(' term ')' { $$ = f_new_inst(FI_FORMAT, $3); } /* | term '.' LEN { $$->code = P('P','l'); } */ @@ -953,30 +923,25 @@ break_command: ; print_one: - term { $$ = f_new_inst(FI_PRINT); $$->a[0].p = $1; $$->a[1].p = NULL; } + term { $$ = f_new_inst(FI_PRINT, $1); } ; print_list: /* EMPTY */ { $$ = NULL; } | print_one { $$ = $1; } | print_one ',' print_list { if ($1) { - $1->next = $3; + f_inst_next($1, $3); $$ = $1; } else $$ = $3; } ; var_listn: term { - $$ = f_new_inst(FI_SET); - $$->a[0].p = NULL; - $$->a[1].p = $1; - $$->next = NULL; + $$ = $1; } | term ',' var_listn { - $$ = f_new_inst(FI_SET); - $$->a[0].p = NULL; - $$->a[1].p = $1; - $$->next = $3; + $$ = $1; + f_inst_next($$, $3); } ; @@ -986,58 +951,42 @@ var_list: /* EMPTY */ { $$ = NULL; } cmd: IF term THEN block { - $$ = f_new_inst(FI_CONDITION); - $$->a[0].p = $2; - $$->a[1].p = $4; + $$ = f_new_inst(FI_CONDITION, $2, $4, NULL); } | IF term THEN block ELSE block { - $$ = f_new_inst(FI_CONDITION); - $$->a[0].p = $2; - $$->a[1].p = $4; - $$->a[2].p = $6; + $$ = f_new_inst(FI_CONDITION, $2, $4, $6); } | SYM '=' term ';' { DBG( "Ook, we'll set value\n" ); if ($1->class == SYM_ATTRIBUTE) { - $$ = f_new_inst_da(FI_EA_SET, *((struct f_dynamic_attr *) $1->def)); - $$->a[0].p = $3; + $$ = f_new_inst(FI_EA_SET, *((struct f_dynamic_attr *) $1->def), $3); } else if (($1->class & ~T_MASK) == SYM_VARIABLE) { - $$ = f_new_inst(FI_SET); - $$->a[0].p = $1; - $$->a[1].p = $3; + $$ = f_new_inst(FI_SET, $3, $1); } else cf_error( "Symbol `%s' is read-only.", $1->name ); } | RETURN term ';' { DBG( "Ook, we'll return the value\n" ); - $$ = f_new_inst(FI_RETURN); - $$->a[0].p = $2; + $$ = f_new_inst(FI_RETURN, $2); } | rtadot dynamic_attr '=' term ';' { - $$ = f_new_inst_da(FI_EA_SET, $2); - $$->a[0].p = $4; + $$ = f_new_inst(FI_EA_SET, $2, $4); } | rtadot static_attr '=' term ';' { - $$ = f_new_inst_sa(FI_RTA_SET, $2); - if ($$->sa.readonly) + if ($2.readonly) cf_error( "This static attribute is read-only."); - $$->a[0].p = $4; + $$ = f_new_inst(FI_RTA_SET, $2, $4); } | PREFERENCE '=' term ';' { - $$ = f_new_inst(FI_PREF_SET); - $$->a[0].p = $3; + $$ = f_new_inst(FI_PREF_SET, $3); } | UNSET '(' rtadot dynamic_attr ')' ';' { - $$ = f_new_inst_da(FI_EA_SET, $4); - $$->aux = EAF_TYPE_UNDEF | EAF_TEMP; - $$->a[0].p = NULL; + $$ = f_new_inst(FI_EA_UNSET, $4); } - | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE); $$->a[0].p = $2; $$->a[1].i = $1; } - | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT); $$->a[0].p = $1; } + | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE, $2, $1); } + | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); } | CASE term '{' switch_body '}' { - $$ = f_new_inst(FI_SWITCH); - $$->a[0].p = $2; - $$->a[1].p = build_tree( $4 ); + $$ = f_new_inst(FI_SWITCH, $2, build_tree($4)); } | rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); } diff --git a/filter/dump.m4 b/filter/dump.m4 index 913a7652..cb8e5c5f 100644 --- a/filter/dump.m4 +++ b/filter/dump.m4 @@ -17,9 +17,9 @@ m4_divert(-1)') m4_define(LINEP, `LINE($@)') m4_define(SYMBOL, `m4_divert(1)debug("%ssymbol %s\n", INDENT, item->sym->name); m4_divert(-1)') -m4_define(VALI, `m4_divert(1)debug("%svalue %s\n", INDENT, val_dump(item->vp)); +m4_define(VALI, `m4_divert(1)debug("%svalue %s\n", INDENT, val_dump(&item->val)); m4_divert(-1)') -m4_define(VALI, `m4_divert(1)debug("%svalue %s\n", INDENT, val_dump(item->vp)); +m4_define(VAR, `m4_divert(1)debug("%svar %s: value %s\n", INDENT, item->sym->name, val_dump(item->vp)); m4_divert(-1)') m4_define(FRET, `m4_divert(1)debug("%sfilter return value %d\n", INDENT, item->fret); m4_divert(-1)') diff --git a/filter/f-inst.c b/filter/f-inst.c index 02c88409..ae2b5289 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -108,6 +108,17 @@ INST(FI_PATHMASK_CONSTRUCT, 0, 1) { ARG_ANY(1); COUNT(2); + + NEW([[]], [[ + uint len = 0; + uint dyn = 0; + for (const struct f_inst *tt = f1; tt; tt = tt->next, len++) + if (tt->fi_code != FI_CONSTANT) + dyn++; + + WHAT().count = len; + ]]); + if (vstk.cnt < what->count) /* TODO: make this check systematic */ runtime("Construction of BGP path mask from %u elements must have at least that number of elements", what->count); @@ -239,13 +250,11 @@ RESULT_OK; } INST(FI_VARIABLE, 0, 1) { - VALP(1); // res = * ((struct f_val *) what->a[0].p); - SAME([[if (strcmp(f1->sym->name, f2->sym->name)) return 0; ]]); + VAR; RESULT_OK; } INST(FI_CONSTANT_INDIRECT, 0, 1) { - VALP(1); - SAME([[if (!val_same(f1->vp, f2->vp)) return 0; ]]); + VALP; RESULT_OK; } INST(FI_PRINT, 1, 0) { @@ -261,15 +270,16 @@ } INST(FI_PRINT_AND_DIE, 0, 0) { POSTFIXIFY([[ - if (what->a[0].p) { - pos = postfixify(dest, what->a[0].p, pos); - dest->items[pos].flags |= FIF_PRINTED; - } + { + uint opos = pos; ]]); - LINE_SIZE([[ - if (what->a[0].p) { - cnt += inst_line_size(what->a[0].p); - } + + ARG_ANY(1); + + POSTFIXIFY([[ + if (opos < pos) + dest->items[pos].flags |= FIF_PRINTED; + } ]]); FRET(2); @@ -544,11 +554,6 @@ runtime( "Setting lclist attribute to non-lclist value" ); l->attrs[0].u.ptr = v1.val.ad; break; - case EAF_TYPE_UNDEF: - if (v1.type != T_VOID) - runtime( "Setting void attribute to non-void value" ); - l->attrs[0].u.data = 0; - break; default: bug("Unknown type in e,S"); } @@ -558,6 +563,28 @@ } } + INST(FI_EA_UNSET, 0, 0) { + DYNAMIC_ATTR; + ACCESS_RTE; + ACCESS_EATTRS; + + { + struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr)); + + l->next = NULL; + l->flags = EALF_SORTED; + l->count = 1; + l->attrs[0].id = da.ea_code; + l->attrs[0].flags = 0; + l->attrs[0].type = EAF_TYPE_UNDEF | EAF_TEMP | EAF_ORIGINATED | EAF_FRESH; + l->attrs[0].u.data = 0; + + f_rta_cow(fs); + l->next = *fs->eattrs; + *fs->eattrs = l; + } + } + INST(FI_PREF_GET, 0, 1) { ACCESS_RTE; RESULT(T_INT, i, (*fs->rte)->pref); @@ -660,6 +687,7 @@ if (!estk.cnt) if (vstk.val[retpos].type == T_BOOL) if (vstk.val[retpos].val.i) + return F_ACCEPT; else return F_REJECT; @@ -674,28 +702,43 @@ } INST(FI_CALL, 0, 1) { - /* First push the code */ - LINEP(2,0); + /* Do not use the symbol on execution */ + if (0) { + UNUSED SYMBOL; + } + + /* Postfixify extracts the function body from the symbol */ + POSTFIXIFY([[ + dest->items[pos].lines[0] = what->sym->def; + ]]); + + /* First push the body on stack */ + LINEX(what->lines[0]); curline.emask |= FE_RETURN; /* Then push the arguments */ LINE(1,1); + + NEW([[]], [[ + if (sym->class != SYM_FUNCTION) + cf_error("You can't call something which is not a function. Really."); + + uint count = 0; + for (const struct f_inst *inst = f1; inst; inst = inst->next) + count++; + + if (count != sym->aux2) + cf_error("Function %s takes %u arguments, got %u.", sym->name, sym->aux2, count); + ]]); } INST(FI_DROP_RESULT, 1, 0) { ARG_ANY(1); } - INST(FI_CLEAR_LOCAL_VARS, 0, 0) { /* Clear local variables */ - SYMBOL(1); - for ( ; sym != NULL; sym = sym->aux2) - ((struct f_val *) sym->def)->type = T_VOID; - } INST(FI_SWITCH, 1, 0) { ARG_ANY(1); - POSTFIXIFY([[ - dest->items[pos].tree = what->a[1].p; - ]]); + TREE; const struct f_tree *t = find_tree(what->tree, &v1); if (!t) { v1.type = T_VOID; @@ -940,8 +983,6 @@ INST(FI_ASSERT, 1, 0) { /* Birdtest Assert */ ARG(1, T_BOOL); - POSTFIXIFY([[ - dest->items[pos].s = what->a[1].p; - ]]); + STRING; CALL(bt_assert_hook, res.val.i, what); } diff --git a/filter/f-inst.h b/filter/f-inst.h new file mode 100644 index 00000000..5c3d1d58 --- /dev/null +++ b/filter/f-inst.h @@ -0,0 +1,124 @@ +/* + * BIRD Internet Routing Daemon -- Filter instructions + * + * (c) 2018--2019 Maria Matejka + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +/* Filter instruction words */ +#define FI__TWOCHAR(a,b) ((a<<8) | b) +#define FI__LIST \ + F(FI_NOP, 0, '0') \ + F(FI_ADD, 0, '+') \ + F(FI_SUBTRACT, 0, '-') \ + F(FI_MULTIPLY, 0, '*') \ + F(FI_DIVIDE, 0, '/') \ + F(FI_AND, 0, '&') \ + F(FI_OR, 0, '|') \ + F(FI_PAIR_CONSTRUCT, 'm', 'p') \ + F(FI_EC_CONSTRUCT, 'm', 'c') \ + F(FI_LC_CONSTRUCT, 'm', 'l') \ + F(FI_PATHMASK_CONSTRUCT, 'm', 'P') \ + F(FI_NEQ, '!', '=') \ + F(FI_EQ, '=', '=') \ + F(FI_LT, 0, '<') \ + F(FI_LTE, '<', '=') \ + F(FI_NOT, 0, '!') \ + F(FI_MATCH, 0, '~') \ + F(FI_NOT_MATCH, '!', '~') \ + F(FI_DEFINED, 'd', 'e') \ + F(FI_TYPE, 0, 'T') \ + F(FI_IS_V4, 'I', 'i') \ + F(FI_SET, 0, 's') \ + F(FI_CONSTANT, 0, 'c') \ + F(FI_VARIABLE, 0, 'V') \ + F(FI_CONSTANT_INDIRECT, 0, 'C') \ + F(FI_PRINT, 0, 'p') \ + F(FI_CONDITION, 0, '?') \ + F(FI_PRINT_AND_DIE, 'p', ',') \ + F(FI_RTA_GET, 0, 'a') \ + F(FI_RTA_SET, 'a', 'S') \ + F(FI_EA_GET, 'e', 'a') \ + F(FI_EA_SET, 'e', 'S') \ + F(FI_PREF_GET, 0, 'P') \ + F(FI_PREF_SET, 'P', 'S') \ + F(FI_LENGTH, 0, 'L') \ + F(FI_ROA_MAXLEN, 'R', 'M') \ + F(FI_ROA_ASN, 'R', 'A') \ + F(FI_SADR_SRC, 'n', 's') \ + F(FI_IP, 'c', 'p') \ + F(FI_ROUTE_DISTINGUISHER, 'R', 'D') \ + F(FI_AS_PATH_FIRST, 'a', 'f') \ + F(FI_AS_PATH_LAST, 'a', 'l') \ + F(FI_AS_PATH_LAST_NAG, 'a', 'L') \ + F(FI_RETURN, 0, 'r') \ + F(FI_CALL, 'c', 'a') \ + F(FI_DROP_RESULT, 'd', 'r') \ + F(FI_CLEAR_LOCAL_VARS, 'c', 'V') \ + F(FI_SWITCH, 'S', 'W') \ + F(FI_IP_MASK, 'i', 'M') \ + F(FI_PATH_PREPEND, 'A', 'p') \ + F(FI_CLIST_ADD, 'C', 'a') \ + F(FI_CLIST_DEL, 'C', 'd') \ + F(FI_CLIST_FILTER, 'C', 'f') \ + F(FI_ROA_CHECK_IMPLICIT, 'R', 'i') \ + F(FI_ROA_CHECK_EXPLICIT, 'R', 'e') \ + F(FI_FORMAT, 0, 'F') \ + F(FI_ASSERT, 'a', 's') + +/* The enum itself */ +enum f_instruction_code { +#define F(c,a,b) \ + c, +FI__LIST +#undef F + FI__MAX, +} PACKED; + +/* Convert the instruction back to the enum name */ +const char *f_instruction_name(enum f_instruction_code fi); + + + +/* Instruction structure for config */ +struct f_inst { + const struct f_inst *next; /* Next instruction to be executed */ + union { /* Instruction content */ + struct { /* Instruction code for dispatching purposes */ + enum f_instruction_code fi_code; + }; + + struct { + enum f_instruction_code fi_code_a; + const struct f_inst *p[3]; /* Three arguments at most */ + }; + + struct { + + + + struct { + enum f_instruction_code + + + + + enum f_iknst + u16 aux; /* Extension to instruction code, T_*, EA_*, EAF_* */ + union { + + union f_inst_attr a[3]; /* The three arguments */ + struct f_val val; /* The value if FI_CONSTANT */ + struct { + union f_inst_attr sa_a[1]; + struct f_static_attr sa; /* Static attribute def for FI_RTA_* */ + }; + struct { + union f_inst_attr da_a[1]; + struct f_dynamic_attr da; /* Dynamic attribute def for FI_EA_* */ + }; + }; + int lineno; +}; + diff --git a/filter/f-util.c b/filter/f-util.c index 4f11a6d9..e94331b6 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -10,57 +10,15 @@ #include "nest/bird.h" #include "conf/conf.h" #include "filter/filter.h" +#include "filter/f-inst-struct.h" #include "lib/idm.h" #include "nest/protocol.h" #include "nest/route.h" #define P(a,b) ((a<<8) | b) -struct f_inst * -f_new_inst(enum f_instruction_code fi_code) -{ - struct f_inst * ret; - ret = cfg_allocz(sizeof(struct f_inst)); - ret->fi_code = fi_code; - ret->lineno = ifs->lino; - return ret; -} - -struct f_inst * -f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da) -{ - struct f_inst *ret = f_new_inst(fi_code); - ret->da = da; - return ret; -} - -struct f_inst * -f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa) -{ - struct f_inst *ret = f_new_inst(fi_code); - ret->sa = sa; - return ret; -} - -/* - * Generate set_dynamic( operation( get_dynamic(), argument ) ) - */ -struct f_inst * -f_generate_complex(enum f_instruction_code fi_code, struct f_dynamic_attr da, struct f_inst *argument) -{ - struct f_inst *set_dyn = f_new_inst_da(FI_EA_SET, da), - *oper = f_new_inst(fi_code), - *get_dyn = f_new_inst_da(FI_EA_GET, da); - - oper->a[0].p = get_dyn; - oper->a[1].p = argument; - - set_dyn->a[0].p = oper; - return set_dyn; -} - static const char * const f_instruction_name_str[] = { -#define F(c,a,b) \ +#define F(c,...) \ [c] = #c, FI__LIST #undef F @@ -88,6 +46,58 @@ filter_name(struct filter *filter) return filter->name; } +void f_inst_next(struct f_inst *first, const struct f_inst *append) +{ + first->next = append; +} + +struct filter *f_new_where(const struct f_inst *where) +{ + struct f_inst acc = { + .fi_code = FI_PRINT_AND_DIE, + .lineno = ifs->lino, + .i_FI_PRINT_AND_DIE = { .fret = F_ACCEPT, }, + }; + + struct f_inst rej = { + .fi_code = FI_PRINT_AND_DIE, + .lineno = ifs->lino, + .i_FI_PRINT_AND_DIE = { .fret = F_REJECT, }, + }; + + struct f_inst i = { + .fi_code = FI_CONDITION, + .lineno = ifs->lino, + .i_FI_CONDITION = { + .f1 = where, + .f2 = &acc, + .f3 = &rej, + }, + }; + + struct filter *f = cfg_alloc(sizeof(struct filter)); + f->name = NULL; + f->root = f_postfixify(&i); + return f; +} + +struct f_inst *f_clear_local_vars(struct f_inst *decls) +{ + /* Prepend instructions to clear local variables */ + struct f_inst *head = NULL; + + for (const struct f_inst *si = decls; si; si = si->next) { + struct f_inst *cur = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_VOID }); + if (head) + f_inst_next(cur, head); + else + f_inst_next(cur, si); + head = cur; /* The first FI_CONSTANT put there */ + } + + return head; +} + #define CA_KEY(n) n->name, n->fda.type #define CA_NEXT(n) n->next #define CA_EQ(na,ta,nb,tb) (!strcmp(na,nb) && (ta == tb)) diff --git a/filter/filter.c b/filter/filter.c index 858d5fc5..a69d1b3d 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -47,6 +47,7 @@ #include "nest/attrs.h" #include "conf/conf.h" #include "filter/filter.h" +#include "filter/f-inst-struct.h" #define CMP_ERROR 999 @@ -614,11 +615,11 @@ val_format_str(struct filter_state *fs, struct f_val *v) { static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS; static uint -inst_line_size(const struct f_inst *what) +inst_line_size(const struct f_inst *what_) { uint cnt = 0; - for ( ; what; what = what->next) { - switch (what->fi_code) { + for ( ; what_; what_ = what_->next) { + switch (what_->fi_code) { #include "filter/f-inst-line-size.c" } } @@ -671,10 +672,10 @@ f_dump_line(const struct f_line *dest, int indent) #endif static uint -postfixify(struct f_line *dest, const struct f_inst *what, uint pos) +postfixify(struct f_line *dest, const struct f_inst *what_, uint pos) { - for ( ; what; what = what->next) { - switch (what->fi_code) { + for ( ; what_; what_ = what_->next) { + switch (what_->fi_code) { #include "filter/f-inst-postfixify.c" } pos++; @@ -683,23 +684,16 @@ postfixify(struct f_line *dest, const struct f_inst *what, uint pos) } struct f_line * -f_postfixify_concat(struct f_inst *first, ...) +f_postfixify_concat(const struct f_inst * const inst[], uint count) { - va_list args; - va_list argd; - va_start(args, first); - va_copy(argd, args); - uint len = 0; - for (struct f_inst *what = first; what; what = va_arg(args, struct f_inst *)) - len += inst_line_size(what); - - va_end(args); + for (uint i=0; ilen = postfixify(out, what, out->len); + for (uint i=0; ilen = postfixify(out, inst[i], out->len); f_dump_line(out, 0); return out; diff --git a/filter/filter.h b/filter/filter.h index 87bd2c36..39f16e93 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -2,6 +2,7 @@ * BIRD Internet Routing Daemon -- Filters * * (c) 1999 Pavel Machek + * (c) 2018--2019 Maria Matejka * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -11,6 +12,7 @@ #include "lib/resource.h" #include "lib/ip.h" +#include "lib/macro.h" #include "nest/route.h" #include "nest/attrs.h" @@ -115,71 +117,80 @@ struct f_static_attr { int readonly:1; /* Don't allow writing */ }; -/* Filter instruction words */ -#define FI__TWOCHAR(a,b) ((a<<8) | b) +/* Possible return values of filter execution */ +enum filter_return { + F_NOP = 0, + F_NONL, + F_RETURN, + F_ACCEPT, /* Need to preserve ordering: accepts < rejects! */ + F_REJECT, + F_ERROR, + F_QUITBIRD, +}; + +/* Filter instruction declarations */ #define FI__LIST \ - F(FI_NOP, 0, '0') \ - F(FI_ADD, 0, '+') \ - F(FI_SUBTRACT, 0, '-') \ - F(FI_MULTIPLY, 0, '*') \ - F(FI_DIVIDE, 0, '/') \ - F(FI_AND, 0, '&') \ - F(FI_OR, 0, '|') \ - F(FI_PAIR_CONSTRUCT, 'm', 'p') \ - F(FI_EC_CONSTRUCT, 'm', 'c') \ - F(FI_LC_CONSTRUCT, 'm', 'l') \ - F(FI_PATHMASK_CONSTRUCT, 'm', 'P') \ - F(FI_NEQ, '!', '=') \ - F(FI_EQ, '=', '=') \ - F(FI_LT, 0, '<') \ - F(FI_LTE, '<', '=') \ - F(FI_NOT, 0, '!') \ - F(FI_MATCH, 0, '~') \ - F(FI_NOT_MATCH, '!', '~') \ - F(FI_DEFINED, 'd', 'e') \ - F(FI_TYPE, 0, 'T') \ - F(FI_IS_V4, 'I', 'i') \ - F(FI_SET, 0, 's') \ - F(FI_CONSTANT, 0, 'c') \ - F(FI_VARIABLE, 0, 'V') \ - F(FI_CONSTANT_INDIRECT, 0, 'C') \ - F(FI_PRINT, 0, 'p') \ - F(FI_CONDITION, 0, '?') \ - F(FI_PRINT_AND_DIE, 'p', ',') \ - F(FI_RTA_GET, 0, 'a') \ - F(FI_RTA_SET, 'a', 'S') \ - F(FI_EA_GET, 'e', 'a') \ - F(FI_EA_SET, 'e', 'S') \ - F(FI_PREF_GET, 0, 'P') \ - F(FI_PREF_SET, 'P', 'S') \ - F(FI_LENGTH, 0, 'L') \ - F(FI_ROA_MAXLEN, 'R', 'M') \ - F(FI_ROA_ASN, 'R', 'A') \ - F(FI_SADR_SRC, 'n', 's') \ - F(FI_IP, 'c', 'p') \ - F(FI_ROUTE_DISTINGUISHER, 'R', 'D') \ - F(FI_AS_PATH_FIRST, 'a', 'f') \ - F(FI_AS_PATH_LAST, 'a', 'l') \ - F(FI_AS_PATH_LAST_NAG, 'a', 'L') \ - F(FI_RETURN, 0, 'r') \ - F(FI_CALL, 'c', 'a') \ - F(FI_DROP_RESULT, 'd', 'r') \ - F(FI_CLEAR_LOCAL_VARS, 'c', 'V') \ - F(FI_SWITCH, 'S', 'W') \ - F(FI_IP_MASK, 'i', 'M') \ - F(FI_PATH_PREPEND, 'A', 'p') \ - F(FI_CLIST_ADD, 'C', 'a') \ - F(FI_CLIST_DEL, 'C', 'd') \ - F(FI_CLIST_FILTER, 'C', 'f') \ - F(FI_ROA_CHECK_IMPLICIT, 'R', 'i') \ - F(FI_ROA_CHECK_EXPLICIT, 'R', 'e') \ - F(FI_FORMAT, 0, 'F') \ - F(FI_ASSERT, 'a', 's') + F(FI_NOP) \ + F(FI_ADD, ARG, ARG) \ + F(FI_SUBTRACT, ARG, ARG) \ + F(FI_MULTIPLY, ARG, ARG) \ + F(FI_DIVIDE, ARG, ARG) \ + F(FI_AND, ARG, LINE) \ + F(FI_OR, ARG, LINE) \ + F(FI_PAIR_CONSTRUCT, ARG, ARG) \ + F(FI_EC_CONSTRUCT, ARG, ARG, ECS) \ + F(FI_LC_CONSTRUCT, ARG, ARG, ARG) \ + F(FI_PATHMASK_CONSTRUCT, ARG, COUNT) \ + F(FI_NEQ, ARG, ARG) \ + F(FI_EQ, ARG, ARG) \ + F(FI_LT, ARG, ARG) \ + F(FI_LTE, ARG, ARG) \ + F(FI_NOT, ARG) \ + F(FI_MATCH, ARG, ARG) \ + F(FI_NOT_MATCH, ARG, ARG) \ + F(FI_DEFINED, ARG) \ + F(FI_TYPE, ARG) \ + F(FI_IS_V4, ARG) \ + F(FI_SET, ARG, SYMBOL) \ + F(FI_CONSTANT, VALI) \ + F(FI_VARIABLE, SYMBOL) \ + F(FI_CONSTANT_INDIRECT, VALP) \ + F(FI_PRINT, ARG) \ + F(FI_CONDITION, ARG, LINE, LINE) \ + F(FI_PRINT_AND_DIE, ARG, FRET) \ + F(FI_RTA_GET, SA) \ + F(FI_RTA_SET, SA, ARG) \ + F(FI_EA_GET, EA) \ + F(FI_EA_SET, EA, ARG) \ + F(FI_EA_UNSET, EA) \ + F(FI_PREF_GET) \ + F(FI_PREF_SET, ARG) \ + F(FI_LENGTH, ARG) \ + F(FI_ROA_MAXLEN, ARG) \ + F(FI_ROA_ASN, ARG) \ + F(FI_SADR_SRC, ARG) \ + F(FI_IP, ARG) \ + F(FI_ROUTE_DISTINGUISHER, ARG) \ + F(FI_AS_PATH_FIRST, ARG) \ + F(FI_AS_PATH_LAST, ARG) \ + F(FI_AS_PATH_LAST_NAG, ARG) \ + F(FI_RETURN, ARG) \ + F(FI_CALL, SYMBOL, LINE) \ + F(FI_DROP_RESULT, ARG) \ + F(FI_SWITCH, ARG, TREE) \ + F(FI_IP_MASK, ARG, ARG) \ + F(FI_PATH_PREPEND, ARG, ARG) \ + F(FI_CLIST_ADD, ARG, ARG) \ + F(FI_CLIST_DEL, ARG, ARG) \ + F(FI_CLIST_FILTER, ARG, ARG) \ + F(FI_ROA_CHECK_IMPLICIT, RTC) \ + F(FI_ROA_CHECK_EXPLICIT, ARG, ARG, RTC) \ + F(FI_FORMAT, ARG) \ + F(FI_ASSERT, ARG, STRING) /* The enum itself */ enum f_instruction_code { -#define F(c,a,b) \ - c, +#define F(c, ...) c, FI__LIST #undef F FI__MAX, @@ -188,47 +199,50 @@ FI__LIST /* Convert the instruction back to the enum name */ const char *f_instruction_name(enum f_instruction_code fi); +struct f_inst; +void f_inst_next(struct f_inst *first, const struct f_inst *append); +struct f_inst *f_clear_local_vars(struct f_inst *decls); + +#define FIA(x) , FIA_##x +#define FIA_ARG const struct f_inst * +#define FIA_LINE const struct f_inst * +#define FIA_COUNT uint +#define FIA_SYMBOL const struct symbol * +#define FIA_VALI struct f_val +#define FIA_VALP const struct f_val * +#define FIA_FRET enum filter_return +#define FIA_ECS enum ec_subtype +#define FIA_SA struct f_static_attr +#define FIA_EA struct f_dynamic_attr +#define FIA_RTC const struct rtable_config * +#define FIA_TREE const struct f_tree * +#define FIA_STRING const char * +#define F(c, ...) \ + struct f_inst *f_new_inst_##c(enum f_instruction_code MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))()(MACRO_FOREACH(FIA, __VA_ARGS__))); +FI__LIST +#undef F +#undef FIA_ARG +#undef FIA_LINE +#undef FIA_LINEP +#undef FIA_COUNT +#undef FIA_SYMBOL +#undef FIA_VALI +#undef FIA_VALP +#undef FIA_FRET +#undef FIA_ECS +#undef FIA_SA +#undef FIA_EA +#undef FIA_RTC +#undef FIA_STRING +#undef FIA + +#define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__) + +/* Flags for instructions */ enum f_instruction_flags { FIF_PRINTED = 1, /* FI_PRINT_AND_DIE: message put in buffer */ }; -union f_inst_attr { - uint i; - void *p; - struct rtable_config *rtc; -}; - -/* Instruction structure for config */ -struct f_inst { - struct f_inst *next; /* Next instruction to be executed */ - enum f_instruction_code fi_code; /* The instruction itself */ - u16 aux; /* Extension to instruction code, T_*, EA_*, EAF_* */ - union { - union f_inst_attr a[3]; /* The three arguments */ - struct f_val val; /* The value if FI_CONSTANT */ - struct { - union f_inst_attr sa_a[1]; - struct f_static_attr sa; /* Static attribute def for FI_RTA_* */ - }; - struct { - union f_inst_attr da_a[1]; - struct f_dynamic_attr da; /* Dynamic attribute def for FI_EA_* */ - }; - }; - int lineno; -}; - -/* Possible return values of filter execution */ -enum filter_return { - F_NOP = 0, - F_NONL, - F_RETURN, - F_ACCEPT, /* Need to preserve ordering: accepts < rejects! */ - F_REJECT, - F_ERROR, - F_QUITBIRD, -}; - /* Filter structures for execution */ struct f_line; @@ -242,6 +256,7 @@ struct f_line_item { const struct f_val *vp; const struct symbol *sym; }; + struct f_val val; const struct f_line *lines[2]; enum filter_return fret; struct f_static_attr sa; @@ -267,9 +282,9 @@ struct filter { }; /* Convert the f_inst infix tree to the f_line structures */ -struct f_line *f_postfixify_concat(struct f_inst *root, ...); -static inline struct f_line *f_postfixify(struct f_inst *root) -{ return f_postfixify_concat(root, NULL); } +struct f_line *f_postfixify_concat(const struct f_inst * const inst[], uint count); +static inline struct f_line *f_postfixify(const struct f_inst *root) +{ return f_postfixify_concat(&root, 1); } #define F_VAL_STACK_MAX 4096 @@ -295,12 +310,9 @@ struct f_exec_stack { enum f_exception emask; /* Exception mask */ } item[F_EXEC_STACK_MAX]; uint cnt; /* Current stack size; 0 for empty */ - }; -struct f_inst *f_new_inst(enum f_instruction_code fi_code); -struct f_inst *f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da); -struct f_inst *f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa); +struct filter *f_new_where(const struct f_inst *); static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, u8 bit, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */ { return (struct f_dynamic_attr) { .type = type, .bit = bit, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */ static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly) diff --git a/filter/interpret.m4 b/filter/interpret.m4 index 829b48f6..f449d580 100644 --- a/filter/interpret.m4 +++ b/filter/interpret.m4 @@ -45,17 +45,22 @@ m4_define(ARG_ANY, `') m4_define(SYMBOL, `const struct symbol *sym = what->sym') -m4_define(VALI, `res = *what->vp') -m4_define(VALP, `res = *what->vp') +m4_define(VALI, `res = what->val') +m4_define(VALP, `res = what->val') +m4_define(VAR, `res = *what->vp') m4_define(FRET, `enum filter_return fret = what->fret') m4_define(ECS, `enum ec_subtype ecs = what->ecs') m4_define(RTC, `struct rtable *table = what->rtc->table') m4_define(STATIC_ATTR, `struct f_static_attr sa = what->sa') m4_define(DYNAMIC_ATTR, `struct f_dynamic_attr da = what->da') +m4_define(TREE, `') +m4_define(STRING, `') +m4_define(COUNT, `') m4_define(POSTFIXIFY, `') m4_define(LINE_SIZE, `') m4_define(SAME, `') -m4_define(COUNT, `') +m4_define(STRUCT, `') +m4_define(NEW, `') m4_m4wrap(` m4_divert(0)DNL diff --git a/filter/line-size.m4 b/filter/line-size.m4 index 0c005fa1..2c6b500b 100644 --- a/filter/line-size.m4 +++ b/filter/line-size.m4 @@ -10,13 +10,16 @@ m4_divert(-1)m4_dnl # Common aliases m4_define(DNL, `m4_dnl') -m4_define(INST, `m4_divert(1)break; case $1: cnt += 1; +m4_define(INST, `m4_divert(1) +#undef what +break; case $1: cnt += 1; +#define what ((const struct f_inst_$1 *) &(what_->i_$1)) m4_divert(-1)') -m4_define(ARG, `m4_divert(1)cnt += inst_line_size(what->a[$1-1].p); +m4_define(ARG, `m4_divert(1)cnt += inst_line_size(what->f$1); m4_divert(-1)') -m4_define(ARG_T, `m4_divert(1)cnt += inst_line_size(what->a[$1-1].p); +m4_define(ARG_T, `m4_divert(1)cnt += inst_line_size(what->f$1); m4_divert(-1)') -m4_define(ARG_ANY, `m4_divert(1)cnt += inst_line_size(what->a[$1-1].p); +m4_define(ARG_ANY, `m4_divert(1)cnt += inst_line_size(what->f$1); m4_divert(-1)') m4_define(LINE_SIZE, `m4_divert(1)$1m4_divert(-1)') @@ -24,7 +27,8 @@ m4_m4wrap(` m4_divert(0)DNL case FI_NOP: bug("This shall not happen"); m4_undivert(1) -break; default: bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff); +#undef what +break; default: bug( "Unknown instruction %d (%c)", what_->fi_code, what_->fi_code & 0xff); ') m4_changequote([[,]]) diff --git a/filter/new.m4 b/filter/new.m4 new file mode 100644 index 00000000..ebb367d0 --- /dev/null +++ b/filter/new.m4 @@ -0,0 +1,84 @@ +m4_divert(-1)m4_dnl +# +# BIRD -- Construction of per-instruction structures +# +# (c) 2018 Maria Matejka +# +# Can be freely distributed and used under the terms of the GNU GPL. +# +# +# Diversions: +# 1 for prepared output +# 2 for function arguments +# 3 for function body + +# Common aliases +m4_define(DNL, `m4_dnl') + +m4_define(FNSTOP, `m4_divert(-1)') +m4_define(FNOUT, `m4_divert(1)') +m4_define(FNARG, `m4_divert(2)') +m4_define(FNBODY, `m4_divert(3)') + +m4_define(INST, `m4_define([[INST_NAME]], [[$1]])FNOUT()DNL +m4_undivert(2)DNL +m4_undivert(3)DNL + return what; +} + +struct f_inst *f_new_inst_$1(enum f_instruction_code fi_code +FNBODY()) { + struct f_inst *what = cfg_allocz(sizeof(struct f_inst)); + what->fi_code = fi_code; + what->lineno = ifs->lino; +FNSTOP()') + +m4_define(WHAT, `what->i_[[]]INST_NAME()') + +m4_define(FNMETAARG, `FNARG(), $1 $2 +FNBODY() WHAT().$2 = $2; +FNSTOP()') +m4_define(ARG, `FNMETAARG(const struct f_inst *, f$1)') +m4_define(ARG_ANY, `FNMETAARG(const struct f_inst *, f$1)') +m4_define(LINE, `FNMETAARG(const struct f_inst *, f$1)') +m4_define(SYMBOL, `FNMETAARG(const struct symbol *, sym)') +m4_define(VALI, `FNMETAARG(struct f_val, vali)') +m4_define(VALP, `FNMETAARG(const struct f_val *, valp)') +m4_define(VAR, `FNARG(), const struct symbol * sym +FNBODY() WHAT().valp = (WHAT().sym = sym)->def; +FNSTOP()') +m4_define(FRET, `FNMETAARG(enum filter_return, fret)') +m4_define(ECS, `FNMETAARG(enum ec_subtype, ecs)') +m4_define(RTC, `FNMETAARG(const struct rtable_config *, rtc)') +m4_define(STATIC_ATTR, `FNMETAARG(struct f_static_attr, sa)') +m4_define(DYNAMIC_ATTR, `FNMETAARG(struct f_dynamic_attr, da)') +m4_define(COUNT, `FNMETAARG(uint, count)') +m4_define(TREE, `FNMETAARG(const struct f_tree *, tree)') +m4_define(STRING, `FNMETAARG(const char *, s)') +m4_define(NEW, `FNARG()$1 +FNBODY()$2 +FNSTOP()') + +m4_m4wrap(` +FNOUT() +m4_undivert(2) +m4_undivert(3) + +m4_divert(0) +#include "nest/bird.h" +#include "conf/conf.h" +#include "filter/filter.h" +#include "filter/f-inst-struct.h" + +struct f_inst *f_new_inst_FI_NOP(enum f_instruction_code fi_code) { + struct f_inst *what = cfg_allocz(sizeof(struct f_inst)); + what->fi_code = fi_code; + what->lineno = ifs->lino; + +m4_undivert(1) + + return what; +} +') + +m4_changequote([[,]]) diff --git a/filter/postfixify.m4 b/filter/postfixify.m4 index 8c96ba64..36cadfba 100644 --- a/filter/postfixify.m4 +++ b/filter/postfixify.m4 @@ -10,37 +10,45 @@ m4_divert(-1)m4_dnl # Common aliases m4_define(DNL, `m4_dnl') -m4_define(POSTFIXIFY_TRAILER, `dest->items[pos].fi_code = what->fi_code; -dest->items[pos].lineno = what->lineno;') +m4_define(POSTFIXIFY_TRAILER, `dest->items[pos].fi_code = what_->fi_code; +dest->items[pos].lineno = what_->lineno;') m4_define(INST, `m4_divert(1)POSTFIXIFY_TRAILER -break; case $1: +#undef what +break; case $1: +#define what ((const struct f_inst_$1 *) &(what_->i_$1)) m4_divert(-1)')) -m4_define(ARG, `m4_divert(1)pos = postfixify(dest, what->a[$1-1].p, pos); +m4_define(ARG, `m4_divert(1)pos = postfixify(dest, what->f$1, pos); m4_divert(-1)') -m4_define(ARG_ANY, `m4_divert(1)pos = postfixify(dest, what->a[$1-1].p, pos); +m4_define(ARG_ANY, `m4_divert(1)pos = postfixify(dest, what->f$1, pos); m4_divert(-1)') -m4_define(LINE, `m4_divert(1)dest->items[pos].lines[$2] = f_postfixify(what->a[$1-1].p); +m4_define(LINE, `m4_divert(1)dest->items[pos].lines[$2] = f_postfixify(what->f$1); m4_divert(-1)') -m4_define(LINEP, `m4_divert(1)dest->items[pos].lines[$2] = what->a[$1-1].p; +m4_define(LINEP, `m4_divert(1)dest->items[pos].lines[$2] = what->fl$1; m4_divert(-1)') -m4_define(SYMBOL, `m4_divert(1)dest->items[pos].sym = what->a[$1-1].p; +m4_define(SYMBOL, `m4_divert(1)dest->items[pos].sym = what->sym; m4_divert(-1)') -m4_define(VALI, `m4_divert(1)dest->items[pos].vp = &(what->val); +m4_define(VALI, `m4_divert(1)dest->items[pos].val = what->vali; m4_divert(-1)') -m4_define(VALP, `m4_divert(1)dest->items[pos].vp = (dest->items[pos].sym = what->a[$1-1].p)->def; +m4_define(VALP, `m4_divert(1)dest->items[pos].val = *(what->valp); m4_divert(-1)') -m4_define(FRET, `m4_divert(1)dest->items[pos].fret = what->a[$1-1].i; +m4_define(VAR, `m4_divert(1)dest->items[pos].vp = (dest->items[pos].sym = what->sym)->def; m4_divert(-1)') -m4_define(ECS, `m4_divert(1)dest->items[pos].ecs = what->aux; +m4_define(FRET, `m4_divert(1)dest->items[pos].fret = what->fret; m4_divert(-1)') -m4_define(RTC, `m4_divert(1)dest->items[pos].rtc = what->a[$1-1].rtc; +m4_define(ECS, `m4_divert(1)dest->items[pos].ecs = what->ecs; +m4_divert(-1)') +m4_define(RTC, `m4_divert(1)dest->items[pos].rtc = what->rtc; m4_divert(-1)') m4_define(STATIC_ATTR, `m4_divert(1)dest->items[pos].sa = what->sa; m4_divert(-1)') m4_define(DYNAMIC_ATTR, `m4_divert(1)dest->items[pos].da = what->da; m4_divert(-1)') -m4_define(COUNT, `m4_divert(1)dest->items[pos].count = what->a[$1-1].i; +m4_define(COUNT, `m4_divert(1)dest->items[pos].count = what->count; +m4_divert(-1)') +m4_define(TREE, `m4_divert(1)dest->items[pos].tree = what->tree; +m4_divert(-1)') +m4_define(STRING, `m4_divert(1)dest->items[pos].s = what->s; m4_divert(-1)') m4_define(POSTFIXIFY, `m4_divert(1)$1m4_divert(-1)') @@ -49,7 +57,8 @@ m4_divert(0)DNL case FI_NOP: bug("This shall not happen"); m4_undivert(1) POSTFIXIFY_TRAILER -break; default: bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff); +#undef what +break; default: bug( "Unknown instruction %d (%c)", what_->fi_code, what_->fi_code & 0xff); ') m4_changequote([[,]]) diff --git a/filter/same.m4 b/filter/same.m4 index 73f2d1c3..10979449 100644 --- a/filter/same.m4 +++ b/filter/same.m4 @@ -29,7 +29,9 @@ m4_divert(-1)') m4_define(VALI, `m4_divert(1)if (!val_same(f1->vp, f2->vp)) return 0; m4_divert(-1)') -m4_define(VALP, `') +m4_define(VALP, `m4_divert(1)if (!val_same(f1->vp, f2->vp)) return 0; +m4_divert(-1)') +m4_define(VAR, `SYMBOL()VALP()') m4_define(FRET, `m4_divert(1)if (f1->fret != f2->fret) return 0; m4_divert(-1)') diff --git a/filter/struct.m4 b/filter/struct.m4 new file mode 100644 index 00000000..66205bfd --- /dev/null +++ b/filter/struct.m4 @@ -0,0 +1,67 @@ +m4_divert(-1)m4_dnl +# +# BIRD -- Definition of per-instruction structures +# +# (c) 2018 Maria Matejka +# +# Can be freely distributed and used under the terms of the GNU GPL. +# + +# Common aliases +m4_define(DNL, `m4_dnl') + +m4_define(INST, `m4_divert(2)struct f_inst_$1 i_$1; +m4_divert(1)}; +struct f_inst_$1 { +m4_divert(-1)')) +m4_define(ARG, `m4_divert(1)const struct f_inst *f$1; +m4_divert(-1)') +m4_define(ARG_ANY, `m4_divert(1)const struct f_inst *f$1; +m4_divert(-1)') +m4_define(LINE, `m4_divert(1)const struct f_inst *f$1; +m4_divert(-1)') +m4_define(LINEP, `m4_divert(1)const struct f_line *fl$1; +m4_divert(-1)') +m4_define(SYMBOL, `m4_divert(1)const struct symbol *sym; +m4_divert(-1)') +m4_define(VALI, `m4_divert(1)struct f_val vali; +m4_divert(-1)') +m4_define(VALP, `m4_divert(1)const struct f_val *valp; +m4_divert(-1)') +m4_define(VAR, `VALP()SYMBOL()') +m4_define(FRET, `m4_divert(1)enum filter_return fret; +m4_divert(-1)') +m4_define(ECS, `m4_divert(1)enum ec_subtype ecs; +m4_divert(-1)') +m4_define(RTC, `m4_divert(1)const struct rtable_config *rtc; +m4_divert(-1)') +m4_define(STATIC_ATTR, `m4_divert(1)struct f_static_attr sa; +m4_divert(-1)') +m4_define(DYNAMIC_ATTR, `m4_divert(1)struct f_dynamic_attr da; +m4_divert(-1)') +m4_define(COUNT, `m4_divert(1)uint count; +m4_divert(-1)') +m4_define(TREE, `m4_divert(1)const struct f_tree *tree; +m4_divert(-1)') +m4_define(STRING, `m4_divert(1)const char *s; +m4_divert(-1)') +m4_define(STRUCT, `m4_divert(1)$1 +m4_divert(-1)') + +m4_m4wrap(` +m4_divert(0)DNL +struct f_inst_FI_NOP { +m4_undivert(1) +}; + +struct f_inst { + const struct f_inst *next; /* Next instruction */ + enum f_instruction_code fi_code; /* Instruction code */ + int lineno; /* Line number */ + union { + m4_undivert(2) + }; +}; +') + +m4_changequote([[,]]) diff --git a/nest/attrs.h b/nest/attrs.h index d9d97136..37227d9b 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -123,7 +123,7 @@ enum ec_subtype { EC_RT = 0x0002, EC_RO = 0x0003, EC_GENERIC = 0xFFFF, -} PACKED; +}; /* Transitive bit (for first u32 half of EC) */ #define EC_TBIT 0x40000000 diff --git a/proto/static/config.Y b/proto/static/config.Y index 56caef24..527046ee 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -14,7 +14,7 @@ CF_DEFINES #define STATIC_CFG ((struct static_config *) this_proto) static struct static_route *this_srt, *this_snh; -static struct f_inst *this_srt_cmds, **this_srt_last_cmd; +static struct f_inst *this_srt_cmds, *this_srt_last_cmd; static struct static_route * static_nexthop_new(void) @@ -111,7 +111,7 @@ stat_route0: ROUTE net_any { add_tail(&STATIC_CFG->routes, &this_srt->n); this_srt->net = $2; this_srt_cmds = NULL; - this_srt_last_cmd = &this_srt_cmds; + this_srt_last_cmd = NULL; this_srt->mp_next = NULL; this_snh = NULL; } @@ -137,7 +137,13 @@ stat_route: ; stat_route_item: - cmd { *this_srt_last_cmd = $1; this_srt_last_cmd = &($1->next); } + cmd { + if (this_srt_last_cmd) + f_inst_next(this_srt_last_cmd, $1); + else + this_srt_cmds = $1; + this_srt_last_cmd = $1; + } ; stat_route_opts: -- cgit v1.2.3 From c0e958e022aac79f69e6aca2652fdb6a529e68e2 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Wed, 30 Jan 2019 14:03:47 +0100 Subject: Filter + Config: Fix bugs, tests and split symbols by type --- conf/cf-lex.l | 22 ++++++-- conf/conf.h | 4 -- conf/confbase.Y | 35 ++++++++---- filter/config.Y | 144 ++++++++++++++++++++++++++++---------------------- filter/f-inst.c | 13 +++-- filter/filter.h | 22 +++++++- filter/filter_test.c | 35 +++++++----- filter/test.conf | 11 +++- nest/config.Y | 52 +++++++++--------- proto/babel/config.Y | 8 +-- proto/bfd/config.Y | 4 +- proto/ospf/config.Y | 16 +++--- proto/ospf/ospf.c | 2 +- proto/ospf/ospf.h | 2 +- proto/rip/config.Y | 4 +- proto/static/config.Y | 2 +- 16 files changed, 224 insertions(+), 152 deletions(-) (limited to 'proto/static') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 9bbb3660..5e7c8418 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -285,7 +285,18 @@ else: { } cf_lval.s = cf_get_symbol(yytext); - return SYM; + switch (cf_lval.s->class) { + case SYM_VOID: return CF_SYM_VOID; + case SYM_PROTO: return CF_SYM_PROTO; + case SYM_TEMPLATE: return CF_SYM_TEMPLATE; + case SYM_FUNCTION: return CF_SYM_FUNCTION; + case SYM_FILTER: return CF_SYM_FILTER; + case SYM_TABLE: return CF_SYM_TABLE; + case SYM_ATTRIBUTE: return CF_SYM_ATTRIBUTE; + case SYM_VARIABLE_RANGE: return CF_SYM_VARIABLE; + case SYM_CONSTANT_RANGE: return CF_SYM_CONSTANT; + default: bug("Unknown symbol class %d", cf_lval.s->class); + } } (.|\n) { @@ -723,9 +734,6 @@ cf_pop_scope(void) char * cf_symbol_class_name(struct symbol *sym) { - if (cf_symbol_is_constant(sym)) - return "constant"; - switch (sym->class) { case SYM_VOID: @@ -740,6 +748,12 @@ cf_symbol_class_name(struct symbol *sym) return "filter"; case SYM_TABLE: return "routing table"; + case SYM_ATTRIBUTE: + return "custom attribute"; + case SYM_CONSTANT_RANGE: + return "constant"; + case SYM_VARIABLE_RANGE: + return "variable"; default: return "unknown type"; } diff --git a/conf/conf.h b/conf/conf.h index 6138ccec..4e3addb3 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -165,10 +165,6 @@ void cf_push_scope(struct symbol *); void cf_pop_scope(void); char *cf_symbol_class_name(struct symbol *sym); -static inline int cf_symbol_is_constant(struct symbol *sym) -{ return (sym->class & 0xff00) == SYM_CONSTANT; } - - /* Parser */ extern char *cf_text; diff --git a/conf/confbase.Y b/conf/confbase.Y index 13f6aade..2195e8fc 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -55,6 +55,7 @@ CF_DECLS enum ec_subtype ecs; struct f_dynamic_attr fda; struct f_static_attr fsa; + struct f_lval flv; struct filter *f; struct f_tree *e; struct f_trie *trie; @@ -81,7 +82,7 @@ CF_DECLS %token IP4 %token IP6 %token VPN_RD -%token SYM +%token CF_SYM_VOID CF_SYM_PROTO CF_SYM_TEMPLATE CF_SYM_FUNCTION CF_SYM_FILTER CF_SYM_TABLE CF_SYM_ATTRIBUTE CF_SYM_VARIABLE CF_SYM_CONSTANT %token TEXT %type ipa_scope @@ -93,6 +94,7 @@ CF_DECLS %type label_stack_start label_stack %type text opttext +%type symbol %nonassoc PREFIX_DUMMY %left AND OR @@ -125,7 +127,7 @@ conf: ';' ; conf: definition ; definition: - DEFINE SYM '=' term ';' { + DEFINE CF_SYM_VOID '=' term ';' { struct f_val *val = cfg_alloc(sizeof(struct f_val)); if (f_eval(f_postfixify($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error"); cf_define_symbol($2, SYM_CONSTANT | val->type, val); @@ -135,18 +137,29 @@ definition: expr: NUM | '(' term ')' { $$ = f_eval_int(f_postfixify($2)); } - | SYM { + | CF_SYM_CONSTANT { if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number expected"); $$ = SYM_VAL($1).i; } ; - expr_us: expr S { $$ = $1 S_; } | expr MS { $$ = $1 MS_; } | expr US { $$ = $1 US_; } ; +symbol: + CF_SYM_VOID + | CF_SYM_PROTO + | CF_SYM_TEMPLATE + | CF_SYM_FUNCTION + | CF_SYM_FILTER + | CF_SYM_TABLE + | CF_SYM_ATTRIBUTE + | CF_SYM_VARIABLE + | CF_SYM_CONSTANT + ; + /* Switches */ bool: @@ -164,7 +177,7 @@ bool: ipa: IP4 { $$ = ipa_from_ip4($1); } | IP6 { $$ = ipa_from_ip6($1); } - | SYM { + | CF_SYM_CONSTANT { if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected"); $$ = SYM_VAL($1).ip; } @@ -172,7 +185,7 @@ ipa: ipa_scope: /* empty */ { $$ = NULL; } - | '%' SYM { $$ = if_get_by_name($2->name); } + | '%' symbol { $$ = if_get_by_name($2->name); } ; @@ -279,7 +292,7 @@ net_: net_ip6: net_ip6_ - | SYM { + | CF_SYM_CONSTANT { if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6)) cf_error("IPv6 network expected"); $$ = * SYM_VAL($1).net; @@ -288,7 +301,7 @@ net_ip6: net_ip: net_ip_ - | SYM { + | CF_SYM_CONSTANT { if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net)) cf_error("IP network expected"); $$ = * SYM_VAL($1).net; @@ -297,7 +310,7 @@ net_ip: net_any: net_ - | SYM { + | CF_SYM_CONSTANT { if ($1->class != (SYM_CONSTANT | T_NET)) cf_error("Network expected"); $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */ @@ -309,7 +322,7 @@ net_or_ipa: | net_ip6_ | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); } | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); } - | SYM { + | CF_SYM_CONSTANT { if ($1->class == (SYM_CONSTANT | T_IP)) net_fill_ip_host(&($$), SYM_VAL($1).ip); else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net)) @@ -346,7 +359,7 @@ time: text: TEXT - | SYM { + | CF_SYM_CONSTANT { if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String expected"); $$ = SYM_VAL($1).s; } diff --git a/filter/config.Y b/filter/config.Y index 607f534e..1306849f 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -17,7 +17,7 @@ static inline u32 pair_a(u32 p) { return p >> 16; } static inline u32 pair_b(u32 p) { return p & 0xFFFF; } #define f_generate_complex(fi_code, da, arg) \ - f_new_inst(FI_EA_SET, da, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg)) + f_new_inst(FI_EA_SET, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg), da) /* * Sets and their items are during parsing handled as lists, linked @@ -179,7 +179,7 @@ f_generate_empty(struct f_dynamic_attr dyn) cf_error("Can't empty that attribute"); } - return f_new_inst(FI_EA_SET, dyn, f_new_inst(FI_CONSTANT, empty)); + return f_new_inst(FI_EA_SET, f_new_inst(FI_CONSTANT, empty), dyn); } #if 0 @@ -389,6 +389,37 @@ assert_done(struct f_inst *expr, const char *start, const char *end) : "???"); } +static struct f_inst * +assert_assign(struct f_lval *lval, struct f_inst *expr, const char *start, const char *end) +{ + struct f_inst *setter, *getter, *checker; + switch (lval->type) { + case F_LVAL_VARIABLE: + setter = f_new_inst(FI_SET, expr, lval->sym); + getter = f_new_inst(FI_VARIABLE, lval->sym); + break; + case F_LVAL_PREFERENCE: + setter = f_new_inst(FI_PREF_SET, expr); + getter = f_new_inst(FI_PREF_GET); + break; + case F_LVAL_SA: + setter = f_new_inst(FI_RTA_SET, expr, lval->sa); + getter = f_new_inst(FI_RTA_GET, lval->sa); + break; + case F_LVAL_EA: + setter = f_new_inst(FI_EA_SET, expr, lval->da); + getter = f_new_inst(FI_EA_GET, lval->da); + break; + default: + bug("Unknown lval type"); + } + + checker = f_new_inst(FI_EQ, expr, getter); + f_inst_next(setter, checker); + + return assert_done(setter, start, end); +} + CF_DECLS CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, @@ -407,17 +438,18 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH, EMPTY, FILTER, WHERE, EVAL, ATTRIBUTE, - BT_ASSERT, BT_TEST_SUITE, FORMAT) + BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, FORMAT) %nonassoc THEN %nonassoc ELSE %type function_params declsn %type cmds_int function_body -%type term block cmd cmds constant constructor print_one print_list var_list var_listn function_call symbol bgp_path_expr bgp_path bgp_path_tail one_decl decls +%type term block cmd cmds constant constructor print_one print_list var_list var_listn function_call symbol_value bgp_path_expr bgp_path bgp_path_tail one_decl decls %type dynamic_attr %type static_attr %type filter filter_body where_filter +%type lvalue %type type %type ec_kind %type break_command @@ -432,7 +464,7 @@ CF_GRAMMAR conf: filter_def ; filter_def: - FILTER SYM { $2 = cf_define_symbol($2, SYM_FILTER, NULL); cf_push_scope( $2 ); } + FILTER CF_SYM_VOID { $2 = cf_define_symbol($2, SYM_FILTER, NULL); cf_push_scope( $2 ); } filter_body { $2->def = $4; $4->name = $2->name; @@ -447,16 +479,13 @@ filter_eval: ; conf: custom_attr ; -custom_attr: ATTRIBUTE type SYM ';' { +custom_attr: ATTRIBUTE type CF_SYM_VOID ';' { cf_define_symbol($3, SYM_ATTRIBUTE, ca_lookup(new_config->pool, $3->name, $2)->fda); }; conf: bt_test_suite ; bt_test_suite: - BT_TEST_SUITE '(' SYM ',' text ')' { - if (!($3->class & SYM_FUNCTION)) - cf_error("Function expected"); - + BT_TEST_SUITE '(' CF_SYM_FUNCTION ',' text ')' { struct f_bt_test_suite *t = cfg_alloc(sizeof(struct f_bt_test_suite)); t->fn = $3->def; t->fn_name = $3->name; @@ -505,7 +534,7 @@ type: ; one_decl: - type SYM { + type CF_SYM_VOID { struct f_val * val = cfg_alloc(sizeof(struct f_val)); val->type = T_VOID; $2 = cf_define_symbol($2, SYM_VARIABLE | $1, val); @@ -545,8 +574,7 @@ filter_body: ; filter: - SYM { - if ($1->class != SYM_FILTER) cf_error("No such filter."); + CF_SYM_FILTER { $$ = $1->def; } | filter_body @@ -573,7 +601,7 @@ function_body: conf: function_def ; function_def: - FUNCTION SYM { DBG( "Beginning of function %s\n", $2->name ); + FUNCTION CF_SYM_VOID { DBG( "Beginning of function %s\n", $2->name ); $2 = cf_define_symbol($2, SYM_FUNCTION, NULL); cf_push_scope($2); } function_params function_body { @@ -647,8 +675,7 @@ set_atom: if (f_eval(f_postfixify($2), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error"); if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type"); } - | SYM { - if (!cf_symbol_is_constant($1)) cf_error("%s: constant expected", $1->name); + | CF_SYM_CONSTANT { if (!f_valid_set_type(SYM_TYPE($1))) cf_error("%s: set-incompatible type", $1->name); $$ = *(struct f_val *)($1->def); } @@ -764,7 +791,7 @@ switch_body: /* EMPTY */ { $$ = NULL; } ; bgp_path_expr: - symbol { $$ = $1; } + symbol_value { $$ = $1; } | '(' term ')' { $$ = $2; } ; @@ -806,31 +833,17 @@ constructor: ; -rtadot: /* EMPTY, we are not permitted RTA. prefix */ - ; - function_call: - SYM '(' var_list ')' { + CF_SYM_FUNCTION '(' var_list ')' { $$ = f_new_inst(FI_CALL, $1, $3); } ; -symbol: - SYM { - switch ($1->class & 0xffff) { - case SYM_CONSTANT_RANGE: - $$ = f_new_inst(FI_CONSTANT_INDIRECT, $1->def); - break; - case SYM_VARIABLE_RANGE: - $$ = f_new_inst(FI_VARIABLE, $1); - break; - case SYM_ATTRIBUTE: - $$ = f_new_inst(FI_EA_GET, *((struct f_dynamic_attr *) $1->def)); - break; - default: - cf_error("%s: variable expected.", $1->name); - } - } +symbol_value: + CF_SYM_CONSTANT { $$ = f_new_inst(FI_CONSTANT_INDIRECT, $1->def); } + | CF_SYM_VARIABLE { $$ = f_new_inst(FI_VARIABLE, $1); } + | CF_SYM_ATTRIBUTE { $$ = f_new_inst(FI_EA_GET, *((struct f_dynamic_attr *) $1->def)); } + ; static_attr: FROM { $$ = f_new_static_attr(T_IP, SA_FROM, 0); } @@ -863,15 +876,15 @@ term: | '!' term { $$ = f_new_inst(FI_NOT, $2); } | DEFINED '(' term ')' { $$ = f_new_inst(FI_DEFINED, $3); } - | symbol { $$ = $1; } + | symbol_value { $$ = $1; } | constant { $$ = $1; } | constructor { $$ = $1; } | PREFERENCE { $$ = f_new_inst(FI_PREF_GET); } - | rtadot static_attr { $$ = f_new_inst(FI_RTA_GET, $2); } + | static_attr { $$ = f_new_inst(FI_RTA_GET, $1); } - | rtadot dynamic_attr { $$ = f_new_inst(FI_EA_GET, $2); } + | dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); } | term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4, $1); } | term '.' TYPE { $$ = f_new_inst(FI_TYPE, $1); } @@ -888,10 +901,10 @@ term: /* Communities */ /* This causes one shift/reduce conflict - | rtadot dynamic_attr '.' ADD '(' term ')' { } - | rtadot dynamic_attr '.' DELETE '(' term ')' { } - | rtadot dynamic_attr '.' CONTAINS '(' term ')' { } - | rtadot dynamic_attr '.' RESET{ } + | dynamic_attr '.' ADD '(' term ')' { } + | dynamic_attr '.' DELETE '(' term ')' { } + | dynamic_attr '.' CONTAINS '(' term ')' { } + | dynamic_attr '.' RESET{ } */ | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_path); } @@ -956,32 +969,29 @@ cmd: | IF term THEN block ELSE block { $$ = f_new_inst(FI_CONDITION, $2, $4, $6); } - | SYM '=' term ';' { - DBG( "Ook, we'll set value\n" ); - if ($1->class == SYM_ATTRIBUTE) { - $$ = f_new_inst(FI_EA_SET, *((struct f_dynamic_attr *) $1->def), $3); - } else if (($1->class & ~T_MASK) == SYM_VARIABLE) { - $$ = f_new_inst(FI_SET, $3, $1); - } else - cf_error( "Symbol `%s' is read-only.", $1->name ); + | CF_SYM_ATTRIBUTE '=' term ';' { + $$ = f_new_inst(FI_EA_SET, $3, *((struct f_dynamic_attr *) $1->def)); + } + | CF_SYM_VARIABLE '=' term ';' { + $$ = f_new_inst(FI_SET, $3, $1); } | RETURN term ';' { DBG( "Ook, we'll return the value\n" ); $$ = f_new_inst(FI_RETURN, $2); } - | rtadot dynamic_attr '=' term ';' { - $$ = f_new_inst(FI_EA_SET, $2, $4); + | dynamic_attr '=' term ';' { + $$ = f_new_inst(FI_EA_SET, $3, $1); } - | rtadot static_attr '=' term ';' { - if ($2.readonly) + | static_attr '=' term ';' { + if ($1.readonly) cf_error( "This static attribute is read-only."); - $$ = f_new_inst(FI_RTA_SET, $2, $4); + $$ = f_new_inst(FI_RTA_SET, $3, $1); } | PREFERENCE '=' term ';' { $$ = f_new_inst(FI_PREF_SET, $3); } - | UNSET '(' rtadot dynamic_attr ')' ';' { - $$ = f_new_inst(FI_EA_UNSET, $4); + | UNSET '(' dynamic_attr ')' ';' { + $$ = f_new_inst(FI_EA_UNSET, $3); } | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE, $2, $1); } | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); } @@ -989,12 +999,13 @@ cmd: $$ = f_new_inst(FI_SWITCH, $2, build_tree($4)); } - | rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); } - | rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( FI_PATH_PREPEND, $2, $6 ); } - | rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD, $2, $6 ); } - | rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_DEL, $2, $6 ); } - | rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_FILTER, $2, $6 ); } + | dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($1); } + | dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( FI_PATH_PREPEND, $1, $5 ); } + | dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD, $1, $5 ); } + | dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_DEL, $1, $5 ); } + | dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_FILTER, $1, $5 ); } | BT_ASSERT '(' get_cf_position term get_cf_position ')' ';' { $$ = assert_done($4, $3 + 1, $5 - 1); } + | BT_CHECK_ASSIGN '(' get_cf_position lvalue get_cf_position ',' term ')' ';' { $$ = assert_assign(&$4, $7, $3 + 1, $5 - 1); } ; get_cf_position: @@ -1002,5 +1013,10 @@ get_cf_position: $$ = cf_text; }; +lvalue: + CF_SYM_VARIABLE { $$ = (struct f_lval) { .type = F_LVAL_VARIABLE, .sym = $1 }; } + | PREFERENCE { $$ = (struct f_lval) { .type = F_LVAL_PREFERENCE }; } + | static_attr { $$ = (struct f_lval) { .type = F_LVAL_SA, .sa = $1 }; } + | dynamic_attr { $$ = (struct f_lval) { .type = F_LVAL_EA, .da = $1 }; }; CF_END diff --git a/filter/f-inst.c b/filter/f-inst.c index ae2b5289..0dd9f9f6 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -109,7 +109,7 @@ ARG_ANY(1); COUNT(2); - NEW([[]], [[ + NEW(, [[ uint len = 0; uint dyn = 0; for (const struct f_inst *tt = f1; tt; tt = tt->next, len++) @@ -329,9 +329,9 @@ } INST(FI_RTA_SET, 1, 0) { - STATIC_ATTR; ACCESS_RTE; ARG_ANY(1); + STATIC_ATTR; if (sa.f_type != v1.type) runtime( "Attempt to set static attribute to incompatible type" ); @@ -475,10 +475,10 @@ } INST(FI_EA_SET, 1, 0) { - DYNAMIC_ATTR; ACCESS_RTE; ACCESS_EATTRS; ARG_ANY(1); + DYNAMIC_ATTR; { struct ea_list *l = lp_alloc(fs->pool, sizeof(struct ea_list) + sizeof(eattr)); @@ -719,7 +719,7 @@ /* Then push the arguments */ LINE(1,1); - NEW([[]], [[ + NEW(, [[ if (sym->class != SYM_FUNCTION) cf_error("You can't call something which is not a function. Really."); @@ -984,5 +984,8 @@ INST(FI_ASSERT, 1, 0) { /* Birdtest Assert */ ARG(1, T_BOOL); STRING; - CALL(bt_assert_hook, res.val.i, what); + if (!bt_assert_hook) + runtime("No bt_assert hook registered, can't assert"); + + bt_assert_hook(res.val.i, what); } diff --git a/filter/filter.h b/filter/filter.h index 39f16e93..15a24fd4 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -128,6 +128,24 @@ enum filter_return { F_QUITBIRD, }; +/* Filter l-value type */ +enum f_lval_type { + F_LVAL_VARIABLE, + F_LVAL_PREFERENCE, + F_LVAL_SA, + F_LVAL_EA, +}; + +/* Filter l-value */ +struct f_lval { + enum f_lval_type type; + union { + const struct symbol *sym; + struct f_dynamic_attr da; + struct f_static_attr sa; + }; +}; + /* Filter instruction declarations */ #define FI__LIST \ F(FI_NOP) \ @@ -159,9 +177,9 @@ enum filter_return { F(FI_CONDITION, ARG, LINE, LINE) \ F(FI_PRINT_AND_DIE, ARG, FRET) \ F(FI_RTA_GET, SA) \ - F(FI_RTA_SET, SA, ARG) \ + F(FI_RTA_SET, ARG, SA) \ F(FI_EA_GET, EA) \ - F(FI_EA_SET, EA, ARG) \ + F(FI_EA_SET, ARG, EA) \ F(FI_EA_UNSET, EA) \ F(FI_PREF_GET) \ F(FI_PREF_SET, ARG) \ diff --git a/filter/filter_test.c b/filter/filter_test.c index e19b0a75..af6b590f 100644 --- a/filter/filter_test.c +++ b/filter/filter_test.c @@ -22,19 +22,21 @@ #define BT_CONFIG_FILE "filter/test.conf" -static struct config * -parse_config_file(const void *filename_void) -{ - bt_bird_init(); +struct parse_config_file_arg { + struct config **cp; + const char *filename; +}; - size_t fn_size = strlen((const char *) filename_void) + 1; +static int +parse_config_file(const void *argv) +{ + const struct parse_config_file_arg *arg = argv; + size_t fn_size = strlen(arg->filename) + 1; char *filename = alloca(fn_size); - strncpy(filename, filename_void, fn_size); - - struct config *c = bt_config_file_parse(filename); - bt_bird_cleanup(); - - return c; + strncpy(filename, arg->filename, fn_size); + + *(arg->cp) = bt_config_file_parse(filename); + return !!*(arg->cp); } static int @@ -68,13 +70,18 @@ int main(int argc, char *argv[]) { bt_init(argc, argv); + bt_bird_init(); + + bt_assert_hook = bt_assert_filter; - struct config *c = parse_config_file(BT_CONFIG_FILE); + struct config *c = NULL; + struct parse_config_file_arg pcfa = { .cp = &c, .filename = BT_CONFIG_FILE }; + bt_test_suite_base(parse_config_file, "conf", (const void *) &pcfa, 0, 0, "parse config file"); + + bt_bird_cleanup(); if (c) { - bt_assert_hook = bt_assert_filter; - struct f_bt_test_suite *t; WALK_LIST(t, c->tests) bt_test_suite_base(run_function, t->fn_name, t->fn, BT_FORKING, BT_TIMEOUT, "%s", t->dsc); diff --git a/filter/test.conf b/filter/test.conf index 39b349cc..e6b6ca4e 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -1336,7 +1336,7 @@ bt_test_suite(t_mixed_prefix, "Testing mixed net types"); filter vpn_filter { - bt_assert(format(net) = "0:1:2 10.1.10.0/24"); + bt_assert(format(net) = "1:2 10.1.10.0/24"); bt_assert(net.type = NET_VPN4); bt_assert(net.type != NET_IP4); bt_assert(net.type != NET_IP6); @@ -1347,6 +1347,15 @@ filter vpn_filter NET_IP6: print "IPV6"; } +# aoiufahkejtrhaweifdsbhydkfj,ysdnm + + bt_check_assign(from, 10.20.30.40); + bt_check_assign(gw, 55.55.55.44); + + bgp_community.add((3,5)); + bgp_ext_community.add((ro, 135, 999)); + bgp_large_community.add((6464156, 89646354, 8675643)); + accept; } diff --git a/nest/config.Y b/nest/config.Y index 51fb0bd7..fb75c593 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -88,7 +88,7 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID) %type idval %type imexport %type rtable -%type optsym +%type optproto sym_proto_or_template %type r_args %type sym_args %type proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode limit_action net_type table_sorted tos password_algorithm @@ -114,7 +114,7 @@ idval: NUM { $$ = $1; } | '(' term ')' { $$ = f_eval_int(f_postfixify($2)); } | IP4 { $$ = ip4_to_u32($1); } - | SYM { + | CF_SYM_CONSTANT { if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD)) $$ = SYM_VAL($1).i; else if (($1->class == (SYM_CONSTANT | T_IP)) && ipa_is_ip4(SYM_VAL($1).ip)) @@ -156,7 +156,7 @@ table_sorted: | SORTED { $$ = 1; } ; -table: net_type TABLE SYM table_sorted { +table: net_type TABLE CF_SYM_VOID table_sorted { struct rtable_config *cf; cf = rt_new_table($3, $1); cf->sorted = $4; @@ -173,6 +173,8 @@ proto_start: | TEMPLATE { $$ = SYM_TEMPLATE; } ; +sym_proto_or_template: CF_SYM_PROTO | CF_SYM_TEMPLATE ; + proto_name: /* EMPTY */ { struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter); @@ -180,11 +182,11 @@ proto_name: s->def = this_proto; this_proto->name = s->name; } - | SYM { + | CF_SYM_VOID { cf_define_symbol($1, this_proto->class, this_proto); this_proto->name = $1->name; } - | FROM SYM { + | FROM sym_proto_or_template { struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter); s->class = this_proto->class; s->def = this_proto; @@ -193,7 +195,7 @@ proto_name: if (($2->class != SYM_TEMPLATE) && ($2->class != SYM_PROTO)) cf_error("Template or protocol name expected"); proto_copy_config(this_proto, $2->def); } - | SYM FROM SYM { + | CF_SYM_VOID FROM sym_proto_or_template { cf_define_symbol($1, this_proto->class, this_proto); this_proto->name = $1->name; @@ -254,12 +256,7 @@ channel_end: proto_channel: channel_start channel_opt_list channel_end; -rtable: - SYM { - if ($1->class != SYM_TABLE) cf_error("Table expected"); - $$ = $1->def; - } - ; +rtable: CF_SYM_TABLE { $$ = $1->def; } ; imexport: FILTER filter { $$ = $2; } @@ -512,8 +509,8 @@ CF_CLI(SHOW PROTOCOLS, proto_patt2, [ | \"\"], [[Show routing CF_CLI(SHOW PROTOCOLS ALL, proto_patt2, [ | \"\"], [[Show routing protocol details]]) { proto_apply_cmd($4, proto_cmd_show, 0, 1); } ; -optsym: - SYM +optproto: + CF_SYM_PROTO | /* empty */ { $$ = NULL; } ; @@ -545,9 +542,8 @@ r_args: $$->show_for = 1; $$->addr = $3; } - | r_args TABLE SYM { + | r_args TABLE CF_SYM_TABLE { $$ = $1; - if ($3->class != SYM_TABLE) cf_error("%s is not a table", $3->name); rt_show_add_table($$, ((struct rtable_config *)$3->def)->table); $$->tables_defined_by = RSD_TDB_DIRECT; } @@ -558,10 +554,10 @@ r_args: rt_show_add_table($$, t->table); $$->tables_defined_by = RSD_TDB_ALL; } - | r_args IMPORT TABLE SYM '.' r_args_channel { + | r_args IMPORT TABLE CF_SYM_PROTO '.' r_args_channel { $$ = $1; struct proto_config *cf = (void *) $4->def; - if ($4->class != SYM_PROTO || !cf->proto) cf_error("%s is not a protocol", $4->name); + if (!cf->proto) cf_error("%s is not a protocol", $4->name); struct channel *c = proto_find_channel_by_name(cf->proto, $6); if (!c) cf_error("Channel %s.%s not found", $4->name, $6); if (!c->in_table) cf_error("No import table in channel %s.%s", $4->name, $6); @@ -590,30 +586,30 @@ r_args: $$ = $1; $$->filtered = 1; } - | r_args export_mode SYM { + | r_args export_mode CF_SYM_PROTO { struct proto_config *c = (struct proto_config *) $3->def; $$ = $1; if ($$->export_mode) cf_error("Export specified twice"); - if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name); + if (!c->proto) cf_error("%s is not a protocol", $3->name); $$->export_mode = $2; $$->export_protocol = c->proto; $$->tables_defined_by = RSD_TDB_INDIRECT; } - | r_args export_mode SYM '.' r_args_channel { + | r_args export_mode CF_SYM_PROTO '.' r_args_channel { struct proto_config *c = (struct proto_config *) $3->def; $$ = $1; if ($$->export_mode) cf_error("Export specified twice"); - if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name); + if (!c->proto) cf_error("%s is not a protocol", $3->name); $$->export_mode = $2; $$->export_channel = proto_find_channel_by_name(c->proto, $5); if (!$$->export_channel) cf_error("Export channel not found"); $$->tables_defined_by = RSD_TDB_INDIRECT; } - | r_args PROTOCOL SYM { + | r_args PROTOCOL CF_SYM_PROTO { struct proto_config *c = (struct proto_config *) $3->def; $$ = $1; if ($$->show_protocol) cf_error("Protocol specified twice"); - if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name); + if (!c->proto) cf_error("%s is not a protocol", $3->name); $$->show_protocol = c->proto; $$->tables_defined_by = RSD_TDB_INDIRECT; } @@ -647,7 +643,7 @@ r_args_for: $$ = cfg_alloc(sizeof(net_addr_ip6_sadr)); net_fill_ip6_sadr($$, $1, IP6_MAX_PREFIX_LENGTH, $3, IP6_MAX_PREFIX_LENGTH); } - | SYM { + | CF_SYM_CONSTANT { if ($1->class == (SYM_CONSTANT | T_IP)) { $$ = cfg_alloc(ipa_is_ip4(SYM_VAL($1).ip) ? sizeof(net_addr_ip4) : sizeof(net_addr_ip6)); @@ -709,7 +705,7 @@ sym_args: | sym_args FILTER { $$ = $1; $$->type = SYM_FILTER; } | sym_args PROTOCOL { $$ = $1; $$->type = SYM_PROTO; } | sym_args TEMPLATE { $$ = $1; $$->type = SYM_TEMPLATE; } - | sym_args SYM { $$ = $1; $$->sym = $2; } + | sym_args symbol { $$ = $1; $$->sym = $2; } ; @@ -779,13 +775,13 @@ CF_CLI(RESTRICT,,,[[Restrict current CLI session to safe commands]]) { this_cli->restricted = 1; cli_msg(16, "Access restricted"); } ; proto_patt: - SYM { $$.ptr = $1; $$.patt = 0; } + CF_SYM_PROTO { $$.ptr = $1; $$.patt = 0; } | ALL { $$.ptr = NULL; $$.patt = 1; } | TEXT { $$.ptr = $1; $$.patt = 1; } ; proto_patt2: - SYM { $$.ptr = $1; $$.patt = 0; } + CF_SYM_PROTO { $$.ptr = $1; $$.patt = 0; } | { $$.ptr = NULL; $$.patt = 1; } | TEXT { $$.ptr = $1; $$.patt = 1; } ; diff --git a/proto/babel/config.Y b/proto/babel/config.Y index b93a423b..78175323 100644 --- a/proto/babel/config.Y +++ b/proto/babel/config.Y @@ -129,16 +129,16 @@ dynamic_attr: BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_ CF_CLI_HELP(SHOW BABEL, ..., [[Show information about Babel protocol]]); -CF_CLI(SHOW BABEL INTERFACES, optsym opttext, [] [\"\"], [[Show information about Babel interfaces]]) +CF_CLI(SHOW BABEL INTERFACES, optproto opttext, [] [\"\"], [[Show information about Babel interfaces]]) { babel_show_interfaces(proto_get_named($4, &proto_babel), $5); }; -CF_CLI(SHOW BABEL NEIGHBORS, optsym opttext, [] [\"\"], [[Show information about Babel neighbors]]) +CF_CLI(SHOW BABEL NEIGHBORS, optproto opttext, [] [\"\"], [[Show information about Babel neighbors]]) { babel_show_neighbors(proto_get_named($4, &proto_babel), $5); }; -CF_CLI(SHOW BABEL ENTRIES, optsym opttext, [], [[Show information about Babel prefix entries]]) +CF_CLI(SHOW BABEL ENTRIES, optproto opttext, [], [[Show information about Babel prefix entries]]) { babel_show_entries(proto_get_named($4, &proto_babel)); }; -CF_CLI(SHOW BABEL ROUTES, optsym opttext, [], [[Show information about Babel route entries]]) +CF_CLI(SHOW BABEL ROUTES, optproto opttext, [], [[Show information about Babel route entries]]) { babel_show_routes(proto_get_named($4, &proto_babel)); }; CF_CODE diff --git a/proto/bfd/config.Y b/proto/bfd/config.Y index 3f5714fd..41228e51 100644 --- a/proto/bfd/config.Y +++ b/proto/bfd/config.Y @@ -134,7 +134,7 @@ bfd_multihop: bfd_neigh_iface: /* empty */ { $$ = NULL; } - | '%' SYM { $$ = if_get_by_name($2->name); } + | '%' symbol { $$ = if_get_by_name($2->name); } | DEV text { $$ = if_get_by_name($2); } ; @@ -167,7 +167,7 @@ bfd_neighbor: ipa bfd_neigh_iface bfd_neigh_local bfd_neigh_multihop CF_CLI_HELP(SHOW BFD, ..., [[Show information about BFD protocol]]); -CF_CLI(SHOW BFD SESSIONS, optsym, [], [[Show information about BFD sessions]]) +CF_CLI(SHOW BFD SESSIONS, optproto, [], [[Show information about BFD sessions]]) { bfd_show_sessions(proto_get_named($4, &proto_bfd)); }; CF_CODE diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 9669b708..38b09deb 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -504,29 +504,29 @@ dynamic_attr: OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_OSPF dynamic_attr: OSPF_ROUTER_ID { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, 0, T_QUAD, EA_OSPF_ROUTER_ID); } ; CF_CLI_HELP(SHOW OSPF, ..., [[Show information about OSPF protocol]]); -CF_CLI(SHOW OSPF, optsym, [], [[Show information about OSPF protocol]]) +CF_CLI(SHOW OSPF, optproto, [], [[Show information about OSPF protocol]]) { ospf_sh(proto_get_named($3, &proto_ospf)); }; -CF_CLI(SHOW OSPF NEIGHBORS, optsym opttext, [] [\"\"], [[Show information about OSPF neighbors]]) +CF_CLI(SHOW OSPF NEIGHBORS, optproto opttext, [] [\"\"], [[Show information about OSPF neighbors]]) { ospf_sh_neigh(proto_get_named($4, &proto_ospf), $5); }; -CF_CLI(SHOW OSPF INTERFACE, optsym opttext, [] [\"\"], [[Show information about interface]]) +CF_CLI(SHOW OSPF INTERFACE, optproto opttext, [] [\"\"], [[Show information about interface]]) { ospf_sh_iface(proto_get_named($4, &proto_ospf), $5); }; CF_CLI_HELP(SHOW OSPF TOPOLOGY, [all] [], [[Show information about OSPF network topology]]) -CF_CLI(SHOW OSPF TOPOLOGY, optsym opttext, [], [[Show information about reachable OSPF network topology]]) +CF_CLI(SHOW OSPF TOPOLOGY, optproto opttext, [], [[Show information about reachable OSPF network topology]]) { ospf_sh_state(proto_get_named($4, &proto_ospf), 0, 1); }; -CF_CLI(SHOW OSPF TOPOLOGY ALL, optsym opttext, [], [[Show information about all OSPF network topology]]) +CF_CLI(SHOW OSPF TOPOLOGY ALL, optproto opttext, [], [[Show information about all OSPF network topology]]) { ospf_sh_state(proto_get_named($5, &proto_ospf), 0, 0); }; CF_CLI_HELP(SHOW OSPF STATE, [all] [], [[Show information about OSPF network state]]) -CF_CLI(SHOW OSPF STATE, optsym opttext, [], [[Show information about reachable OSPF network state]]) +CF_CLI(SHOW OSPF STATE, optproto opttext, [], [[Show information about reachable OSPF network state]]) { ospf_sh_state(proto_get_named($4, &proto_ospf), 1, 1); }; -CF_CLI(SHOW OSPF STATE ALL, optsym opttext, [], [[Show information about all OSPF network state]]) +CF_CLI(SHOW OSPF STATE ALL, optproto opttext, [], [[Show information about all OSPF network state]]) { ospf_sh_state(proto_get_named($5, &proto_ospf), 1, 0); }; CF_CLI_HELP(SHOW OSPF LSADB, ..., [[Show content of OSPF LSA database]]); @@ -544,7 +544,7 @@ lsadb_args: | lsadb_args LSID idval { $$ = $1; $$->lsid = $3; } | lsadb_args SELF { $$ = $1; $$->router = SH_ROUTER_SELF; } | lsadb_args ROUTER idval { $$ = $1; $$->router = $3; } - | lsadb_args SYM { $$ = $1; $$->name = $2; } + | lsadb_args CF_SYM_PROTO { $$ = $1; $$->proto = (struct ospf_proto *) proto_get_named($2, &proto_ospf); } ; CF_CODE diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index ef2a0df4..816f33aa 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -1402,7 +1402,7 @@ lsa_compare_for_lsadb(const void *p1, const void *p2) void ospf_sh_lsadb(struct lsadb_show_data *ld) { - struct ospf_proto *p = (struct ospf_proto *) proto_get_named(ld->name, &proto_ospf); + struct ospf_proto *p = ld->proto; uint num = p->gr->hash_entries; uint i, j; int last_dscope = -1; diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 7fac47c8..82ae4df4 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -900,7 +900,7 @@ struct ospf_lsreq_header #define SH_ROUTER_SELF 0xffffffff struct lsadb_show_data { - struct symbol *name; /* Protocol to request data from */ + struct ospf_proto *proto; /* Protocol to request data from */ u16 type; /* LSA Type, 0 -> all */ u16 scope; /* Scope, 0 -> all, hack to handle link scope as 1 */ u32 area; /* Specified for area scope */ diff --git a/proto/rip/config.Y b/proto/rip/config.Y index 265912b2..4ab793d1 100644 --- a/proto/rip/config.Y +++ b/proto/rip/config.Y @@ -191,10 +191,10 @@ dynamic_attr: RIP_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_RIP_T CF_CLI_HELP(SHOW RIP, ..., [[Show information about RIP protocol]]); -CF_CLI(SHOW RIP INTERFACES, optsym opttext, [] [\"\"], [[Show information about RIP interfaces]]) +CF_CLI(SHOW RIP INTERFACES, optproto opttext, [] [\"\"], [[Show information about RIP interfaces]]) { rip_show_interfaces(proto_get_named($4, &proto_rip), $5); }; -CF_CLI(SHOW RIP NEIGHBORS, optsym opttext, [] [\"\"], [[Show information about RIP neighbors]]) +CF_CLI(SHOW RIP NEIGHBORS, optproto opttext, [] [\"\"], [[Show information about RIP neighbors]]) { rip_show_neighbors(proto_get_named($4, &proto_rip), $5); }; diff --git a/proto/static/config.Y b/proto/static/config.Y index 527046ee..0e53c978 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -157,7 +157,7 @@ stat_route_opt_list: ; -CF_CLI(SHOW STATIC, optsym, [], [[Show details of static protocol]]) +CF_CLI(SHOW STATIC, optproto, [], [[Show details of static protocol]]) { static_show(proto_get_named($3, &proto_static)); } ; CF_CODE -- cgit v1.2.3 From 4f082dfa892e95f86ca8137410992a248110b6ef Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Fri, 8 Feb 2019 13:38:12 +0100 Subject: Filter: merged filter instruction constructors, counting line size on instruction construct --- configure.ac | 8 ++- filter/Makefile | 12 +--- filter/config.Y | 24 +++---- filter/data.h | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++ filter/decl.m4 | 128 ++++++++++++++++++++++++++++++++++++++ filter/f-inst.c | 36 +++++------ filter/f-inst.h | 131 ++------------------------------------ filter/f-util.c | 19 +----- filter/f-util.h | 151 -------------------------------------------- filter/filter.c | 86 ++++++++++++++++++++----- filter/filter_test.c | 2 +- filter/interpret.m4 | 7 ++- filter/line-size.m4 | 41 ------------ filter/new.m4 | 78 ----------------------- filter/struct.m4 | 73 ---------------------- filter/tree.c | 2 +- filter/tree_test.c | 2 +- filter/trie.c | 2 +- filter/trie_test.c | 2 +- nest/a-path.c | 2 +- nest/cmds.c | 2 +- nest/rt-table.c | 2 +- proto/static/config.Y | 2 +- sysdep/unix/main.c | 2 +- 24 files changed, 432 insertions(+), 551 deletions(-) create mode 100644 filter/data.h create mode 100644 filter/decl.m4 delete mode 100644 filter/f-util.h delete mode 100644 filter/line-size.m4 delete mode 100644 filter/new.m4 delete mode 100644 filter/struct.m4 (limited to 'proto/static') diff --git a/configure.ac b/configure.ac index 33bc9101..850e771f 100644 --- a/configure.ac +++ b/configure.ac @@ -18,6 +18,12 @@ AC_ARG_ENABLE([debug], [enable_debug=no] ) +AC_ARG_ENABLE([debug-generated], + [AS_HELP_STRING([--enable-debug-generated], [enable this to abstain from generating #line @<:@no@:>@])], + [], + [enable_debug_generated=no] +) + AC_ARG_ENABLE([memcheck], [AS_HELP_STRING([--enable-memcheck], [check memory allocations when debugging @<:@yes@:>@])], [], @@ -156,7 +162,7 @@ test -z "$M4" && AC_MSG_ERROR([M4 is missing.]) AC_MSG_CHECKING([bison version]) BIRD_CHECK_BISON_VERSION(BISON_VERSION) AC_MSG_RESULT([$BISON_VERSION]) -if test "$bird_bison_synclines" = yes; then +if test "$bird_bison_synclines" = yes && test "$enable_debug_generated" = no; then M4FLAGS="$M4FLAGS -s" fi diff --git a/filter/Makefile b/filter/Makefile index 15f2c3d0..f5f50045 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -1,13 +1,10 @@ -src := filter.c f-util.c tree.c trie.c f-inst-new.c +src := filter.c f-util.c tree.c trie.c obj := $(src-o-files) $(all-daemon) $(cf-local) M4FLAGS_FILTERS=$(filter-out -s,$(M4FLAGS)) -$(o)f-inst-line-size.c: $(s)line-size.m4 $(s)f-inst.c $(objdir)/.dir-stamp - $(M4) $(M4FLAGS_FILTERS) -P $^ >$@ - $(o)f-inst-postfixify.c: $(s)postfixify.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(M4) $(M4FLAGS_FILTERS) -P $^ >$@ @@ -17,16 +14,13 @@ $(o)f-inst-interpret.c: $(s)interpret.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(o)f-inst-same.c: $(s)same.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(M4) $(M4FLAGS_FILTERS) -P $^ >$@ -$(o)f-inst-struct.h: $(s)struct.m4 $(s)f-inst.c $(objdir)/.dir-stamp - $(M4) $(M4FLAGS_FILTERS) -P $^ >$@ - -$(o)f-inst-new.c: $(s)new.m4 $(s)f-inst.c $(objdir)/.dir-stamp +$(o)f-inst-decl.h: $(s)decl.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(M4) $(M4FLAGS_FILTERS) -P $^ >$@ $(o)f-inst-dump.c: $(s)dump.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(M4) $(M4FLAGS_FILTERS) -P $^ >$@ -$(o)filter.o: $(o)f-inst-interpret.c $(o)f-inst-line-size.c $(o)f-inst-postfixify.c $(o)f-inst-same.c $(o)f-inst-dump.c $(o)f-inst-struct.h +$(o)filter.o: $(o)f-inst-interpret.c $(o)f-inst-postfixify.c $(o)f-inst-same.c $(o)f-inst-dump.c $(o)f-inst-decl.h tests_src := tree_test.c filter_test.c trie_test.c tests_targets := $(tests_targets) $(tests-target-files) diff --git a/filter/config.Y b/filter/config.Y index 31ceb3f5..42624f44 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -11,7 +11,7 @@ CF_HDR #include "filter/f-inst.h" -#include "filter/f-util.h" +#include "filter/data.h" CF_DEFINES @@ -418,7 +418,7 @@ assert_assign(struct f_lval *lval, struct f_inst *expr, const char *start, const } checker = f_new_inst(FI_EQ, expr, getter); - f_inst_next(setter, checker); + setter->next = checker; return assert_done(setter, start, end); } @@ -550,7 +550,7 @@ one_decl: decls: /* EMPTY */ { $$ = NULL; } | one_decl ';' decls { $$ = $1; - f_inst_next($$, $3); + $$->next = $3; } ; @@ -559,7 +559,7 @@ declsn: one_decl { $$.inst = $1; $$.count = 1; } | one_decl ';' declsn { $$ = $3; $$.count++; - f_inst_next($$.inst, $1); + $$.inst->next = $1; } ; @@ -640,7 +640,7 @@ cmds: /* EMPTY */ { $$ = NULL; } ; cmds_int: cmd { $$[0] = $$[1] = $1; } - | cmds_int cmd { $$[1] = $2; f_inst_next($1[1], $2); $$[0] = $1[0]; } + | cmds_int cmd { $$[1] = $2; $1[1]->next = $2; $$[0] = $1[0]; } ; block: @@ -803,11 +803,11 @@ bgp_path: ; bgp_path_tail: - NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .asn = $1, .kind = PM_ASN, }, }); f_inst_next($$, $2); } - | NUM DDOT NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .from = $1, .to = $3, .kind = PM_ASN_RANGE }, }); f_inst_next($$, $4); } - | '*' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_ASTERISK }, }); f_inst_next($$, $2); } - | '?' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_QUESTION }, }); f_inst_next($$, $2); } - | bgp_path_expr bgp_path_tail { $$ = $1; f_inst_next($$, $2); } + NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .asn = $1, .kind = PM_ASN, }, }); $$->next = $2; } + | NUM DDOT NUM bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .from = $1, .to = $3, .kind = PM_ASN_RANGE }, }); $$->next = $4; } + | '*' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_ASTERISK }, }); $$->next = $2; } + | '?' bgp_path_tail { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_QUESTION }, }); $$->next = $2; } + | bgp_path_expr bgp_path_tail { $$ = $1; $$->next = $2; } | { $$ = NULL; } ; @@ -946,7 +946,7 @@ print_list: /* EMPTY */ { $$ = NULL; } | print_one { $$ = $1; } | print_one ',' print_list { if ($1) { - f_inst_next($1, $3); + $1->next = $3; $$ = $1; } else $$ = $3; } @@ -957,7 +957,7 @@ var_listn: term { } | term ',' var_listn { $$ = $1; - f_inst_next($$, $3); + $$->next = $3; } ; diff --git a/filter/data.h b/filter/data.h new file mode 100644 index 00000000..58db3e44 --- /dev/null +++ b/filter/data.h @@ -0,0 +1,169 @@ +/* + * BIRD Internet Routing Daemon -- Dynamic data structures + * + * (c) 1999 Pavel Machek + * (c) 2018--2019 Maria Matejka + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#ifndef _BIRD_FILTER_DATA_H_ +#define _BIRD_FILTER_DATA_H_ + +#include "nest/bird.h" + +/* Type numbers must be in 0..0xff range */ +#define T_MASK 0xff + +/* Internal types */ +enum f_type { +/* Do not use type of zero, that way we'll see errors easier. */ + T_VOID = 1, + +/* User visible types, which fit in int */ + T_INT = 0x10, + T_BOOL = 0x11, + T_PAIR = 0x12, /* Notice that pair is stored as integer: first << 16 | second */ + T_QUAD = 0x13, + +/* Put enumerational types in 0x30..0x3f range */ + T_ENUM_LO = 0x30, + T_ENUM_HI = 0x3f, + + T_ENUM_RTS = 0x30, + T_ENUM_BGP_ORIGIN = 0x31, + T_ENUM_SCOPE = 0x32, + T_ENUM_RTC = 0x33, + T_ENUM_RTD = 0x34, + T_ENUM_ROA = 0x35, + T_ENUM_NETTYPE = 0x36, + T_ENUM_RA_PREFERENCE = 0x37, + +/* new enums go here */ + T_ENUM_EMPTY = 0x3f, /* Special hack for atomic_aggr */ + +#define T_ENUM T_ENUM_LO ... T_ENUM_HI + +/* Bigger ones */ + T_IP = 0x20, + T_NET = 0x21, + T_STRING = 0x22, + T_PATH_MASK = 0x23, /* mask for BGP path */ + T_PATH = 0x24, /* BGP path */ + T_CLIST = 0x25, /* Community list */ + T_EC = 0x26, /* Extended community value, u64 */ + T_ECLIST = 0x27, /* Extended community list */ + T_LC = 0x28, /* Large community value, lcomm */ + T_LCLIST = 0x29, /* Large community list */ + T_RD = 0x2a, /* Route distinguisher for VPN addresses */ + T_PATH_MASK_ITEM = 0x2b, /* Path mask item for path mask constructors */ + + T_SET = 0x80, + T_PREFIX_SET = 0x81, +} PACKED; + +/* Filter value; size of this affects filter memory consumption */ +struct f_val { + enum f_type type; /* T_* */ + union { + uint i; + u64 ec; + lcomm lc; + ip_addr ip; + const net_addr *net; + char *s; + const struct f_tree *t; + const struct f_trie *ti; + const struct adata *ad; + const struct f_path_mask *path_mask; + struct f_path_mask_item pmi; + } val; +}; + +/* Dynamic attribute definition (eattrs) */ +struct f_dynamic_attr { + u8 type; /* EA type (EAF_*) */ + u8 bit; /* For bitfield accessors */ + enum f_type f_type; /* Filter type */ + uint ea_code; /* EA code */ +}; + +enum f_sa_code { + SA_FROM = 1, + SA_GW, + SA_NET, + SA_PROTO, + SA_SOURCE, + SA_SCOPE, + SA_DEST, + SA_IFNAME, + SA_IFINDEX, +} PACKED; + +/* Static attribute definition (members of struct rta) */ +struct f_static_attr { + enum f_type f_type; /* Filter type */ + enum f_sa_code sa_code; /* Static attribute id */ + int readonly:1; /* Don't allow writing */ +}; + +/* Filter l-value type */ +enum f_lval_type { + F_LVAL_VARIABLE, + F_LVAL_PREFERENCE, + F_LVAL_SA, + F_LVAL_EA, +}; + +/* Filter l-value */ +struct f_lval { + enum f_lval_type type; + union { + const struct symbol *sym; + struct f_dynamic_attr da; + struct f_static_attr sa; + }; +}; + +/* IP prefix range structure */ +struct f_prefix { + net_addr net; /* The matching prefix must match this net */ + u8 lo, hi; /* And its length must fit between lo and hi */ +}; + +struct f_tree { + struct f_tree *left, *right; + struct f_val from, to; + void *data; +}; + +struct f_trie_node +{ + ip_addr addr, mask, accept; + uint plen; + struct f_trie_node *c[2]; +}; + +struct f_trie +{ + linpool *lp; + int zero; + uint node_size; + struct f_trie_node root[0]; /* Root trie node follows */ +}; + +struct f_tree *f_new_tree(void); +struct f_tree *build_tree(struct f_tree *); +const struct f_tree *find_tree(const struct f_tree *t, const struct f_val *val); +int same_tree(const struct f_tree *t0, const struct f_tree *t2); +void tree_format(const struct f_tree *t, buffer *buf); + +struct f_trie *f_new_trie(linpool *lp, uint node_size); +void *trie_add_prefix(struct f_trie *t, const net_addr *n, uint l, uint h); +int trie_match_net(const struct f_trie *t, const net_addr *n); +int trie_same(const struct f_trie *t1, const struct f_trie *t2); +void trie_format(const struct f_trie *t, buffer *buf); + +extern const struct f_val f_const_empty_path, f_const_empty_clist, f_const_empty_eclist, f_const_empty_lclist; + +#endif diff --git a/filter/decl.m4 b/filter/decl.m4 new file mode 100644 index 00000000..bdbb3e27 --- /dev/null +++ b/filter/decl.m4 @@ -0,0 +1,128 @@ +m4_divert(-1)m4_dnl +# +# BIRD -- Construction of per-instruction structures +# +# (c) 2018 Maria Matejka +# +# Can be freely distributed and used under the terms of the GNU GPL. +# +# +# Global Diversions: +# 4 enum fi_code +# 1 struct f_inst_FI_... +# 2 union in struct f_inst +# 3 constructors +# +# Per-inst Diversions: +# 11 content of struct f_inst_FI_... +# 12 constructor arguments +# 13 constructor body + +# Flush the completed instruction + +m4_define(FID_END, `m4_divert(-1)') + +m4_define(FID_ZONE, `m4_divert($1) /* $2 for INST_NAME() */') +m4_define(FID_STRUCT, `FID_ZONE(1, Per-instruction structure)') +m4_define(FID_UNION, `FID_ZONE(2, Union member)') +m4_define(FID_NEW, `FID_ZONE(3, Constructor)') +m4_define(FID_ENUM, `FID_ZONE(4, Code enum)') + +m4_define(FID_STRUCT_IN, `m4_divert(101)') +m4_define(FID_NEW_ARGS, `m4_divert(102)') +m4_define(FID_NEW_BODY, `m4_divert(103)') + +m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[ +FID_ENUM +INST_NAME(), +FID_STRUCT +struct f_inst_[[]]INST_NAME() { +m4_undivert(101) +}; +FID_UNION +struct f_inst_[[]]INST_NAME() i_[[]]INST_NAME(); +FID_NEW +static inline struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code +m4_undivert(102) +) { + struct f_inst *what_ = cfg_allocz(sizeof(struct f_inst)); + what_->fi_code = fi_code; + what_->lineno = ifs->lino; + what_->size = 1; + struct f_inst_[[]]INST_NAME() *what UNUSED = &(what_->i_[[]]INST_NAME()); +m4_undivert(103) + return what_; +} +FID_END +]])') + +m4_define(INST, `INST_FLUSH()m4_define([[INST_NAME]], [[$1]])') + +m4_define(FID_MEMBER, `m4_dnl +FID_STRUCT_IN +$1 $2; +FID_NEW_ARGS +, $1 $2 +FID_NEW_BODY +what->$2 = $2; +FID_END') + +m4_define(ARG, `FID_MEMBER(const struct f_inst *, f$1) +FID_NEW_BODY +for (const struct f_inst *child = f$1; child; child = child->next) what_->size += child->size; +FID_END') +m4_define(ARG_ANY, `FID_MEMBER(const struct f_inst *, f$1) +FID_NEW_BODY +for (const struct f_inst *child = f$1; child; child = child->next) what_->size += child->size; +FID_END') +m4_define(LINE, `FID_MEMBER(const struct f_inst *, f$1)') +m4_define(LINEP, `FID_STRUCT_IN +const struct f_line *fl$1; +FID_END') +m4_define(SYMBOL, `FID_MEMBER(const struct symbol *, sym)') +m4_define(VALI, `FID_MEMBER(struct f_val, vali)') +m4_define(VALP, `FID_MEMBER(const struct f_val *, valp)') +m4_define(VAR, `m4_dnl +FID_STRUCT_IN +const struct f_val *valp; +const struct symbol *sym; +FID_NEW_ARGS +, const struct symbol *sym +FID_NEW_BODY +what->valp = (what->sym = sym)->def; +FID_END') +m4_define(FRET, `FID_MEMBER(enum filter_return, fret)') +m4_define(ECS, `FID_MEMBER(enum ec_subtype, ecs)') +m4_define(RTC, `FID_MEMBER(const struct rtable_config *, rtc)') +m4_define(STATIC_ATTR, `FID_MEMBER(struct f_static_attr, sa)') +m4_define(DYNAMIC_ATTR, `FID_MEMBER(struct f_dynamic_attr, da)') +m4_define(COUNT, `FID_MEMBER(uint, count)') +m4_define(TREE, `FID_MEMBER(const struct f_tree *, tree)') +m4_define(STRING, `FID_MEMBER(const char *, s)') + +m4_m4wrap(` +INST_FLUSH() +m4_divert(0) +/* Filter instruction codes */ +enum f_instruction_code { +m4_undivert(4) +}; + +/* Per-instruction structures */ +m4_undivert(1) + +struct f_inst { + const struct f_inst *next; /* Next instruction */ + enum f_instruction_code fi_code; /* Instruction code */ + int size; /* How many instructions are underneath */ + int lineno; /* Line number */ + union { + m4_undivert(2) + }; +}; + +/* Instruction constructors */ +m4_undivert(3) +') + +m4_changequote([[,]]) diff --git a/filter/f-inst.c b/filter/f-inst.c index 0dd9f9f6..afb895c5 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -109,15 +109,15 @@ ARG_ANY(1); COUNT(2); - NEW(, [[ - uint len = 0; - uint dyn = 0; - for (const struct f_inst *tt = f1; tt; tt = tt->next, len++) - if (tt->fi_code != FI_CONSTANT) - dyn++; + FID_NEW_BODY + uint len = 0; + uint dyn = 0; + for (const struct f_inst *tt = f1; tt; tt = tt->next, len++) + if (tt->fi_code != FI_CONSTANT) + dyn++; - WHAT().count = len; - ]]); + what->count = len; + FID_END if (vstk.cnt < what->count) /* TODO: make this check systematic */ runtime("Construction of BGP path mask from %u elements must have at least that number of elements", what->count); @@ -719,17 +719,17 @@ /* Then push the arguments */ LINE(1,1); - NEW(, [[ - if (sym->class != SYM_FUNCTION) - cf_error("You can't call something which is not a function. Really."); + FID_NEW_BODY + if (sym->class != SYM_FUNCTION) + cf_error("You can't call something which is not a function. Really."); - uint count = 0; - for (const struct f_inst *inst = f1; inst; inst = inst->next) - count++; - - if (count != sym->aux2) - cf_error("Function %s takes %u arguments, got %u.", sym->name, sym->aux2, count); - ]]); + uint count = 0; + for (const struct f_inst *inst = f1; inst; inst = inst->next) + count++; + + if (count != sym->aux2) + cf_error("Function %s takes %u arguments, got %u.", sym->name, sym->aux2, count); + FID_END } INST(FI_DROP_RESULT, 1, 0) { diff --git a/filter/f-inst.h b/filter/f-inst.h index 63124aa1..1423e685 100644 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@ -10,137 +10,21 @@ #ifndef _BIRD_F_INST_H_ #define _BIRD_F_INST_H_ +#include "nest/bird.h" +#include "conf/conf.h" #include "filter/filter.h" -#include "filter/f-util.h" +#include "filter/data.h" -/* Filter l-value type */ -enum f_lval_type { - F_LVAL_VARIABLE, - F_LVAL_PREFERENCE, - F_LVAL_SA, - F_LVAL_EA, -}; - -/* Filter l-value */ -struct f_lval { - enum f_lval_type type; - union { - const struct symbol *sym; - struct f_dynamic_attr da; - struct f_static_attr sa; - }; -}; +/* Include generated filter instruction declarations */ +#include "filter/f-inst-decl.h" -/* Filter instruction declarations */ -#define FI__LIST \ - F(FI_NOP) \ - F(FI_ADD, ARG, ARG) \ - F(FI_SUBTRACT, ARG, ARG) \ - F(FI_MULTIPLY, ARG, ARG) \ - F(FI_DIVIDE, ARG, ARG) \ - F(FI_AND, ARG, LINE) \ - F(FI_OR, ARG, LINE) \ - F(FI_PAIR_CONSTRUCT, ARG, ARG) \ - F(FI_EC_CONSTRUCT, ARG, ARG, ECS) \ - F(FI_LC_CONSTRUCT, ARG, ARG, ARG) \ - F(FI_PATHMASK_CONSTRUCT, ARG, COUNT) \ - F(FI_NEQ, ARG, ARG) \ - F(FI_EQ, ARG, ARG) \ - F(FI_LT, ARG, ARG) \ - F(FI_LTE, ARG, ARG) \ - F(FI_NOT, ARG) \ - F(FI_MATCH, ARG, ARG) \ - F(FI_NOT_MATCH, ARG, ARG) \ - F(FI_DEFINED, ARG) \ - F(FI_TYPE, ARG) \ - F(FI_IS_V4, ARG) \ - F(FI_SET, ARG, SYMBOL) \ - F(FI_CONSTANT, VALI) \ - F(FI_VARIABLE, SYMBOL) \ - F(FI_CONSTANT_INDIRECT, VALP) \ - F(FI_PRINT, ARG) \ - F(FI_CONDITION, ARG, LINE, LINE) \ - F(FI_PRINT_AND_DIE, ARG, FRET) \ - F(FI_RTA_GET, SA) \ - F(FI_RTA_SET, ARG, SA) \ - F(FI_EA_GET, EA) \ - F(FI_EA_SET, ARG, EA) \ - F(FI_EA_UNSET, EA) \ - F(FI_PREF_GET) \ - F(FI_PREF_SET, ARG) \ - F(FI_LENGTH, ARG) \ - F(FI_ROA_MAXLEN, ARG) \ - F(FI_ROA_ASN, ARG) \ - F(FI_SADR_SRC, ARG) \ - F(FI_IP, ARG) \ - F(FI_ROUTE_DISTINGUISHER, ARG) \ - F(FI_AS_PATH_FIRST, ARG) \ - F(FI_AS_PATH_LAST, ARG) \ - F(FI_AS_PATH_LAST_NAG, ARG) \ - F(FI_RETURN, ARG) \ - F(FI_CALL, SYMBOL, LINE) \ - F(FI_DROP_RESULT, ARG) \ - F(FI_SWITCH, ARG, TREE) \ - F(FI_IP_MASK, ARG, ARG) \ - F(FI_PATH_PREPEND, ARG, ARG) \ - F(FI_CLIST_ADD, ARG, ARG) \ - F(FI_CLIST_DEL, ARG, ARG) \ - F(FI_CLIST_FILTER, ARG, ARG) \ - F(FI_ROA_CHECK_IMPLICIT, RTC) \ - F(FI_ROA_CHECK_EXPLICIT, ARG, ARG, RTC) \ - F(FI_FORMAT, ARG) \ - F(FI_ASSERT, ARG, STRING) - -/* The enum itself */ -enum f_instruction_code { -#define F(c, ...) c, -FI__LIST -#undef F - FI__MAX, -} PACKED; +#define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__) /* Convert the instruction back to the enum name */ const char *f_instruction_name(enum f_instruction_code fi); -struct f_inst; -void f_inst_next(struct f_inst *first, const struct f_inst *append); struct f_inst *f_clear_local_vars(struct f_inst *decls); -#define FIA(x) , FIA_##x -#define FIA_ARG const struct f_inst * -#define FIA_LINE const struct f_inst * -#define FIA_COUNT uint -#define FIA_SYMBOL const struct symbol * -#define FIA_VALI struct f_val -#define FIA_VALP const struct f_val * -#define FIA_FRET enum filter_return -#define FIA_ECS enum ec_subtype -#define FIA_SA struct f_static_attr -#define FIA_EA struct f_dynamic_attr -#define FIA_RTC const struct rtable_config * -#define FIA_TREE const struct f_tree * -#define FIA_STRING const char * -#define F(c, ...) \ - struct f_inst *f_new_inst_##c(enum f_instruction_code MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))()(MACRO_FOREACH(FIA, __VA_ARGS__))); -FI__LIST -#undef F -#undef FIA_ARG -#undef FIA_LINE -#undef FIA_LINEP -#undef FIA_COUNT -#undef FIA_SYMBOL -#undef FIA_VALI -#undef FIA_VALP -#undef FIA_FRET -#undef FIA_ECS -#undef FIA_SA -#undef FIA_EA -#undef FIA_RTC -#undef FIA_STRING -#undef FIA - -#define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__) - /* Flags for instructions */ enum f_instruction_flags { FIF_PRINTED = 1, /* FI_PRINT_AND_DIE: message put in buffer */ @@ -202,7 +86,4 @@ struct f_bt_test_suite { const char *dsc; /* Description */ }; -/* Include the auto-generated structures */ -#include "filter/f-inst-struct.h" - #endif diff --git a/filter/f-util.c b/filter/f-util.c index eb948fa0..82aaa385 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -17,22 +17,6 @@ #define P(a,b) ((a<<8) | b) -static const char * const f_instruction_name_str[] = { -#define F(c,...) \ - [c] = #c, -FI__LIST -#undef F -}; - -const char * -f_instruction_name(enum f_instruction_code fi) -{ - if (fi < FI__MAX) - return f_instruction_name_str[fi]; - else - bug("Got unknown instruction code: %d", fi); -} - char * filter_name(struct filter *filter) { @@ -56,18 +40,21 @@ struct filter *f_new_where(const struct f_inst *where) struct f_inst acc = { .fi_code = FI_PRINT_AND_DIE, .lineno = ifs->lino, + .size = 1, .i_FI_PRINT_AND_DIE = { .fret = F_ACCEPT, }, }; struct f_inst rej = { .fi_code = FI_PRINT_AND_DIE, .lineno = ifs->lino, + .size = 1, .i_FI_PRINT_AND_DIE = { .fret = F_REJECT, }, }; struct f_inst i = { .fi_code = FI_CONDITION, .lineno = ifs->lino, + .size = 3, .i_FI_CONDITION = { .f1 = where, .f2 = &acc, diff --git a/filter/f-util.h b/filter/f-util.h deleted file mode 100644 index a7d77bbd..00000000 --- a/filter/f-util.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * BIRD Internet Routing Daemon -- Filter utils - * - * (c) 1999 Pavel Machek - * (c) 2018--2019 Maria Matejka - * - * Can be freely distributed and used under the terms of the GNU GPL. - */ - -#ifndef _BIRD_F_UTIL_H_ -#define _BIRD_F_UTIL_H_ - -/* IP prefix range structure */ -struct f_prefix { - net_addr net; /* The matching prefix must match this net */ - u8 lo, hi; /* And its length must fit between lo and hi */ -}; - -/* Type numbers must be in 0..0xff range */ -#define T_MASK 0xff - -/* Internal types */ -enum f_type { -/* Do not use type of zero, that way we'll see errors easier. */ - T_VOID = 1, - -/* User visible types, which fit in int */ - T_INT = 0x10, - T_BOOL = 0x11, - T_PAIR = 0x12, /* Notice that pair is stored as integer: first << 16 | second */ - T_QUAD = 0x13, - -/* Put enumerational types in 0x30..0x3f range */ - T_ENUM_LO = 0x30, - T_ENUM_HI = 0x3f, - - T_ENUM_RTS = 0x30, - T_ENUM_BGP_ORIGIN = 0x31, - T_ENUM_SCOPE = 0x32, - T_ENUM_RTC = 0x33, - T_ENUM_RTD = 0x34, - T_ENUM_ROA = 0x35, - T_ENUM_NETTYPE = 0x36, - T_ENUM_RA_PREFERENCE = 0x37, - -/* new enums go here */ - T_ENUM_EMPTY = 0x3f, /* Special hack for atomic_aggr */ - -#define T_ENUM T_ENUM_LO ... T_ENUM_HI - -/* Bigger ones */ - T_IP = 0x20, - T_NET = 0x21, - T_STRING = 0x22, - T_PATH_MASK = 0x23, /* mask for BGP path */ - T_PATH = 0x24, /* BGP path */ - T_CLIST = 0x25, /* Community list */ - T_EC = 0x26, /* Extended community value, u64 */ - T_ECLIST = 0x27, /* Extended community list */ - T_LC = 0x28, /* Large community value, lcomm */ - T_LCLIST = 0x29, /* Large community list */ - T_RD = 0x2a, /* Route distinguisher for VPN addresses */ - T_PATH_MASK_ITEM = 0x2b, /* Path mask item for path mask constructors */ - - T_SET = 0x80, - T_PREFIX_SET = 0x81, -} PACKED; - -/* Filter value; size of this affects filter memory consumption */ -struct f_val { - enum f_type type; /* T_* */ - union { - uint i; - u64 ec; - lcomm lc; - ip_addr ip; - const net_addr *net; - char *s; - const struct f_tree *t; - const struct f_trie *ti; - const struct adata *ad; - const struct f_path_mask *path_mask; - struct f_path_mask_item pmi; - } val; -}; - -#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); - -/* Dynamic attribute definition (eattrs) */ -struct f_dynamic_attr { - u8 type; /* EA type (EAF_*) */ - u8 bit; /* For bitfield accessors */ - enum f_type f_type; /* Filter type */ - uint ea_code; /* EA code */ -}; - -enum f_sa_code { - SA_FROM = 1, - SA_GW, - SA_NET, - SA_PROTO, - SA_SOURCE, - SA_SCOPE, - SA_DEST, - SA_IFNAME, - SA_IFINDEX, -} PACKED; - -/* Static attribute definition (members of struct rta) */ -struct f_static_attr { - enum f_type f_type; /* Filter type */ - enum f_sa_code sa_code; /* Static attribute id */ - int readonly:1; /* Don't allow writing */ -}; - -struct f_tree { - struct f_tree *left, *right; - struct f_val from, to; - void *data; -}; - -struct f_trie_node -{ - ip_addr addr, mask, accept; - uint plen; - struct f_trie_node *c[2]; -}; - -struct f_trie -{ - linpool *lp; - int zero; - uint node_size; - struct f_trie_node root[0]; /* Root trie node follows */ -}; - -struct f_tree *f_new_tree(void); -struct f_tree *build_tree(struct f_tree *); -const struct f_tree *find_tree(const struct f_tree *t, const struct f_val *val); -int same_tree(const struct f_tree *t0, const struct f_tree *t2); -void tree_format(const struct f_tree *t, buffer *buf); - -struct f_trie *f_new_trie(linpool *lp, uint node_size); -void *trie_add_prefix(struct f_trie *t, const net_addr *n, uint l, uint h); -int trie_match_net(const struct f_trie *t, const net_addr *n); -int trie_same(const struct f_trie *t1, const struct f_trie *t2); -void trie_format(const struct f_trie *t, buffer *buf); - -extern const struct f_val f_const_empty_path, f_const_empty_clist, f_const_empty_eclist, f_const_empty_lclist; - -#endif diff --git a/filter/filter.c b/filter/filter.c index ff702f2b..0cb56fe4 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -48,7 +48,7 @@ #include "conf/conf.h" #include "filter/filter.h" #include "filter/f-inst.h" -#include "filter/f-util.h" +#include "filter/data.h" #define CMP_ERROR 999 @@ -64,6 +64,75 @@ struct filter_state { void (*bt_assert_hook)(int result, const struct f_line_item *assert); +static const char * const f_instruction_name_str[] = { + /* TODO: Make this better */ + [FI_ADD] = "FI_ADD", + [FI_SUBTRACT] = "FI_SUBTRACT", + [FI_MULTIPLY] = "FI_MULTIPLY", + [FI_DIVIDE] = "FI_DIVIDE", + [FI_AND] = "FI_AND", + [FI_OR] = "FI_OR", + [FI_PAIR_CONSTRUCT] = "FI_PAIR_CONSTRUCT", + [FI_EC_CONSTRUCT] = "FI_EC_CONSTRUCT", + [FI_LC_CONSTRUCT] = "FI_LC_CONSTRUCT", + [FI_PATHMASK_CONSTRUCT] = "FI_PATHMASK_CONSTRUCT", + [FI_NEQ] = "FI_NEQ", + [FI_EQ] = "FI_EQ", + [FI_LT] = "FI_LT", + [FI_LTE] = "FI_LTE", + [FI_NOT] = "FI_NOT", + [FI_MATCH] = "FI_MATCH", + [FI_NOT_MATCH] = "FI_NOT_MATCH", + [FI_DEFINED] = "FI_DEFINED", + [FI_TYPE] = "FI_TYPE", + [FI_IS_V4] = "FI_IS_V4", + [FI_SET] = "FI_SET", + [FI_CONSTANT] = "FI_CONSTANT", + [FI_VARIABLE] = "FI_VARIABLE", + [FI_CONSTANT_INDIRECT] = "FI_CONSTANT_INDIRECT", + [FI_PRINT] = "FI_PRINT", + [FI_CONDITION] = "FI_CONDITION", + [FI_PRINT_AND_DIE] = "FI_PRINT_AND_DIE", + [FI_RTA_GET] = "FI_RTA_GET", + [FI_RTA_SET] = "FI_RTA_SET", + [FI_EA_GET] = "FI_EA_GET", + [FI_EA_SET] = "FI_EA_SET", + [FI_EA_UNSET] = "FI_EA_UNSET", + [FI_PREF_GET] = "FI_PREF_GET", + [FI_PREF_SET] = "FI_PREF_SET", + [FI_LENGTH] = "FI_LENGTH", + [FI_SADR_SRC] = "FI_SADR_SRC", + [FI_ROA_MAXLEN] = "FI_ROA_MAXLEN", + [FI_ROA_ASN] = "FI_ROA_ASN", + [FI_IP] = "FI_IP", + [FI_ROUTE_DISTINGUISHER] = "FI_ROUTE_DISTINGUISHER", + [FI_AS_PATH_FIRST] = "FI_AS_PATH_FIRST", + [FI_AS_PATH_LAST] = "FI_AS_PATH_LAST", + [FI_AS_PATH_LAST_NAG] = "FI_AS_PATH_LAST_NAG", + [FI_RETURN] = "FI_RETURN", + [FI_CALL] = "FI_CALL", + [FI_DROP_RESULT] = "FI_DROP_RESULT", + [FI_SWITCH] = "FI_SWITCH", + [FI_IP_MASK] = "FI_IP_MASK", + [FI_PATH_PREPEND] = "FI_PATH_PREPEND", + [FI_CLIST_ADD] = "FI_CLIST_ADD", + [FI_CLIST_DEL] = "FI_CLIST_DEL", + [FI_CLIST_FILTER] = "FI_CLIST_FILTER", + [FI_ROA_CHECK_IMPLICIT] = "FI_ROA_CHECK_IMPLICIT", + [FI_ROA_CHECK_EXPLICIT] = "FI_ROA_CHECK_EXPLICIT", + [FI_FORMAT] = "FI_FORMAT", + [FI_ASSERT] = "FI_ASSERT", +}; + +const char * +f_instruction_name(enum f_instruction_code fi) +{ + if (fi < (sizeof(f_instruction_name_str) / sizeof(f_instruction_name_str[0]))) + return f_instruction_name_str[fi]; + else + bug("Got unknown instruction code: %d", fi); +} + /* Special undef value for paths and clists */ static inline int undef_value(struct f_val v) @@ -615,18 +684,6 @@ val_format_str(struct filter_state *fs, struct f_val *v) { static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS; -static uint -inst_line_size(const struct f_inst *what_) -{ - uint cnt = 0; - for ( ; what_; what_ = what_->next) { - switch (what_->fi_code) { -#include "filter/f-inst-line-size.c" - } - } - return cnt; -} - #define INDENT (((const char *) f_dump_line_indent_str) + sizeof(f_dump_line_indent_str) - (indent) - 1) static const char f_dump_line_indent_str[] = " "; @@ -685,7 +742,8 @@ f_postfixify_concat(const struct f_inst * const inst[], uint count) { uint len = 0; for (uint i=0; inext) + len += what->size; struct f_line *out = cfg_allocz(sizeof(struct f_line) + sizeof(struct f_line_item)*len); diff --git a/filter/filter_test.c b/filter/filter_test.c index a02f0832..edd73ac8 100644 --- a/filter/filter_test.c +++ b/filter/filter_test.c @@ -17,7 +17,7 @@ #include "test/bt-utils.h" #include "filter/filter.h" -#include "filter/f-util.h" +#include "filter/data.h" #include "filter/f-inst.h" #include "conf/conf.h" diff --git a/filter/interpret.m4 b/filter/interpret.m4 index dfd5c6a7..e32b3a76 100644 --- a/filter/interpret.m4 +++ b/filter/interpret.m4 @@ -63,10 +63,11 @@ m4_define(TREE, `') m4_define(STRING, `') m4_define(COUNT, `') m4_define(POSTFIXIFY, `') -m4_define(LINE_SIZE, `') m4_define(SAME, `') -m4_define(STRUCT, `') -m4_define(NEW, `') +m4_define(FID_STRUCT_IN, `m4_divert(-1)') +m4_define(FID_NEW_ARGS, `m4_divert(-1)') +m4_define(FID_NEW_BODY, `m4_divert(-1)') +m4_define(FID_END, `m4_divert(2)') m4_m4wrap(` INST_FLUSH() diff --git a/filter/line-size.m4 b/filter/line-size.m4 deleted file mode 100644 index 051d3b90..00000000 --- a/filter/line-size.m4 +++ /dev/null @@ -1,41 +0,0 @@ -m4_divert(-1)m4_dnl -# -# BIRD -- Line size counting -# -# (c) 2018 Maria Matejka -# -# Can be freely distributed and used under the terms of the GNU GPL. -# - -# Common aliases -m4_define(DNL, `m4_dnl') - -m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[ -m4_divert(1) -case INST_NAME(): -cnt += 1; -#define what ((const struct f_inst_]]INST_NAME()[[ *) &(what_->i_]]INST_NAME()[[)) -m4_undivert(2) -#undef what -break; -m4_divert(-1) -]])') -m4_define(INST, `INST_FLUSH()m4_define([[INST_NAME]], [[$1]])') - -m4_define(ARG, `m4_divert(2)cnt += inst_line_size(what->f$1); -m4_divert(-1)') -m4_define(ARG_T, `m4_divert(2)cnt += inst_line_size(what->f$1); -m4_divert(-1)') -m4_define(ARG_ANY, `m4_divert(2)cnt += inst_line_size(what->f$1); -m4_divert(-1)') -m4_define(LINE_SIZE, `m4_divert(2)$1m4_divert(-1)') - -m4_m4wrap(` -INST_FLUSH() -m4_divert(0)DNL -m4_undivert(1) - -default: bug( "Unknown instruction %d (%c)", what_->fi_code, what_->fi_code & 0xff); -') - -m4_changequote([[,]]) diff --git a/filter/new.m4 b/filter/new.m4 deleted file mode 100644 index 38295e5c..00000000 --- a/filter/new.m4 +++ /dev/null @@ -1,78 +0,0 @@ -m4_divert(-1)m4_dnl -# -# BIRD -- Construction of per-instruction structures -# -# (c) 2018 Maria Matejka -# -# Can be freely distributed and used under the terms of the GNU GPL. -# -# -# Diversions: -# 1 for prepared output -# 2 for function arguments -# 3 for function body - -# Common aliases -m4_define(DNL, `m4_dnl') - -m4_define(FNSTOP, `m4_divert(-1)') -m4_define(FNOUT, `m4_divert(1)') -m4_define(FNARG, `m4_divert(2)') -m4_define(FNBODY, `m4_divert(3)') - -m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[ -FNOUT()DNL -struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code -m4_undivert(2) -) { - struct f_inst *what = cfg_allocz(sizeof(struct f_inst)); - what->fi_code = fi_code; - what->lineno = ifs->lino; -m4_undivert(3) - return what; -} -FNSTOP() -]]DNL -)') - -m4_define(INST, `INST_FLUSH()m4_define([[INST_NAME]], [[$1]])') - -m4_define(WHAT, `what->i_[[]]INST_NAME()') - -m4_define(FNMETAARG, `FNARG(), $1 $2 -FNBODY() WHAT().$2 = $2; -FNSTOP()') -m4_define(ARG, `FNMETAARG(const struct f_inst *, f$1)') -m4_define(ARG_ANY, `FNMETAARG(const struct f_inst *, f$1)') -m4_define(LINE, `FNMETAARG(const struct f_inst *, f$1)') -m4_define(SYMBOL, `FNMETAARG(const struct symbol *, sym)') -m4_define(VALI, `FNMETAARG(struct f_val, vali)') -m4_define(VALP, `FNMETAARG(const struct f_val *, valp)') -m4_define(VAR, `FNARG(), const struct symbol * sym -FNBODY() WHAT().valp = (WHAT().sym = sym)->def; -FNSTOP()') -m4_define(FRET, `FNMETAARG(enum filter_return, fret)') -m4_define(ECS, `FNMETAARG(enum ec_subtype, ecs)') -m4_define(RTC, `FNMETAARG(const struct rtable_config *, rtc)') -m4_define(STATIC_ATTR, `FNMETAARG(struct f_static_attr, sa)') -m4_define(DYNAMIC_ATTR, `FNMETAARG(struct f_dynamic_attr, da)') -m4_define(COUNT, `FNMETAARG(uint, count)') -m4_define(TREE, `FNMETAARG(const struct f_tree *, tree)') -m4_define(STRING, `FNMETAARG(const char *, s)') -m4_define(NEW, `FNARG()$1 -FNBODY()$2 -FNSTOP()') - -m4_m4wrap(` -INST_FLUSH() -m4_divert(0) -#include "nest/bird.h" -#include "conf/conf.h" -#include "filter/filter.h" -#include "filter/f-inst.h" - -m4_undivert(1) - -') - -m4_changequote([[,]]) diff --git a/filter/struct.m4 b/filter/struct.m4 deleted file mode 100644 index 7af28cfd..00000000 --- a/filter/struct.m4 +++ /dev/null @@ -1,73 +0,0 @@ -m4_divert(-1)m4_dnl -# -# BIRD -- Definition of per-instruction structures -# -# (c) 2018 Maria Matejka -# -# Can be freely distributed and used under the terms of the GNU GPL. -# - -# Common aliases -m4_define(DNL, `m4_dnl') - -m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[ -m4_divert(1) -struct f_inst_[[]]INST_NAME() { -m4_undivert(2) -}; -m4_divert(3) -struct f_inst_[[]]INST_NAME() i_[[]]INST_NAME(); -m4_divert(-1) -]])') -m4_define(INST, `INST_FLUSH()m4_define([[INST_NAME]], [[$1]])') - -m4_define(ARG, `m4_divert(2)const struct f_inst *f$1; -m4_divert(-1)') -m4_define(ARG_ANY, `m4_divert(2)const struct f_inst *f$1; -m4_divert(-1)') -m4_define(LINE, `m4_divert(2)const struct f_inst *f$1; -m4_divert(-1)') -m4_define(LINEP, `m4_divert(2)const struct f_line *fl$1; -m4_divert(-1)') -m4_define(SYMBOL, `m4_divert(2)const struct symbol *sym; -m4_divert(-1)') -m4_define(VALI, `m4_divert(2)struct f_val vali; -m4_divert(-1)') -m4_define(VALP, `m4_divert(2)const struct f_val *valp; -m4_divert(-1)') -m4_define(VAR, `VALP()SYMBOL()') -m4_define(FRET, `m4_divert(2)enum filter_return fret; -m4_divert(-1)') -m4_define(ECS, `m4_divert(2)enum ec_subtype ecs; -m4_divert(-1)') -m4_define(RTC, `m4_divert(2)const struct rtable_config *rtc; -m4_divert(-1)') -m4_define(STATIC_ATTR, `m4_divert(2)struct f_static_attr sa; -m4_divert(-1)') -m4_define(DYNAMIC_ATTR, `m4_divert(2)struct f_dynamic_attr da; -m4_divert(-1)') -m4_define(COUNT, `m4_divert(2)uint count; -m4_divert(-1)') -m4_define(TREE, `m4_divert(2)const struct f_tree *tree; -m4_divert(-1)') -m4_define(STRING, `m4_divert(2)const char *s; -m4_divert(-1)') -m4_define(STRUCT, `m4_divert(2)$1 -m4_divert(-1)') - -m4_m4wrap(` -INST_FLUSH() -m4_divert(0)DNL -m4_undivert(1) - -struct f_inst { - const struct f_inst *next; /* Next instruction */ - enum f_instruction_code fi_code; /* Instruction code */ - int lineno; /* Line number */ - union { - m4_undivert(3) - }; -}; -') - -m4_changequote([[,]]) diff --git a/filter/tree.c b/filter/tree.c index 879b0859..46d6e529 100644 --- a/filter/tree.c +++ b/filter/tree.c @@ -10,7 +10,7 @@ #include "nest/bird.h" #include "conf/conf.h" #include "filter/filter.h" -#include "filter/f-util.h" +#include "filter/data.h" /** * find_tree diff --git a/filter/tree_test.c b/filter/tree_test.c index 9e0de50f..6472d17e 100644 --- a/filter/tree_test.c +++ b/filter/tree_test.c @@ -10,7 +10,7 @@ #include "test/bt-utils.h" #include "filter/filter.h" -#include "filter/f-util.h" +#include "filter/data.h" #include "conf/conf.h" #define MAX_TREE_HEIGHT 13 diff --git a/filter/trie.c b/filter/trie.c index dccf9130..3038f5ec 100644 --- a/filter/trie.c +++ b/filter/trie.c @@ -73,7 +73,7 @@ #include "lib/string.h" #include "conf/conf.h" #include "filter/filter.h" -#include "filter/f-util.h" +#include "filter/data.h" /* diff --git a/filter/trie_test.c b/filter/trie_test.c index b6959c4a..38c387b0 100644 --- a/filter/trie_test.c +++ b/filter/trie_test.c @@ -10,7 +10,7 @@ #include "test/bt-utils.h" #include "filter/filter.h" -#include "filter/f-util.h" +#include "filter/data.h" #include "conf/conf.h" #define TESTS_NUM 10 diff --git a/nest/a-path.c b/nest/a-path.c index ac13d0fa..62369af3 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -13,7 +13,7 @@ #include "lib/resource.h" #include "lib/unaligned.h" #include "lib/string.h" -#include "filter/f-util.h" +#include "filter/data.h" // static inline void put_as(byte *data, u32 as) { put_u32(data, as); } // static inline u32 get_as(byte *data) { return get_u32(data); } diff --git a/nest/cmds.c b/nest/cmds.c index 40d397cc..2b83033f 100644 --- a/nest/cmds.c +++ b/nest/cmds.c @@ -15,7 +15,7 @@ #include "lib/string.h" #include "lib/resource.h" #include "filter/filter.h" -#include "filter/f-util.h" +#include "filter/data.h" extern int shutting_down; extern int configuring; diff --git a/nest/rt-table.c b/nest/rt-table.c index d72a8695..6c8e662e 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -39,7 +39,7 @@ #include "lib/string.h" #include "conf/conf.h" #include "filter/filter.h" -#include "filter/f-util.h" +#include "filter/data.h" #include "lib/hash.h" #include "lib/string.h" #include "lib/alloca.h" diff --git a/proto/static/config.Y b/proto/static/config.Y index 0e53c978..3e9ac578 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -139,7 +139,7 @@ stat_route: stat_route_item: cmd { if (this_srt_last_cmd) - f_inst_next(this_srt_last_cmd, $1); + this_srt_last_cmd->next = $1; else this_srt_cmds = $1; this_srt_last_cmd = $1; diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index f9002d58..0fdd5b34 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -36,7 +36,7 @@ #include "nest/locks.h" #include "conf/conf.h" #include "filter/filter.h" -#include "filter/f-util.h" +#include "filter/data.h" #include "unix.h" #include "krt.h" -- cgit v1.2.3 From 23e3b1e6652bac4a003a7eb1e074bdaf7ebb4900 Mon Sep 17 00:00:00 2001 From: Jan Maria Matejka Date: Wed, 22 May 2019 15:16:32 +0000 Subject: Filter: Some people can't pronounce "postfixify" correctly. Let's try "linearize" instead. This is just a naming change. --- conf/confbase.Y | 4 ++-- filter/config.Y | 14 +++++++------- filter/decl.m4 | 30 +++++++++++++++--------------- filter/f-inst.c | 8 ++++---- filter/f-inst.h | 8 ++++---- filter/f-util.c | 2 +- nest/config.Y | 4 ++-- proto/static/config.Y | 2 +- 8 files changed, 36 insertions(+), 36 deletions(-) (limited to 'proto/static') diff --git a/conf/confbase.Y b/conf/confbase.Y index 9978aec8..bcfd3f1a 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -147,14 +147,14 @@ conf: definition ; definition: DEFINE CF_SYM_VOID '=' term ';' { struct f_val *val = cfg_alloc(sizeof(struct f_val)); - if (f_eval(f_postfixify($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error"); + if (f_eval(f_linearize($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error"); cf_define_symbol($2, SYM_CONSTANT | val->type, val, val); } ; expr: NUM - | '(' term ')' { $$ = f_eval_int(f_postfixify($2)); } + | '(' term ')' { $$ = f_eval_int(f_linearize($2)); } | CF_SYM_KNOWN { if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected"); $$ = SYM_VAL($1).i; } diff --git a/filter/config.Y b/filter/config.Y index 5f9b8356..3898748c 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -481,7 +481,7 @@ filter_def: conf: filter_eval ; filter_eval: - EVAL term { f_eval_int(f_postfixify($2)); } + EVAL term { f_eval_int(f_linearize($2)); } ; conf: custom_attr ; @@ -600,7 +600,7 @@ function_params: function_body: decls '{' cmds '}' { - $$ = f_postfixify($3); + $$ = f_linearize($3); $$->vars = decls_count; } ; @@ -661,7 +661,7 @@ set_atom: | VPN_RD { $$.type = T_RD; $$.val.ec = $1; } | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); } | '(' term ')' { - if (f_eval(f_postfixify($2), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error"); + if (f_eval(f_linearize($2), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error"); if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type"); } | CF_SYM_KNOWN { @@ -673,13 +673,13 @@ set_atom: switch_atom: NUM { $$.type = T_INT; $$.val.i = $1; } - | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int(f_postfixify($2)); } + | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int(f_linearize($2)); } | fipa { $$ = $1; } | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); } ; cnum: - term { $$ = f_eval_int(f_postfixify($1)); } + term { $$ = f_eval_int(f_linearize($1)); } pair_item: '(' cnum ',' cnum ')' { $$ = f_new_pair_item($2, $2, $4, $4); } @@ -766,7 +766,7 @@ switch_body: /* EMPTY */ { $$ = NULL; } | switch_body switch_items ':' cmds { /* Fill data fields */ struct f_tree *t; - struct f_line *line = f_postfixify($4); + struct f_line *line = f_linearize($4); for (t = $2; t; t = t->left) t->data = line; $$ = f_merge_items($1, $2); @@ -775,7 +775,7 @@ switch_body: /* EMPTY */ { $$ = NULL; } struct f_tree *t = f_new_tree(); t->from.type = t->to.type = T_VOID; t->right = t; - t->data = f_postfixify($3); + t->data = f_linearize($3); $$ = f_merge_items($1, t); } ; diff --git a/filter/decl.m4 b/filter/decl.m4 index c9b5c8c5..d8497535 100644 --- a/filter/decl.m4 +++ b/filter/decl.m4 @@ -12,7 +12,7 @@ m4_divert(-1)m4_dnl # 5 enum fi_code to string # 6 dump line item # 7 dump line item callers -# 8 postfixify +# 8 linearize # 9 same (filter comparator) # 1 union in struct f_inst # 3 constructors @@ -23,7 +23,7 @@ m4_divert(-1)m4_dnl # 102 constructor arguments # 103 constructor body # 104 dump line item content -# 105 postfixify body +# 105 linearize body # 106 comparator body # 107 struct f_line_item content # 108 interpreter body @@ -45,7 +45,7 @@ m4_define(FID_ENUM, `FID_ZONE(4, Code enum)') m4_define(FID_ENUM_STR, `FID_ZONE(5, Code enum to string)') m4_define(FID_DUMP, `FID_ZONE(6, Dump line)') m4_define(FID_DUMP_CALLER, `FID_ZONE(7, Dump line caller)') -m4_define(FID_POSTFIXIFY, `FID_ZONE(8, Postfixify)') +m4_define(FID_LINEARIZE, `FID_ZONE(8, Linearize)') m4_define(FID_SAME, `FID_ZONE(9, Comparison)') m4_define(FID_INTERPRET, `FID_ZONE(10, Interpret)') @@ -53,7 +53,7 @@ m4_define(FID_STRUCT_IN, `m4_divert(101)') m4_define(FID_NEW_ARGS, `m4_divert(102)') m4_define(FID_NEW_BODY, `m4_divert(103)') m4_define(FID_DUMP_BODY, `m4_divert(104)m4_define([[FID_DUMP_BODY_EXISTS]])') -m4_define(FID_POSTFIXIFY_BODY, `m4_divert(105)m4_define([[FID_POSTFIXIFY_BODY_EXISTS]])') +m4_define(FID_LINEARIZE_BODY, `m4_divert(105)m4_define([[FID_LINEARIZE_BODY_EXISTS]])') m4_define(FID_SAME_BODY, `m4_divert(106)') m4_define(FID_LINE_IN, `m4_divert(107)') m4_define(FID_INTERPRET_BODY, `m4_divert(108)') @@ -112,7 +112,7 @@ m4_undivert(104) } FID_ALL_TARGETS -FID_POSTFIXIFY +FID_LINEARIZE case INST_NAME(): { #define what (&(what_->i_]]INST_NAME()[[)) #define item (&(dest->items[pos].i_]]INST_NAME()[[)) @@ -123,7 +123,7 @@ case INST_NAME(): { dest->items[pos].lineno = what_->lineno; break; } -m4_undefine([[FID_POSTFIXIFY_BODY_EXISTS]]) +m4_undefine([[FID_LINEARIZE_BODY_EXISTS]]) FID_SAME case INST_NAME(): @@ -170,7 +170,7 @@ FID_NEW_ARGS FID_NEW_BODY what->$2 = $2; m4_ifelse($3,,,[[ -FID_POSTFIXIFY_BODY +FID_LINEARIZE_BODY item->$3 = what->$2; ]]) m4_ifelse($4,,,[[ @@ -195,8 +195,8 @@ FID_NEW_ARGS FID_NEW_BODY what->f$1 = f$1; for (const struct f_inst *child = f$1; child; child = child->next) what_->size += child->size; -FID_POSTFIXIFY_BODY -pos = postfixify(dest, what->f$1, pos);m4_dnl +FID_LINEARIZE_BODY +pos = linearize(dest, what->f$1, pos);m4_dnl FID_ALL()') m4_define(ARG, `ARG_ANY($1) @@ -226,8 +226,8 @@ FID_NEW_BODY what->f$1 = f$1; FID_DUMP_BODY f_dump_line(item->fl$1, indent + 1); -FID_POSTFIXIFY_BODY -item->fl$1 = f_postfixify(what->f$1); +FID_LINEARIZE_BODY +item->fl$1 = f_linearize(what->f$1); FID_SAME_BODY if (!f_same(f1->fl$1, f2->fl$1)) return 0; FID_INTERPRET_BODY @@ -310,9 +310,9 @@ FID_WR_PUT(7) debug("%sFilter line %p dump done\n", INDENT, dest); } -/* Postfixify */ +/* Linearize */ static uint -postfixify(struct f_line *dest, const struct f_inst *what_, uint pos) +linearize(struct f_line *dest, const struct f_inst *what_, uint pos) { for ( ; what_; what_ = what_->next) { switch (what_->fi_code) { @@ -324,7 +324,7 @@ FID_WR_PUT(8) } struct f_line * -f_postfixify_concat(const struct f_inst * const inst[], uint count) +f_linearize_concat(const struct f_inst * const inst[], uint count) { uint len = 0; for (uint i=0; ilen = postfixify(out, inst[i], out->len); + out->len = linearize(out, inst[i], out->len); #if DEBUGGING f_dump_line(out, 0); diff --git a/filter/f-inst.c b/filter/f-inst.c index 4a4f6016..d0bfa95b 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -295,7 +295,7 @@ , const struct f_val val FID_NEW_BODY what->val = val; - FID_POSTFIXIFY_BODY + FID_LINEARIZE_BODY item->val = what->val; FID_SAME_BODY if (!val_same(&(f1->val), &(f2->val))) return 0; @@ -316,7 +316,7 @@ , const struct symbol *sym FID_NEW_BODY what->sym = sym; - FID_POSTFIXIFY_BODY + FID_LINEARIZE_BODY item->valp = (item->sym = what->sym)->val; FID_SAME_BODY if (strcmp(f1->sym->name, f2->sym->name) || !val_same(f1->sym->val, f2->sym->val)) return 0; @@ -339,14 +339,14 @@ LINE(3,1); } INST(FI_PRINT_AND_DIE, 0, 0) { - FID_POSTFIXIFY_BODY + FID_LINEARIZE_BODY { uint opos = pos; FID_ALL ARG_ANY(1); - FID_POSTFIXIFY_BODY + FID_LINEARIZE_BODY if (opos < pos) dest->items[pos].flags |= FIF_PRINTED; } diff --git a/filter/f-inst.h b/filter/f-inst.h index 21cec454..f0dcec64 100644 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@ -17,7 +17,7 @@ * translates into f_new_inst_FI_code(...) and the types are checked in * compile time. * - * 2 Postfixify before interpreting + * 2 Linearize before interpreting * The infix tree is always interpreted in the same order. Therefore we * sort the instructions one after another into struct f_line. Results * and arguments of these instructions are implicitly put on a value @@ -73,9 +73,9 @@ struct f_line { }; /* Convert the f_inst infix tree to the f_line structures */ -struct f_line *f_postfixify_concat(const struct f_inst * const inst[], uint count); -static inline struct f_line *f_postfixify(const struct f_inst *root) -{ return f_postfixify_concat(&root, 1); } +struct f_line *f_linearize_concat(const struct f_inst * const inst[], uint count); +static inline struct f_line *f_linearize(const struct f_inst *root) +{ return f_linearize_concat(&root, 1); } void f_dump_line(const struct f_line *, uint indent); diff --git a/filter/f-util.c b/filter/f-util.c index 79201fba..5500f282 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -58,7 +58,7 @@ struct filter *f_new_where(const struct f_inst *where) }; struct filter *f = cfg_allocz(sizeof(struct filter)); - f->root = f_postfixify(&i); + f->root = f_linearize(&i); return f; } diff --git a/nest/config.Y b/nest/config.Y index fe642489..e4dedc66 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -112,7 +112,7 @@ rtrid: idval: NUM { $$ = $1; } - | '(' term ')' { $$ = f_eval_int(f_postfixify($2)); } + | '(' term ')' { $$ = f_eval_int(f_linearize($2)); } | IP4 { $$ = ip4_to_u32($1); } | CF_SYM_KNOWN { if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD)) @@ -733,7 +733,7 @@ CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]]) { protos_dump_all(); cli_msg(0, ""); } ; CF_CLI(EVAL, term, , [[Evaluate an expression]]) -{ cmd_eval(f_postfixify($2)); } ; +{ cmd_eval(f_linearize($2)); } ; CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]]) CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug|trace|info|remote|warning|error|auth [, ...] }) [], [[Control echoing of log messages]]) { diff --git a/proto/static/config.Y b/proto/static/config.Y index 3e9ac578..6e410879 100644 --- a/proto/static/config.Y +++ b/proto/static/config.Y @@ -40,7 +40,7 @@ static_route_finish(void) if (net_type_match(this_srt->net, NB_DEST) == !this_srt->dest) cf_error("Unexpected or missing nexthop/type"); - this_srt->cmds = f_postfixify(this_srt_cmds); + this_srt->cmds = f_linearize(this_srt_cmds); } CF_DECLS -- cgit v1.2.3