0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

tmp: tmp progress on trie API

This commit is contained in:
Vojtech Vilimek 2023-04-28 11:10:01 +02:00
parent 7e68ba64a9
commit 3719d746bc
3 changed files with 191 additions and 23 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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); }