Filter: Implement last_nonaggregated operator on bgp_path
This commit is contained in:
parent
c2106b674c
commit
9c9cc35c02
5 changed files with 45 additions and 3 deletions
|
@ -1119,9 +1119,12 @@ foot).
|
|||
|
||||
<cf><m/P/.last</cf> returns the last ASN (the source ASN) in path <m/P/.
|
||||
|
||||
<cf><m/P/.last_nonaggregated</cf> returns the last ASN in the non-aggregated part of the path <m/P/.
|
||||
|
||||
Both <cf/first/ and <cf/last/ return zero if there is no appropriate
|
||||
ASN, for example if the path contains an AS set element as the first (or
|
||||
the last) part.
|
||||
the last) part. If the path ends with an AS set, <cf/last_nonaggregated/
|
||||
may be used to get last ASN before any AS set.
|
||||
|
||||
<cf><m/P/.len</cf> returns the length of path <m/P/.
|
||||
|
||||
|
|
|
@ -283,7 +283,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
|||
LEN,
|
||||
DEFINED,
|
||||
ADD, DELETE, CONTAINS, RESET,
|
||||
PREPEND, FIRST, LAST, MATCH,
|
||||
PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
|
||||
ROA_CHECK,
|
||||
EMPTY,
|
||||
FILTER, WHERE, EVAL)
|
||||
|
@ -752,6 +752,7 @@ term:
|
|||
| term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
|
||||
| term '.' FIRST { $$ = f_new_inst(); $$->code = P('a','f'); $$->a1.p = $1; }
|
||||
| term '.' LAST { $$ = f_new_inst(); $$->code = P('a','l'); $$->a1.p = $1; }
|
||||
| term '.' LAST_NONAGGREGATED { $$ = f_new_inst(); $$->code = P('a','L'); $$->a1.p = $1; }
|
||||
|
||||
/* Communities */
|
||||
/* This causes one shift/reduce conflict
|
||||
|
|
|
@ -1091,6 +1091,14 @@ interpret(struct f_inst *what)
|
|||
res.type = T_INT;
|
||||
res.val.i = as;
|
||||
break;
|
||||
case P('a','L'): /* Get last ASN from non-aggregated part of AS PATH */
|
||||
ONEARG;
|
||||
if (v1.type != T_PATH)
|
||||
runtime( "AS path expected" );
|
||||
|
||||
res.type = T_INT;
|
||||
res.val.i = as_path_get_last_nonaggregated(v1.val.ad);
|
||||
break;
|
||||
case 'r':
|
||||
ONEARG;
|
||||
res = v1;
|
||||
|
|
|
@ -220,7 +220,7 @@ as_path_get_last(struct adata *path, u32 *orig_as)
|
|||
p += BS * len;
|
||||
}
|
||||
break;
|
||||
default: bug("as_path_get_first: Invalid path segment");
|
||||
default: bug("Invalid path segment");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,6 +229,35 @@ as_path_get_last(struct adata *path, u32 *orig_as)
|
|||
return found;
|
||||
}
|
||||
|
||||
u32
|
||||
as_path_get_last_nonaggregated(struct adata *path)
|
||||
{
|
||||
u8 *p = path->data;
|
||||
u8 *q = p+path->length;
|
||||
u32 res = 0;
|
||||
int len;
|
||||
|
||||
while (p<q)
|
||||
{
|
||||
switch (*p++)
|
||||
{
|
||||
case AS_PATH_SET:
|
||||
return res;
|
||||
|
||||
case AS_PATH_SEQUENCE:
|
||||
if (len = *p++)
|
||||
res = get_as(p + BS * (len - 1));
|
||||
p += BS * len;
|
||||
break;
|
||||
|
||||
default: bug("Invalid path segment");
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
as_path_get_first(struct adata *path, u32 *last_as)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,7 @@ int as_path_getlen(struct adata *path);
|
|||
int as_path_getlen_int(struct adata *path, int bs);
|
||||
int as_path_get_first(struct adata *path, u32 *orig_as);
|
||||
int as_path_get_last(struct adata *path, u32 *last_as);
|
||||
u32 as_path_get_last_nonaggregated(struct adata *path);
|
||||
int as_path_contains(struct adata *path, u32 as, int min);
|
||||
int as_path_match_set(struct adata *path, struct f_tree *set);
|
||||
struct adata *as_path_filter(struct linpool *pool, struct adata *path, struct f_tree *set, u32 key, int pos);
|
||||
|
|
Loading…
Reference in a new issue