Commit ef113c6f authored by Ondrej Zajicek (work)'s avatar Ondrej Zajicek (work)
Browse files

Filter: Allow to use sets in path masks

parent e2b530aa
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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; }
+1 −0
Original line number Diff line number Diff line
@@ -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);
+30 −1
Original line number Diff line number Diff line
@@ -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);
	      }

+3 −1
Original line number Diff line number Diff line
@@ -60,11 +60,13 @@ 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;