0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-09-19 11:55:21 +00:00

Merge commit 'cc1099a0' into thread-next

Updated f_implicit_roa_check() to use type methods and moved to filter/f-util.c
This commit is contained in:
Maria Matejka 2023-10-29 00:14:52 +02:00
commit a725e3e580
7 changed files with 272 additions and 212 deletions

View File

@ -723,7 +723,7 @@ cf_lex_symbol(const char *data)
return ENUM;
}
case SYM_METHOD:
return sym->method->arg_num ? CF_SYM_METHOD_ARGS : CF_SYM_METHOD_BARE;
return (sym->method->arg_num > 1) ? CF_SYM_METHOD_ARGS : CF_SYM_METHOD_BARE;
case SYM_VOID:
return CF_SYM_UNDEFINED;
default:

View File

@ -244,21 +244,6 @@ f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3, u32 t3)
return t;
}
static inline struct f_inst *
f_implicit_roa_check(struct rtable_config *tab)
{
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);
}
/*
* Remove all new lines and doubled whitespaces
* and convert all tabulators to spaces
@ -897,17 +882,15 @@ static_attr:
| GW_MPLS { $$ = f_new_static_attr(T_INT, SA_GW_MPLS, 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();
} '(' var_list ')' {
$$ = $1->method->new_inst(FM.object, $4);
f_method_call_end();
$$ = f_dispatch_method($1, FM.object, $4);
}
;
@ -946,32 +929,15 @@ term:
| '-' '-' '-' 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 ')' {
switch ($3->type) {
case T_PATH: $$ = f_new_inst(FI_PATH_DEL, $3, $5); break;
case T_CLIST: $$ = f_new_inst(FI_CLIST_DEL, $3, $5); break;
case T_ECLIST: $$ = f_new_inst(FI_ECLIST_DEL, $3, $5); break;
case T_LCLIST: $$ = f_new_inst(FI_LCLIST_DEL, $3, $5); break;
default: cf_error("Can't delete from type %s", f_type_name($3->type));
}
$$ = f_dispatch_method_x("delete", $3->type, $3, $5);
cf_warn("delete(x,y) function is deprecated, please use x.delete(y)");
}
| FILTER '(' term ',' term ')' {
switch ($3->type) {
case T_PATH: $$ = f_new_inst(FI_PATH_FILTER, $3, $5); break;
case T_CLIST: $$ = f_new_inst(FI_CLIST_FILTER, $3, $5); break;
case T_ECLIST: $$ = f_new_inst(FI_ECLIST_FILTER, $3, $5); break;
case T_LCLIST: $$ = f_new_inst(FI_LCLIST_FILTER, $3, $5); break;
default: cf_error("Can't filter type %s", f_type_name($3->type));
}
$$ = f_dispatch_method_x("filter", $3->type, $3, $5);
cf_warn("filter(x,y) function is deprecated, please use x.filter(y)");
}
@ -1086,10 +1052,10 @@ cmd:
| CASE term '{' switch_body '}' {
$$ = f_new_inst(FI_SWITCH, $2, $4);
}
| lvalue '.' {
f_method_call_start(f_lval_getter(&$1));
} method_name_cont ';' {
f_method_call_end();
$$ = f_lval_setter(&$1, $4);
}
| BT_ASSERT '(' get_cf_position term get_cf_position ')' ';' { $$ = assert_done($4, $3 + 1, $5 - 1); }

View File

@ -16,7 +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 btype args_type[];
};
/* Filter value; size of this affects filter memory consumption */

View File

