diff --git a/filter/decl.m4 b/filter/decl.m4 index 5242c04c..75e65212 100644 --- a/filter/decl.m4 +++ b/filter/decl.m4 @@ -494,6 +494,15 @@ f_const_promotion(struct f_inst *arg, enum f_type want) }; return 1; } + else if ((c->type == T_SET) && (want == T_PREFIX_SET)) { + if (c->val.t) + return 0; + *c = (struct f_val) { + .type = T_PREFIX_SET, + .val.ti = f_new_trie(cfg_mem, 0), + }; + return 1; + } return 0; } diff --git a/filter/f-inst.c b/filter/f-inst.c index b1d14b9d..999b7fc7 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -983,7 +983,7 @@ RESULT(T_INT, i, v1.val.lc.ldp2); } - INST(FI_MIN, 1, 1) { /* Get minimum element from set */ + INST(FI_MIN, 1, 1) { /* Get minimum element from list */ ARG_ANY(1); RESULT_TYPE(f_type_element_type(v1.type)); switch(v1.type) @@ -1017,7 +1017,7 @@ } } - INST(FI_MAX, 1, 1) { /* Get maximum element from set */ + INST(FI_MAX, 1, 1) { /* Get maximum element from list */ ARG_ANY(1); RESULT_TYPE(f_type_element_type(v1.type)); switch(v1.type) @@ -1215,15 +1215,18 @@ { const struct f_tree *set = NULL; u32 key = 0; + int use_set = 0; if (v2.type == T_INT) key = v2.val.i; - else if ((v2.type == T_SET) && path_set_type(v2.val.t)) + else if ((v2.type == T_SET) && path_set_type(v2.val.t)) { + use_set = 1; set = v2.val.t; + } else runtime("Can't delete non-integer (set)"); - RESULT_(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, set, key, 0) ]]); + RESULT_(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, set, key, use_set, 0) ]]); } else if (v1.type == T_CLIST) @@ -1275,12 +1278,20 @@ if (v1.type == T_PATH) { + const struct f_tree *set = NULL; u32 key = 0; + int use_set = 0; - if ((v2.type == T_SET) && path_set_type(v2.val.t)) - RESULT_(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, v2.val.t, key, 1) ]]); + if (v2.type == T_INT) + key = v2.val.i; + else if ((v2.type == T_SET) && path_set_type(v2.val.t)) { + use_set = 1; + set = v2.val.t; + } else - runtime("Can't filter integer"); + runtime("Can't filter non-integer (set)"); + + RESULT_(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, set, key, use_set, 1) ]]); } else if (v1.type == T_CLIST) diff --git a/filter/test.conf b/filter/test.conf index c0fe4e70..65c680cd 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -131,6 +131,13 @@ define is3 = [5, 17, 2, 11, 8, 15, 3, 19]; function t_int_set() int set is; { + bt_assert([] = empty_set); + is = []; + is = empty_set; + bt_assert(is = empty_set); + bt_assert(is = []); + bt_assert(0 !~ is); + bt_assert(1 ~ [1,2,3]); bt_assert(5 ~ [1..20]); bt_assert(2 ~ [ 1, 2, 3 ]); @@ -139,6 +146,7 @@ int set is; bt_assert(999 !~ [ 666, 333 ]); bt_assert(1 !~ []); bt_assert(1 !~ empty_set); + bt_assert(1 !~ is); is = [ 2, 3, 4, 7..11 ]; bt_assert(10 ~ is); @@ -171,7 +179,6 @@ int set is; bt_assert([1,2] != [1,3]); bt_assert([1,4..10,20] = [1,4..10,20]); - bt_assert([] = empty_set); bt_assert(format([ 1, 2, 1, 1, 1, 3, 4, 1, 1, 1, 5 ]) = "[1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5]"); bt_assert(format([]) = "[]"); @@ -241,6 +248,9 @@ function t_pair_set() pair pp; pair set ps; { + ps = []; + ps = empty_set; + pp = (1, 2); ps = [(1,(one+one)), (3,4)..(4,8), (5,*), (6,3..6)]; bt_assert(format(ps) = "[(1,2), (3,4)..(4,8), (5,0)..(5,65535), (6,3)..(6,6)]"); @@ -381,6 +391,9 @@ define ip1222 = 1.2.2.2; function t_ip_set() ip set ips; { + ips = []; + ips = empty_set; + ips = [ 1.1.1.0 .. 1.1.1.255, ip1222]; bt_assert(format(ips) = "[1.1.1.0..1.1.1.255, 1.2.2.2]"); bt_assert(1.1.1.0 ~ ips); @@ -493,6 +506,15 @@ function test_pxset(prefix set pxs) function t_prefix_set() prefix set pxs; { + pxs = []; + pxs = empty_set; + bt_assert(format(pxs) = "[]"); + #bt_assert(pxs = []); + #bt_assert(pxs = empty_set); + bt_assert(1.2.0.0/16 !~ []); + bt_assert(1.2.0.0/16 !~ empty_set); + bt_assert(1.2.0.0/16 !~ pxs); + pxs = [ 1.2.0.0/16, 1.4.0.0/16+, 44.66.88.64/30{24,28}, 12.34.56.0/24{8,16} ]; bt_assert(format(pxs) = "[1.2.0.0/16{0.1.0.0}, 1.4.0.0/16{0.1.255.255}, 12.34.0.0/16{1.255.0.0}, 44.66.88.64/28{0.0.1.240}]"); @@ -577,6 +599,15 @@ bt_test_suite(t_prefix6, "Testing prefix IPv6"); function t_prefix6_set() prefix set pxs; { + pxs = []; + pxs = empty_set; + bt_assert(format(pxs) = "[]"); + #bt_assert(pxs = []); + #bt_assert(pxs = empty_set); + bt_assert(12::34/128 !~ []); + bt_assert(12::34/128 !~ empty_set); + bt_assert(12::34/128 !~ pxs); + bt_assert(1180::/16 ~ [ 1100::/8{15, 17} ]); bt_assert(12::34 = 12::34); bt_assert(12::34 ~ [ 12::33..12::35 ]); @@ -586,8 +617,6 @@ prefix set pxs; bt_assert(12::34 !~ [ 12::33, 12::35 ]); bt_assert(1000::/9 !~ [ 1000::/8- ]); bt_assert(1000::/17 !~ [ 1000::/8{15, 16} ]); - bt_assert(12::34 !~ []); - bt_assert(12::34 !~ empty_set); pxs = [ 1102::/16, 1104::/16+]; bt_assert(1102::/16 ~ pxs); @@ -711,8 +740,6 @@ int set set12; bt_assert(p2 ~ [= * [3] * =]); bt_assert(p2 !~ [= * [] * =]); bt_assert(p2 !~ [= * empty_set * =]); - #bt_assert(delete(prepend(prepend(+empty+, 0), 1), []) = prepend(+empty+, 1)); - #bt_assert(filter(prepend(prepend(+empty+, 0), 1), []) = prepend(+empty+, 0)); bt_assert(p2.len = 5); bt_assert(p2.first = 5); @@ -723,6 +750,8 @@ int set set12; bt_assert(filter(p2, [1..3]) = prepend(prepend(prepend(+empty+, 1), 2), 3)); bt_assert(delete(p2, []) = p2); bt_assert(filter(p2, []) = +empty+); + bt_assert(delete(prepend(prepend(+empty+, 0), 1), []) = prepend(prepend(+empty+, 0), 1)); + bt_assert(filter(prepend(prepend(+empty+, 0), 1), []) = +empty+); p2 = prepend( + empty +, 5 ); p2 = prepend( p2, 4 ); @@ -1189,6 +1218,12 @@ bt_test_suite(t_rd, "Testing route distinguishers"); function t_rd_set() rd set rds; { + rds = []; + rds = empty_set; + bt_assert(rds = []); + bt_assert(rds = empty_set); + bt_assert(10:20 !~ rds); + rds = [10:20, 100000:100..100000:200]; bt_assert(format(rds) = "[10:20, 100000:100..100000:200]"); diff --git a/nest/a-path.c b/nest/a-path.c index 2e34a3d1..ed4457b0 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -602,7 +602,7 @@ as_path_match_set(const struct adata *path, const struct f_tree *set) } const struct adata * -as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tree *set, u32 key, int pos) +as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tree *set, u32 key, int use_set, int pos) { if (!path) return NULL; @@ -629,7 +629,7 @@ as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tr u32 as = get_as(p); int match; - if (set) + if (use_set) { struct f_val v = {T_INT, .val.i = as}; match = !!find_tree(set, &v); diff --git a/nest/a-path_test.c b/nest/a-path_test.c index 9ed0a786..e02c6fd0 100644 --- a/nest/a-path_test.c +++ b/nest/a-path_test.c @@ -136,8 +136,8 @@ t_path_include(void) int counts_of_contains = count_asn_in_array(as_nums, as_nums[i]); bt_assert_msg(as_path_contains(as_path, as_nums[i], counts_of_contains), "AS Path should contains %d-times number %d", counts_of_contains, as_nums[i]); - bt_assert(as_path_filter(lp, as_path, NULL, as_nums[i], 0) != NULL); - bt_assert(as_path_filter(lp, as_path, NULL, as_nums[i], 1) != NULL); + bt_assert(as_path_filter(lp, as_path, NULL, as_nums[i], 0, 0) != NULL); + bt_assert(as_path_filter(lp, as_path, NULL, as_nums[i], 0, 1) != NULL); } for (i = 0; i < 10000; i++) diff --git a/nest/attrs.h b/nest/attrs.h index ef2b95e6..c92a8826 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -49,7 +49,7 @@ int as_path_get_last(const struct adata *path, u32 *last_as); u32 as_path_get_last_nonaggregated(const struct adata *path); int as_path_contains(const struct adata *path, u32 as, int min); int as_path_match_set(const struct adata *path, const struct f_tree *set); -const struct adata *as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tree *set, u32 key, int pos); +const struct adata *as_path_filter(struct linpool *pool, const struct adata *path, const struct f_tree *set, u32 key, int use_set, int pos); static inline struct adata *as_path_prepend(struct linpool *pool, const struct adata *path, u32 as) { return as_path_prepend2(pool, path, AS_PATH_SEQUENCE, as); }