summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2023-06-12 11:37:50 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2023-09-12 15:27:46 +0200
commit5951dfbd5ed21d973e7627740c069d6612d7b899 (patch)
tree473a1e79b5837700b7abe93f5437e1afe494ce94
parentae8ecafda9e28bfd417795fbb43408d6857df76d (diff)
Filter: any lvalue can get its methods called
-rw-r--r--doc/bird.sgml6
-rw-r--r--filter/config.Y61
-rw-r--r--filter/test.conf11
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;
}