#define SAME_PREFIX(A,B,X,L) ((X) ? ip4_prefix_equal((A)->v4.addr, net4_prefix(B), (L)) : ip6_prefix_equal((A)->v6.addr, net6_prefix(B), (L)))
#define GET_NET_BITS(N,X,A,B) ((X) ? ip4_getbits(net4_prefix(N), (A), (B)) : ip6_getbits(net6_prefix(N), (A), (B)))
#define GET_NODE_BITS(N,X,A,B) ((X) ? ip4_getbits((N)->v4.addr, (A), (B)) : ip6_getbits((N)->v6.addr, (A), (B)))
-//#define GET_ACCEPT_BITS(N,X,B) ((X) ? ip4_getbits((N)->v4.accept, (B), TRIE_STEP) : ip6_getbits((N)->v6.accept, (B), TRIE_STEP))
#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) \
((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)))
-void
-_print_net(const net_addr *net, int v4)
-{
- char buf[64];
- net_format(net, buf, 64);
- log("net: %s", buf);
-}
-
-void
-_print_node(const struct f_trie_node *n, int v4)
-{
- if (n == NULL)
- {
- log("node: (null)");
- return;
- }
-
- int nlen = v4 ? n->v4.plen : n->v6.plen;
-
- char buf[64];
- net_addr curr;
- if (v4)
- net_fill_ip4(&curr, ip4_and(n->v4.addr, ip4_mkmask(nlen)), nlen);
- else
- net_fill_ip6(&curr, ip6_and(n->v6.addr, ip6_mkmask(nlen)), nlen);
-
- net_format(&curr, buf, 64);
-
- log("node: %s", buf);
-}
-
/**
* trie_walk_init
* @s: walk state
s->local_pos = 1;
s->accept_length = plen;
- //if (include_successors && (GET_LOCAL(n, v4) < TRIE_LOCAL_MASK(net, nlen, v4)))
- //goto find_successor;
-
if (include_successors)
{
if (GET_LOCAL(n, v4) != 0 && !MATCH_LOCAL_MASK(n, net, nlen, v4))
pos = 2 * pos;
}
- //if (GET_CHILD(n, v4, bits) != NULL)
- //{
- s->local_pos = pos;
- return 0;
- //}
+ s->local_pos = pos;
+ return 0;
}
-// if (v4)
-// {
-// struct net_addr_ip4 *net4 = &((net_addr_union *) net)->ip4;
-// /* succesor is not in current node */
-// if (include_successors && (GET_LOCAL(n, v4) < trie_local_mask4(net4->prefix, net4->pxlen, nlen)))
-// goto find_successor;
-//
-// /* successor could be in current node */
-// if (include_successors)
-// {
-// int pos = 1;
-// u32 bits = ip4_getbits(net4->prefix, nlen, TRIE_STEP);
-//
-// /* calculate pos for local bitmap */
-// for (int i = 0; i < net4->pxlen - plen; i++)
-// {
-// if (bits & (1u << (TRIE_STEP - i - 1)))
-// pos = 2 * pos + 1;
-// else
-// pos = 2 * pos;
-// }
-//
-// if (n->v4.c[bits] != NULL)
-// {
-// s->local_pos = pos;
-// return 1;
-// }
-//
-// /* if the prefix on position pos is present, go one step back */
-// if (GET_LOCAL(n, v4) & (1u << pos))
-// if (pos == 1)
-// {}
-// else
-// s->local_pos = pos / 2;
-// else
-// s->local_pos = pos;
-//
-// return 1;
-// }
-// }
-// else
-// {
-// struct net_addr_ip6 *net6 = &((net_addr_union *) net)->ip6;
-// if (include_successors && (GET_LOCAL(n, v4) < trie_local_mask6(net6->prefix, net6->pxlen, nlen)))
-// goto find_successor;
-//
-// if (include_successors)
-// {
-// return 1;
-// }
-// }
}
else
{
{
if (s->stack_pos == 0)
return 0;
-// if (s->stack_pos == 0)
-// {
-// if (s->stack[0] == NULL)
-// { /* no elements, -> invalid state */ log(" return 4 invalid"); return 0; }
-//
-// /* empty trie with only root node !? */
-// bug("couldn't happen");
-// }
-
/*
* If we end up on node that has compressed path, we need to step up node
* for better decision making
*/
-// if (n == NULL || (v4 ? n->v4.plen < s->stack[s->stack_pos - 1]->v4.plen :
-// n->v6.plen < s->stack[s->stack_pos - 1]->v6.plen && NEXT_PREFIX(n, net, v4)))
-// {
-// s->stack_pos--;
-// n = s->stack[s->stack_pos];
-// }
s->stack_pos--;
n = s->stack[s->stack_pos];
ASSERT(n != NULL);
- //u32 nlen = v4 ? n->v4.plen : n->v6.plen;
- //s->accept_length = nlen;
- //u32 bits = GET_NET_BITS(net, v4, nlen, TRIE_STEP);
-
- //uint 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)
- //{
- // u32 clen; /* child prefix length */
- // do
- // {
- // clen = v4 ? child->v4.plen : child->v6.plen;
-
- // s->stack_pos++;
- // s->stack[s->stack_pos] = child;
- // s->local_pos = 0x1f;
-
- // n = child;
- // nlen = clen;
- // bits = GET_NET_BITS(net, v4, nlen, TRIE_STEP);
- // child = GET_CHILD(n, v4, bits);
- // }
- // while (child != NULL && clen > nlen && NEXT_PREFIX(child, net, v4));
- //}
-
- //s->accept_length = nlen;
- ///* the while cycle above wasn't entered */
- //if (s->local_pos != 0x1f)
- // s->local_pos = 0x10 | bits;
-
/* We find the nearest successor in subsequent trie_walk_next() */
int nlen = v4 ? n->v4.plen : n->v6.plen;
const struct f_trie_node *child = GET_CHILD(n, v4, bits);
if (child != NULL)
{
- int clen = v4 ? child->v4.plen : child->v6.plen; /* child prefix length */
+ s->accept_length = nlen;
+
+ /* Performs basically more granular net_comapre_ip{4,6}() */
+ struct net_addr_ip4 *net4 = NULL;
+ struct net_addr_ip6 *net6 = NULL;
+
+ 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)
+ {
+ 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;
+
+ // TODO handle properly search with short prefix length
+ int clen =0;
/* We are dealing with a compressed child */
if (clen > nlen + TRIE_STEP)
{
s->stack_pos++;
s->stack[s->stack_pos] = child;
}
+ else
+ die("hidden");
/* successive siblings walk */
const struct f_trie_node *ns = NULL;
for (u32 i = bits + 1; i < (1u << TRIE_STEP); i++)
{
- /* n is parent and ns is older sibling of child */
+ /* The node n is parent and the node ns is older sibling of the node child */
if ((ns = v4 ? (struct f_trie_node *) n->v4.c[i] : (struct f_trie_node *) n->v6.c[i]) == NULL)
continue;
- //if (GET_NODE_BITS(ns, v4, len, TRIE_STEP) < bits)
- // break;
- if (GET_NET_BITS(net, v4, len, TRIE_STEP) < bits)
+ // TODO
+ if (!SAME_PREFIX(ns, net, v4, len - TRIE_STEP))
+ break;
+
+ if (bits < GET_NODE_BITS(ns, v4, len, TRIE_STEP))
+ //if (GET_NET_BITS(net, v4, len, TRIE_STEP) < bits)
break;
+
+ s->stack[s->stack_pos] = ns;
}
- if (ns == NULL)
- ns = child;
+ s->accept_length = len + TRIE_STEP;
- //if (GET_NODE_BITS(ns, v4, len, TRIE_STEP) < bits)
- // s->local_pos = 0x1f;
- if (GET_NET_BITS(net, v4, len, TRIE_STEP) < bits)
- s->local_pos = 0x1f;
- else
- s->local_pos = 1;
+// if (ns && !SAME_PREFIX(ns, net, v4, len))
+// {
+// //s->local_pos = 0x10 + (bits - 1);
+// s->local_pos = 0x1f;
+// return 0;
+// }
- s->accept_length = len;
+ 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);
return 0;
}
-
-// if (clen > nlen && NEXT_PREFIX(child, net, v4))
-// {
-// //clen = v4 ? child->v4.plen : child->v6.plen;
-//
-// s->stack_pos++;
-// s->stack[s->stack_pos] = child;
-// s->local_pos = 0x1f;
-//
-// n = child;
-// nlen = clen;
-//
-// bits = GET_NET_BITS(net, v4, nlen, TRIE_STEP);
-// child = GET_CHILD(n, v4, bits);
-// }
else
s->local_pos = 0x10 + bits;
-// if (plen > nlen && NEXT_PREFIX(child, net, v4))
-// {
-// s->stack_pos++;
-// s->stack[s->stack_pos] = child;
-// s->local_pos = 0x1f;
-// }
-
-// if (s->local_pos != 0x1f)
-// {
-// s->local_pos = 0x10 + bits;
-// }
+
}
else
{
nlen = v4 ? n->v4.plen : n->v6.plen;
s->accept_length = nlen;
-
-// if (k4)
-// /* compressed child */
-// if (n->v4.c[bits] != NULL && n->v4.c[bits]->plen > nlen + TRIE_STEP &&
-// ip4_getbits((n->v4.c[bits]->addr), nlen + TRIE_STEP, TRIE_STEP) < ip4_getbits(((net_addr_ip4 *)net)->prefix, nlen + TRIE_STEP, TRIE_STEP))
-// {
-// s->stack_pos++;
-// s->stack[s->stack_pos] = (const struct f_trie_node *) n->v4.c[bits];
-// s->local_pos = 0x1f;
-// }
-// else
-// s->local_pos = 0x10 + bits;
-// else
-// {}
}
return 0;
find_successor:;
- log("find_successor");
ASSERT(n != NULL);
u32 nlen = v4 ? n->v4.plen : n->v6.plen;
- {
- _print_node(n, v4);
- }
u32 bits = GET_NET_BITS(net, v4, nlen, TRIE_STEP);
s->local_pos = 0x10 + bits;
-// //const struct f_trie_node *old = n;
-// if (v4)
-// {
-// struct net_addr_ip4 *addr = &((union net_addr_union *) &local)->ip4;
-// u32 bits = ip4_getbits(addr->prefix, nlen, TRIE_STEP);
-// /* what about compress nodes ?!? TODO */
-// s->local_pos = 0x10 + bits;
-// }
-// else
-// {
-// }
return 0;
}
* 1
* 2 3
* 4 5 6 7
- * 8 9 A B C D E e
+ * 8 9 A B C D E F
*
* We walk them depth-first, including virtual positions 10-1F that are
* equivalent of position 1 in child nodes 0-F.
get_random_prefix(&px->prefix, v6, tight);
add_tail(prefixes, &px->n);
- char buf[64];
- bt_format_net(buf, 64, &px->prefix.net);
- bt_debug("ADD %s{%d,%d}\n", buf, px->prefix.lo, px->prefix.hi);
+ //char buf[64];
+ //bt_format_net(buf, 64, &px->prefix.net);
+ //bt_debug("ADD %s{%d,%d}\n", buf, px->prefix.lo, px->prefix.hi);
+ //log("ADD %s{%d,%d}", buf, px->prefix.lo, px->prefix.hi);
}
return prefixes;
px->prefix.hi = plus ? IP4_MAX_PREFIX_LENGTH : pl;
add_tail(pxlist, &px->n);
- char buf[64];
- bt_format_net(buf, 64, &px->prefix.net);
- bt_debug("ADD %s{%d,%d}\n", buf, px->prefix.lo, px->prefix.hi);
+ //char buf[64];
+ //bt_format_net(buf, 64, &px->prefix.net);
+ //bt_debug("ADD %s{%d,%d}\n", buf, px->prefix.lo, px->prefix.hi);
}
bt_syscall(errno, "fgets()");
{
bt_bird_init();
bt_config_parse(BT_CONFIG_SIMPLE);
+ //unsigned int r = rand();
+ //printf("random seed %u\n", r);
+ //srandom(r);
+ //srandom(1985510202);
for (int round = 0; round < TESTS_NUM*8; round++)
{
qsort(pxset, num, sizeof(struct f_prefix), compare_prefixes);
- // print sorted prefixes
- bt_debug("sorted prefixes\n");
- for (struct f_prefix *px = pxset; px < pxset + num; px++)
- {
- char buf[64];
- 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);
-
- pos = 0;
- uint pxc = 0;
- /* Last argument should have no effect on the walk */
- TRIE_WALK2(trie, net, NULL, 1)
- {
- log_networks(&net, &pxset[pos].net);
- bt_assert(net_equal(&net, &pxset[pos].net));
-
- /* Skip possible duplicates */
- while (net_equal(&pxset[pos].net, &pxset[pos + 1].net))
- pos++;
-
- pos++;
- pxc++;
- }
- TRIE_WALK2_END;
-
- bt_assert(pos == num);
- bt_assert(pxc == trie->prefix_count);
- bt_debug("Full walk inclusive done\n");
-
/* Prepare net for subnet walk - start with random prefix from trie */
if (num)
/* Subnet walk */
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);
+
+ if (!net_equal(&net, &pxset[pos + 1].net) || !(net_compare(&net, &from.net) >= 0))
+ {
+ /* 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);
+
/* Skip possible duplicates */
while (net_equal(&pxset[pos].net, &pxset[pos + 1].net))
pos++;
pos++;
+
}
TRIE_WALK2_END;
- bt_assert(pos == num);
+
+ bt_debug("pos == num %u %u; p0 %u \n", pos, num, p0);
bt_debug("Subnet walk done inclusive for %s (found %d nets)\n", buf0, pos - p0);
+ bt_assert(pos == num);
/* 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);
+ //bt_debug(" -> %s ", buf0);
if (net_compare(&pxset[pos].net, &from.net) >= 0)
{
- bt_debug("true, breaking\n");
+ //bt_debug("true, breaking\n");
break;
}
else
- bt_debug("false\n");
+ {} //bt_debug("false\n");
}
p0 = pos;
/* 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)
+ if (!net_equal(&net, &pxset[pos].net) || !(net_compare(&net, &from.net) >= 0))
{
- bt_format_net(buf0, 64, &pxset[pos + 1].net);
- bt_debug(" (next: %s)\n", buf0);
+ if (pos < num)
+ {
+ bt_format_net(buf0, 64, &net);
+ bt_debug("got: %s", buf0);
+ bt_format_net(buf0, 64, &pxset[pos].net);
+ bt_debug(" expected %s", buf0);
+ }
+
+ /* Make sure that net is from inserted prefixes */
+ if (pos + 1 < num)
+ {
+ bt_format_net(buf0, 64, &pxset[pos + 1].net);
+ bt_debug(" (next: %s)\n", buf0);
+ }
+ else
+ bt_debug("\n");
}
- else
- bt_debug("\n");
bt_assert(net_equal(&net, &pxset[pos].net));
bt_assert(net_compare(&net, &from.net) >= 0);