[prev in list] [next in list] [prev in thread] [next in thread]
List: bird-users
Subject: operator to prepend bgp path multiple times
From: Alexander Zubkov <green () qrator ! net>
Date: 2022-01-01 19:24:00
Message-ID: CABr+u0b=9CYKrt4uaNcwG6dHfmgVJLkTDjgE5qP2M9jF8S0Mnw () mail ! gmail ! com
[Download RAW message or body]
Hi,
I suggest to add a new operator: prepend_times(P, A, N) - that will
allow to prepend AS A to path P several times (N). Now we need to use
some function like this:
function add_prepends(int asn, int num) {
if num = 1 then {
bgp_path.prepend(asn);
} else if num = 2 then {
bgp_path.prepend(asn);
bgp_path.prepend(asn);
} else if num = 3 then {
...
}
Usually the number of prepends is observable, so this function can fit
most of cases, but with available operator it will be a bit more
convenient, a little syntactic sugar. But it is not something that is
hard to live without, of course.
In my patch, I chose to "join" implementations of prepend() and
prepend_times(). It is questionable, because it requires some
additional supporting stuff if I understood right. So may be it is
better to implement it as separate operators.
["bird-prepend-times.patch" (text/x-patch)]
commit 876c19f58a5814241bd5110f6cd2f6889a581691
Author: Alexander Zubkov <green@qrator.net>
Date: Sat Jan 1 06:05:45 2022 +0100
Filter: add operator to prepend bgppath multiple times
New operator allows to prepend ASN A to path P N times:
prepend_times(P, A, N)
P.prepend_times(A, N)
diff --git a/filter/config.Y b/filter/config.Y
index 8916ea97..78228a1f 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -22,6 +22,12 @@ static inline u32 pair_b(u32 p) { return p & 0xFFFF; }
#define f_generate_complex(fi_code, da, arg) \
f_new_inst(FI_EA_SET, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg), da)
+#define f_generate_complex2(fi_code, da, arg1, arg2) \
+ f_new_inst(FI_EA_SET, f_new_inst(fi_code, f_new_inst(FI_EA_GET, da), arg1, arg2), \
da) +
+#define f_new_int_const(arg) \
+ f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = arg, })
+
/*
* Sets and their items are during parsing handled as lists, linked
* through left ptr. The first item in a list also contains a pointer
@@ -286,7 +292,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
DATA, DATA1, DATA2,
DEFINED,
ADD, DELETE, CONTAINS, RESET,
- PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
+ PREPEND, PREPEND_TIMES, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
MIN, MAX,
EMPTY,
FILTER, WHERE, EVAL, ATTRIBUTE,
@@ -816,7 +822,8 @@ term:
| '-' EMPTY '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_clist); }
| '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_CONSTANT, f_const_empty_eclist); }
| '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_CONSTANT, \
f_const_empty_lclist); }
- | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND, $3, $5); }
+ | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND, $3, $5, \
f_new_int_const(1)); } + | PREPEND_TIMES '(' term ',' term ',' term ')' { $$ = \
f_new_inst(FI_PATH_PREPEND, $3, $5, $7); } | ADD '(' term ',' term ')' { $$ = \
f_new_inst(FI_CLIST_ADD, $3, $5); } | DELETE '(' term ',' term ')' { $$ = \
f_new_inst(FI_CLIST_DEL, $3, $5); } | FILTER '(' term ',' term ')' { $$ = \
f_new_inst(FI_CLIST_FILTER, $3, $5); } @@ -908,7 +915,8 @@ cmd:
}
| dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($1); }
- | dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( \
FI_PATH_PREPEND, $1, $5 ); } + | dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = \
f_generate_complex2( FI_PATH_PREPEND, $1, $5, f_new_int_const(1) ); } + | \
dynamic_attr '.' PREPEND_TIMES '(' term ',' term ')' ';' { $$ = \
f_generate_complex2( FI_PATH_PREPEND, $1, $5, $7 ); } | dynamic_attr '.' ADD '(' \
term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD, $1, $5 ); } | \
dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_DEL, \
$1, $5 ); } | dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( \
FI_CLIST_FILTER, $1, $5 ); }
diff --git a/filter/f-inst.c b/filter/f-inst.c
index 901d2939..5974f343 100644
--- a/filter/f-inst.c
+++ b/filter/f-inst.c
@@ -1143,10 +1143,15 @@
ipa_from_ip6(ip6_and(ipa_to_ip6(v1.val.ip), ip6_mkmask(v2.val.i))) ]]);
}
- INST(FI_PATH_PREPEND, 2, 1) { /* Path prepend */
+ INST(FI_PATH_PREPEND, 3, 1) { /* Path prepend */
ARG(1, T_PATH);
ARG(2, T_INT);
- RESULT(T_PATH, ad, [[ as_path_prepend(fpool, v1.val.ad, v2.val.i) ]]);
+ ARG(3, T_INT);
+ struct adata *path = v1.val.ad;
+ for (int i = 0; i < v3.val.i; ++i) {
+ path = as_path_prepend(fpool, path, v2.val.i);
+ }
+ RESULT(T_PATH, ad, path);
}
INST(FI_CLIST_ADD, 2, 1) { /* (Extended) Community list add */
diff --git a/filter/test.conf b/filter/test.conf
index 6a28e4b3..2a64792f 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -665,6 +665,14 @@ int set set12;
bt_assert(delete(p2, [4..5]) = prepend(prepend(prepend(prepend(+empty+, 3), 3), 2), \
1));
bt_assert(format([= 1 2+ 3 =]) = "[= 1 2 + 3 =]");
+
+ p2 = prepend_times( + empty +, 1, 3 );
+ p2 = prepend_times( p2, 2, 2 );
+ p2 = prepend_times( p2, 3, 0 );
+ p2 = prepend_times( p2, 4, 1 );
+
+ bt_assert(format(p2) = "(path 4 2 2 1 1 1)");
+ bt_assert(p2.len = 6);
}
bt_test_suite(t_path, "Testing paths");
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic