};
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)
{
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;
}
s->start_pos = 1;
}
+ log("return 1");
return 1;
}
/* 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);
+ }
+
+ 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--;
- /* Search whole trie except skipped parts */
- if (include_successors)
- s->start_pos = 1;
+ 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;
}
{
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);
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++)
{
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);
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++)
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);
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))
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