mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 02:01:55 +00:00
changes in trie_walk_init() - preview
This commit is contained in:
parent
b290284769
commit
362081da85
278
filter/trie.c
278
filter/trie.c
@ -787,6 +787,20 @@ done:
|
|||||||
#define NEXT_PREFIX(A,B,X) ((X) ? ip4_compare((A)->v4.addr, net4_prefix(B)) < 0 : ip6_compare((A)->v6.addr, net6_prefix(B)) < 0)
|
#define NEXT_PREFIX(A,B,X) ((X) ? ip4_compare((A)->v4.addr, net4_prefix(B)) < 0 : ip6_compare((A)->v6.addr, net6_prefix(B)) < 0)
|
||||||
#define MATCH_LOCAL_MASK(A,B,L,X) \
|
#define MATCH_LOCAL_MASK(A,B,L,X) \
|
||||||
((X) ? (A)->v4.local >= trie_local_mask4(net4_prefix(B), (B)->pxlen, (L)) : (A)->v6.local >= trie_local_mask6(net6_prefix(B), (B)->pxlen, (L)))
|
((X) ? (A)->v4.local >= trie_local_mask4(net4_prefix(B), (B)->pxlen, (L)) : (A)->v6.local >= trie_local_mask6(net6_prefix(B), (B)->pxlen, (L)))
|
||||||
|
#define SELECT_CHILD(pos,step) ((1u << (step)) + (pos))
|
||||||
|
/*
|
||||||
|
* We want to select a specific subtrie base on it's index in child array c.
|
||||||
|
*
|
||||||
|
* 1
|
||||||
|
* 2 3
|
||||||
|
* 4 5 6 7
|
||||||
|
* 8 9 A B C D E F
|
||||||
|
* -----------------------------------------------------
|
||||||
|
* 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trie_walk_init
|
* trie_walk_init
|
||||||
@ -798,14 +812,13 @@ done:
|
|||||||
* Initialize walk state for subsequent walk through nodes of the trie @t by
|
* Initialize walk state for subsequent walk through nodes of the trie @t by
|
||||||
* trie_walk_next(). The argument @net allows to restrict walk to given subnet,
|
* trie_walk_next(). The argument @net allows to restrict walk to given subnet,
|
||||||
* otherwise full walk over all nodes is used. This is done by finding node at
|
* otherwise full walk over all nodes is used. This is done by finding node at
|
||||||
* or below @net and starting position in it. The argument @include_successors
|
* or below @net and starting position in it. The argument @include_successors,
|
||||||
* removes the restriction for all subnets lexicographically succeeding the
|
* which requeries specifing the @net argument, removes the restriction for all
|
||||||
* @net. In case of @net search fail the walk state starting position points to
|
* nets lexicographically succeeding the @net. This is done by storing the walken
|
||||||
* the nearest parent node availible. If you use @net and @include_successors,
|
* nodes on the state's stack.
|
||||||
* beware that the trie_walk_next() could return a net preceding the one
|
|
||||||
* specified in @net.
|
|
||||||
*
|
*
|
||||||
* If desired start position node was found in trie, 1 is returned, 0 otherwise.
|
* For set @include_successors the return value is 1 if the @net is present in
|
||||||
|
* the trie @t, in all other cases 0.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_addr *net, u8 include_successors)
|
trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_addr *net, u8 include_successors)
|
||||||
@ -819,7 +832,6 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad
|
|||||||
.stack[0] = &t->root
|
.stack[0] = &t->root
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Local work copy of @net */
|
|
||||||
if (!net)
|
if (!net)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -842,25 +854,29 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad
|
|||||||
if (!include_successors)
|
if (!include_successors)
|
||||||
s->stack[0] = n;
|
s->stack[0] = n;
|
||||||
else
|
else
|
||||||
{
|
|
||||||
s->stack[s->stack_pos] = n;
|
s->stack[s->stack_pos] = n;
|
||||||
}
|
|
||||||
|
|
||||||
s->start_pos = 1;
|
|
||||||
if (nlen == plen)
|
if (nlen == plen)
|
||||||
{
|
{
|
||||||
/* Find proper local_pos, while accept_length is not used */
|
/* Find proper local_pos, while accept_length is not used */
|
||||||
s->local_pos = 1;
|
int step = net->pxlen - plen;
|
||||||
|
s->local_pos = (1u << step) + GET_NET_BITS(net, v4, plen, step);
|
||||||
s->accept_length = plen;
|
s->accept_length = plen;
|
||||||
|
|
||||||
if (include_successors)
|
if (!include_successors)
|
||||||
{
|
{
|
||||||
|
s->start_pos = s->local_pos;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (GET_LOCAL(n, v4) != 0 && !MATCH_LOCAL_MASK(n, net, nlen, v4))
|
if (GET_LOCAL(n, v4) != 0 && !MATCH_LOCAL_MASK(n, net, nlen, v4))
|
||||||
goto find_successor;
|
{
|
||||||
|
s->local_pos = (1u << TRIE_STEP) + GET_NET_BITS(net, v4, nlen, TRIE_STEP);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int pos = 1;
|
int pos = 1;
|
||||||
u32 bits = GET_NET_BITS(net, v4, nlen, TRIE_STEP);
|
int bits = GET_NET_BITS(net, v4, nlen, TRIE_STEP);
|
||||||
|
|
||||||
for (int i = 0; i < net->pxlen - plen; i++)
|
for (int i = 0; i < net->pxlen - plen; i++)
|
||||||
{
|
{
|
||||||
if (bits & (1u << (TRIE_STEP - i - 1)))
|
if (bits & (1u << (TRIE_STEP - i - 1)))
|
||||||
@ -872,8 +888,6 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad
|
|||||||
s->local_pos = pos;
|
s->local_pos = pos;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Start from pos 1 in current node, but first try accept mask */
|
/* Start from pos 1 in current node, but first try accept mask */
|
||||||
@ -893,150 +907,164 @@ 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 */
|
/* We do not override the trie root in case of inclusive search */
|
||||||
if (!include_successors)
|
if (!include_successors)
|
||||||
s->stack[0] = NULL;
|
|
||||||
/* We are out of path, find nearest successor */
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
s->stack[0] = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are out of path, find nearest successor */
|
||||||
if (s->stack_pos == 0)
|
if (s->stack_pos == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we end up on node that has compressed path, we need to step up node
|
* If we end up on node that has compressed path, we need to step up node
|
||||||
* for better decision making
|
* for better decision making
|
||||||
*/
|
*/
|
||||||
|
|
||||||
s->stack_pos--;
|
s->stack_pos--;
|
||||||
n = s->stack[s->stack_pos];
|
n = s->stack[s->stack_pos];
|
||||||
|
|
||||||
ASSERT(n != NULL);
|
ASSERT(n != NULL);
|
||||||
|
|
||||||
/* We find the nearest successor in subsequent trie_walk_next() */
|
|
||||||
int nlen = v4 ? n->v4.plen : n->v6.plen;
|
int nlen = v4 ? n->v4.plen : n->v6.plen;
|
||||||
u32 bits = GET_NET_BITS(net, v4, nlen, TRIE_STEP);
|
|
||||||
const struct f_trie_node *child = GET_CHILD(n, v4, bits);
|
|
||||||
if (child != NULL)
|
|
||||||
{
|
|
||||||
s->accept_length = nlen;
|
s->accept_length = nlen;
|
||||||
|
|
||||||
/* Performs basically more granular net_comapre_ip{4,6}() */
|
|
||||||
struct net_addr_ip4 *net4 = NULL;
|
struct net_addr_ip4 *net4 = NULL;
|
||||||
struct net_addr_ip6 *net6 = NULL;
|
struct net_addr_ip6 *net6 = NULL;
|
||||||
|
|
||||||
if (v4) net4 = (struct net_addr_ip4 *) net;
|
if (v4) net4 = (net_addr_ip4 *) net;
|
||||||
else net6 = (struct net_addr_ip6 *) net;
|
else net6 = (net_addr_ip6 *) net;
|
||||||
|
|
||||||
int cmp = v4 ? ip4_compare(child->v4.addr, net4->prefix)
|
/* We known for sure that the searched prefix is not in the trie */
|
||||||
|
int cmp;
|
||||||
|
int bits = GET_NET_BITS(net, v4, nlen, TRIE_STEP);
|
||||||
|
const struct f_trie_node *child = GET_CHILD(n, v4, bits);
|
||||||
|
while (child)
|
||||||
|
{
|
||||||
|
cmp = v4 ? ip4_compare(child->v4.addr, net4->prefix)
|
||||||
: ip6_compare(child->v6.addr, net6->prefix);
|
: ip6_compare(child->v6.addr, net6->prefix);
|
||||||
if (cmp < 0)
|
|
||||||
{
|
|
||||||
s->stack_pos++;
|
|
||||||
s->stack[s->stack_pos] = child;
|
|
||||||
s->local_pos = 0x1f;
|
|
||||||
}
|
|
||||||
else if (cmp > 0)
|
|
||||||
{
|
|
||||||
/* We continue in child node */
|
|
||||||
if (bits % 2 == 0)
|
|
||||||
s->local_pos = 0x08 + (bits >> 1);
|
|
||||||
else
|
|
||||||
s->local_pos = MIN(0x10 + bits, 0x1f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (v4 ? child->v4.plen <= net4->pxlen : child->v6.plen < net6->pxlen)
|
|
||||||
{
|
|
||||||
/* We continue in child node */
|
|
||||||
if (bits % 2 == 0)
|
|
||||||
s->local_pos = 0x08 + (bits >> 1);
|
|
||||||
else
|
|
||||||
s->local_pos = MIN(0x10 + bits, 0x1f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s->stack_pos++;
|
|
||||||
s->stack[s->stack_pos] = child;
|
|
||||||
s->local_pos = 0x01;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
if (cmp == 0)
|
||||||
// TODO handle properly search with short prefix length
|
|
||||||
int clen =0;
|
|
||||||
/* We are dealing with a compressed child */
|
|
||||||
if (clen > nlen + TRIE_STEP)
|
|
||||||
{
|
{
|
||||||
int len = nlen;
|
if (v4 ? child->v4.plen <= net4->pxlen : child->v6.plen <= net6->pxlen)
|
||||||
while (GET_NODE_BITS(child, v4, len, TRIE_STEP) == bits && len < MIN(clen, plen))
|
bits = 0;
|
||||||
{
|
|
||||||
len += TRIE_STEP;
|
|
||||||
bits = GET_NET_BITS(net, v4, len, TRIE_STEP);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len > nlen)
|
|
||||||
{
|
|
||||||
s->stack_pos++;
|
|
||||||
s->stack[s->stack_pos] = child;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
die("hidden");
|
bits = 15;
|
||||||
|
}
|
||||||
/* successive siblings walk */
|
else if (cmp < 0)
|
||||||
const struct f_trie_node *ns = NULL;
|
|
||||||
for (u32 i = bits + 1; i < (1u << TRIE_STEP); i++)
|
|
||||||
{
|
{
|
||||||
/* The node n is parent and the node ns is older sibling of the node child */
|
for (int i = bits; i < (1 << TRIE_STEP); i++)
|
||||||
if ((ns = v4 ? (struct f_trie_node *) n->v4.c[i] : (struct f_trie_node *) n->v6.c[i]) == NULL)
|
{
|
||||||
continue;
|
const struct f_trie_node *tmp = GET_CHILD(n, v4, i);
|
||||||
|
if (!tmp) continue;
|
||||||
// TODO
|
if (v4 ? ip4_compare(tmp->v4.addr, net4->prefix) > 0
|
||||||
if (!SAME_PREFIX(ns, net, v4, len - TRIE_STEP))
|
: ip6_compare(tmp->v6.addr, net6->prefix) > 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (bits < GET_NODE_BITS(ns, v4, len, TRIE_STEP))
|
child = tmp;
|
||||||
//if (GET_NET_BITS(net, v4, len, TRIE_STEP) < bits)
|
}
|
||||||
break;
|
bits = 15;
|
||||||
|
}
|
||||||
|
else /* cmp > 0 */
|
||||||
|
bits = 0;
|
||||||
|
|
||||||
s->stack[s->stack_pos] = ns;
|
s->stack_pos++;
|
||||||
|
s->stack[s->stack_pos] = n = child;
|
||||||
|
child = GET_CHILD(child, v4, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->accept_length = len + TRIE_STEP;
|
nlen = (v4) ? n->v4.plen : n->v6.plen;
|
||||||
|
cmp = v4 ? ip4_compare(n->v4.addr, net4->prefix)
|
||||||
// if (ns && !SAME_PREFIX(ns, net, v4, len))
|
: ip6_compare(n->v6.addr, net6->prefix);
|
||||||
// {
|
|
||||||
// //s->local_pos = 0x10 + (bits - 1);
|
|
||||||
// s->local_pos = 0x1f;
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (GET_NET_BITS(net, v4, len, TRIE_STEP) > GET_NODE_BITS(child, v4, len, TRIE_STEP))
|
|
||||||
s->local_pos = 0x1f; // + GET_NET_BITS(net, v4, nlen, TRIE_STEP);
|
|
||||||
else
|
|
||||||
s->local_pos = 0x01; //0x10 + GET_NET_BITS(net, v4, nlen, TRIE_STEP);
|
|
||||||
|
|
||||||
|
if (cmp == 0)
|
||||||
|
{
|
||||||
|
bits = GET_NET_BITS(net, v4, nlen, TRIE_STEP);
|
||||||
|
if (plen - nlen >= TRIE_STEP)
|
||||||
|
{
|
||||||
|
s->local_pos = SELECT_CHILD(bits, TRIE_STEP);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
s->local_pos = 0x10 + bits;
|
|
||||||
|
|
||||||
}
|
int pos = 1;
|
||||||
else
|
for (int i = 0; i < net->pxlen - plen; i++)
|
||||||
{
|
{
|
||||||
s->local_pos = 0x10 + bits;
|
if (bits & (1u << (TRIE_STEP - i - 1)))
|
||||||
|
pos = 2 * pos + 1;
|
||||||
|
else
|
||||||
|
pos = 2 * pos;
|
||||||
}
|
}
|
||||||
|
s->local_pos = pos;
|
||||||
nlen = v4 ? n->v4.plen : n->v6.plen;
|
}
|
||||||
|
else if (cmp < 0)
|
||||||
|
{
|
||||||
|
s->local_pos = SELECT_CHILD(bits, TRIE_STEP);
|
||||||
s->accept_length = nlen;
|
s->accept_length = nlen;
|
||||||
}
|
}
|
||||||
return 0;
|
else /* cmp > 0 */
|
||||||
|
{
|
||||||
find_successor:;
|
}
|
||||||
ASSERT(n != NULL);
|
|
||||||
u32 nlen = v4 ? n->v4.plen : n->v6.plen;
|
|
||||||
|
|
||||||
u32 bits = GET_NET_BITS(net, v4, nlen, TRIE_STEP);
|
|
||||||
s->local_pos = 0x10 + bits;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// if (child)
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// /* Performs basically more granular net_comapre_ip{4,6}() */
|
||||||
|
// if (v4) net4 = (struct net_addr_ip4 *) net;
|
||||||
|
// else net6 = (struct net_addr_ip6 *) net;
|
||||||
|
//
|
||||||
|
// int cmp = v4 ? ip4_compare(child->v4.addr, net4->prefix)
|
||||||
|
// : ip6_compare(child->v6.addr, net6->prefix);
|
||||||
|
// if (cmp < 0)
|
||||||
|
// {
|
||||||
|
// while ()
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
// /* We continue as we've just finished walk in a child node */
|
||||||
|
// s->local_pos = before_pos(bits + 1, TRIE_STEP);
|
||||||
|
// s->stack_pos++;
|
||||||
|
// s->stack[s->stack_pos] = child;
|
||||||
|
// s->local_pos = last_pos(TRIE_STEP);
|
||||||
|
// }
|
||||||
|
// else if (cmp > 0)
|
||||||
|
// {
|
||||||
|
// /* We continue in child node */
|
||||||
|
// if (bits % 2 == 0)
|
||||||
|
// {
|
||||||
|
// s->stack_pos++;
|
||||||
|
// s->stack[s->stack_pos] = child;
|
||||||
|
// s->local_pos = 1; //last_pos(TRIE_STEP);
|
||||||
|
// }
|
||||||
|
// //s->local_pos = 0x08 + (bits >> 1);
|
||||||
|
// //s->local_pos = before_pos(bits, TRIE_STEP);
|
||||||
|
// //s->local_pos = MAX(0, after_pos(bits - 1, TRIE_STEP)); //s->local_pos = before_pos(bits >> 1, TRIE_STEP);
|
||||||
|
// else
|
||||||
|
// //s->local_pos = MIN((1u << TRIE_STEP) + bits, (1u << TRIE_STEP) + 15);
|
||||||
|
// s->local_pos = after_pos(bits, TRIE_STEP);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// if (v4 ? child->v4.plen <= net4->pxlen : child->v6.plen < net6->pxlen)
|
||||||
|
// {
|
||||||
|
// /* We continue in child node */
|
||||||
|
// if (bits % 2 == 0)
|
||||||
|
// s->local_pos = before_pos(bits >> 1, TRIE_STEP);
|
||||||
|
// //s->local_pos = 0x08 + (bits >> 1);
|
||||||
|
// else
|
||||||
|
// //s->local_pos = MIN((1u << TRIE_STEP) + bits, (1u << TRIE_STEP) + 15);
|
||||||
|
// s->local_pos = after_pos(bits, TRIE_STEP);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// /* We continue in current node from first position */
|
||||||
|
// s->stack_pos++;
|
||||||
|
// s->stack[s->stack_pos] = child;
|
||||||
|
// s->local_pos = 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// s->local_pos = 0x10 + bits;
|
||||||
|
// return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GET_ACCEPT_BIT(N,X,B) ((X) ? ip4_getbit((N)->v4.accept, (B)) : ip6_getbit((N)->v6.accept, (B)))
|
#define GET_ACCEPT_BIT(N,X,B) ((X) ? ip4_getbit((N)->v4.accept, (B)) : ip6_getbit((N)->v6.accept, (B)))
|
||||||
|
@ -655,6 +655,11 @@ t_trie_walk(void)
|
|||||||
{
|
{
|
||||||
bt_bird_init();
|
bt_bird_init();
|
||||||
bt_config_parse(BT_CONFIG_SIMPLE);
|
bt_config_parse(BT_CONFIG_SIMPLE);
|
||||||
|
unsigned int r = rand();
|
||||||
|
printf("random seed t_trie_walk %u\n", r);
|
||||||
|
srandom(r);
|
||||||
|
//srandom(732437807);
|
||||||
|
//srandom(1182332329);
|
||||||
|
|
||||||
for (int round = 0; round < TESTS_NUM*8; round++)
|
for (int round = 0; round < TESTS_NUM*8; round++)
|
||||||
{
|
{
|
||||||
@ -886,10 +891,12 @@ t_trie_walk_inclusive(void)
|
|||||||
{
|
{
|
||||||
bt_bird_init();
|
bt_bird_init();
|
||||||
bt_config_parse(BT_CONFIG_SIMPLE);
|
bt_config_parse(BT_CONFIG_SIMPLE);
|
||||||
//unsigned int r = rand();
|
//srandom(25273275);
|
||||||
//printf("random seed %u\n", r);
|
//srandom(1959294931);
|
||||||
//srandom(r);
|
//srandom(1182332329);
|
||||||
//srandom(1985510202);
|
unsigned int r = rand();
|
||||||
|
printf("random seed t_trie_walk_inclusive %u\n", r);
|
||||||
|
srandom(r);
|
||||||
|
|
||||||
for (int round = 0; round < TESTS_NUM*8; round++)
|
for (int round = 0; round < TESTS_NUM*8; round++)
|
||||||
{
|
{
|
||||||
@ -909,7 +916,6 @@ t_trie_walk_inclusive(void)
|
|||||||
|
|
||||||
qsort(pxset, num, sizeof(struct f_prefix), compare_prefixes);
|
qsort(pxset, num, sizeof(struct f_prefix), compare_prefixes);
|
||||||
|
|
||||||
|
|
||||||
/* Prepare net for subnet walk - start with random prefix from trie */
|
/* Prepare net for subnet walk - start with random prefix from trie */
|
||||||
if (num)
|
if (num)
|
||||||
pos = bt_random() % num;
|
pos = bt_random() % num;
|
||||||
|
Loading…
Reference in New Issue
Block a user