]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
tmp: tmp progress on trie API
authorVojtech Vilimek <vojtech.vilimek@nic.cz>
Fri, 28 Apr 2023 09:10:01 +0000 (11:10 +0200)
committerVojtech Vilimek <vojtech.vilimek@nic.cz>
Fri, 28 Apr 2023 09:10:01 +0000 (11:10 +0200)
filter/trie.c
filter/trie_test.c
lib/ip.h

index 288a4d13fb4c1333315280c6da5c4c9387a797f1..2a029f950c432db3c34f7655ed1ecbf35dbe29ad 100644 (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);
+    }
+
+    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;
 }
 
index 37bbbd1bca30529473938637265b40c4b09aee56..540f221b0edb2a416312828a79b4273da56e8895 100644 (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
index 73083ac991cb5f8354e0eb5d9ff5649df7d41d21..20e7a33633bd12373eaf64eda0eac2ca435c0ea4 100644 (file)
--- 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); }