diff --git a/doc/bird.sgml b/doc/bird.sgml
index f3c34a14..de7041a9 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -1165,8 +1165,10 @@ foot).
is 4 3 2 1, then: bgp_path ˜ [= * 4 3 * =] is true,
but bgp_path ˜ [= * 4 5 * =] is false. BGP mask
expressions can also contain integer expressions enclosed in parenthesis
- and integer variables, for example [= * 4 (1+2) a =]. There is
- also old syntax that uses / .. / instead of [= .. =] and ? instead of *.
+ and integer variables, for example [= * 4 (1+2) a =]. You can
+ also use ranges, for example [= * 3..5 2 100..200 * =].
+ There is also old (deprecated) syntax that uses / .. / instead of [= .. =]
+ and ? instead of *.
next = $2; $$->kind = PM_ASN; $$->val = $1; }
+ | NUM DDOT NUM bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $4; $$->kind = PM_ASN_RANGE; $$->val = $1; $$->val2 = $3; }
| '*' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; $$->val = 0; }
| '?' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_QUESTION; $$->val = 0; }
| bgp_path_expr bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN_EXPR; $$->val = (uintptr_t) $1; }
diff --git a/filter/filter.c b/filter/filter.c
index eddf4228..dce98e4d 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -79,6 +79,10 @@ pm_format(struct f_path_mask *p, buffer *buf)
buffer_puts(buf, "* ");
break;
+ case PM_ASN_RANGE:
+ buffer_print(buf, "%u..%u ", p->val, p->val2);
+ break;
+
case PM_ASN_EXPR:
buffer_print(buf, "%u ", f_eval_asn((struct f_inst *) p->val));
break;
diff --git a/filter/test.conf b/filter/test.conf
index a99d0a51..ad8f9386 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -90,20 +90,23 @@ clist l2;
eclist el;
eclist el2;
{
+ print "Entering path test...";
pm1 = / 4 3 2 1 /;
- pm2 = [= 4 3 2 1 =];
+ pm2 = [= 3..6 3 2 1..2 =];
print "Testing path masks: ", pm1, " ", pm2;
p2 = prepend( + empty +, 1 );
p2 = prepend( p2, 2 );
p2 = prepend( p2, 3 );
p2 = prepend( p2, 4 );
- print "Testing paths: ", p2;
+ print "Testing path: (4 3 2 1) = ", p2;
print "Should be true: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 3 ~ p2, " ", p2 ~ [2, 10..20], " ", p2 ~ [4, 10..20];
print "4 = ", p2.len;
p2 = prepend( p2, 5 );
- print "Should be false: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 10 ~ p2, " ", p2 ~ [8, ten..(2*ten)];
+ print "Testing path: (5 4 3 2 1) = ", p2;
+ print "Should be false: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 10 ~ p2, " ", p2 ~ [8, ten..(2*ten)], " ", p2 ~ [= 1..4 4 3 2 1 =], " ", p2 ~ [= 5 4 4..100 2 1 =];
print "Should be true: ", p2 ~ / ? 4 3 2 1 /, " ", p2, " ", / ? 4 3 2 1 /;
print "Should be true: ", p2 ~ [= * 4 3 * 1 =], " ", p2, " ", [= * 4 3 * 1 =];
+ print "Should be true: ", p2 ~ [= 5..6 4..10 1..3 1..3 1..65536 =];
print "Should be true: ", p2 ~ [= (3+2) (2*2) 3 2 1 =], " ", p2 ~ mkpath(5, 4);
print "Should be true: ", p2.len = 5, " ", p2.first = 5, " ", p2.last = 1;
print "5 = ", p2.len;
diff --git a/nest/a-path.c b/nest/a-path.c
index 32e2d27e..e1031b7b 100644
--- a/nest/a-path.c
+++ b/nest/a-path.c
@@ -435,18 +435,23 @@ parse_path(struct adata *path, struct pm_pos *pos)
static int
-pm_match(struct pm_pos *pos, u32 asn)
+pm_match(struct pm_pos *pos, u32 asn, u32 asn2)
{
+ u32 gas;
if (! pos->set)
- return pos->val.asn == asn;
+ return ((pos->val.asn >= asn) && (pos->val.asn <= asn2));
u8 *p = pos->val.sp;
int len = *p++;
int i;
for (i = 0; i < len; i++)
- if (get_as(p + i * BS) == asn)
+ {
+ gas = get_as(p + i * BS);
+
+ if ((gas >= asn) && (gas <= asn2))
return 1;
+ }
return 0;
}
@@ -490,7 +495,7 @@ pm_mark(struct pm_pos *pos, int i, int plen, int *nl, int *nh)
* next part of mask, we advance each marked state.
* We start with marked first position, when we
* run out of marked positions, we reject. When
- * we process the whole mask, we accept iff final position
+ * we process the whole mask, we accept if final position
* (auxiliary position after last real position in AS path)
* is marked.
*/
@@ -502,6 +507,7 @@ as_path_match(struct adata *path, struct f_path_mask *mask)
int plen = parse_path(path, pos);
int l, h, i, nh, nl;
u32 val = 0;
+ u32 val2 = 0;
/* l and h are bound of interval of positions where
are marked states */
@@ -525,12 +531,16 @@ as_path_match(struct adata *path, struct f_path_mask *mask)
h = plen;
break;
- case PM_ASN:
- val = mask->val;
+ case PM_ASN: /* Define single ASN as ASN..ASN - very narrow interval */
+ val2 = val = mask->val;
goto step;
case PM_ASN_EXPR:
- val = f_eval_asn((struct f_inst *) mask->val);
+ val2 = val = f_eval_asn((struct f_inst *) mask->val);
goto step;
+ case PM_ASN_RANGE:
+ val = mask->val;
+ val2 = mask->val2;
+ goto step;
case PM_QUESTION:
step:
nh = nl = -1;
@@ -538,7 +548,7 @@ as_path_match(struct adata *path, struct f_path_mask *mask)
if (pos[i].mark)
{
pos[i].mark = 0;
- if ((mask->kind == PM_QUESTION) || pm_match(pos + i, val))
+ if ((mask->kind == PM_QUESTION) || pm_match(pos + i, val, val2))
pm_mark(pos, i, plen, &nl, &nh);
}
diff --git a/nest/attrs.h b/nest/attrs.h
index 0171c6a8..670b048f 100644
--- a/nest/attrs.h
+++ b/nest/attrs.h
@@ -45,11 +45,13 @@ struct adata *as_path_filter(struct linpool *pool, struct adata *path, struct f_
#define PM_QUESTION 1
#define PM_ASTERISK 2
#define PM_ASN_EXPR 3
+#define PM_ASN_RANGE 4
struct f_path_mask {
struct f_path_mask *next;
int kind;
uintptr_t val;
+ uintptr_t val2;
};
int as_path_match(struct adata *path, struct f_path_mask *mask);