From b2d6d2948af268812a8f55f260d340194eb3f7ac Mon Sep 17 00:00:00 2001 From: Alexander Zubkov Date: Fri, 4 Mar 2022 14:07:58 +0100 Subject: Filter: Add literal for empty set Add literal for empty set [], which works both for tree-based sets and prefix sets by using existing constant promotion mechanism. Minor changes by committer. --- filter/data.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'filter/data.c') diff --git a/filter/data.c b/filter/data.c index 56c1fb17..276738a9 100644 --- a/filter/data.c +++ b/filter/data.c @@ -79,6 +79,8 @@ f_type_element_type(enum f_type t) }; } +const struct f_trie f_const_empty_trie = { .ipv4 = -1, }; + const struct f_val f_const_empty_path = { .type = T_PATH, .val.ad = &null_adata, @@ -91,6 +93,9 @@ const struct f_val f_const_empty_path = { }, f_const_empty_lclist = { .type = T_LCLIST, .val.ad = &null_adata, +}, f_const_empty_prefix_set = { + .type = T_PREFIX_SET, + .val.ti = &f_const_empty_trie, }; static struct adata * @@ -301,6 +306,12 @@ val_same(const struct f_val *v1, const struct f_val *v2) int clist_set_type(const struct f_tree *set, struct f_val *v) { + if (!set) + { + v->type = T_VOID; + return 1; + } + switch (set->from.type) { case T_PAIR: @@ -537,6 +548,9 @@ val_in_range(const struct f_val *v1, const struct f_val *v2) if (v2->type != T_SET) return F_CMP_ERROR; + if (!v2->val.t) + return 0; + /* With integrated Quad<->IP implicit conversion */ if ((v1->type == v2->val.t->from.type) || ((v1->type == T_QUAD) && val_is_ip4(&(v2->val.t->from)) && val_is_ip4(&(v2->val.t->to)))) -- cgit v1.2.3 From fb1d8f65136aa6190b527b691f24abe16a461471 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Fri, 4 Mar 2022 17:51:50 +0100 Subject: Filter: Apply constant promotion for FI_EQ / FI_NEQ Equality comparison is defined on all values, even of different types, but we still want to do constant promotion if possible. --- filter/data.c | 2 +- filter/decl.m4 | 6 ++++++ filter/f-inst.c | 2 ++ filter/test.conf | 8 ++++---- 4 files changed, 13 insertions(+), 5 deletions(-) (limited to 'filter/data.c') diff --git a/filter/data.c b/filter/data.c index 276738a9..2bb5920c 100644 --- a/filter/data.c +++ b/filter/data.c @@ -192,7 +192,7 @@ val_compare(const struct f_val *v1, const struct f_val *v2) if (val_is_ip4(v1) && (v2->type == T_QUAD)) return uint_cmp(ipa_to_u32(v1->val.ip), v2->val.i); - debug( "Types do not match in val_compare\n" ); + DBG( "Types do not match in val_compare\n" ); return F_CMP_ERROR; } diff --git a/filter/decl.m4 b/filter/decl.m4 index fc26e193..a2a8c88a 100644 --- a/filter/decl.m4 +++ b/filter/decl.m4 @@ -186,6 +186,12 @@ if (f$1->type && f$2->type && (f$1->type != f$2->type) && cf_error("Arguments $1 and $2 of %s must be of the same type", f_instruction_name(what->fi_code)); FID_INTERPRET_BODY()') +m4_define(ARG_PREFER_SAME_TYPE, ` +FID_NEW_BODY()m4_dnl +if (f$1->type && f$2->type && (f$1->type != f$2->type)) + (void) (f_const_promotion(f$2, f$1->type) || f_const_promotion(f$1, f$2->type)); +FID_INTERPRET_BODY()') + # Executing another filter line. This replaces the recursion # that was needed in the former implementation. m4_define(LINEX, `FID_INTERPRET_EXEC()LINEX_($1)FID_INTERPRET_NEW()return $1 FID_INTERPRET_BODY()') diff --git a/filter/f-inst.c b/filter/f-inst.c index d321f06d..500732c6 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -423,12 +423,14 @@ INST(FI_NEQ, 2, 1) { ARG_ANY(1); ARG_ANY(2); + ARG_PREFER_SAME_TYPE(1, 2); RESULT(T_BOOL, i, !val_same(&v1, &v2)); } INST(FI_EQ, 2, 1) { ARG_ANY(1); ARG_ANY(2); + ARG_PREFER_SAME_TYPE(1, 2); RESULT(T_BOOL, i, val_same(&v1, &v2)); } diff --git a/filter/test.conf b/filter/test.conf index 50c58b3a..401a999b 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -498,8 +498,8 @@ prefix set s1; s0 = []; s1 = []; bt_assert(pxs != s0); - bt_assert(pxs = s1); - #bt_assert(pxs = []); + bt_assert(pxs = s1); + bt_assert(pxs = []); } function t_prefix_set() @@ -507,7 +507,7 @@ prefix set pxs; { pxs = []; bt_assert(format(pxs) = "[]"); - #bt_assert(pxs = []); + bt_assert(pxs = []); bt_assert(1.2.0.0/16 !~ []); bt_assert(1.2.0.0/16 !~ pxs); @@ -600,7 +600,7 @@ prefix set pxs; { pxs = []; bt_assert(format(pxs) = "[]"); - #bt_assert(pxs = []); + bt_assert(pxs = []); bt_assert(12::34/128 !~ []); bt_assert(12::34/128 !~ pxs); -- cgit v1.2.3 From cb339a30677901f2c248de08ff535cf0a9efab3d Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Mon, 14 Mar 2022 20:36:20 +0100 Subject: Filter: Implement for loops For loops allow to iterate over elements in compound data like BGP paths or community lists. The syntax is: for [ ] in do --- doc/bird.sgml | 26 ++++++++++++---- filter/config.Y | 21 ++++++++++++- filter/data.c | 1 + filter/f-inst.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ filter/test.conf | 40 +++++++++++++++++++++++- nest/a-path.c | 29 ++++++++++++++++++ nest/a-set.c | 48 +++++++++++++++++++++++++++++ nest/attrs.h | 4 +++ 8 files changed, 254 insertions(+), 8 deletions(-) (limited to 'filter/data.c') diff --git a/doc/bird.sgml b/doc/bird.sgml index f933128c..89b1541c 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1683,7 +1683,8 @@ prefix and an ASN as arguments. Control structures