2 * Filters: Utility Functions Tests
4 * (c) 2015 CZ.NIC z.s.p.o.
6 * Can be freely distributed and used under the terms of the GNU GPL.
9 #include "test/birdtest.h"
10 #include "test/bt-utils.h"
12 #include "filter/filter.h"
13 #include "filter/data.h"
14 #include "conf/conf.h"
17 #define PREFIXES_NUM 32
18 #define PREFIX_TESTS_NUM 10000
19 #define PREFIX_BENCH_NUM 100000000
21 #define TRIE_BUFFER_SIZE 1024
22 #define TEST_BUFFER_SIZE (1024*1024)
23 #define BIG_BUFFER_SIZE 10000
25 /* Wrapping structure for storing f_prefixes structures in list */
26 struct f_prefix_node
{
28 struct f_prefix prefix
;
34 return (bt_random() % max
);
42 for (r
= bt_random(); r
& 1; r
= r
>> 1)
49 compare_prefixes(const void *a
, const void *b
)
51 return net_compare(&((const struct f_prefix
*) a
)->net
,
52 &((const struct f_prefix
*) b
)->net
);
56 matching_ip4_nets(const net_addr_ip4
*a
, const net_addr_ip4
*b
)
58 ip4_addr cmask
= ip4_mkmask(MIN(a
->pxlen
, b
->pxlen
));
59 return ip4_compare(ip4_and(a
->prefix
, cmask
), ip4_and(b
->prefix
, cmask
)) == 0;
63 matching_ip6_nets(const net_addr_ip6
*a
, const net_addr_ip6
*b
)
65 ip6_addr cmask
= ip6_mkmask(MIN(a
->pxlen
, b
->pxlen
));
66 return ip6_compare(ip6_and(a
->prefix
, cmask
), ip6_and(b
->prefix
, cmask
)) == 0;
70 matching_nets(const net_addr
*a
, const net_addr
*b
)
72 if (a
->type
!= b
->type
)
75 return (a
->type
== NET_IP4
) ?
76 matching_ip4_nets((const net_addr_ip4
*) a
, (const net_addr_ip4
*) b
) :
77 matching_ip6_nets((const net_addr_ip6
*) a
, (const net_addr_ip6
*) b
);
81 is_prefix_included(list
*prefixes
, const net_addr
*needle
)
83 struct f_prefix_node
*n
;
84 WALK_LIST(n
, *prefixes
)
85 if (matching_nets(&n
->prefix
.net
, needle
) &&
86 (n
->prefix
.lo
<= needle
->pxlen
) && (needle
->pxlen
<= n
->prefix
.hi
))
89 bt_format_net(buf
, 64, &n
->prefix
.net
);
90 bt_debug("FOUND %s %d-%d\n", buf
, n
->prefix
.lo
, n
->prefix
.hi
);
99 get_random_net(net_addr
*net
, int v6
)
103 uint pxlen
= xrandom(24)+8;
104 ip4_addr ip4
= ip4_from_u32((u32
) bt_random());
105 net_fill_ip4(net
, ip4_and(ip4
, ip4_mkmask(pxlen
)), pxlen
);
109 uint pxlen
= xrandom(120)+8;
110 ip6_addr ip6
= ip6_build(bt_random(), bt_random(), bt_random(), bt_random());
111 net_fill_ip6(net
, ip6_and(ip6
, ip6_mkmask(pxlen
)), pxlen
);
116 get_random_prefix(struct f_prefix
*px
, int v6
, int tight
)
118 get_random_net(&px
->net
, v6
);
122 px
->lo
= px
->hi
= px
->net
.pxlen
;
124 else if (bt_random() % 2)
127 px
->hi
= px
->net
.pxlen
;
131 px
->lo
= px
->net
.pxlen
;
132 px
->hi
= net_max_prefix_length
[px
->net
.type
];
137 get_random_ip4_subnet(net_addr_ip4
*net
, const net_addr_ip4
*src
, int pxlen
)
139 *net
= NET_ADDR_IP4(ip4_and(src
->prefix
, ip4_mkmask(pxlen
)), pxlen
);
141 if (pxlen
> src
->pxlen
)
143 ip4_addr rnd
= ip4_from_u32((u32
) bt_random());
144 ip4_addr mask
= ip4_xor(ip4_mkmask(src
->pxlen
), ip4_mkmask(pxlen
));
145 net
->prefix
= ip4_or(net
->prefix
, ip4_and(rnd
, mask
));
150 get_random_ip6_subnet(net_addr_ip6
*net
, const net_addr_ip6
*src
, int pxlen
)
152 *net
= NET_ADDR_IP6(ip6_and(src
->prefix
, ip6_mkmask(pxlen
)), pxlen
);
154 if (pxlen
> src
->pxlen
)
156 ip6_addr rnd
= ip6_build(bt_random(), bt_random(), bt_random(), bt_random());
157 ip6_addr mask
= ip6_xor(ip6_mkmask(src
->pxlen
), ip6_mkmask(pxlen
));
158 net
->prefix
= ip6_or(net
->prefix
, ip6_and(rnd
, mask
));
163 get_random_subnet(net_addr
*net
, const net_addr
*src
, int pxlen
)
165 if (src
->type
== NET_IP4
)
166 get_random_ip4_subnet((net_addr_ip4
*) net
, (const net_addr_ip4
*) src
, pxlen
);
168 get_random_ip6_subnet((net_addr_ip6
*) net
, (const net_addr_ip6
*) src
, pxlen
);
172 get_inner_net(net_addr
*net
, const struct f_prefix
*src
)
178 step
= get_exp_random();
179 step
= MIN(step
, src
->hi
- src
->lo
);
180 pxlen
= (bt_random() % 2) ? (src
->lo
+ step
) : (src
->hi
- step
);
183 pxlen
= src
->lo
+ bt_random() % (src
->hi
- src
->lo
+ 1);
185 get_random_subnet(net
, &src
->net
, pxlen
);
189 swap_random_bits_ip4(net_addr_ip4
*net
, int num
)
191 for (int i
= 0; i
< num
; i
++)
193 ip4_addr swap
= IP4_NONE
;
194 ip4_setbit(&swap
, bt_random() % net
->pxlen
);
195 net
->prefix
= ip4_xor(net
->prefix
, swap
);
200 swap_random_bits_ip6(net_addr_ip6
*net
, int num
)
202 for (int i
= 0; i
< num
; i
++)
204 ip6_addr swap
= IP6_NONE
;
205 ip6_setbit(&swap
, bt_random() % net
->pxlen
);
206 net
->prefix
= ip6_xor(net
->prefix
, swap
);
211 swap_random_bits(net_addr
*net
, int num
)
213 if (net
->type
== NET_IP4
)
214 swap_random_bits_ip4((net_addr_ip4
*) net
, num
);
216 swap_random_bits_ip6((net_addr_ip6
*) net
, num
);
220 get_outer_net(net_addr
*net
, const struct f_prefix
*src
)
224 int max
= net_max_prefix_length
[src
->net
.type
];
226 if ((src
->lo
> 0) && (bt_random() % 3))
228 step
= 1 + get_exp_random();
229 step
= MIN(step
, src
->lo
);
230 pxlen
= src
->lo
- step
;
232 else if ((src
->hi
< max
) && (bt_random() % 2))
234 step
= 1 + get_exp_random();
235 step
= MIN(step
, max
- src
->hi
);
236 pxlen
= src
->hi
+ step
;
240 pxlen
= src
->lo
+ bt_random() % (src
->hi
- src
->lo
+ 1);
244 get_random_subnet(net
, &src
->net
, pxlen
);
246 /* Perhaps swap some bits in prefix */
247 if ((net
->pxlen
> 0) && (inside
|| (bt_random() % 4)))
248 swap_random_bits(net
, 1 + get_exp_random());
252 make_random_prefix_list(linpool
*lp
, int num
, int v6
, int tight
)
254 list
*prefixes
= lp_allocz(lp
, sizeof(struct f_prefix_node
));
257 for (int i
= 0; i
< num
; i
++)
259 struct f_prefix_node
*px
= lp_allocz(lp
, sizeof(struct f_prefix_node
));
260 get_random_prefix(&px
->prefix
, v6
, tight
);
261 add_tail(prefixes
, &px
->n
);
264 bt_format_net(buf
, 64, &px
->prefix
.net
);
265 bt_debug("ADD %s{%d,%d}\n", buf
, px
->prefix
.lo
, px
->prefix
.hi
);
271 static struct f_trie
*
272 make_trie_from_prefix_list(linpool
*lp
, list
*prefixes
)
274 struct f_trie
*trie
= f_new_trie(lp
, 0);
276 struct f_prefix_node
*n
;
277 WALK_LIST(n
, *prefixes
)
278 trie_add_prefix(trie
, &n
->prefix
.net
, n
->prefix
.lo
, n
->prefix
.hi
);
284 * Read sequence of prefixes from file handle and return prefix list.
285 * Each prefix is on one line, sequence terminated by empty line or eof.
286 * Arg @plus means prefix should include all longer ones.
289 read_prefix_list(linpool
*lp
, FILE *f
, int v6
, int plus
)
293 uint a0
, a1
, a2
, a3
, pl
;
297 list
*pxlist
= lp_allocz(lp
, sizeof(struct f_prefix_node
));
301 while (fgets(s
, 32, f
))
306 n
= sscanf(s
, "%u.%u.%u.%u/%u", &a0
, &a1
, &a2
, &a3
, &pl
);
309 bt_abort_msg("Invalid content of trie_data");
311 struct f_prefix_node
*px
= lp_allocz(lp
, sizeof(struct f_prefix_node
));
312 net_fill_ip4(&px
->prefix
.net
, ip4_build(a0
, a1
, a2
, a3
), pl
);
314 px
->prefix
.hi
= plus
? IP4_MAX_PREFIX_LENGTH
: pl
;
315 add_tail(pxlist
, &px
->n
);
318 bt_format_net(buf
, 64, &px
->prefix
.net
);
319 bt_debug("ADD %s{%d,%d}\n", buf
, px
->prefix
.lo
, px
->prefix
.hi
);
322 bt_syscall(errno
, "fgets()");
323 return EMPTY_LIST(*pxlist
) ? NULL
: pxlist
;
327 * Open file, read multiple sequences of prefixes from it. Fill @data with
328 * prefix lists and @trie with generated tries. Return number of sequences /
329 * tries. Use separate linpool @lp0 for prefix lists and @lp1 for tries.
330 * Arg @plus means prefix should include all longer ones.
333 read_prefix_file(const char *filename
, int plus
,
334 linpool
*lp0
, linpool
*lp1
,
335 list
*data
[], struct f_trie
*trie
[])
337 FILE *f
= fopen(filename
, "r");
338 bt_syscall(!f
, "fopen(%s)", filename
);
342 while (pxlist
= read_prefix_list(lp0
, f
, 0, plus
))
345 trie
[n
] = make_trie_from_prefix_list(lp1
, pxlist
);
351 bt_debug("DONE reading %d tries\n", n
);
357 * Select random subset of @dn prefixes from prefix list @src of length @sn,
358 * and store them to buffer @dst (of size @dn). Prefixes may be chosen multiple
359 * times. Randomize order of prefixes in @dst buffer.
362 select_random_prefix_subset(list
*src
[], net_addr dst
[], int sn
, int dn
)
369 /* Compute total prefix number */
370 for (int i
= 0; i
< sn
; i
++)
371 pn
+= list_length(src
[i
]);
373 /* Change of selecting a prefix */
374 int rnd
= (pn
/ dn
) + 10;
377 /* Iterate indefinitely over src array */
378 for (int i
= 0; 1; i
++, i
= (i
< sn
) ? i
: 0)
380 struct f_prefix_node
*px
;
381 WALK_LIST(px
, *src
[i
])
383 if (xrandom(rnd
) != 0)
386 net_copy(&dst
[n
], &px
->prefix
.net
);
396 /* Shuffle networks */
397 for (int i
= 0; i
< dn
; i
++)
405 net_copy(&tmp
, &dst
[i
]);
406 net_copy(&dst
[i
], &dst
[j
]);
407 net_copy(&dst
[j
], &tmp
);
411 /* Fill @dst buffer with @dn randomly generated /32 prefixes */
413 make_random_addresses(net_addr dst
[], int dn
)
415 for (int i
= 0; i
< dn
; i
++)
416 net_fill_ip4(&dst
[i
], ip4_from_u32((u32
) bt_random()), IP4_MAX_PREFIX_LENGTH
);
420 test_match_net(list
*prefixes
, struct f_trie
*trie
, const net_addr
*net
)
423 bt_format_net(buf
, 64, net
);
424 bt_debug("TEST %s\n", buf
);
426 int should_be
= is_prefix_included(prefixes
, net
);
427 int is_there
= trie_match_net(trie
, net
);
429 bt_assert_msg(should_be
== is_there
, "Prefix %s %s match", buf
,
430 (should_be
? "should" : "should not"));
434 t_match_random_net(void)
437 bt_config_parse(BT_CONFIG_SIMPLE
);
440 linpool
*lp
= lp_new_default(&root_pool
);
441 for (int round
= 0; round
< TESTS_NUM
; round
++)
443 list
*prefixes
= make_random_prefix_list(lp
, PREFIXES_NUM
, v6
, 0);
444 struct f_trie
*trie
= make_trie_from_prefix_list(lp
, prefixes
);
446 for (int i
= 0; i
< PREFIX_TESTS_NUM
; i
++)
449 get_random_net(&net
, v6
);
450 test_match_net(prefixes
, trie
, &net
);
462 t_match_inner_net(void)
465 bt_config_parse(BT_CONFIG_SIMPLE
);
468 linpool
*lp
= lp_new_default(&root_pool
);
469 for (int round
= 0; round
< TESTS_NUM
; round
++)
471 list
*prefixes
= make_random_prefix_list(lp
, PREFIXES_NUM
, v6
, 0);
472 struct f_trie
*trie
= make_trie_from_prefix_list(lp
, prefixes
);
474 struct f_prefix_node
*n
= HEAD(*prefixes
);
475 for (int i
= 0; i
< PREFIX_TESTS_NUM
; i
++)
478 get_inner_net(&net
, &n
->prefix
);
479 test_match_net(prefixes
, trie
, &net
);
481 n
= NODE_VALID(NODE_NEXT(n
)) ? NODE_NEXT(n
) : HEAD(*prefixes
);
493 t_match_outer_net(void)
496 bt_config_parse(BT_CONFIG_SIMPLE
);
499 linpool
*lp
= lp_new_default(&root_pool
);
500 for (int round
= 0; round
< TESTS_NUM
; round
++)
502 list
*prefixes
= make_random_prefix_list(lp
, PREFIXES_NUM
, v6
, 0);
503 struct f_trie
*trie
= make_trie_from_prefix_list(lp
, prefixes
);
505 struct f_prefix_node
*n
= HEAD(*prefixes
);
506 for (int i
= 0; i
< PREFIX_TESTS_NUM
; i
++)
509 get_outer_net(&net
, &n
->prefix
);
510 test_match_net(prefixes
, trie
, &net
);
512 n
= NODE_VALID(NODE_NEXT(n
)) ? NODE_NEXT(n
) : HEAD(*prefixes
);
525 * Read prefixes from @filename, build set of tries, prepare test data and do
526 * PREFIX_BENCH_NUM trie lookups. With @plus = 0, use random subset of known
527 * prefixes as test data, with @plus = 1, use randomly generated /32 prefixes
531 benchmark_trie_dataset(const char *filename
, int plus
)
534 linpool
*lp0
= lp_new_default(&root_pool
);
535 linpool
*lp1
= lp_new_default(&root_pool
);
536 list
*data
[TRIE_BUFFER_SIZE
];
537 struct f_trie
*trie
[TRIE_BUFFER_SIZE
];
540 bt_reset_suite_case_timer();
541 bt_log_suite_case_result(1, "Reading %s", filename
, n
);
542 n
= read_prefix_file(filename
, plus
, lp0
, lp1
, data
, trie
);
543 bt_log_suite_case_result(1, "Read prefix data, %d lists, ", n
);
545 size_t trie_size
= rmemsize(lp1
).effective
* 1000 / (1024*1024);
546 bt_log_suite_case_result(1, "Trie size %u.%03u MB",
547 (uint
) (trie_size
/ 1000), (uint
) (trie_size
% 1000));
549 int t
= PREFIX_BENCH_NUM
/ n
;
550 int tb
= MIN(t
, TEST_BUFFER_SIZE
);
551 nets
= lp_alloc(lp0
, tb
* sizeof(net_addr
));
554 select_random_prefix_subset(data
, nets
, n
, tb
);
556 make_random_addresses(nets
, tb
);
558 bt_log_suite_case_result(1, "Make test data, %d (%d) tests", t
, tb
);
559 bt_reset_suite_case_timer();
563 for (int i = 0; i < t; i++)
564 for (int j = 0; j < n; j++)
565 test_match_net(data[j], trie[j], &nets[i]);
569 for (int i
= 0; i
< t
; i
++)
570 for (int j
= 0; j
< n
; j
++)
571 if (trie_match_net(trie
[j
], &nets
[i
% TEST_BUFFER_SIZE
]))
574 bt_log_suite_case_result(1, "Matching done, %d / %d matches", match
, t
* n
);
583 t_bench_trie_datasets_subset(void)
586 bt_config_parse(BT_CONFIG_SIMPLE
);
588 /* Specific datasets, not included */
589 benchmark_trie_dataset("trie-data-bgp-1", 0);
590 benchmark_trie_dataset("trie-data-bgp-10", 0);
591 benchmark_trie_dataset("trie-data-bgp-100", 0);
592 benchmark_trie_dataset("trie-data-bgp-1000", 0);
600 t_bench_trie_datasets_random(void)
603 bt_config_parse(BT_CONFIG_SIMPLE
);
605 /* Specific datasets, not included */
606 benchmark_trie_dataset("trie-data-bgp-1", 1);
607 benchmark_trie_dataset("trie-data-bgp-10", 1);
608 benchmark_trie_dataset("trie-data-bgp-100", 1);
609 benchmark_trie_dataset("trie-data-bgp-1000", 1);
621 bt_config_parse(BT_CONFIG_SIMPLE
);
624 linpool
*lp
= lp_new_default(&root_pool
);
625 for (int round
= 0; round
< TESTS_NUM
*4; round
++)
627 list
*prefixes
= make_random_prefix_list(lp
, 100 * PREFIXES_NUM
, v6
, 0);
628 struct f_trie
*trie1
= f_new_trie(lp
, 0);
629 struct f_trie
*trie2
= f_new_trie(lp
, 0);
631 struct f_prefix_node
*n
;
632 WALK_LIST(n
, *prefixes
)
633 trie_add_prefix(trie1
, &n
->prefix
.net
, n
->prefix
.lo
, n
->prefix
.hi
);
635 WALK_LIST_BACKWARDS(n
, *prefixes
)
636 trie_add_prefix(trie2
, &n
->prefix
.net
, n
->prefix
.lo
, n
->prefix
.hi
);
638 bt_assert(trie_same(trie1
, trie2
));
649 log_networks(const net_addr
*a
, const net_addr
*b
)
651 if (bt_verbose
>= BT_VERBOSE_ABSOLUTELY_ALL
)
655 bt_format_net(buf0
, 64, a
);
656 bt_format_net(buf1
, 64, b
);
657 bt_debug("Found %s expected %s\n", buf0
, buf1
);
665 bt_config_parse(BT_CONFIG_SIMPLE
);
667 linpool
*lp
= lp_new_default(&root_pool
);
668 for (int round
= 0; round
< TESTS_NUM
*8; round
++)
670 int level
= round
/ TESTS_NUM
;
672 int num
= PREFIXES_NUM
* (int[]){1, 10, 100, 1000}[level
/ 2];
673 int pos
= 0, end
= 0;
674 list
*prefixes
= make_random_prefix_list(lp
, num
, v6
, 1);
675 struct f_trie
*trie
= make_trie_from_prefix_list(lp
, prefixes
);
676 struct f_prefix
*pxset
= malloc((num
+ 1) * sizeof(struct f_prefix
));
678 struct f_prefix_node
*n
;
679 WALK_LIST(n
, *prefixes
)
680 pxset
[pos
++] = n
->prefix
;
681 memset(&pxset
[pos
], 0, sizeof (struct f_prefix
));
683 qsort(pxset
, num
, sizeof(struct f_prefix
), compare_prefixes
);
687 bt_debug("Full walk (round %d, %d nets)\n", round
, num
);
691 TRIE_WALK(trie
, net
, NULL
)
693 log_networks(&net
, &pxset
[pos
].net
);
694 bt_assert(net_equal(&net
, &pxset
[pos
].net
));
696 /* Skip possible duplicates */
697 while (net_equal(&pxset
[pos
].net
, &pxset
[pos
+ 1].net
))
705 bt_assert(pos
== num
);
706 bt_assert(pxc
== trie
->prefix_count
);
707 bt_debug("Full walk done\n");
710 /* Prepare net for subnet walk - start with random prefix */
711 pos
= bt_random() % num
;
712 end
= pos
+ (int[]){2, 2, 3, 4}[level
/ 2];
715 struct f_prefix from
= pxset
[pos
];
717 /* Find a common superprefix to several subsequent prefixes */
718 for (; pos
< end
; pos
++)
720 if (net_equal(&from
.net
, &pxset
[pos
].net
))
724 ip4_pxlen(net4_prefix(&from
.net
), net4_prefix(&pxset
[pos
].net
)) :
725 ip6_pxlen(net6_prefix(&from
.net
), net6_prefix(&pxset
[pos
].net
));
726 from
.net
.pxlen
= MIN(from
.net
.pxlen
, common
);
729 ((net_addr_ip4
*) &from
.net
)->prefix
=
730 ip4_and(net4_prefix(&from
.net
), net4_prefix(&pxset
[pos
].net
));
732 ((net_addr_ip6
*) &from
.net
)->prefix
=
733 ip6_and(net6_prefix(&from
.net
), net6_prefix(&pxset
[pos
].net
));
736 /* Fix irrelevant bits */
738 ((net_addr_ip4
*) &from
.net
)->prefix
=
739 ip4_and(net4_prefix(&from
.net
), ip4_mkmask(net4_pxlen(&from
.net
)));
741 ((net_addr_ip6
*) &from
.net
)->prefix
=
742 ip6_and(net6_prefix(&from
.net
), ip6_mkmask(net6_pxlen(&from
.net
)));
745 /* Find initial position for final prefix */
746 for (pos
= 0; pos
< num
; pos
++)
747 if (compare_prefixes(&pxset
[pos
], &from
) >= 0)
752 bt_format_net(buf0
, 64, &from
.net
);
753 bt_debug("Subnet walk for %s (round %d, %d nets)\n", buf0
, round
, num
);
756 TRIE_WALK(trie
, net
, &from
.net
)
758 log_networks(&net
, &pxset
[pos
].net
);
759 bt_assert(net_equal(&net
, &pxset
[pos
].net
));
760 bt_assert(net_in_netX(&net
, &from
.net
));
762 /* Skip possible duplicates */
763 while (net_equal(&pxset
[pos
].net
, &pxset
[pos
+ 1].net
))
770 bt_assert((pos
== num
) || !net_in_netX(&pxset
[pos
].net
, &from
.net
));
771 bt_debug("Subnet walk done for %s (found %d nets)\n", buf0
, pos
- p0
);
781 find_covering_nets(struct f_prefix
*prefixes
, int num
, const net_addr
*net
, net_addr
*found
)
784 net_addr
*n
= &key
.net
;
791 struct f_prefix
*px
=
792 bsearch(&key
, prefixes
, num
, sizeof(struct f_prefix
), compare_prefixes
);
796 net_copy(&found
[found_num
], n
);
805 if (n
->type
== NET_IP4
)
806 ip4_clrbit(&((net_addr_ip4
*) n
)->prefix
, n
->pxlen
);
808 ip6_clrbit(&((net_addr_ip6
*) n
)->prefix
, n
->pxlen
);
813 t_trie_walk_to_root(void)
816 bt_config_parse(BT_CONFIG_SIMPLE
);
818 linpool
*lp
= lp_new_default(&root_pool
);
819 for (int round
= 0; round
< TESTS_NUM
* 4; round
++)
821 int level
= round
/ TESTS_NUM
;
823 int num
= PREFIXES_NUM
* (int[]){32, 512}[level
/ 2];
825 int st
= 0, sn
= 0, sm
= 0;
827 list
*prefixes
= make_random_prefix_list(lp
, num
, v6
, 1);
828 struct f_trie
*trie
= make_trie_from_prefix_list(lp
, prefixes
);
829 struct f_prefix
*pxset
= malloc((num
+ 1) * sizeof(struct f_prefix
));
831 struct f_prefix_node
*pxn
;
832 WALK_LIST(pxn
, *prefixes
)
833 pxset
[pos
++] = pxn
->prefix
;
834 memset(&pxset
[pos
], 0, sizeof (struct f_prefix
));
836 qsort(pxset
, num
, sizeof(struct f_prefix
), compare_prefixes
);
839 for (i
= 0; i
< (PREFIX_TESTS_NUM
/ 10); i
++)
842 get_random_net(&from
, v6
);
845 int found_num
= find_covering_nets(pxset
, num
, &from
, found
);
848 if (bt_verbose
>= BT_VERBOSE_ABSOLUTELY_ALL
)
851 bt_format_net(buf
, 64, &from
);
852 bt_debug("Lookup for %s (expect %d)\n", buf
, found_num
);
855 /* Walk to root, separate for IPv4 and IPv6 */
858 TRIE_WALK_TO_ROOT_IP4(trie
, (net_addr_ip4
*) &from
, net
)
860 log_networks((net_addr
*) &net
, &found
[n
]);
861 bt_assert((n
< found_num
) && net_equal((net_addr
*) &net
, &found
[n
]));
864 TRIE_WALK_TO_ROOT_END
;
868 TRIE_WALK_TO_ROOT_IP6(trie
, (net_addr_ip6
*) &from
, net
)
870 log_networks((net_addr
*) &net
, &found
[n
]);
871 bt_assert((n
< found_num
) && net_equal((net_addr
*) &net
, &found
[n
]));
874 TRIE_WALK_TO_ROOT_END
;
877 bt_assert(n
== found_num
);
885 bt_debug("Success in %d / %d, sum %d, max %d\n", sn
, i
, st
, sm
);
895 main(int argc
, char *argv
[])
899 bt_test_suite(t_match_random_net
, "Testing random prefix matching");
900 bt_test_suite(t_match_inner_net
, "Testing random inner prefix matching");
901 bt_test_suite(t_match_outer_net
, "Testing random outer prefix matching");
902 bt_test_suite(t_trie_same
, "A trie filled forward should be same with a trie filled backward.");
903 bt_test_suite(t_trie_walk
, "Testing TRIE_WALK() on random tries");
904 bt_test_suite(t_trie_walk_to_root
, "Testing TRIE_WALK_TO_ROOT() on random tries");
906 // bt_test_suite(t_bench_trie_datasets_subset, "Benchmark tries from datasets by random subset of nets");
907 // bt_test_suite(t_bench_trie_datasets_random, "Benchmark tries from datasets by generated addresses");
909 return bt_exit_value();