0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +00:00

Filter: any lvalue can get its methods called

This commit is contained in:
Maria Matejka 2023-06-12 11:37:50 +02:00 committed by Igor Putovny
parent 7b65343937
commit f88583b903
3 changed files with 56 additions and 24 deletions

View File

@ -1585,7 +1585,8 @@ in the foot).
Statement <cf><m/P/ = prepend(<m/P/, <m/A/);</cf> can be shortened to Statement <cf><m/P/ = prepend(<m/P/, <m/A/);</cf> can be shortened to
<cf><m/P/.prepend(<m/A/);</cf> if <m/P/ is appropriate route attribute <cf><m/P/.prepend(<m/A/);</cf> if <m/P/ is appropriate route attribute
(for example <cf/bgp_path/). Similarly for <cf/delete/ and <cf/filter/. (for example <cf/bgp_path/) or a local variable.
Similarly for <cf/delete/ and <cf/filter/.
<tag><label id="type-bgpmask">bgpmask</tag> <tag><label id="type-bgpmask">bgpmask</tag>
BGP masks are patterns used for BGP path matching (using <cf>path BGP masks are patterns used for BGP path matching (using <cf>path
@ -1634,7 +1635,8 @@ in the foot).
Statement <cf><m/C/ = add(<m/C/, <m/P/);</cf> can be shortened to Statement <cf><m/C/ = add(<m/C/, <m/P/);</cf> can be shortened to
<cf><m/C/.add(<m/P/);</cf> if <m/C/ is appropriate route attribute (for <cf><m/C/.add(<m/P/);</cf> if <m/C/ is appropriate route attribute (for
example <cf/bgp_community/). Similarly for <cf/delete/ and <cf/filter/. example <cf/bgp_community/) or a local variable.
Similarly for <cf/delete/ and <cf/filter/.
<cf><m/C/.min</cf> returns the minimum element of clist <m/C/. <cf><m/C/.min</cf> returns the minimum element of clist <m/C/.

View File

@ -293,27 +293,34 @@ assert_done(struct f_inst *expr, const char *start, const char *end)
} }
static struct f_inst * static struct f_inst *
assert_assign(struct f_lval *lval, struct f_inst *expr, const char *start, const char *end) f_lval_getter(struct f_lval *lval)
{ {
struct f_inst *setter, *getter, *checker;
switch (lval->type) { switch (lval->type) {
case F_LVAL_VARIABLE: case F_LVAL_VARIABLE: return f_new_inst(FI_VAR_GET, lval->sym);
setter = f_new_inst(FI_VAR_SET, expr, lval->sym); case F_LVAL_SA: return f_new_inst(FI_RTA_GET, lval->sa);
getter = f_new_inst(FI_VAR_GET, lval->sym); case F_LVAL_EA: return f_new_inst(FI_EA_GET, lval->da);
break; default: bug("Unknown lval type");
case F_LVAL_SA: }
setter = f_new_inst(FI_RTA_SET, expr, lval->sa);
getter = f_new_inst(FI_RTA_GET, lval->sa);
break;
case F_LVAL_EA:
setter = f_new_inst(FI_EA_SET, expr, lval->da);
getter = f_new_inst(FI_EA_GET, lval->da);
break;
default:
bug("Unknown lval type");
} }
checker = f_new_inst(FI_EQ, expr, getter); static struct f_inst *
f_lval_setter(struct f_lval *lval, struct f_inst *expr)
{
switch (lval->type) {
case F_LVAL_VARIABLE: return f_new_inst(FI_VAR_SET, expr, lval->sym);
case F_LVAL_SA: return f_new_inst(FI_RTA_SET, expr, lval->sa);
case F_LVAL_EA: return f_new_inst(FI_EA_SET, expr, lval->da);
default: bug("Unknown lval type");
}
}
static struct f_inst *
assert_assign(struct f_lval *lval, struct f_inst *expr, const char *start, const char *end)
{
struct f_inst *setter = f_lval_setter(lval, expr),
*getter = f_lval_getter(lval);
struct f_inst *checker = f_new_inst(FI_EQ, expr, getter);
setter->next = checker; setter->next = checker;
return assert_done(setter, start, end); return assert_done(setter, start, end);
@ -1005,11 +1012,11 @@ cmd:
$$ = f_new_inst(FI_SWITCH, $2, $4); $$ = f_new_inst(FI_SWITCH, $2, $4);
} }
| dynamic_attr '.' { | lvalue '.' {
f_push_method_scope(f_new_inst(FI_EA_GET, $1)); f_push_method_scope(f_lval_getter(&$1));
} method_cmd ';' { } method_cmd ';' {
f_pop_method_scope(); f_pop_method_scope();
$$ = f_new_inst(FI_EA_SET, $4, $1); $$ = f_lval_setter(&$1, $4);
} }
| BT_ASSERT '(' get_cf_position term get_cf_position ')' ';' { $$ = assert_done($4, $3 + 1, $5 - 1); } | BT_ASSERT '(' get_cf_position term get_cf_position ')' ';' { $$ = assert_done($4, $3 + 1, $5 - 1); }
| BT_CHECK_ASSIGN '(' get_cf_position lvalue get_cf_position ',' term ')' ';' { $$ = assert_assign(&$4, $7, $3 + 1, $5 - 1); } | BT_CHECK_ASSIGN '(' get_cf_position lvalue get_cf_position ',' term ')' ';' { $$ = assert_assign(&$4, $7, $3 + 1, $5 - 1); }
@ -1021,7 +1028,19 @@ get_cf_position:
}; };
lvalue: lvalue:
CF_SYM_KNOWN { cf_assert_symbol($1, SYM_VARIABLE); $$ = (struct f_lval) { .type = F_LVAL_VARIABLE, .sym = $1 }; } CF_SYM_KNOWN {
switch ($1->class)
{
case SYM_VARIABLE_RANGE:
$$ = (struct f_lval) { .type = F_LVAL_VARIABLE, .sym = $1 };
break;
case SYM_ATTRIBUTE:
$$ = (struct f_lval) { .type = F_LVAL_EA, .da = *($1->attribute) };
break;
default:
cf_error("Variable name or custom attribute name required");
}
}
| static_attr { $$ = (struct f_lval) { .type = F_LVAL_SA, .sa = $1 }; } | static_attr { $$ = (struct f_lval) { .type = F_LVAL_SA, .sa = $1 }; }
| dynamic_attr { $$ = (struct f_lval) { .type = F_LVAL_EA, .da = $1 }; }; | dynamic_attr { $$ = (struct f_lval) { .type = F_LVAL_EA, .da = $1 }; };

View File

@ -9,6 +9,8 @@ router id 62.168.0.1;
/* We have to setup any protocol */ /* We have to setup any protocol */
protocol device { } protocol device { }
attribute bgppath mypath;
attribute lclist mylclist;
/* /*
@ -1641,6 +1643,15 @@ filter vpn_filter
bgp_ext_community.add((ro, 135, 999)); bgp_ext_community.add((ro, 135, 999));
bgp_large_community.add((6464156, 89646354, 8675643)); bgp_large_community.add((6464156, 89646354, 8675643));
mypath.prepend(65533);
mylclist.add((1234, 5678, 90123));
bgppath locpath;
lclist loclclist;
locpath.prepend(65533);
loclclist.add((1234, 5678, 90123));
accept; accept;
} }