Filter: Add operators to pick community components

Add operators that can be used to pick components from
pair (standard community) or lc (large community) types.
For example:

(10, 20).asn --> 10
(10, 20).data --> 20

(10, 20, 30).asn --> 10
(10, 20, 30).data1 --> 20
(10, 20, 30).data2 --> 30

Signed-off-by: Alexander Zubkov <green@qrator.net>
This commit is contained in:
Alexander Zubkov 2021-12-28 03:46:13 +01:00 committed by Ondrej Zajicek (work)
parent a39cd2cc0b
commit a2a268da4f
3 changed files with 53 additions and 8 deletions

View file

@ -283,6 +283,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
ROA_CHECK, ASN, SRC, DST,
IS_V4, IS_V6,
LEN, MAXLEN,
DATA, DATA1, DATA2,
DEFINED,
ADD, DELETE, CONTAINS, RESET,
PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
@ -789,13 +790,16 @@ term:
| term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER, $1); }
| term '.' LEN { $$ = f_new_inst(FI_LENGTH, $1); }
| term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN, $1); }
| term '.' ASN { $$ = f_new_inst(FI_ROA_ASN, $1); }
| term '.' ASN { $$ = f_new_inst(FI_ASN, $1); }
| term '.' SRC { $$ = f_new_inst(FI_NET_SRC, $1); }
| term '.' DST { $$ = f_new_inst(FI_NET_DST, $1); }
| term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK, $1, $5); }
| term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST, $1); }
| term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST, $1); }
| term '.' LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG, $1); }
| term '.' DATA { $$ = f_new_inst(FI_PAIR_DATA, $1); }
| term '.' DATA1 { $$ = f_new_inst(FI_LC_DATA1, $1); }
| term '.' DATA2 { $$ = f_new_inst(FI_LC_DATA2, $1); }
/* Communities */
/* This causes one shift/reduce conflict

View file

@ -910,14 +910,31 @@
((net_addr_roa6 *) v1.val.net)->max_pxlen);
}
INST(FI_ROA_ASN, 1, 1) { /* Get ROA ASN */
ARG(1, T_NET);
if (!net_is_roa(v1.val.net))
runtime( "ROA expected" );
INST(FI_ASN, 1, 1) { /* Get ROA ASN or community ASN part */
ARG_ANY(1);
RESULT_TYPE(T_INT);
switch(v1.type)
{
case T_NET:
if (!net_is_roa(v1.val.net))
runtime( "ROA expected" );
RESULT(T_INT, i, (v1.val.net->type == NET_ROA4) ?
((net_addr_roa4 *) v1.val.net)->asn :
((net_addr_roa6 *) v1.val.net)->asn);
RESULT_(T_INT, i, (v1.val.net->type == NET_ROA4) ?
((net_addr_roa4 *) v1.val.net)->asn :
((net_addr_roa6 *) v1.val.net)->asn);
break;
case T_PAIR:
RESULT_(T_INT, i, v1.val.i >> 16);
break;
case T_LC:
RESULT_(T_INT, i, v1.val.lc.asn);
break;
default:
runtime( "Net, pair or lc expected" );
}
}
INST(FI_IP, 1, 1) { /* Convert prefix to ... */
@ -951,6 +968,21 @@
RESULT(T_INT, i, as_path_get_last_nonaggregated(v1.val.ad));
}
INST(FI_PAIR_DATA, 1, 1) { /* Get data part from the standard community */
ARG(1, T_PAIR);
RESULT(T_INT, i, v1.val.i & 0xFFFF);
}
INST(FI_LC_DATA1, 1, 1) { /* Get data1 part from the large community */
ARG(1, T_LC);
RESULT(T_INT, i, v1.val.lc.ldp1);
}
INST(FI_LC_DATA2, 1, 1) { /* Get data2 part from the large community */
ARG(1, T_LC);
RESULT(T_INT, i, v1.val.lc.ldp2);
}
INST(FI_RETURN, 1, 1) {
NEVER_CONSTANT;
/* Acquire the return value */

View file

@ -684,6 +684,11 @@ clist l;
clist l2;
clist r;
{
bt_assert((10, 20).asn = 10);
bt_assert((10, 20).data = 20);
bt_assert(p23.asn = 2);
bt_assert(p23.data = 3);
l = - empty -;
bt_assert(l !~ [(*,*)]);
bt_assert((l ~ [(*,*)]) != (l !~ [(*,*)]));
@ -940,6 +945,10 @@ lclist r;
bt_assert(---empty--- = ---empty---);
bt_assert((10, 20, 30) !~ ---empty---);
bt_assert((10, 20, 30).asn = 10);
bt_assert((10, 20, 30).data1 = 20);
bt_assert((10, 20, 30).data2 = 30);
ll = --- empty ---;
ll = add(ll, (ten, 20, 30));
ll = add(ll, (1000, 2000, 3000));