From b2902847692af80f7d0521852d2cf7549aad3100 Mon Sep 17 00:00:00 2001 From: Vojtech Vilimek Date: Wed, 5 Jul 2023 11:59:10 +0200 Subject: [PATCH] tests pass (several times) --- filter/trie.c | 277 ++++++++++++--------------------------------- filter/trie_test.c | 112 +++++++++--------- 2 files changed, 128 insertions(+), 261 deletions(-) diff --git a/filter/trie.c b/filter/trie.c index 3e2c1a3a..aba33f03 100644 --- a/filter/trie.c +++ b/filter/trie.c @@ -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; +// if (ns && !SAME_PREFIX(ns, net, v4, len)) +// { +// //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 = 1; - - s->accept_length = len; + 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. diff --git a/filter/trie_test.c b/filter/trie_test.c index 540f221b..edacd5dc 100644 --- a/filter/trie_test.c +++ b/filter/trie_test.c @@ -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);