From: Maria Matejka Date: Sat, 28 Oct 2023 22:14:52 +0000 (+0200) Subject: Merge commit 'cc1099a0' into thread-next X-Git-Tag: v3.0.0~373 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a725e3e580bcd4d0120191f0d38f661fa5d6a1d3;p=thirdparty%2Fbird.git Merge commit 'cc1099a0' into thread-next Updated f_implicit_roa_check() to use type methods and moved to filter/f-util.c --- a725e3e580bcd4d0120191f0d38f661fa5d6a1d3 diff --cc filter/config.Y index aaba2201f,7cc6f8823..1922955ff --- a/filter/config.Y +++ b/filter/config.Y @@@ -244,21 -244,23 +244,6 @@@ f_new_lc_item(u32 f1, u32 t1, u32 f2, u return t; } --static inline struct f_inst * - f_implicit_roa_check(struct rtable_config *tab) -f_const_empty(enum f_type t) --{ - const struct ea_class *def = ea_class_find("bgp_path"); - if (!def) - cf_error("Fatal: Couldn't find BGP path attribute definition."); - - struct f_static_attr fsa = f_new_static_attr(T_NET, SA_NET, 1); - - return f_new_inst(FI_ROA_CHECK, - f_new_inst(FI_RTA_GET, fsa), - f_new_inst(FI_AS_PATH_LAST, f_new_inst(FI_EA_GET, def)), - tab); - switch (t) { - case T_PATH: - case T_CLIST: - case T_ECLIST: - case T_LCLIST: - return f_new_inst(FI_CONSTANT, (struct f_val) { - .type = t, - .val.ad = &null_adata, - }); - default: - return f_new_inst(FI_CONSTANT, (struct f_val) {}); - } --} -- /* * Remove all new lines and doubled whitespaces * and convert all tabulators to spaces @@@ -894,14 -861,15 +879,13 @@@ static_attr | IFNAME { $$ = f_new_static_attr(T_STRING, SA_IFNAME, 0); } | IFINDEX { $$ = f_new_static_attr(T_INT, SA_IFINDEX, 1); } | WEIGHT { $$ = f_new_static_attr(T_INT, SA_WEIGHT, 0); } - | PREFERENCE { $$ = f_new_static_attr(T_INT, SA_PREF, 0); } | GW_MPLS { $$ = f_new_static_attr(T_INT, SA_GW_MPLS, 0); } - | ONLINK { $$ = f_new_static_attr(T_BOOL, SA_ONLINK, 0); } ; - term_dot_method: term '.' { f_method_call_start($1); } method_name_cont { $$ = $4; }; + term_dot_method: term '.' { f_method_call_start($1); } method_name_cont { f_method_call_end(); $$ = $4; }; method_name_cont: CF_SYM_METHOD_BARE { - $$ = $1->method->new_inst(FM.object, NULL); - f_method_call_end(); + $$ = f_dispatch_method($1, FM.object, NULL); } | CF_SYM_METHOD_ARGS { f_method_call_args(); @@@ -938,20 -903,17 +921,15 @@@ term | static_attr { $$ = f_new_inst(FI_RTA_GET, $1); } - | dynamic_attr { $$ = f_new_inst(FI_EA_GET, $1); } - | term_dot_method - | '+' EMPTY '+' { $$ = f_const_empty(T_PATH); } - | '-' EMPTY '-' { $$ = f_const_empty(T_CLIST); } - | '-' '-' EMPTY '-' '-' { $$ = f_const_empty(T_ECLIST); } - | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_const_empty(T_LCLIST); } + | '+' EMPTY '+' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_PATH)); } + | '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_CLIST)); } + | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_ECLIST)); } + | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_get_empty(T_LCLIST)); } | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND, $3, $5); } | ADD '(' term ',' term ')' { - switch ($3->type) { - case T_CLIST: $$ = f_new_inst(FI_CLIST_ADD, $3, $5); break; - case T_ECLIST: $$ = f_new_inst(FI_ECLIST_ADD, $3, $5); break; - case T_LCLIST: $$ = f_new_inst(FI_LCLIST_ADD, $3, $5); break; - default: cf_error("Can't add to type %s", f_type_name($3->type)); - } + $$ = f_dispatch_method_x("add", $3->type, $3, $5); cf_warn("add(x,y) function is deprecated, please use x.add(y)"); } | DELETE '(' term ',' term ')' { diff --cc filter/data.h index b668ead05,e136b65f3..8fbbcef54 --- a/filter/data.h +++ b/filter/data.h @@@ -16,7 -67,9 +16,9 @@@ struct f_method { struct symbol *sym; struct f_inst *(*new_inst)(struct f_inst *obj, struct f_inst *args); + const struct f_method *next; uint arg_num; - enum f_type args_type[]; ++ enum btype args_type[]; }; /* Filter value; size of this affects filter memory consumption */ diff --cc filter/decl.m4 index 9d6b64ad0,217488eca..63670932d --- a/filter/decl.m4 +++ b/filter/decl.m4 @@@ -420,17 -422,13 +423,13 @@@ 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_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)); - - *method = (struct f_method) { - .sym = sym, - .new_inst = f_new_method_]]INST_NAME()[[, - .arg_num = INST_METHOD_NUM_ARGS, - }; - method = lp_allocz(global_root_scope_linpool, sizeof(struct f_method) + INST_METHOD_NUM_ARGS * sizeof(enum f_type)); ++ method = lp_allocz(global_root_scope_linpool, sizeof(struct f_method) + INST_METHOD_NUM_ARGS * sizeof(enum btype)); + method->new_inst = f_new_method_]]INST_NAME()[[; + method->arg_num = INST_METHOD_NUM_ARGS; + m4_undivert(113) + f_register_method(INST_METHOD_OBJECT_TYPE, INST_METHOD_NAME, method); ]])m4_dnl @@@ -633,10 -631,27 +632,27 @@@ struct sym_scope *f_type_method_scope(e return (t < ARRAY_SIZE(f_type_method_scopes)) ? &f_type_method_scopes[t] : NULL; } + static void -f_register_method(enum f_type t, const byte *name, struct f_method *dsc) ++f_register_method(enum btype t, const byte *name, struct f_method *dsc) + { + struct sym_scope *scope = &f_type_method_scopes[t]; + struct symbol *sym = cf_find_symbol_scope(scope, name); + + if (!sym) + { - sym = cf_new_symbol(scope, global_root_scope_pool, global_root_scope_linpool, name); ++ sym = cf_root_symbol(name, scope); + sym->class = SYM_METHOD; + } + + dsc->sym = sym; + dsc->next = sym->method; + sym->method = dsc; + } + void f_type_methods_register(void) { - struct symbol *sym; struct f_method *method; + FID_WR_PUT(13) for (uint i = 0; i < ARRAY_SIZE(f_type_method_scopes); i++) diff --cc filter/f-inst.c index c66d64a1e,a9de0960f..94268220b --- a/filter/f-inst.c +++ b/filter/f-inst.c @@@ -1335,79 -1330,152 +1305,122 @@@ runtime("Can't delete non-pair"); } - INST(FI_ECLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */ + INST(FI_ECLIST_DELETE_EC, 2, 1) { ARG(1, T_ECLIST); - ARG_ANY(2); + ARG(2, T_EC); METHOD_CONSTRUCTOR("delete"); - /* v2.val is either EC or EC-set */ - if ((v2.type == T_SET) && eclist_set_type(v2.val.t) || (v2.type == T_ECLIST)) - RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]); - else if (v2.type != T_EC) - runtime("Can't delete non-ec"); - else - RESULT(T_ECLIST, ad, [[ ec_set_del(fpool, v1.val.ad, v2.val.ec) ]]); + RESULT(T_ECLIST, ad, [[ ec_set_del(fpool, v1.val.ad, v2.val.ec) ]]); + } + + INST(FI_ECLIST_DELETE_ECLIST, 2, 1) { + ARG(1, T_ECLIST); + ARG(2, T_ECLIST); + METHOD_CONSTRUCTOR("delete"); + RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]); } - INST(FI_LCLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */ + INST(FI_ECLIST_DELETE_SET, 2, 1) { + ARG(1, T_ECLIST); + ARG(2, T_SET); + METHOD_CONSTRUCTOR("delete"); + + if (!eclist_set_type(v2.val.t)) + runtime("Mismatched set type"); + + RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]); + } + + INST(FI_LCLIST_DELETE_LC, 2, 1) { ARG(1, T_LCLIST); - ARG_ANY(2); + ARG(2, T_LC); METHOD_CONSTRUCTOR("delete"); - /* v2.val is either LC or LC-set */ - if ((v2.type == T_SET) && lclist_set_type(v2.val.t) || (v2.type == T_LCLIST)) - RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]); - else if (v2.type != T_LC) - runtime("Can't delete non-lc"); - else - RESULT(T_LCLIST, ad, [[ lc_set_del(fpool, v1.val.ad, v2.val.lc) ]]); + RESULT(T_LCLIST, ad, [[ lc_set_del(fpool, v1.val.ad, v2.val.lc) ]]); + } + + INST(FI_LCLIST_DELETE_LCLIST, 2, 1) { + ARG(1, T_LCLIST); + ARG(2, T_LCLIST); + METHOD_CONSTRUCTOR("delete"); + RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]); } - INST(FI_PATH_FILTER, 2, 1) { /* (Extended) Community list add or delete */ + INST(FI_LCLIST_DELETE_SET, 2, 1) { + ARG(1, T_LCLIST); + ARG(2, T_SET); + METHOD_CONSTRUCTOR("delete"); + + if (!lclist_set_type(v2.val.t)) + runtime("Mismatched set type"); + + RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]); + } + + INST(FI_PATH_FILTER_SET, 2, 1) { ARG(1, T_PATH); - ARG_ANY(2); + ARG(2, T_SET); METHOD_CONSTRUCTOR("filter"); - if ((v2.type == T_SET) && path_set_type(v2.val.t)) - RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 1) ]]); - else - runtime("Can't filter integer"); - } + if (!path_set_type(v2.val.t)) + runtime("Mismatched set type"); - INST(FI_CLIST_FILTER, 2, 1) { + RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 1) ]]); + } + + INST(FI_CLIST_FILTER_CLIST, 2, 1) { ARG(1, T_CLIST); - ARG_ANY(2); + ARG(2, T_CLIST); METHOD_CONSTRUCTOR("filter"); - /* Community (or cluster) list */ - struct f_val dummy; + RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]); + } - if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy) || (v2.type == T_CLIST)) - RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]); - else - runtime("Can't filter pair"); + INST(FI_CLIST_FILTER_SET, 2, 1) { + ARG(1, T_CLIST); + ARG(2, T_SET); + METHOD_CONSTRUCTOR("filter"); + + if (!clist_set_type(v2.val.t, &(struct f_val){})) + runtime("Mismatched set type"); + + RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]); } - INST(FI_ECLIST_FILTER, 2, 1) { + INST(FI_ECLIST_FILTER_ECLIST, 2, 1) { ARG(1, T_ECLIST); - ARG_ANY(2); + ARG(2, T_ECLIST); METHOD_CONSTRUCTOR("filter"); - /* v2.val is either EC or EC-set */ - if ((v2.type == T_SET) && eclist_set_type(v2.val.t) || (v2.type == T_ECLIST)) - RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]); - else - runtime("Can't filter ec"); + RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]); + } + + INST(FI_ECLIST_FILTER_SET, 2, 1) { + ARG(1, T_ECLIST); + ARG(2, T_SET); + METHOD_CONSTRUCTOR("filter"); + + if (!eclist_set_type(v2.val.t)) + runtime("Mismatched set type"); + + RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]); } - INST(FI_LCLIST_FILTER, 2, 1) { + INST(FI_LCLIST_FILTER_LCLIST, 2, 1) { ARG(1, T_LCLIST); - ARG_ANY(2); + ARG(2, T_LCLIST); METHOD_CONSTRUCTOR("filter"); - /* v2.val is either LC or LC-set */ - if ((v2.type == T_SET) && lclist_set_type(v2.val.t) || (v2.type == T_LCLIST)) - RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]); - else - runtime("Can't filter lc"); + RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]); + } + + INST(FI_LCLIST_FILTER_SET, 2, 1) { + ARG(1, T_LCLIST); + ARG(2, T_SET); + METHOD_CONSTRUCTOR("filter"); + + if (!lclist_set_type(v2.val.t)) + runtime("Mismatched set type"); + + RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]); } - INST(FI_ROA_CHECK_IMPLICIT, 0, 1) { /* ROA Check */ - NEVER_CONSTANT; - RTC(1); - struct rtable *table = rtc->table; - ACCESS_RTE; - ACCESS_EATTRS; - const net_addr *net = (*fs->rte)->net->n.addr; - - /* We ignore temporary attributes, probably not a problem here */ - /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */ - eattr *e = ea_find(*fs->eattrs, EA_CODE(PROTOCOL_BGP, 0x02)); - - if (!e || ((e->type & EAF_TYPE_MASK) != EAF_TYPE_AS_PATH)) - runtime("Missing AS_PATH attribute"); - - u32 as = 0; - as_path_get_last(e->u.ptr, &as); - - if (!table) - runtime("Missing ROA table"); - - if (table->addr_type != NET_ROA4 && table->addr_type != NET_ROA6) - runtime("Table type must be either ROA4 or ROA6"); - - if (table->addr_type != (net->type == NET_IP4 ? NET_ROA4 : NET_ROA6)) - RESULT(T_ENUM_ROA, i, ROA_UNKNOWN); /* Prefix and table type mismatch */ - else - RESULT(T_ENUM_ROA, i, [[ net_roa_check(table, net, as) ]]); - } - - INST(FI_ROA_CHECK_EXPLICIT, 2, 1) { /* ROA Check */ + INST(FI_ROA_CHECK, 2, 1) { /* ROA Check */ NEVER_CONSTANT; ARG(1, T_NET); ARG(2, T_INT); diff --cc filter/f-inst.h index c741265b2,f5dfcd202..fa1fdbde6 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@@ -96,12 -96,17 +96,15 @@@ void f_add_lines(const struct f_line_it struct filter *f_new_where(struct f_inst *); + struct f_inst *f_dispatch_method(struct symbol *sym, struct f_inst *obj, struct f_inst *args); -struct f_inst *f_dispatch_method_x(const char *name, enum f_type t, struct f_inst *obj, struct f_inst *args); ++struct f_inst *f_dispatch_method_x(const char *name, enum btype t, struct f_inst *obj, struct f_inst *args); struct f_inst *f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block); ++struct f_inst *f_implicit_roa_check(struct rtable_config *tab); 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 0d998f3db,7ce3f9c8c..7ae304d60 --- a/filter/f-util.c +++ b/filter/f-util.c @@@ -41,6 -42,43 +42,43 @@@ f_new_where(struct f_inst *where return f; } + static inline int + f_match_signature(const struct f_method *dsc, struct f_inst *args) + { + uint i; + + for (i = 1; args && (i < dsc->arg_num); args = args->next, i++) + if (dsc->args_type[i] && (args->type != dsc->args_type[i])) + return 0; + + return !args && !(i < dsc->arg_num); + } + + struct f_inst * + f_dispatch_method(struct symbol *sym, struct f_inst *obj, struct f_inst *args) + { + /* Note! We should revert args */ + + for (const struct f_method *dsc = sym->method; dsc; dsc = dsc->next) + if (f_match_signature(dsc, args)) + return dsc->new_inst(obj, args); + + cf_error("Cannot dispatch method '%s'", sym->name); + } + + struct f_inst * -f_dispatch_method_x(const char *name, enum f_type t, struct f_inst *obj, struct f_inst *args) ++f_dispatch_method_x(const char *name, enum btype t, struct f_inst *obj, struct f_inst *args) + { + struct sym_scope *scope = f_type_method_scope(t); + struct symbol *sym = cf_find_symbol_scope(scope, name); + + if (!sym) + cf_error("Cannot dispatch method '%s'", name); + + return f_dispatch_method(sym, obj, args); + } + + struct f_inst * f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block) { @@@ -75,6 -113,6 +113,28 @@@ return ms->method->new_inst(term, loop_start); } ++struct f_inst * ++f_implicit_roa_check(struct rtable_config *tab) ++{ ++ const struct ea_class *def = ea_class_find("bgp_path"); ++ if (!def) ++ bug("Couldn't find BGP AS Path attribute definition."); ++ ++ struct f_inst *path_getter = f_new_inst(FI_EA_GET, def); ++ struct sym_scope *scope = f_type_method_scope(path_getter->type); ++ struct symbol *ms = scope ? cf_find_symbol_scope(scope, "last") : NULL; ++ ++ if (!ms) ++ bug("Couldn't find the \"last\" method for AS Path."); ++ ++ struct f_static_attr fsa = f_new_static_attr(T_NET, SA_NET, 1); ++ ++ return f_new_inst(FI_ROA_CHECK, ++ f_new_inst(FI_RTA_GET, fsa), ++ f_dispatch_method(ms, path_getter, NULL), ++ tab); ++} ++ struct f_inst * f_print(struct f_inst *vars, int flush, enum filter_return fret) {