]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
tests pass (several times)
authorVojtech Vilimek <vojtech.vilimek@nic.cz>
Wed, 5 Jul 2023 09:59:10 +0000 (11:59 +0200)
committerVojtech Vilimek <vojtech.vilimek@nic.cz>
Wed, 5 Jul 2023 09:59:10 +0000 (11:59 +0200)
filter/trie.c
filter/trie_test.c

index 3e2c1a3a2cf19a3d70735d2ba8551f00f1aa380b..aba33f0336016f068542f7bfde4f434559beda84 100644 (file)
@@ -784,42 +784,10 @@ done:
 #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
@@ -885,9 +853,6 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad
        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))
@@ -904,64 +869,10 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad
              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
       {
@@ -988,61 +899,15 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad
   {
     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;
@@ -1050,8 +915,53 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad
     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)
       {
@@ -1067,63 +977,47 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad
          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
     {
@@ -1132,45 +1026,16 @@ trie_walk_init(struct f_trie_walk_state *s, const struct f_trie *t, const net_ad
 
     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;
 }
 
@@ -1208,7 +1073,7 @@ trie_walk_next(struct f_trie_walk_state *s, net_addr *net)
    *          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.
index 540f221b0edb2a416312828a79b4273da56e8895..edacd5dc3cf52a56e37a8a0c62e16532797c4dea 100644 (file)
@@ -260,9 +260,10 @@ make_random_prefix_list(int num, int v6, int tight)
     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;
@@ -314,9 +315,9 @@ read_prefix_list(FILE *f, int v6, int plus)
     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()");
@@ -885,6 +886,10 @@ t_trie_walk_inclusive(void)
 {
   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++)
   {
@@ -904,39 +909,6 @@ t_trie_walk_inclusive(void)
 
     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)
@@ -994,20 +966,43 @@ t_trie_walk_inclusive(void)
     /* 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);
@@ -1015,14 +1010,14 @@ t_trie_walk_inclusive(void)
     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;
@@ -1032,18 +1027,25 @@ t_trie_walk_inclusive(void)
     /* 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);