]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: any lvalue can get its methods called
authorMaria Matejka <mq@ucw.cz>
Mon, 12 Jun 2023 09:37:50 +0000 (11:37 +0200)
committerMaria Matejka <mq@ucw.cz>
Mon, 12 Jun 2023 09:40:05 +0000 (11:40 +0200)
doc/bird.sgml
filter/config.Y
filter/test.conf

index 8041faa90b219fdcc72f273e85e747644f67c74e..77a563c6cbbb243c0f60fffaf18069b4efe84ddb 100644 (file)
@@ -1585,7 +1585,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
@@ -1634,7 +1635,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/.
 
index 7bbfbaa297a6ad5a6d08e1e6dc703412b10c6d36..116def0c10e87176c3e17411662e90ac60c18c87 100644 (file)
@@ -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);
@@ -1005,11 +1012,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); }
@@ -1021,7 +1028,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 }; };
 
index 600c551e41754507c6dcae72fa60f02d1e708c0d..1f78300a9d42c2ef2877ff102751e09383b55e90 100644 (file)
@@ -9,6 +9,8 @@ router id 62.168.0.1;
 /* We have to setup any protocol */
 protocol device { }
 
+attribute bgppath mypath;
+attribute lclist mylclist;
 
 
 /*
@@ -1641,6 +1643,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;
 }