route compare function doesn't consider prefixlen

Brett Ciphery brett.ciphery at windriver.com
Wed Jan 11 10:01:52 EST 2012


I've been playing around with a route cache in libnl and using an
nl_cache_foreach_filter to return specific routes based on a
destination, something like:

...
rtnl_route_set_family(filter, AF_INET);
rtnl_route_set_table(filter, RT_TABLE_MAIN);
nl_addr_parse( "10.0.0.0/16", AF_INET, &addrfilter);
rtnl_route_set_dst(filter, addrfilter);
nl_cache_foreach_filter(route_cache, (struct nl_object *)
filter, route_process, NULL);
...

But noticed it doesn't use the prefixlen in the route_compare function.
As an example, the above addrfilter will match a route of 10.0.0.0/8 as
well as 10.0.0.0/16 (why they're both set is another issue).

The problem is the call to nl_addr_cmp from route_compare
(route_obj.c:306):

diff |= ROUTE_DIFF(DST,         nl_addr_cmp(a->rt_dst, b->rt_dst));

doesn't consider prefixlen.  The below patch fixes it, but I see there
is also an nl_addr_cmp_prefix() maybe meant to be used, but it wasn't
giving me correct behaviour either when used inside route_compare.


--- a/lib/addr.c
+++ b/lib/addr.c
@@ -497,7 +497,10 @@ int nl_addr_cmp(struct nl_addr *a, struct nl_addr
*b)
                d = a->a_len - b->a_len;

                if (a->a_len && d == 0)
-                       return memcmp(a->a_addr, b->a_addr, a->a_len);
+                       d = memcmp(a->a_addr, b->a_addr, a->a_len);
+
+                       if (d == 0)
+                               return (a->a_prefixlen -
b->a_prefixlen);
        }

        return d;



Thoughts?

Brett



More information about the libnl mailing list