diff options
author | Maria Matejka <mq@ucw.cz> | 2023-06-12 11:37:50 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2023-09-12 15:27:46 +0200 |
commit | 5951dfbd5ed21d973e7627740c069d6612d7b899 (patch) | |
tree | 473a1e79b5837700b7abe93f5437e1afe494ce94 | |
parent | ae8ecafda9e28bfd417795fbb43408d6857df76d (diff) |
Filter: any lvalue can get its methods called
-rw-r--r-- | doc/bird.sgml | 6 | ||||
-rw-r--r-- | filter/config.Y | 61 | ||||
-rw-r--r-- | filter/test.conf | 11 |
3 files changed, 55 insertions, 23 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index 351039dc..dc1d2285 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1604,7 +1604,8 @@ in the foot). 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 - (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> BGP masks are patterns used for BGP path matching (using <cf>path @@ -1653,7 +1654,8 @@ in the foot). 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 - 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/. diff --git a/filter/config.Y b/filter/config.Y index d6d96afc..58c0c16b 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -293,27 +293,34 @@ assert_done(struct f_inst *expr, const char *start, const char *end) } 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) { - case F_LVAL_VARIABLE: - setter = f_new_inst(FI_VAR_SET, expr, lval->sym); - getter = f_new_inst(FI_VAR_GET, lval->sym); - break; - 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"); + case F_LVAL_VARIABLE: return f_new_inst(FI_VAR_GET, lval->sym); + case F_LVAL_SA: return f_new_inst(FI_RTA_GET, lval->sa); + case F_LVAL_EA: return f_new_inst(FI_EA_GET, lval->da); + default: bug("Unknown lval type"); + } +} + +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); - checker = f_new_inst(FI_EQ, expr, getter); + struct f_inst *checker = f_new_inst(FI_EQ, expr, getter); setter->next = checker; return assert_done(setter, start, end); @@ -1014,11 +1021,11 @@ cmd: $$ = f_new_inst(FI_SWITCH, $2, $4); } - | dynamic_attr '.' { - f_push_method_scope(f_new_inst(FI_EA_GET, $1)); + | lvalue '.' { + f_push_method_scope(f_lval_getter(&$1)); } method_cmd ';' { 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_CHECK_ASSIGN '(' get_cf_position lvalue get_cf_position ',' term ')' ';' { $$ = assert_assign(&$4, $7, $3 + 1, $5 - 1); } @@ -1030,7 +1037,19 @@ get_cf_position: }; 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 }; } | dynamic_attr { $$ = (struct f_lval) { .type = F_LVAL_EA, .da = $1 }; }; diff --git a/filter/test.conf b/filter/test.conf index c74c2691..6d786034 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -9,6 +9,8 @@ router id 62.168.0.1; /* We have to setup any protocol */ protocol device { } +attribute bgppath mypath; +attribute lclist mylclist; /* @@ -1694,6 +1696,15 @@ filter vpn_filter bgp_ext_community.add((ro, 135, 999)); 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; } |