On 05/22/2017 03:30 PM, Ondrej Zajicek wrote:
@@ -231,6 +232,20 @@ fib_find(struct fib *f, const net_addr *a) case NET_ROA6: return FIB_FIND(f, a, roa6); case NET_FLOW4: return FIB_FIND(f, a, flow4); case NET_FLOW6: return FIB_FIND(f, a, flow6); + case NET_SADR_IP6: + { + if (a->length != sizeof(net_addr_sadr_ip6)) + { + // dst only search + net_addr_ip6 a0; + net_copy((net_addr *)&a0, a); + a0.length = sizeof(net_addr_sadr_ip6); + + return FIB_FIND(f, &a0, sadr_dst); + } + else + return FIB_FIND(f, a, sadr_ip6); + } No. Generic fib_find() should implement exact-match search with matching net_addr type. If you need/want partial match, it should be done as a separate function. BTW, where do you need that?
I use it in net_route_sadr_ip6 below, the call to net_route_ip6 does destination only search. I wouldn't want to search all source prefix lengths for a specific dst length if there is no entry for that dst length at all.
Perhaps we should add some generic function partial-match IP-based search for network types that support it (e.g., ROA, SADR). But it would need a different interface, so caller could enumerate all valid matches. This seems like a good idea.
+static inline void * +net_route_sadr_ip6(rtable *t, net_addr_sadr_ip6 *n) +{ + net *r; + + net_addr_ip6 dst = NET_ADDR_IP6(n->dst_prefix, n->dst_pxlen); + dst.type = NET_SADR_IP6; + + // search for matching dst + while (r = net_route_ip6(t, &dst)) + { + // found a matching dst, start search for entries that match both prefixes + net_addr_sadr_ip6 full_addr = + NET_ADDR_SADR_IP6(dst.prefix, dst.pxlen, n->src_prefix, n->src_pxlen); + + while (r = net_find_valid(t, (net_addr *) &full_addr), (!r) && (full_addr.src_pxlen > 0)) + { + full_addr.src_pxlen--; + ip6_clrbit(&full_addr.src_prefix, full_addr.src_pxlen); + } + + if (r) + return r; + dst.pxlen--; You should set dst.pxlen based on r found by net_route_ip6(), to avoid repeated iteration over the same prefix lengths that did not match in the inner cycle. That would be set in the call to net_route_ip6.