From 3719d746bcf9d1fb4640f3a7ce62e8f7a739d8e2 Mon Sep 17 00:00:00 2001 From: Vojtech Vilimek Date: Fri, 28 Apr 2023 11:10:01 +0200 Subject: [PATCH] tmp: tmp progress on trie API --- filter/trie.c | 117 +++++++++++++++++++++++++++++++++++++++++---- filter/trie_test.c | 94 +++++++++++++++++++++++++++++++----- lib/ip.h | 3 -- 3 files changed, 191 insertions(+), 23 deletions(-) diff --git a/filter/trie.c b/filter/trie.c index 288a4d13..2a029f95 100644 --- a/filter/trie.c +++ b/filter/trie.c @@ -817,12 +817,13 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad }; if (!net) - return 1; + { log("return 0"); return 0; } /* We want to find node of level at least plen */ int plen = ROUND_DOWN_POW2(net->pxlen, TRIE_STEP); const struct f_trie_node *n = &t->root; const int v4 = t->ipv4; + int step; while (n) { @@ -838,7 +839,7 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad if (nlen == plen) { /* Find proper local_pos, while accept_length is not used */ - int step = net->pxlen - plen; + step = net->pxlen - plen; s->start_pos = s->local_pos = (1u << step) + GET_NET_BITS(net, v4, plen, step); s->accept_length = plen; } @@ -859,6 +860,7 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad s->start_pos = 1; } + log("return 1"); return 1; } @@ -873,15 +875,114 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad /* We do not override the trie root in case of inclusive search */ if (!include_successors) s->stack[0] = NULL; + /* We are out of path, find nearest successor */ + else + { + int nlen; + char buf[64]; + char buf2[64]; + net_format(net, buf, 64); + net_addr curr; + if (n == NULL) + log("node is null"); + //bug("node is null"); + else { + nlen = v4 ? n->v4.plen : n->v6.plen; + if (v4) + net_fill_ip4(&curr, ip4_and(n->v4.addr, ip4_mkmask(n->v4.plen)), n->v4.plen); + //net_fill_ip4(&curr, n->v4.addr, n->v4.plen); + else + net_fill_ip6(&curr, ip6_and(n->v6.addr, ip6_mkmask(n->v6.plen)), n->v6.plen); + //net_fill_ip6(&curr, n->v6.addr, n->v6.plen); + net_format(&curr, buf2, 64); - /* Be careful about underflow */ - else if (s->stack_pos > 0) - s->stack_pos--; + log(" !SAME_PREFIX: %s vs. %s\n", buf, buf2); + } - /* Search whole trie except skipped parts */ - if (include_successors) - s->start_pos = 1; + if (s->stack_pos > 0) + n = s->stack[s->stack_pos - 1]; + else + { + log("root fallback"); + n = &t->root; + } + nlen = v4 ? n->v4.plen : n->v6.plen; + + log("phase 2 after back step"); + net_format(net, buf, 64); + if (v4) + net_fill_ip4(&curr, ip4_and(n->v4.addr, ip4_mkmask(n->v4.plen)), n->v4.plen); + //net_fill_ip4(&curr, n->v4.addr, n->v4.plen); + else + net_fill_ip6(&curr, ip6_and(n->v6.addr, ip6_mkmask(n->v6.plen)), n->v6.plen); + //net_fill_ip6(&curr, n->v6.addr, n->v6.plen); + net_format(&curr, buf2, 64); + log(" (%d) SAME_PREFIX: %s vs. %s\n", SAME_PREFIX(n, net, v4, MIN(net->pxlen, nlen)), buf, buf2); + + step = net->pxlen - plen; + /* Stack position point one element ahead */ + if (s->stack_pos == 1) + { + //bug("there"); + log("there"); + s->stack_pos--; + s->start_pos = s->local_pos = 1; + } + else if (s->stack_pos > 1) + { + //bug("over"); + log("over"); + s->stack_pos--; + + nlen = (v4) ? n->v4.plen : n->v6.plen; + int next = (GET_NET_BITS(net, v4, nlen, step) + 1) % TRIE_STEP; + while (s->stack_pos != 0 && next == 0) + { + n = s->stack[s->start_pos]; + step--; + s->stack_pos--; + next = (GET_NET_BITS(net, v4, nlen, step) + 1) % TRIE_STEP; + } + + /* Fix the stack_pos, one decrement one than needed */ + s->stack_pos++; + + if ((n = GET_CHILD(n, v4, next)) != NULL) + { + log("settting the positions"); + s->stack[s->stack_pos] = n; + //s->start_pos = (1u << step) + GET_NET_BITS(net, v4, plen, step); + s->start_pos = 2 * (1u << step) + GET_NET_BITS(net, v4, plen, step); + s->local_pos = 2 * (1u << step) + GET_NET_BITS(net, v4, plen, step); + } + //s->start_pos = s->local_pos = (1u << step) + GET_NET_BITS(net, v4, plen, step); + //s->accept_length = plen; + /* s->start_pos and s->local_pos is already initialized */ + } + /* Be careful around underflow */ + else /* stack_pos == 0 */ + { + bug("here"); + + //return 0; + s->stack[0] = &t->root; + s->start_pos = s->local_pos = (1u << step); + s->accept_length = plen; + } + + struct net_addr net_copy; + memcpy(&net_copy, net, sizeof(struct net_addr)); +/* + if (v4) + net_fill_ip4(net, ip4_and(), len); + else + net_fill_ip6(net, ip6_and(), len); +*/ + //trie_walk_next(s, &net_copy); + } + + log("return 2"); return 0; } diff --git a/filter/trie_test.c b/filter/trie_test.c index 37bbbd1b..540f221b 100644 --- a/filter/trie_test.c +++ b/filter/trie_test.c @@ -890,7 +890,8 @@ t_trie_walk_inclusive(void) { int level = round / TESTS_NUM; int v6 = level % 2; - int num = PREFIXES_NUM * (int[]){1, 10, 100, 1000}[level / 2]; + //int num = PREFIXES_NUM * (int[]){0, 1, 10, 100, 1000}[level / 2]; + int num = PREFIXES_NUM * (int[]){32, 512}[level / 2]; int pos = 0, end = 0; list *prefixes = make_random_prefix_list(num, v6, 1); struct f_trie *trie = make_trie_from_prefix_list(prefixes); @@ -903,7 +904,7 @@ t_trie_walk_inclusive(void) qsort(pxset, num, sizeof(struct f_prefix), compare_prefixes); - /* // print sorted prefixes + // print sorted prefixes bt_debug("sorted prefixes\n"); for (struct f_prefix *px = pxset; px < pxset + num; px++) { @@ -911,7 +912,7 @@ t_trie_walk_inclusive(void) bt_format_net(buf, 64, &px->net); bt_debug("%s{%d,%d}\n", buf, px->lo, px->hi); } - + /* Full walk */ bt_debug("Full walk inclusive (round %d, %d nets)\n", round, num); @@ -937,12 +938,20 @@ t_trie_walk_inclusive(void) bt_debug("Full walk inclusive done\n"); - /* Prepare net for subnet walk - start with random prefix */ - pos = bt_random() % num; + /* Prepare net for subnet walk - start with random prefix from trie */ + if (num) + pos = bt_random() % num; + else + pos = 0; end = pos + (int[]){2, 2, 3, 4}[level / 2]; end = MIN(end, num); - struct f_prefix from = pxset[pos]; + struct f_prefix from; + + if (num) + from = pxset[pos]; + else + get_random_prefix(&from, v6, 1); /* Find a common superprefix to several subsequent prefixes */ for (; pos < end; pos++) @@ -977,11 +986,6 @@ t_trie_walk_inclusive(void) if (compare_prefixes(&pxset[pos], &from) >= 0) break; - /* Account for subnets before searched net from */ - //for (; pos < num; pos++) - //if (net_compare(&pxset[pos].net, &from.net) >= 0) - //break; - int p0 = pos; char buf0[64]; bt_format_net(buf0, 64, &from.net); @@ -991,7 +995,8 @@ t_trie_walk_inclusive(void) TRIE_WALK2(trie, net, &from.net, 1) { log_networks(&net, &pxset[pos].net); - bt_assert(net_compare(&net, &pxset[pos].net) >= 0); + //bt_assert(net_compare(&net, &pxset[pos].net) >= 0); + bt_assert(net_compare(&net, &from.net) >= 0); /* Skip possible duplicates */ while (net_equal(&pxset[pos].net, &pxset[pos + 1].net)) @@ -1004,11 +1009,76 @@ t_trie_walk_inclusive(void) bt_assert(pos == num); bt_debug("Subnet walk done inclusive for %s (found %d nets)\n", buf0, pos - p0); + /* Prepare net for subnet walk - start with random prefix (likely not from trie) */ + get_random_prefix(&from, v6, 1); + + for (pos = 0; pos < num; pos++) + { + bt_format_net(buf0, 64, &pxset[pos].net); + bt_debug(" -> %s ", buf0); + if (net_compare(&pxset[pos].net, &from.net) >= 0) + { + bt_debug("true, breaking\n"); + break; + } + else + bt_debug("false\n"); + } + + p0 = pos; + bt_format_net(buf0, 64, &from.net); + bt_debug("Subnet walk inclusive for random %s (round %d, %d nets)\n", buf0, round, num); + + /* Subnet walk */ + TRIE_WALK2(trie, net, &from.net, 1) + { + /* Make sure that net is from inserted prefixes */ + bt_format_net(buf0, 64, &net); + bt_debug("got: %s", buf0); + bt_format_net(buf0, 64, &pxset[pos].net); + bt_debug(" expected %s", buf0); + if (pos + 1 < num) + { + bt_format_net(buf0, 64, &pxset[pos + 1].net); + bt_debug(" (next: %s)\n", buf0); + } + else + bt_debug("\n"); + + bt_assert(net_equal(&net, &pxset[pos].net)); + bt_assert(net_compare(&net, &from.net) >= 0); + + while (net_equal(&pxset[pos].net, &pxset[pos + 1].net)) + pos++; + + pos++; + } + TRIE_WALK2_END; + + bt_debug("Subnet walk inclusive for random %s (found %d nets from %d)\n", buf0, pos - p0, num - p0); + bt_assert(pos == num); + tmp_flush(); } bt_bird_cleanup(); return 1; + + + /* + * empty trie + * inclusive after last element + * inclusive before first element + * not found root (empty trie) + * not found root (after last) + * not found root (before first) + * not found root (single element) + * not found root inbetween + * not found first level + * not found first level (after) + * not found first level (before) + * general case (found / not found on higher level) + */ } int diff --git a/lib/ip.h b/lib/ip.h index 73083ac9..20e7a336 100644 --- a/lib/ip.h +++ b/lib/ip.h @@ -145,9 +145,6 @@ static inline ip4_addr ip4_xor(ip4_addr a, ip4_addr b) static inline ip4_addr ip4_not(ip4_addr a) { return _MI4(~_I(a)); } -static inline int ip4_less(ip4_addr a, ip4_addr b) -{ return _I(a) < _I(b); } - static inline int ip6_equal(ip6_addr a, ip6_addr b) { return _I0(a) == _I0(b) && _I1(a) == _I1(b) && _I2(a) == _I2(b) && _I3(a) == _I3(b); }