]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Allow to use sets in path masks
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 6 Aug 2019 14:58:13 +0000 (16:58 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 6 Aug 2019 14:58:13 +0000 (16:58 +0200)
filter/config.Y
filter/test.conf
nest/a-path.c
nest/attrs.h

index 8171a7c20b6569afea605a0574ad1146e6a0ee9b..a67a72a8354f2e867489a505288d322bfc5993ce 100644 (file)
@@ -801,6 +801,10 @@ bgp_path:
 bgp_path_tail:
    NUM bgp_path_tail           { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .asn = $1, .kind = PM_ASN, }, }); $$->next = $2;  }
  | NUM DDOT NUM bgp_path_tail  { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .from = $1, .to = $3, .kind = PM_ASN_RANGE }, }); $$->next = $4; }
+ | '[' set_items ']' bgp_path_tail {
+   if ($2->from.type != T_INT) cf_error("Only integer sets allowed in path mask");
+   $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .set = build_tree($2), .kind = PM_ASN_SET }, }); $$->next = $4;
+ }
  | '*' bgp_path_tail           { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_ASTERISK }, }); $$->next = $2; }
  | '?' bgp_path_tail           { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PATH_MASK_ITEM, .val.pmi = { .kind = PM_QUESTION }, }); $$->next = $2; }
  | bgp_path_expr bgp_path_tail { $$ = $1; $$->next = $2; }
index 9abd76f320b0d291ee5d195bf941584091e44663..04074965c06e904845ff4801e7bf5395e266dd87 100644 (file)
@@ -626,6 +626,7 @@ bgppath p2;
        bt_assert(p2 !~ [8, ten..(2*ten)]);
        bt_assert(p2 ~ [= * 4 3 * 1 =]);
        bt_assert(p2 ~ [= (3+2) (2*2) 3 2 1 =]);
+       bt_assert(p2 ~ [= 5 [2, 4, 6] 3 [1..2] 1 =]);
        bt_assert(p2 ~ mkpath(5, 4));
 
        bt_assert(p2.len = 5);
index a1b7c42f8cd5333865c27d652b670e3644bf937f..4ee34cf4ee38fcbd24b80d0934b23c02dfd9cb0e 100644 (file)
@@ -740,6 +740,31 @@ pm_match(struct pm_pos *pos, u32 asn, u32 asn2)
   return 0;
 }
 
+static int
+pm_match_set(struct pm_pos *pos, struct f_tree *set)
+{
+  struct f_val asn = { .type = T_INT };
+
+  if (! pos->set)
+  {
+    asn.val.i = pos->val.asn;
+    return !!find_tree(set, &asn);
+  }
+
+  const u8 *p = pos->val.sp;
+  int len = *p++;
+  int i;
+
+  for (i = 0; i < len; i++)
+  {
+    asn.val.i = get_as(p + i * BS);
+    if (find_tree(set, &asn))
+      return 1;
+  }
+
+  return 0;
+}
+
 static void
 pm_mark(struct pm_pos *pos, int i, int plen, int *nl, int *nh)
 {
@@ -824,13 +849,17 @@ as_path_match(const struct adata *path, const struct f_path_mask *mask)
          val2 = mask->item[m].to;
          goto step;
        case PM_QUESTION:
+       case PM_ASN_SET:
        step:
          nh = nl = -1;
          for (i = h; i >= l; i--)
            if (pos[i].mark)
              {
                pos[i].mark = 0;
-               if ((mask->item[m].kind == PM_QUESTION) || pm_match(pos + i, val, val2))
+               if ((mask->item[m].kind == PM_QUESTION) ||
+                   ((mask->item[m].kind != PM_ASN_SET) ?
+                    pm_match(pos + i, val, val2) :
+                    pm_match_set(pos + i, mask->item[m].set)))
                  pm_mark(pos, i, plen, &nl, &nh);
              }
 
index 4efcff7902871138e3de6e166468ba5e076f535f..a17b8c0517e255f24741ff3ba34f1a5029de4e04 100644 (file)
@@ -60,16 +60,18 @@ static inline struct adata *as_path_prepend(struct linpool *pool, const struct a
 #define PM_ASTERISK    2
 #define PM_ASN_EXPR    3
 #define PM_ASN_RANGE   4
+#define PM_ASN_SET     5
 
 struct f_path_mask_item {
   union {
     u32 asn; /* PM_ASN */
     struct f_line *expr; /* PM_ASN_EXPR */
+    struct f_tree *set; /* PM_ASN_SET */
     struct { /* PM_ASN_RANGE */
       u32 from;
       u32 to;
     };
-  }; 
+  };
   int kind;
 };