@ -53,6 +53,7 @@ m4_define(FID_NEW_ATTRIBUTES, `m4_divert(110)')
m4_define(FID_NEW_BODY, `m4_divert(103)')
m4_define(FID_NEW_METHOD, `m4_divert(111)')
m4_define(FID_METHOD_CALL, `m4_divert(112)')
m4_define(FID_TYPE_SIGNATURE, `m4_divert(113)')
m4_define(FID_DUMP_BODY, `m4_divert(104)m4_define([[FID_DUMP_BODY_EXISTS]])')
m4_define(FID_LINEARIZE_BODY, `m4_divert(105)')
m4_define(FID_SAME_BODY, `m4_divert(106)')
@ -125,7 +126,7 @@ FID_IFCONST([[
constargs = 0;
]])
} while (child$1 = child$1->next);
m4_define([[INST_METHOD_NUM_ARGS]],m4_eval($1-1))m4_dnl
m4_define([[INST_METHOD_NUM_ARGS]],$1)m4_dnl
m4_ifelse($1,1,,[[FID_NEW_METHOD()m4_dnl
struct f_inst *arg$1 = args;
if (args == NULL) cf_error("Not enough arguments"); /* INST_NAME */
@ -183,6 +184,8 @@ m4_define(ARG_TYPE, `ARG_TYPE_STATIC($1,$2) ARG_TYPE_DYNAMIC($1,$2)')
m4_define(ARG_TYPE_STATIC, `m4_dnl
m4_ifelse($1,1,[[m4_define([[INST_METHOD_OBJECT_TYPE]],$2)]],)m4_dnl
FID_TYPE_SIGNATURE()m4_dnl
method->args_type[m4_eval($1-1)] = $2;
FID_NEW_BODY()m4_dnl
if (f$1->type && (f$1->type != ($2)) && !f_const_promotion(f$1, ($2)))
cf_error("Argument $1 of %s must be of type %s, got type %s",
@ -231,7 +234,7 @@ FID_NEW_ARGS()m4_dnl
, struct f_inst * f$1
FID_NEW_BODY()m4_dnl
whati->f$1 = f$1;
m4_define([[INST_METHOD_NUM_ARGS]],m4_eval($1-1))m4_dnl
m4_define([[INST_METHOD_NUM_ARGS]],$1)m4_dnl
FID_NEW_METHOD()m4_dnl
struct f_inst *arg$1 = args;
if (args == NULL) cf_error("Not enough arguments"); /* INST_NAME */
@ -306,7 +309,7 @@ INST([[FI_METHOD__]]$1[[__]]$2, m4_eval($3 + 1), 1) {
METHOD_CONSTRUCTOR("$2");
}')
m4_define(METHOD_R, `METHOD($1, $2, $3, [[ RESULT($4, $5, $6) ]])')
m4_define(METHOD_R, `METHOD($1, $2, 0, [[ RESULT($3, $4, $5) ]])')
# 2) Code wrapping
# The code produced in 1xx temporary diversions is a raw code without
@ -422,15 +425,11 @@ m4_undivert(112)
FID_METHOD_SCOPE_INIT()m4_dnl
[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 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 +632,27 @@ struct sym_scope *f_type_method_scope(enum btype t)
return (t < ARRAY_SIZE(f_type_method_scopes)) ? &f_type_method_scopes[t] : NULL;
}
static void
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_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++)

View File

@ -503,8 +503,8 @@
RESULT(T_BOOL, i, (v1.type != T_VOID) && !undef_value(v1));
}
METHOD_R(T_NET, type, 0, T_ENUM_NETTYPE, i, v1.val.net->type);
METHOD_R(T_IP, is_v4, 0, T_BOOL, i, ipa_is_ip4(v1.val.ip));
METHOD_R(T_NET, type, T_ENUM_NETTYPE, i, v1.val.net->type);
METHOD_R(T_IP, is_v4, T_BOOL, i, ipa_is_ip4(v1.val.ip));
/* Add initialized variable */
INST(FI_VAR_INIT, 1, 0) {
@ -560,10 +560,10 @@
RESULT_VAL(val);
}
METHOD_R(T_PATH, empty, 0, T_PATH, ad, &null_adata);
METHOD_R(T_CLIST, empty, 0, T_CLIST, ad, &null_adata);
METHOD_R(T_ECLIST, empty, 0, T_ECLIST, ad, &null_adata);
METHOD_R(T_LCLIST, empty, 0, T_LCLIST, ad, &null_adata);
METHOD_R(T_PATH, empty, T_PATH, ad, &null_adata);
METHOD_R(T_CLIST, empty, T_CLIST, ad, &null_adata);
METHOD_R(T_ECLIST, empty, T_ECLIST, ad, &null_adata);
METHOD_R(T_LCLIST, empty, T_LCLIST, ad, &null_adata);
/* Common loop begin instruction, always created by f_for_cycle() */
INST(FI_FOR_LOOP_START, 0, 3) {
@ -920,11 +920,11 @@
}
/* 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));
METHOD_R(T_NET, len, T_INT, i, net_pxlen(v1.val.net));
METHOD_R(T_PATH, len, T_INT, i, as_path_getlen(v1.val.ad));
METHOD_R(T_CLIST, len, T_INT, i, int_set_get_size(v1.val.ad));
METHOD_R(T_ECLIST, len, T_INT, i, ec_set_get_size(v1.val.ad));
METHOD_R(T_LCLIST, len, T_INT, i, lc_set_get_size(v1.val.ad));
INST(FI_NET_SRC, 1, 1) { /* Get src prefix */
ARG(1, T_NET);
@ -1008,10 +1008,7 @@
((net_addr_roa6 *) v1.val.net)->max_pxlen);
]]);
/* Get ROA ASN or community ASN part */
METHOD_R(T_PAIR, asn, 0, T_INT, i, v1.val.i >> 16);
METHOD_R(T_LC, asn, 0, T_INT, i, v1.val.lc.asn);
/* Get ROA ASN */
METHOD(T_NET, asn, 0, [[
if (!net_is_roa(v1.val.net))
runtime( "ROA expected" );
@ -1021,9 +1018,8 @@
((net_addr_roa6 *) v1.val.net)->asn);
]]);
/* Convert prefix to IP */
METHOD_R(T_NET, ip, 0, T_IP, ip, net_prefix(v1.val.net));
METHOD_R(T_NET, ip, T_IP, ip, net_prefix(v1.val.net));
INST(FI_ROUTE_DISTINGUISHER, 1, 1) {
ARG(1, T_NET);
@ -1033,81 +1029,47 @@
RESULT(T_RD, ec, net_rd(v1.val.net));
}
INST(FI_AS_PATH_FIRST, 1, 1) { /* Get first ASN from AS PATH */
ARG(1, T_PATH);
METHOD_CONSTRUCTOR("first");
u32 as = 0;
as_path_get_first(v1.val.ad, &as);
RESULT(T_INT, i, as);
}
/* Get first ASN from AS PATH */
METHOD_R(T_PATH, first, T_INT, i, ({ u32 as = 0; as_path_get_first(v1.val.ad, &as); as; }));
INST(FI_AS_PATH_LAST, 1, 1) { /* Get last ASN from AS PATH */
ARG(1, T_PATH);
METHOD_CONSTRUCTOR("last");
u32 as = 0;
as_path_get_last(v1.val.ad, &as);
RESULT(T_INT, i, as);
}
/* Get last ASN from AS PATH */
METHOD_R(T_PATH, last, T_INT, i, ({ u32 as = 0; as_path_get_last(v1.val.ad, &as); as; }));
/* Get last ASN from non-aggregated part of AS PATH */
METHOD_R(T_PATH, last_nonaggregated, 0, T_INT, i, as_path_get_last_nonaggregated(v1.val.ad));
METHOD_R(T_PATH, last_nonaggregated, T_INT, i, as_path_get_last_nonaggregated(v1.val.ad));
/* Get ASN part from the standard community ASN */
METHOD_R(T_PAIR, asn, T_INT, i, v1.val.i >> 16);
/* Get data part from the standard community */
METHOD_R(T_PAIR, data, 0, T_INT, i, v1.val.i & 0xFFFF);
METHOD_R(T_PAIR, data, T_INT, i, v1.val.i & 0xFFFF);
/* Get ASN part from the large community */
METHOD_R(T_LC, asn, T_INT, i, v1.val.lc.asn);
/* Get data1 part from the large community */
METHOD_R(T_LC, data1, 0, T_INT, i, v1.val.lc.ldp1);
METHOD_R(T_LC, data1, T_INT, i, v1.val.lc.ldp1);
/* Get data2 part from the large community */
METHOD_R(T_LC, data2, 0, T_INT, i, v1.val.lc.ldp2);
METHOD_R(T_LC, data2, T_INT, i, v1.val.lc.ldp2);
INST(FI_CLIST_MIN, 1, 1) { /* Get minimum element from list */
ARG(1, T_CLIST);
METHOD_CONSTRUCTOR("min");
u32 val = 0;
int_set_min(v1.val.ad, &val);
RESULT(T_PAIR, i, val);
}
/* Get minimum element from clist */
METHOD_R(T_CLIST, min, T_PAIR, i, ({ u32 val = 0; int_set_min(v1.val.ad, &val); val; }));
INST(FI_CLIST_MAX, 1, 1) { /* Get minimum element from list */
ARG(1, T_CLIST);
METHOD_CONSTRUCTOR("max");
u32 val = 0;
int_set_max(v1.val.ad, &val);
RESULT(T_PAIR, i, val);
}
/* Get maximum element from clist */
METHOD_R(T_CLIST, max, T_PAIR, i, ({ u32 val = 0; int_set_max(v1.val.ad, &val); val; }));
INST(FI_ECLIST_MIN, 1, 1) { /* Get minimum element from list */
ARG(1, T_ECLIST);
METHOD_CONSTRUCTOR("min");
u64 val = 0;
ec_set_min(v1.val.ad, &val);
RESULT(T_EC, ec, val);
}
/* Get minimum element from eclist */
METHOD_R(T_ECLIST, min, T_EC, ec, ({ u64 val = 0; ec_set_min(v1.val.ad, &val); val; }));
INST(FI_ECLIST_MAX, 1, 1) { /* Get minimum element from list */
ARG(1, T_ECLIST);
METHOD_CONSTRUCTOR("max");
u64 val = 0;
ec_set_max(v1.val.ad, &val);
RESULT(T_EC, ec, val);
}
/* Get maximum element from eclist */
METHOD_R(T_ECLIST, max, T_EC, ec, ({ u64 val = 0; ec_set_max(v1.val.ad, &val); val; }));
INST(FI_LCLIST_MIN, 1, 1) { /* Get minimum element from list */
ARG(1, T_LCLIST);
METHOD_CONSTRUCTOR("min");
lcomm val = {};
lc_set_min(v1.val.ad, &val);
RESULT(T_LC, lc, val);
}
/* Get minimum element from lclist */
METHOD_R(T_LCLIST, min, T_LC, lc, ({ lcomm val = {}; lc_set_min(v1.val.ad, &val); val; }));
INST(FI_LCLIST_MAX, 1, 1) { /* Get minimum element from list */
ARG(1, T_LCLIST);
METHOD_CONSTRUCTOR("max");
lcomm val = {};
lc_set_max(v1.val.ad, &val);
RESULT(T_LC, lc, val);
}
/* Get maximum element from lclist */
METHOD_R(T_LCLIST, max, T_LC, lc, ({ lcomm val = {}; lc_set_max(v1.val.ad, &val); val; }));
INST(FI_RETURN, 1, 0) {
NEVER_CONSTANT;
@ -1259,7 +1221,8 @@
RESULT(T_PATH, ad, [[ as_path_prepend(fpool, v1.val.ad, v2.val.i) ]]);
}
INST(FI_CLIST_ADD, 2, 1) { /* (Extended) Community list add */
/* Community list add */
INST(FI_CLIST_ADD, 2, 1) {
ARG(1, T_CLIST);
ARG_ANY(2);
METHOD_CONSTRUCTOR("add");
@ -1277,47 +1240,54 @@
runtime("Can't add non-pair");
}
INST(FI_ECLIST_ADD, 2, 1) {
INST(FI_ECLIST_ADD_EC, 2, 1) {
ARG(1, T_ECLIST);
ARG_ANY(2);
ARG(2, T_EC);
METHOD_CONSTRUCTOR("add");
/* v2.val is either EC or EC-set */
if ((v2.type == T_SET) && eclist_set_type(v2.val.t))
runtime("Can't add set");
else if (v2.type == T_ECLIST)
RESULT(T_ECLIST, ad, [[ ec_set_union(fpool, v1.val.ad, v2.val.ad) ]]);
else if (v2.type != T_EC)
runtime("Can't add non-ec");
else
RESULT(T_ECLIST, ad, [[ ec_set_add(fpool, v1.val.ad, v2.val.ec) ]]);
RESULT(T_ECLIST, ad, [[ ec_set_add(fpool, v1.val.ad, v2.val.ec) ]]);
}
INST(FI_LCLIST_ADD, 2, 1) {
INST(FI_ECLIST_ADD_ECLIST, 2, 1) {
ARG(1, T_ECLIST);
ARG(2, T_ECLIST);
METHOD_CONSTRUCTOR("add");
RESULT(T_ECLIST, ad, [[ ec_set_union(fpool, v1.val.ad, v2.val.ad) ]]);
}
INST(FI_LCLIST_ADD_LC, 2, 1) {
ARG(1, T_LCLIST);
ARG_ANY(2);
ARG(2, T_LC);
METHOD_CONSTRUCTOR("add");
/* v2.val is either LC or LC-set */
if ((v2.type == T_SET) && lclist_set_type(v2.val.t))
runtime("Can't add set");
else if (v2.type == T_LCLIST)
RESULT(T_LCLIST, ad, [[ lc_set_union(fpool, v1.val.ad, v2.val.ad) ]]);
else if (v2.type != T_LC)
runtime("Can't add non-lc");
else
RESULT(T_LCLIST, ad, [[ lc_set_add(fpool, v1.val.ad, v2.val.lc) ]]);
RESULT(T_LCLIST, ad, [[ lc_set_add(fpool, v1.val.ad, v2.val.lc) ]]);
}
INST(FI_PATH_DEL, 2, 1) { /* Path delete */
INST(FI_LCLIST_ADD_LCLIST, 2, 1) {
ARG(1, T_LCLIST);
ARG(2, T_LCLIST);
METHOD_CONSTRUCTOR("add");
RESULT(T_LCLIST, ad, [[ lc_set_union(fpool, v1.val.ad, v2.val.ad) ]]);
}
INST(FI_PATH_DELETE_INT, 2, 1) {
ARG(1, T_PATH);
ARG_ANY(2);
ARG(2, T_INT);
METHOD_CONSTRUCTOR("delete");
if ((v2.type == T_SET) && path_set_type(v2.val.t) || (v2.type == T_INT))
RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 0) ]]);
else
runtime("Can't delete non-integer (set)");
RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 0) ]]);
}
INST(FI_CLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */
INST(FI_PATH_DELETE_SET, 2, 1) {
ARG(1, T_PATH);
ARG(2, T_SET);
METHOD_CONSTRUCTOR("delete");
if (!path_set_type(v2.val.t))
runtime("Mismatched set type");
RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, &v2, 0) ]]);
}
/* Community list delete */
INST(FI_CLIST_DELETE, 2, 1) {
ARG(1, T_CLIST);
ARG_ANY(2);
METHOD_CONSTRUCTOR("delete");
@ -1335,76 +1305,119 @@
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_LCLIST_DEL, 2, 1) { /* (Extended) Community list add or delete */
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_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_PATH_FILTER, 2, 1) { /* (Extended) Community list add or delete */
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_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;
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");
RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]);
}
INST(FI_ECLIST_FILTER, 2, 1) {
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_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_LCLIST_FILTER, 2, 1) {
ARG(1, T_LCLIST);
ARG_ANY(2);
INST(FI_ECLIST_FILTER_SET, 2, 1) {
ARG(1, T_ECLIST);
ARG(2, T_SET);
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");
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_LCLIST, 2, 1) {
ARG(1, T_LCLIST);
ARG(2, T_LCLIST);
METHOD_CONSTRUCTOR("filter");
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, 2, 1) { /* ROA Check */

View File

@ -96,7 +96,10 @@ void f_add_lines(const struct f_line_item *what, struct filter_iterator *fit);
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 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_static_attr f_new_static_attr(btype type, int code, int readonly)

View File

@ -30,7 +30,8 @@ filter_name(const struct filter *filter)
return filter->sym->name;
}
struct filter *f_new_where(struct f_inst *where)
struct filter *
f_new_where(struct f_inst *where)
{
struct f_inst *cond = f_new_inst(FI_CONDITION, where,
f_new_inst(FI_DIE, F_ACCEPT),
@ -41,6 +42,43 @@ struct filter *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 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,28 @@ f_for_cycle(struct symbol *var, struct f_inst *term, struct f_inst *block)
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)
{