Commit 9c9cc35c authored by Ondřej Zajíček's avatar Ondřej Zajíček

Filter: Implement last_nonaggregated operator on bgp_path

parent c2106b67
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment