From: Maria Matejka Date: Sat, 28 Oct 2023 22:00:07 +0000 (+0200) Subject: Merge commit 'fdd39c81' into thread-next X-Git-Tag: v3.0.0~375 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ef027449988c232e0bc5ee04458425eae3da374a;p=thirdparty%2Fbird.git Merge commit 'fdd39c81' into thread-next --- ef027449988c232e0bc5ee04458425eae3da374a diff --cc filter/config.Y index 4ce9ee0f7,1f5d2bc53..aaba2201f --- a/filter/config.Y +++ b/filter/config.Y @@@ -383,17 -368,14 +383,13 @@@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UN EMPTY, FILTER, WHERE, EVAL, ATTRIBUTE, FROM_HEX, - BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT) + BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT, STACKS) - CF_METHODS(IS_V4, TYPE, IP, RD, LEN, MAXLEN, ASN, SRC, DST, MASK, - FIRST, LAST, LAST_NONAGGREGATED, DATA, DATA1, DATA2, MIN, MAX, - EMPTY, PREPEND, ADD, DELETE, FILTER) - %nonassoc THEN %nonassoc ELSE %type cmds_int cmd_prep - %type term term_bs cmd cmd_var cmds cmds_scoped constant constructor print_list var var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail term_dot_method method_name_cont + %type term term_bs cmd cmd_var cmds cmds_scoped constant constructor var var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail term_dot_method method_name_cont -%type dynamic_attr %type static_attr %type filter where_filter %type filter_body function_body @@@ -1043,10 -998,9 +1029,9 @@@ cmd { new_config->current_scope->active = 0; } term { new_config->current_scope->active = 1; } DO cmd { cf_pop_block_scope(new_config); - $$ = f_new_inst(FI_FOR_INIT, $6, $3); - $$->next = f_new_inst(FI_FOR_NEXT, $3, $9); + $$ = f_for_cycle($3, $6, $9); } - | symbol_known '=' term ';' { + | CF_SYM_KNOWN '=' term ';' { switch ($1->class) { case SYM_VARIABLE_RANGE: $$ = f_new_inst(FI_VAR_SET, $3, $1); @@@ -1081,30 -1036,17 +1066,21 @@@ cf_error( "This static attribute is read-only."); $$ = f_new_inst(FI_RTA_SET, $3, $1); } - | UNSET '(' dynamic_attr ')' ';' { - $$ = f_new_inst(FI_EA_UNSET, $3); + | UNSET '(' CF_SYM_KNOWN ')' ';' { + if ($3->class != SYM_ATTRIBUTE) + cf_error("Can't unset %s", $3->name); + if ($3->attribute->readonly) + cf_error("Attribute %s is read-only", $3->attribute->name); + $$ = f_new_inst(FI_EA_UNSET, $3->attribute); } - | break_command print_list ';' { - struct f_inst *breaker = f_new_inst(FI_DIE, $1); - if ($2) { - struct f_inst *printer = f_new_inst(FI_PRINT, $2); - struct f_inst *flusher = f_new_inst(FI_FLUSH); - printer->next = flusher; - flusher->next = breaker; - $$ = printer; - } else - $$ = breaker; + | break_command var_list ';' { + $$ = f_print($2, !!$2, $1); } - | PRINT print_list ';' { - $$ = f_new_inst(FI_PRINT, $2); - $$->next = f_new_inst(FI_FLUSH); + | PRINT var_list ';' { + $$ = f_print($2, 1, F_NOP); } - | PRINTN print_list ';' { - $$ = f_new_inst(FI_PRINT, $2); + | PRINTN var_list ';' { + $$ = f_print($2, 0, F_NOP); } | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); } | CASE term '{' switch_body '}' { diff --cc filter/decl.m4 index 890056875,d292f65b9..9d6b64ad0 --- a/filter/decl.m4 +++ b/filter/decl.m4 @@@ -399,9 -419,11 +420,9 @@@ m4_undivert(112 } FID_METHOD_SCOPE_INIT()m4_dnl -- [INST_METHOD_OBJECT_TYPE] = {}, ++ [INST_METHOD_OBJECT_TYPE] = { .active = 1, }, FID_METHOD_REGISTER()m4_dnl - sym = cf_new_symbol(&f_type_method_scopes[INST_METHOD_OBJECT_TYPE], - global_root_scope_pool, global_root_scope_linpool, - INST_METHOD_NAME); + sym = cf_root_symbol(INST_METHOD_NAME, &f_type_method_scopes[INST_METHOD_OBJECT_TYPE]); sym->class = SYM_METHOD; sym->method = method = lp_allocz(global_root_scope_linpool, sizeof(struct f_method)); diff --cc filter/f-inst.c index 8a00438b7,6977f6561..c66d64a1e --- a/filter/f-inst.c +++ b/filter/f-inst.c @@@ -684,18 -625,12 +632,17 @@@ LINE(3,0); } - INST(FI_PRINT, 0, 0) { + INST(FI_PRINT, 1, 0) { NEVER_CONSTANT; - VARARG; + ARG_ANY(1); - if (whati->varcount && !(fs->flags & FF_SILENT)) + if (!(fs->flags & FF_SILENT)) - val_format(&v1, &fs->buf); + { + if (!fs->buf.class) + log_prepare(&fs->buf, *L_INFO); + - for (uint i=0; ivarcount; i++) - val_format(&(vv(i)), &fs->buf.buf); ++ val_format(&v1, &fs->buf.buf); + } } INST(FI_FLUSH, 0, 0) { @@@ -955,52 -939,18 +902,29 @@@ INST(FI_EA_UNSET, 0, 0) { DYNAMIC_ATTR; ACCESS_RTE; - ACCESS_EATTRS; - f_rta_cow(fs); - ea_unset_attr(fs->eattrs, fs->pool, 1, da.ea_code); + ea_unset_attr(&fs->rte->attrs, 1, da); + } + + INST(FI_DEFAULT, 2, 1) { + ARG_ANY(1); + ARG_ANY(2); + RESULT_TYPE(f_type_element_type(v2.type)); + + log(L_INFO "Type of arg 1 is: %d", v1.type); + + if (v1.type == T_VOID) + RESULT_VAL(v2); + else + RESULT_VAL(v1); } - INST(FI_NET_LENGTH, 1, 1) { /* Get length of */ - ARG(1, T_NET); - METHOD_CONSTRUCTOR("len"); - RESULT(T_INT, i, net_pxlen(v1.val.net)); - } - - INST(FI_PATH_LENGTH, 1, 1) { /* Get length of */ - ARG(1, T_PATH); - METHOD_CONSTRUCTOR("len"); - RESULT(T_INT, i, as_path_getlen(v1.val.ad)); - } - - INST(FI_CLIST_LENGTH, 1, 1) { /* Get length of */ - ARG(1, T_CLIST); - METHOD_CONSTRUCTOR("len"); - RESULT(T_INT, i, int_set_get_size(v1.val.ad)); - } - - INST(FI_ECLIST_LENGTH, 1, 1) { /* Get length of */ - ARG(1, T_ECLIST); - METHOD_CONSTRUCTOR("len"); - RESULT(T_INT, i, ec_set_get_size(v1.val.ad)); - } - - INST(FI_LCLIST_LENGTH, 1, 1) { /* Get length of */ - ARG(1, T_LCLIST); - METHOD_CONSTRUCTOR("len"); - RESULT(T_INT, i, lc_set_get_size(v1.val.ad)); - } + /* Get length of */ + METHOD_R(T_NET, len, 0, T_INT, i, net_pxlen(v1.val.net)); + METHOD_R(T_PATH, len, 0, T_INT, i, as_path_getlen(v1.val.ad)); + METHOD_R(T_CLIST, len, 0, T_INT, i, int_set_get_size(v1.val.ad)); + METHOD_R(T_ECLIST, len, 0, T_INT, i, ec_set_get_size(v1.val.ad)); + METHOD_R(T_LCLIST, len, 0, T_INT, i, lc_set_get_size(v1.val.ad)); INST(FI_NET_SRC, 1, 1) { /* Get src prefix */ ARG(1, T_NET); diff --cc filter/f-inst.h index 57186c953,8c304de5d..c741265b2 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@@ -96,9 -96,15 +96,12 @@@ void f_add_lines(const struct f_line_it struct filter *f_new_where(struct f_inst *); + struct f_inst *f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block); + struct f_inst *f_print(struct f_inst *vars, int flush, enum filter_return fret); + -static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, 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, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */ -static inline struct f_dynamic_attr f_new_dynamic_attr_bit(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 = EAF_TYPE_BITFIELD, .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) -{ return (struct f_static_attr) { .f_type = f_type, .sa_code = code, .readonly = readonly }; } +static inline struct f_static_attr f_new_static_attr(btype type, int code, int readonly) +{ return (struct f_static_attr) { .type = type, .sa_code = code, .readonly = readonly }; } +struct f_inst *f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn); /* Hook for call bt_assert() function in configuration */ extern void (*bt_assert_hook)(int result, const struct f_line_item *assert); diff --cc filter/f-util.c index 82a06bddc,98b7d1a87..0d998f3db --- a/filter/f-util.c +++ b/filter/f-util.c @@@ -40,3 -40,203 +40,61 @@@ struct filter *f_new_where(struct f_ins f->root = f_linearize(cond, 0); return f; } + + struct f_inst * + f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block) + { + ASSERT((var->class & ~0xff) == SYM_VARIABLE); + ASSERT(term->next == NULL); + + /* Static type check */ + if (term->type == T_VOID) + cf_error("Couldn't infer the type of FOR expression, please assign it to a variable."); + - enum f_type el_type = f_type_element_type(term->type); ++ enum btype el_type = f_type_element_type(term->type); + struct sym_scope *scope = el_type ? f_type_method_scope(term->type) : NULL; + struct symbol *ms = scope ? cf_find_symbol_scope(scope, "!for_next") : NULL; + + if (!ms) + cf_error("Type %s is not iterable, can't be used in FOR", f_type_name(term->type)); + + if (var->class != (SYM_VARIABLE | el_type)) + cf_error("Loop variable '%s' in FOR must be of type %s, got %s", + var->name, f_type_name(el_type), f_type_name(var->class & 0xff)); + + /* Push the iterator auxiliary value onto stack */ + struct f_inst *iter = term->next = f_new_inst(FI_CONSTANT, (struct f_val) {}); + + /* Initialize the iterator variable */ + iter->next = f_new_inst(FI_CONSTANT, (struct f_val) { .type = el_type }); + + /* Prepend the loop block with loop beginning instruction */ + struct f_inst *loop_start = f_new_inst(FI_FOR_LOOP_START, var); + loop_start->next = block; + + return ms->method->new_inst(term, loop_start); + } + + struct f_inst * + f_print(struct f_inst *vars, int flush, enum filter_return fret) + { + #define AX(...) do { struct f_inst *_tmp = f_new_inst(__VA_ARGS__); _tmp->next = output; output = _tmp; } while (0) + struct f_inst *output = NULL; + if (fret != F_NOP) + AX(FI_DIE, fret); + + if (flush) + AX(FI_FLUSH); + + while (vars) + { + struct f_inst *tmp = vars; + vars = vars->next; + tmp->next = NULL; + + AX(FI_PRINT, tmp); + } + + return output; + #undef AX + } - - -#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)) -#define CA_FN(n,t) (mem_hash(n, strlen(n)) ^ (t*0xaae99453U)) -#define CA_ORDER 8 /* Fixed */ - -struct ca_storage { - struct ca_storage *next; - struct f_dynamic_attr fda; - u32 uc; - char name[0]; -}; - -HASH(struct ca_storage) ca_hash; - -static struct idm ca_idm; -static struct ca_storage **ca_storage; -static uint ca_storage_max; - -static void -ca_free(resource *r) -{ - struct custom_attribute *ca = (void *) r; - struct ca_storage *cas = HASH_FIND(ca_hash, CA, ca->name, ca->fda->type); - ASSERT(cas); - - ca->name = NULL; - ca->fda = NULL; - if (!--cas->uc) { - uint id = EA_CUSTOM_ID(cas->fda.ea_code); - idm_free(&ca_idm, id); - HASH_REMOVE(ca_hash, CA, cas); - ca_storage[id] = NULL; - mb_free(cas); - } -} - -static void -ca_dump(resource *r) -{ - struct custom_attribute *ca = (void *) r; - debug("name \"%s\" id 0x%04x ea_type 0x%02x f_type 0x%02x\n", - ca->name, ca->fda->ea_code, ca->fda->type, ca->fda->f_type); -} - -static struct resclass ca_class = { - .name = "Custom attribute", - .size = sizeof(struct custom_attribute), - .free = ca_free, - .dump = ca_dump, - .lookup = NULL, - .memsize = NULL, -}; - -struct custom_attribute * -ca_lookup(pool *p, const char *name, int f_type) -{ - int ea_type; - - switch (f_type) { - case T_INT: - ea_type = EAF_TYPE_INT; - break; - case T_IP: - ea_type = EAF_TYPE_IP_ADDRESS; - break; - case T_QUAD: - ea_type = EAF_TYPE_ROUTER_ID; - break; - case T_PATH: - ea_type = EAF_TYPE_AS_PATH; - break; - case T_CLIST: - ea_type = EAF_TYPE_INT_SET; - break; - case T_ECLIST: - ea_type = EAF_TYPE_EC_SET; - break; - case T_LCLIST: - ea_type = EAF_TYPE_LC_SET; - break; - default: - cf_error("Custom route attribute of unsupported type"); - } - - static int inited = 0; - if (!inited) { - idm_init(&ca_idm, config_pool, 8); - HASH_INIT(ca_hash, config_pool, CA_ORDER); - - ca_storage_max = 256; - ca_storage = mb_allocz(config_pool, sizeof(struct ca_storage *) * ca_storage_max); - - inited++; - } - - struct ca_storage *cas = HASH_FIND(ca_hash, CA, name, ea_type); - if (cas) { - cas->uc++; - } else { - - uint id = idm_alloc(&ca_idm); - - if (id >= EA_CUSTOM_BIT) - cf_error("Too many custom attributes."); - - if (id >= ca_storage_max) { - ca_storage_max *= 2; - ca_storage = mb_realloc(ca_storage, sizeof(struct ca_storage *) * ca_storage_max * 2); - } - - cas = mb_allocz(config_pool, sizeof(struct ca_storage) + strlen(name) + 1); - cas->fda = f_new_dynamic_attr(ea_type, f_type, EA_CUSTOM(id)); - cas->uc = 1; - - strcpy(cas->name, name); - ca_storage[id] = cas; - - HASH_INSERT(ca_hash, CA, cas); - } - - struct custom_attribute *ca = ralloc(p, &ca_class); - ca->fda = &(cas->fda); - ca->name = cas->name; - return ca; -} - -const char * -ea_custom_name(uint ea) -{ - uint id = EA_CUSTOM_ID(ea); - if (id >= ca_storage_max) - return NULL; - - if (!ca_storage[id]) - return NULL; - - return ca_storage[id]->name; -} - diff --cc filter/filter.c index 7eb109a17,65fb92a41..c5597734d --- a/filter/filter.c +++ b/filter/filter.c @@@ -122,12 -170,11 +122,13 @@@ interpret(struct filter_state *fs, cons /* The same as with the value stack. Not resetting the stack for performance reasons. */ fstk->ecnt = 1; - fstk->estk[0].line = line; - fstk->estk[0].pos = 0; + fstk->estk[0] = (struct filter_exec_stack) { + .line = line, + .pos = 0, + }; #define curline fstk->estk[fstk->ecnt-1] + #define prevline fstk->estk[fstk->ecnt-2] #ifdef LOCAL_DEBUG debug("Interpreting line.");