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. --- nest/attrs.h | 111 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 50 deletions(-) (limited to 'nest/attrs.h') diff --git a/nest/attrs.h b/nest/attrs.h index 102f378a..d9d97136 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -31,15 +31,15 @@ struct f_tree; int as_path_valid(byte *data, uint len, int bs, int confed, char *err, uint elen); -int as_path_16to32(byte *dst, byte *src, uint len); -int as_path_32to16(byte *dst, byte *src, uint len); +int as_path_16to32(byte *dst, const byte *src, uint len); +int as_path_32to16(byte *dst, const byte *src, uint len); int as_path_contains_as4(const struct adata *path); int as_path_contains_confed(const struct adata *path); struct adata *as_path_strip_confed(struct linpool *pool, const struct adata *op); struct adata *as_path_prepend2(struct linpool *pool, const struct adata *op, int seq, u32 as); struct adata *as_path_to_old(struct linpool *pool, const struct adata *path); -void as_path_cut(struct adata *path, uint num); -struct adata *as_path_merge(struct linpool *pool, struct adata *p1, struct adata *p2); +struct adata *as_path_cut(struct linpool *pool, const struct adata *path, uint num); +const struct adata *as_path_merge(struct linpool *pool, const struct adata *p1, const struct adata *p2); void as_path_format(const struct adata *path, byte *buf, uint size); int as_path_getlen(const struct adata *path); int as_path_getlen_int(const struct adata *path, int bs); @@ -48,8 +48,8 @@ int as_path_get_first_regular(const struct adata *path, u32 *last_as); int as_path_get_last(const struct adata *path, u32 *last_as); u32 as_path_get_last_nonaggregated(const struct adata *path); int as_path_contains(const struct adata *path, u32 as, int min); -int as_path_match_set(const struct adata *path, struct f_tree *set); -struct adata *as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32 key, int pos); +int as_path_match_set(const struct adata *path, const struct f_tree *set); +const struct adata *as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tree *set, u32 key, int pos); static inline struct adata *as_path_prepend(struct linpool *pool, const struct adata *path, u32 as) { return as_path_prepend2(pool, path, AS_PATH_SEQUENCE, as); } @@ -61,20 +61,30 @@ static inline struct adata *as_path_prepend(struct linpool *pool, const struct a #define PM_ASN_EXPR 3 #define PM_ASN_RANGE 4 -struct f_path_mask { - struct f_path_mask *next; +struct f_path_mask_item { + union { + u32 asn; /* PM_ASN */ + struct f_line *expr; /* PM_ASN_EXPR */ + struct { /* PM_ASN_RANGE */ + u32 from; + u32 to; + }; + }; int kind; - uintptr_t val; - uintptr_t val2; }; -int as_path_match(const struct adata *path, struct f_path_mask *mask); +struct f_path_mask { + uint len; + struct f_path_mask_item item[0]; +}; + +int as_path_match(const struct adata *path, const struct f_path_mask *mask); /* Counterparts to appropriate as_path_* functions */ static inline int -aggregator_16to32(byte *dst, byte *src) +aggregator_16to32(byte *dst, const byte *src) { put_u32(dst, get_u16(src)); memcpy(dst+4, src+2, 4); @@ -82,7 +92,7 @@ aggregator_16to32(byte *dst, byte *src) } static inline int -aggregator_32to16(byte *dst, byte *src) +aggregator_32to16(byte *dst, const byte *src) { put_u16(dst, get_u32(src)); memcpy(dst+2, src+4, 4); @@ -90,13 +100,13 @@ aggregator_32to16(byte *dst, byte *src) } static inline int -aggregator_contains_as4(struct adata *a) +aggregator_contains_as4(const struct adata *a) { return get_u32(a->data) > 0xFFFF; } static inline struct adata * -aggregator_to_old(struct linpool *pool, struct adata *a) +aggregator_to_old(struct linpool *pool, const struct adata *a) { struct adata *d = lp_alloc_adata(pool, 8); put_u32(d->data, 0xFFFF); @@ -109,26 +119,27 @@ aggregator_to_old(struct linpool *pool, struct adata *a) /* Extended Community subtypes (kinds) */ -#define EC_RT 0x0002 -#define EC_RO 0x0003 - -#define EC_GENERIC 0xFFFF +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 #define ECOMM_LENGTH 8 -static inline int int_set_get_size(struct adata *list) +static inline int int_set_get_size(const struct adata *list) { return list->length / 4; } -static inline int ec_set_get_size(struct adata *list) +static inline int ec_set_get_size(const struct adata *list) { return list->length / 8; } -static inline int lc_set_get_size(struct adata *list) +static inline int lc_set_get_size(const struct adata *list) { return list->length / 12; } -static inline u32 *int_set_get_data(struct adata *list) +static inline u32 *int_set_get_data(const struct adata *list) { return (u32 *) list->data; } static inline u32 ec_hi(u64 ec) { return ec >> 32; } @@ -137,16 +148,16 @@ static inline u64 ec_get(const u32 *l, int i) { return (((u64) l[i]) << 32) | l[i+1]; } /* RFC 4360 3.1. Two-Octet AS Specific Extended Community */ -static inline u64 ec_as2(u64 kind, u64 key, u64 val) -{ return ((kind | 0x0000) << 48) | (key << 32) | val; } +static inline u64 ec_as2(enum ec_subtype kind, u64 key, u64 val) +{ return (((u64) kind | 0x0000) << 48) | (key << 32) | val; } /* RFC 5668 4-Octet AS Specific BGP Extended Community */ -static inline u64 ec_as4(u64 kind, u64 key, u64 val) -{ return ((kind | 0x0200) << 48) | (key << 16) | val; } +static inline u64 ec_as4(enum ec_subtype kind, u64 key, u64 val) +{ return (((u64) kind | 0x0200) << 48) | (key << 16) | val; } /* RFC 4360 3.2. IPv4 Address Specific Extended Community */ -static inline u64 ec_ip4(u64 kind, u64 key, u64 val) -{ return ((kind | 0x0100) << 48) | (key << 16) | val; } +static inline u64 ec_ip4(enum ec_subtype kind, u64 key, u64 val) +{ return (((u64) kind | 0x0100) << 48) | (key << 16) | val; } static inline u64 ec_generic(u64 key, u64 val) { return (key << 32) | val; } @@ -173,29 +184,29 @@ static inline u32 *lc_copy(u32 *dst, const u32 *src) { memcpy(dst, src, LCOMM_LENGTH); return dst + 3; } -int int_set_format(struct adata *set, int way, int from, byte *buf, uint size); +int int_set_format(const struct adata *set, int way, int from, byte *buf, uint size); int ec_format(byte *buf, u64 ec); -int ec_set_format(struct adata *set, int from, byte *buf, uint size); +int ec_set_format(const struct adata *set, int from, byte *buf, uint size); int lc_format(byte *buf, lcomm lc); -int lc_set_format(struct adata *set, int from, byte *buf, uint size); -int int_set_contains(struct adata *list, u32 val); -int ec_set_contains(struct adata *list, u64 val); -int lc_set_contains(struct adata *list, lcomm val); -struct adata *int_set_prepend(struct linpool *pool, struct adata *list, u32 val); -struct adata *int_set_add(struct linpool *pool, struct adata *list, u32 val); -struct adata *ec_set_add(struct linpool *pool, struct adata *list, u64 val); -struct adata *lc_set_add(struct linpool *pool, struct adata *list, lcomm val); -struct adata *int_set_del(struct linpool *pool, struct adata *list, u32 val); -struct adata *ec_set_del(struct linpool *pool, struct adata *list, u64 val); -struct adata *lc_set_del(struct linpool *pool, struct adata *list, lcomm val); -struct adata *int_set_union(struct linpool *pool, struct adata *l1, struct adata *l2); -struct adata *ec_set_union(struct linpool *pool, struct adata *l1, struct adata *l2); -struct adata *lc_set_union(struct linpool *pool, struct adata *l1, struct adata *l2); - -struct adata *ec_set_del_nontrans(struct linpool *pool, struct adata *set); -struct adata *int_set_sort(struct linpool *pool, struct adata *src); -struct adata *ec_set_sort(struct linpool *pool, struct adata *src); -struct adata *lc_set_sort(struct linpool *pool, struct adata *src); +int lc_set_format(const struct adata *set, int from, byte *buf, uint size); +int int_set_contains(const struct adata *list, u32 val); +int ec_set_contains(const struct adata *list, u64 val); +int lc_set_contains(const struct adata *list, lcomm val); +const struct adata *int_set_prepend(struct linpool *pool, const struct adata *list, u32 val); +const struct adata *int_set_add(struct linpool *pool, const struct adata *list, u32 val); +const struct adata *ec_set_add(struct linpool *pool, const struct adata *list, u64 val); +const struct adata *lc_set_add(struct linpool *pool, const struct adata *list, lcomm val); +const struct adata *int_set_del(struct linpool *pool, const struct adata *list, u32 val); +const struct adata *ec_set_del(struct linpool *pool, const struct adata *list, u64 val); +const struct adata *lc_set_del(struct linpool *pool, const struct adata *list, lcomm val); +const struct adata *int_set_union(struct linpool *pool, const struct adata *l1, const struct adata *l2); +const struct adata *ec_set_union(struct linpool *pool, const struct adata *l1, const struct adata *l2); +const struct adata *lc_set_union(struct linpool *pool, const struct adata *l1, const struct adata *l2); + +struct adata *ec_set_del_nontrans(struct linpool *pool, const struct adata *set); +struct adata *int_set_sort(struct linpool *pool, const struct adata *src); +struct adata *ec_set_sort(struct linpool *pool, const struct adata *src); +struct adata *lc_set_sort(struct linpool *pool, const struct adata *src); void ec_set_sort_x(struct adata *set); /* Sort in place */ -- 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 'nest/attrs.h') 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 de12cd18fb213ee9cc872fec77b789f34cfd7cc4 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Tue, 12 Feb 2019 14:16:28 +0100 Subject: Filter: Merged filter line item dumpers into common generated source --- filter/Makefile | 7 ++-- filter/decl.m4 | 125 +++++++++++++++++++++++++++++++++++++++++--------------- filter/dump.m4 | 51 ----------------------- filter/filter.c | 30 +------------- filter/filter.h | 15 +++++++ nest/a-set.c | 13 +++--- nest/attrs.h | 8 ++++ 7 files changed, 123 insertions(+), 126 deletions(-) delete mode 100644 filter/dump.m4 (limited to 'nest/attrs.h') diff --git a/filter/Makefile b/filter/Makefile index df7ff3f9..e3b7ec26 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -22,11 +22,10 @@ $(o)inst-gen.h: $(s)decl.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(o)inst-gen.c: $(s)decl.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(M4) $(M4FLAGS_FILTERS) -DTARGET=C -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-postfixify.c $(o)f-inst-same.c $(o)f-inst-dump.c $(o)inst-gen.h +$(o)filter.o: $(o)f-inst-interpret.c $(o)f-inst-postfixify.c $(o)f-inst-same.c $(o)inst-gen.h tests_src := tree_test.c filter_test.c trie_test.c tests_targets := $(tests_targets) $(tests-target-files) tests_objs := $(tests_objs) $(src-o-files) + +$(call clean,inst-gen.h inst-gen.c) diff --git a/filter/decl.m4 b/filter/decl.m4 index 9c35677e..6199d4be 100644 --- a/filter/decl.m4 +++ b/filter/decl.m4 @@ -10,6 +10,8 @@ m4_divert(-1)m4_dnl # Global Diversions: # 4 enum fi_code # 5 enum fi_code to string +# 6 dump line item +# 7 dump line item callers # 1 struct f_inst_FI_... # 2 union in struct f_inst # 3 constructors @@ -18,8 +20,10 @@ m4_divert(-1)m4_dnl # 101 content of struct f_inst_FI_... # 102 constructor arguments # 103 constructor body +# 104 dump line item content # -# Put-around Diversions: 9xx +# Diversions for TARGET=C: 8xx +# Diversions for TARGET=H: 9xx # Flush the completed instruction m4_define(FID_END, `m4_divert(-1)') @@ -32,10 +36,13 @@ 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_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_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_ALL, `m4_ifdef([[FID_CURDIV]], [[m4_divert(FID_CURDIV)m4_undefine([[FID_CURDIV]])]])') m4_define(FID_C, `m4_ifelse(TARGET, [[C]], FID_ALL, [[m4_define(FID_CURDIV, m4_divnum)m4_divert(-1)]])') @@ -57,7 +64,9 @@ FID_NEW struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code m4_undivert(102) ) -FID_H ; FID_C +FID_H +; +FID_C { struct f_inst *what_ = cfg_allocz(sizeof(struct f_inst)); what_->fi_code = fi_code; @@ -67,6 +76,19 @@ FID_H ; FID_C m4_undivert(103) return what_; } + +FID_DUMP_CALLER +case INST_NAME(): f_dump_line_item_]]INST_NAME()[[(item, indent + 1); break; + +FID_DUMP +m4_ifdef([[FID_DUMP_BODY_EXISTS]], +[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item, const int indent)]] +, +[[static inline void f_dump_line_item_]]INST_NAME()[[(const struct f_line_item *item UNUSED, const int indent UNUSED)]]) +m4_undefine([[FID_DUMP_BODY_EXISTS]]) +{ +m4_undivert(104) +} FID_ALL FID_END ]])') @@ -80,23 +102,32 @@ FID_NEW_ARGS , $1 $2 FID_NEW_BODY what->$2 = $2; +m4_ifelse($3,,,[[ +FID_DUMP_BODY +debug("%s$3\n", INDENT, $4); +]]) FID_END') -m4_define(ARG, `FID_MEMBER(const struct f_inst *, f$1) +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) +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(LINE, `FID_MEMBER(const struct f_inst *, f$1,,) +FID_DUMP_BODY +f_dump_line(item->lines[$2], indent + 1); +FID_END') m4_define(LINEP, `FID_STRUCT_IN const struct f_line *fl$1; +FID_DUMP_BODY +f_dump_line(item->lines[$2], indent + 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(SYMBOL, `FID_MEMBER(const struct symbol *, sym, symbol %s, item->sym->name)') +m4_define(VALI, `FID_MEMBER(struct f_val, vali, value %s, val_dump(&item->val))') +m4_define(VALP, `FID_MEMBER(const struct f_val *, valp, value %s, val_dump(&item->val))') m4_define(VAR, `m4_dnl FID_STRUCT_IN const struct f_val *valp; @@ -105,39 +136,33 @@ FID_NEW_ARGS , const struct symbol *sym FID_NEW_BODY what->valp = (what->sym = sym)->def; +FID_DUMP_BODY +debug("%svariable %s with value %s\n", INDENT, item->sym->name, val_dump(item->vp)); 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(FRET, `FID_MEMBER(enum filter_return, fret, %s, filter_return_str(item->fret))') +m4_define(ECS, `FID_MEMBER(enum ec_subtype, ecs, ec subtype %s, ec_subtype_str(item->ecs))') +m4_define(RTC, `FID_MEMBER(const struct rtable_config *, rtc, route table %s, item->rtc->name)') 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_define(COUNT, `FID_MEMBER(uint, count, number %u, item->count)') +m4_define(TREE, `FID_MEMBER(const struct f_tree *, tree, tree %p, item->tree)') +m4_define(STRING, `FID_MEMBER(const char *, s, string \"%s\", item->s)') + +m4_define(FID_WR_PUT_LIST) +m4_define(FID_WR_DROP_LIST) + +m4_define(FID_WR_IPUT, `m4_define([[FID_WR_CUR_DIRECT]], m4_eval(FID_WR_CUR_DIRECT + 1))m4_define([[FID_WR_PUT_LIST]], FID_WR_PUT_LIST[[]]FID_WR_DPUT($1)FID_WR_DPUT(FID_WR_CUR_DIRECT))m4_divert(FID_WR_CUR_DIRECT)') +m4_define(FID_WR_IDROP, `m4_define([[FID_WR_CUR_DIRECT]], m4_eval(FID_WR_CUR_DIRECT + 1))m4_define([[FID_WR_DROP_LIST]], FID_WR_DROP_LIST[[]]FID_WR_DPUT($1)FID_WR_DPUT(FID_WR_CUR_DIRECT))m4_divert(FID_WR_CUR_DIRECT)') -m4_define(FID_WR_UNDIVERT_LIST,FID_WR_DPUT(900)) -m4_define(FID_WR_CUR_DIRECT,900) -m4_define(FID_WR_PUT, `m4_ifelse(1, m4_eval(m4_divnum > -1), [[m4_divert(-1) - m4_define([[FID_WR_CUR_DIRECT]], m4_eval(FID_WR_CUR_DIRECT + 1)) - m4_define([[FID_WR_UNDIVERT_LIST]], FID_WR_UNDIVERT_LIST[[]]/* wrput $1 */FID_WR_DPUT($1)/* wrputdir FID_WR_CUR_DIRECT */FID_WR_DPUT(FID_WR_CUR_DIRECT)) - m4_divert(FID_WR_CUR_DIRECT)]], [[m4_define([[FID_WR_UNDIVERT_LIST]], FID_WR_UNDIVERT_LIST[[]]/* wrdrop $1 */FID_WR_DROP($1))]])') +m4_define(FID_WR_DIRECT, `m4_define([[FID_WR_CUR_DIRECT]],$1)m4_ifelse(TARGET,[[$2]],[[m4_define([[FID_WR_PUT]], [[FID_WR_IPUT($]][[@)]])m4_define([[FID_WR_PUT_LIST]],FID_WR_PUT_LIST[[]]FID_WR_DPUT($1))]],[[m4_define([[FID_WR_PUT]], [[FID_WR_IDROP($]][[@)]])m4_define([[FID_WR_DROP_LIST]],FID_WR_DROP_LIST[[]]FID_WR_DPUT($1))]])m4_divert($1)') +m4_dnl m4_define(FID_WR_CUR_DIRECT,m4_ifelse(TARGET,`C',800,TARGET,`H',900,m4_errprint(`Bad TARGET: 'TARGET)m4_m4exit(1))) m4_changequote([[,]]) -m4_divert(900) -FID_C +FID_WR_DIRECT(800,C) #include "nest/bird.h" #include "filter/filter.h" #include "filter/f-inst.h" -FID_H - -/* Filter instruction codes */ -enum f_instruction_code { -FID_WR_PUT(4) -}; - -FID_C - /* Instruction codes to string */ static const char * const f_instruction_name_str[] = { FID_WR_PUT(5) @@ -152,7 +177,39 @@ f_instruction_name(enum f_instruction_code fi) bug("Got unknown instruction code: %d", fi); } -FID_H +/* Instruction constructors */ +FID_WR_PUT(3) + +/* Line dumpers */ +#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[] = " "; +void f_dump_line(const struct f_line *dest, int indent); + +FID_WR_PUT(6) + +void f_dump_line(const struct f_line *dest, int indent) +{ + if (!dest) { + debug("%sNo filter line (NULL)\n", INDENT); + return; + } + debug("%sFilter line %p (len=%u)\n", INDENT, dest, dest->len); + for (uint i=0; ilen; i++) { + const struct f_line_item *item = &dest->items[i]; + debug("%sInstruction %s at line %u\n", INDENT, f_instruction_name(item->fi_code), item->lineno); + switch (item->fi_code) { +FID_WR_PUT(7) + default: bug("Unknown instruction %x in f_dump_line", item->fi_code); + } + } + debug("%sFilter line %p dump done\n", INDENT, dest); +} + +FID_WR_DIRECT(900,H) +/* Filter instruction codes */ +enum f_instruction_code { +FID_WR_PUT(4) +}; /* Per-instruction structures */ FID_WR_PUT(1) @@ -167,12 +224,12 @@ struct f_inst { }; }; -FID_ALL /* Instruction constructors */ FID_WR_PUT(3) + m4_divert(-1) m4_changequote(`,') -m4_m4wrap(`INST_FLUSH()m4_define(FID_WR_DPUT, [[m4_undivert($1)]])m4_define(FID_WR_DROP, [[m4_divert(-1)m4_undivert($1)m4_divert(0)]])m4_divert(0)FID_WR_UNDIVERT_LIST[[]]m4_divert(-1)') +m4_m4wrap(`INST_FLUSH()m4_define(FID_WR_DPUT, [[m4_undivert($1)]])m4_divert(0)FID_WR_PUT_LIST[[]]m4_divert(-1)FID_WR_DROP_LIST[[]]') m4_changequote([[,]]) diff --git a/filter/dump.m4 b/filter/dump.m4 deleted file mode 100644 index 4ea3e3be..00000000 --- a/filter/dump.m4 +++ /dev/null @@ -1,51 +0,0 @@ -m4_divert(-1)m4_dnl -# -# BIRD -- Dumping instruction lines -# -# (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(): -m4_undivert(2) -break; -m4_divert(-1) -]])') -m4_define(INST, `INST_FLUSH()m4_define([[INST_NAME]], [[$1]])') - -m4_define(LINE, `m4_divert(2)f_dump_line(item->lines[$2], indent + 1); -m4_divert(-1)') -m4_define(LINEP, `LINE($@)') -m4_define(SYMBOL, `m4_divert(2)debug("%ssymbol %s\n", INDENT, item->sym->name); -m4_divert(-1)') -m4_define(VALI, `m4_divert(2)debug("%svalue %s\n", INDENT, val_dump(&item->val)); -m4_divert(-1)') -m4_define(VAR, `m4_divert(2)debug("%svar %s: value %s\n", INDENT, item->sym->name, val_dump(item->vp)); -m4_divert(-1)') -m4_define(FRET, `m4_divert(2)debug("%sfilter return value %d\n", INDENT, item->fret); -m4_divert(-1)') -m4_define(ECS, `m4_divert(2)debug("%sec subtype %d\n", INDENT, item->ecs); -m4_divert(-1)') -m4_define(RTC, `m4_divert(2)debug("%sroute table %s\n", INDENT, item->rtc->name); -m4_divert(-1)') -m4_define(STATIC_ATTR, `m4_divert(2)debug("%sstatic attribute %u/%u/%u\n", INDENT, item->sa.f_type, item->sa.sa_code, item->sa.readonly); -m4_divert(-1)') -m4_define(DYNAMIC_ATTR, `m4_divert(2)debug("%sdynamic attribute %u/%u/%u/%u\n", INDENT, item->da.type, item->da.bit, item->da.f_type, item->da.ea_code); -m4_divert(-1)') -m4_define(DUMP, `m4_divert(2)$1m4_divert(-1)') - -m4_m4wrap(` -INST_FLUSH() -m4_divert(0)DNL -m4_undivert(1) - -default: bug( "Unknown instruction %d (%c)", item->fi_code, item->fi_code & 0xff); -') - -m4_changequote([[,]]) diff --git a/filter/filter.c b/filter/filter.c index ebd2e4dc..f08c91db 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -112,34 +112,6 @@ val_format_str(struct filter_state *fs, struct f_val *v) { static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS; -#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[] = " "; - -static void f_dump_line(const struct f_line *dest, int indent); - -static void -f_dump_line_item(const struct f_line_item *item, int indent) -{ - debug("%sInstruction %s at line %u\n", INDENT, f_instruction_name(item->fi_code), item->lineno); - switch (item->fi_code) { -#include "filter/f-inst-dump.c" - } -} - -static void -f_dump_line(const struct f_line *dest, int indent) -{ - if (!dest) { - debug("%sNo filter line (NULL)\n", INDENT); - return; - } - debug("%sFilter line %p (len=%u)\n", INDENT, dest, dest->len); - for (uint i=0; ilen; i++) - f_dump_line_item(&dest->items[i], indent+1); - debug("%sFilter line %p dump done\n", INDENT, dest); -#undef INDENT -} - static uint postfixify(struct f_line *dest, const struct f_inst *what_, uint pos) { @@ -166,7 +138,7 @@ f_postfixify_concat(const struct f_inst * const inst[], uint count) out->len = postfixify(out, inst[i], out->len); #if DEBUGGING - f_dump_line(out, 0); +// f_dump_line(out, 0); #endif return out; } diff --git a/filter/filter.h b/filter/filter.h index 9f1a8e50..d03c6438 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -27,6 +27,21 @@ enum filter_return { F_QUITBIRD, }; +static inline const char *filter_return_str(const enum filter_return fret) { + switch (fret) { +#define FRS(x) case x: return #x + FRS(F_NOP); + FRS(F_NONL); + FRS(F_RETURN); + FRS(F_ACCEPT); + FRS(F_REJECT); + FRS(F_ERROR); + FRS(F_QUITBIRD); +#undef FRS + default: bug("This shall not happen"); + } +} + struct f_val; /* The filter encapsulating structure to be pointed-to from outside */ diff --git a/nest/a-set.c b/nest/a-set.c index 10ddd139..78922ffd 100644 --- a/nest/a-set.c +++ b/nest/a-set.c @@ -72,15 +72,12 @@ ec_format(byte *buf, u64 ec) char tbuf[16], *kind; type = ec >> 48; - switch (type & 0xf0ff) - { - case EC_RT: kind = "rt"; break; - case EC_RO: kind = "ro"; break; + kind = ec_subtype_str(type & 0xf0ff); - default: - kind = tbuf; - bsprintf(kind, "unknown 0x%x", type); - } + if (!kind) { + kind = tbuf; + bsprintf(kind, "unknown 0x%x", type); + } switch (ec >> 56) { diff --git a/nest/attrs.h b/nest/attrs.h index 37227d9b..4efcff79 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -125,6 +125,14 @@ enum ec_subtype { EC_GENERIC = 0xFFFF, }; +static inline const char *ec_subtype_str(const enum ec_subtype ecs) { + switch (ecs) { + case EC_RT: return "rt"; + case EC_RO: return "ro"; + default: return NULL; + } +} + /* Transitive bit (for first u32 half of EC) */ #define EC_TBIT 0x40000000 -- cgit v1.2.3