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

Filter: Implement last_nonaggregated operator on bgp_path

parent c2106b67
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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/.

+2 −1
Original line number Diff line number Diff line
@@ -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
+8 −0
Original line number Diff line number Diff line
@@ -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;
+30 −1
Original line number Diff line number Diff line
@@ -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)
{
+1 −0
Original line number Diff line number Diff line
@@ -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);