]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
route: replace rt_find with rb_tree_find_node
authorRoy Marples <roy@marples.name>
Mon, 4 Mar 2019 10:29:56 +0000 (10:29 +0000)
committerRoy Marples <roy@marples.name>
Mon, 4 Mar 2019 10:29:56 +0000 (10:29 +0000)
src/if-options.c
src/ipv4.c
src/route.c
src/route.h

index ccd5b5453d547e251607e065692cd9132b08b93e..074912d42bb949373ca67df24dec38e046689e8c 100644 (file)
@@ -2279,7 +2279,7 @@ default_config(struct dhcpcd_ctx *ctx)
        ifo->reboot = DEFAULT_REBOOT;
        ifo->metric = -1;
        ifo->auth.options |= DHCPCD_AUTH_REQUIRE;
-       rb_tree_init(&ifo->routes, &rt_rb_tree_ops);
+       rb_tree_init(&ifo->routes, &rt_compare_list_ops);
 #ifdef AUTH
        TAILQ_INIT(&ifo->auth.tokens);
 #endif
index 952b24fee7227d7a44429716b08f67a5a46a69db..1bdfc4c53a3a2159287e4101c15f212668508bd6 100644 (file)
@@ -263,7 +263,7 @@ inet_dhcproutes(rb_tree_t *routes, struct interface *ifp)
        /* An address does have to exist. */
        assert(state->addr);
 
-       rb_tree_init(&nroutes, &rt_rb_tree_ops);
+       rb_tree_init(&nroutes, &rt_compare_list_ops);
 
        /* First, add a subnet route. */
        if (!(ifp->flags & IFF_POINTOPOINT) &&
@@ -451,7 +451,7 @@ inet_getroutes(struct dhcpcd_ctx *ctx, rb_tree_t *routes)
        /* If there is no default route, see if we can use an IPv4LL one. */
        memset(&def, 0, sizeof(def));
        def.rt_dest.sa_family = AF_INET;
-       have_default = (rt_find(routes, &def) != NULL);
+       have_default = (rb_tree_find_node(routes, &def) != NULL);
        if (!have_default) {
                TAILQ_FOREACH(ifp, ctx->ifaces, next) {
                        if (ifp->active &&
index 7d4c68034301d05748f5d18329ebc085547b71e6..501bd014dc73479e436494e2392911539d2436b5 100644 (file)
         (N) = (S))
 #endif
 
+/*
+ * On some systems, host routes have no need for a netmask.
+ * However DHCP specifies host routes using an all-ones netmask.
+ * This handy function allows easy comparison when the two
+ * differ.
+ */
+static int
+rt_cmp_netmask(const struct rt *rt1, const struct rt *rt2)
+{
+
+       if (rt1->rt_flags & RTF_HOST && rt2->rt_flags & RTF_HOST)
+               return 0;
+       return sa_cmp(&rt1->rt_netmask, &rt2->rt_netmask);
+}
+
+static bool rt_compare_os;
+#define NODE_CMP(a, b) ((a) == (b) ? 0 : (a) < (b) ? -1 : 1)
+
 static int
-rt_compare(__unused void *context, const void *node1, const void *node2)
+rt_compare(void *context, const void *node1, const void *node2)
 {
        const struct rt *rt1 = node1, *rt2 = node2;
        bool rt1u, rt2u;
@@ -82,49 +100,63 @@ rt_compare(__unused void *context, const void *node1, const void *node2)
        c = sa_cmp(&rt1->rt_dest, &rt2->rt_dest);
        if (c != 0)
                return c;
-       c = sa_cmp(&rt1->rt_netmask, &rt2->rt_netmask);
+       c = rt_cmp_netmask(rt1, rt2);
        if (c != 0)
                return c;
 
-       /* Finally by interface metric. */
+#ifndef HAVE_ROUTE_METRIC
+       if (context == &rt_compare_os) {
+#ifdef ROUTE_PER_GATEWAY
+               c = NODE_CMP(rt1, rt2);
+#endif
+               return c;
+       }
+#else
+       UNUSED(context);
+#endif
        if (rt1->rt_ifp == NULL || rt2->rt_ifp == NULL)
-               /* option or freed route */
-               c = rt1 == rt2 ? 0 : rt1 < rt2 ? -1 : 1;
+               c = 0;
        else
                c = (int)(rt1->rt_ifp->metric - rt2->rt_ifp->metric);
 
        return c;
 }
 
-const rb_tree_ops_t rt_rb_tree_ops = {
+static const rb_tree_ops_t rt_compare_os_ops = {
+       .rbto_compare_nodes = rt_compare,
+       .rbto_compare_key = rt_compare,
+       .rbto_node_offset = offsetof(struct rt, rt_tree),
+       .rbto_context = &rt_compare_os
+};
+
+const rb_tree_ops_t rt_compare_list_ops = {
        .rbto_compare_nodes = rt_compare,
        .rbto_compare_key = rt_compare,
        .rbto_node_offset = offsetof(struct rt, rt_tree),
        .rbto_context = NULL
 };
 
-void
-rt_init(struct dhcpcd_ctx *ctx)
+static int
+rt_compare_free(__unused void *context, const void *node1, const void *node2)
 {
 
-       rb_tree_init(&ctx->routes, &rt_rb_tree_ops);
-       rb_tree_init(&ctx->kroutes, &rt_rb_tree_ops);
-       rb_tree_init(&ctx->froutes, &rt_rb_tree_ops);
+       return NODE_CMP(node1, node2);
 }
 
-/*
- * On some systems, host routes have no need for a netmask.
- * However DHCP specifies host routes using an all-ones netmask.
- * This handy function allows easy comparison when the two
- * differ.
- */
-static int
-rt_cmp_netmask(const struct rt *rt1, const struct rt *rt2)
+static const rb_tree_ops_t rt_compare_free_ops = {
+       .rbto_compare_nodes = rt_compare_free,
+       .rbto_compare_key = rt_compare_free,
+       .rbto_node_offset = offsetof(struct rt, rt_tree),
+       .rbto_context = NULL
+};
+
+void
+rt_init(struct dhcpcd_ctx *ctx)
 {
 
-       if (rt1->rt_flags & RTF_HOST && rt2->rt_flags & RTF_HOST)
-               return 0;
-       return sa_cmp(&rt1->rt_netmask, &rt2->rt_netmask);
+       rb_tree_init(&ctx->routes, &rt_compare_os_ops);
+       rb_tree_init(&ctx->kroutes, &rt_compare_os_ops);
+       rb_tree_init(&ctx->froutes, &rt_compare_free_ops);
 }
 
 static void
@@ -300,25 +332,6 @@ rt_freeif(struct interface *ifp)
        }
 }
 
-struct rt *
-rt_find(rb_tree_t *rts, const struct rt *f)
-{
-       struct rt *rt;
-
-       assert(rts != NULL);
-       assert(f != NULL);
-       RB_TREE_FOREACH(rt, rts) {
-               if (sa_cmp(&rt->rt_dest, &f->rt_dest) == 0 &&
-#ifdef HAVE_ROUTE_METRIC
-                   (f->rt_ifp == NULL ||
-                   rt->rt_ifp->metric == f->rt_ifp->metric) &&
-#endif
-                   rt_cmp_netmask(f, rt) == 0)
-                       return rt;
-       }
-       return NULL;
-}
-
 static void
 rt_kfree(struct rt *rt)
 {
@@ -327,10 +340,11 @@ rt_kfree(struct rt *rt)
 
        assert(rt != NULL);
        ctx = rt->rt_ifp->ctx;
-       if ((f = rt_find(&ctx->kroutes, rt)) != NULL) {
-               rb_tree_remove_node(&ctx->kroutes, f);
-               rt_free(f);
-       }
+       f = rb_tree_find_node(&ctx->kroutes, rt);
+       if (f == NULL)
+               return;
+       rb_tree_remove_node(&ctx->kroutes, f);
+       rt_free(f);
 }
 
 /* If something other than dhcpcd removes a route,
@@ -346,7 +360,7 @@ rt_recvrt(int cmd, const struct rt *rt)
        assert(rt->rt_ifp->ctx != NULL);
 
        ctx = rt->rt_ifp->ctx;
-       f = rt_find(&ctx->kroutes, rt);
+       f = rb_tree_find_node(&ctx->kroutes, rt);
 
        switch(cmd) {
        case RTM_DELETE:
@@ -354,7 +368,8 @@ rt_recvrt(int cmd, const struct rt *rt)
                        rb_tree_remove_node(&ctx->kroutes, f);
                        rt_free(f);
                }
-               if ((f = rt_find(&ctx->routes, rt)) != NULL) {
+               f = rb_tree_find_node(&ctx->routes, rt);
+               if (f != NULL) {
                        rb_tree_remove_node(&ctx->routes, f);
                        rt_desc("deleted", f);
                        rt_free(f);
@@ -404,7 +419,7 @@ rt_add(struct rt *nrt, struct rt *ort)
 
        change = false;
        if (ort == NULL) {
-               ort = rt_find(&ctx->kroutes, nrt);
+               ort = rb_tree_find_node(&ctx->kroutes, nrt);
                if (ort != NULL &&
                    ((ort->rt_flags & RTF_REJECT &&
                      nrt->rt_flags & RTF_REJECT) ||
@@ -533,7 +548,8 @@ rt_doroute(struct rt *rt)
 
        ctx = rt->rt_ifp->ctx;
        /* Do we already manage it? */
-       if ((or = rt_find(&ctx->routes, rt))) {
+       or = rb_tree_find_node(&ctx->routes, rt);
+       if (or != NULL) {
                if (rt->rt_dflags & RTDF_FAKE)
                        return true;
                if (or->rt_dflags & RTDF_FAKE ||
@@ -549,7 +565,8 @@ rt_doroute(struct rt *rt)
                rt_free(or);
        } else {
                if (rt->rt_dflags & RTDF_FAKE) {
-                       if ((or = rt_find(&ctx->kroutes, rt)) == NULL)
+                       or = rb_tree_find_node(&ctx->kroutes, rt);
+                       if (or == NULL)
                                return false;
                        if (!rt_cmp(rt, or))
                                return false;
@@ -569,12 +586,8 @@ rt_build(struct dhcpcd_ctx *ctx, int af)
        struct rt *rt, *rtn;
        unsigned long long o;
 
-       /* We need to have the interfaces in the correct order to ensure
-        * our routes are managed correctly. */
-       if_sortinterfaces(ctx);
-
-       rb_tree_init(&routes, &rt_rb_tree_ops);
-       rb_tree_init(&added, &rt_rb_tree_ops);
+       rb_tree_init(&routes, &rt_compare_list_ops);
+       rb_tree_init(&added, &rt_compare_os_ops);
 
        switch (af) {
 #ifdef INET
@@ -596,7 +609,7 @@ rt_build(struct dhcpcd_ctx *ctx, int af)
                    rt->rt_gateway.sa_family != af)
                        continue;
                /* Is this route already in our table? */
-               if ((rt_find(&added, rt)) != NULL)
+               if (rb_tree_find_node(&added, rt) != NULL)
                        continue;
                if (rt_doroute(rt)) {
                        rb_tree_remove_node(&routes, rt);
@@ -609,7 +622,7 @@ rt_build(struct dhcpcd_ctx *ctx, int af)
                rb_tree_remove_node(&ctx->routes, rt);
                if (rt->rt_dest.sa_family == af &&
                    rt->rt_gateway.sa_family == af &&
-                   rt_find(&added, rt) == NULL)
+                   rb_tree_find_node(&added, rt) == NULL)
                {
                        o = rt->rt_ifp->options ?
                            rt->rt_ifp->options->options :
@@ -622,7 +635,7 @@ rt_build(struct dhcpcd_ctx *ctx, int af)
                rt_free(rt);
        }
 
-       /* XXX This can be optimised if */
+       /* XXX This needs to be optimised. */
        while ((rt = RB_TREE_MIN(&added)) != NULL) {
                rb_tree_remove_node(&added, rt);
                rb_tree_insert_node(&ctx->routes, rt);
index 1568ccc228dcd943bfdfce67d3d0643f2e8605af..19b0d4c9998a86353d941b0a263633c9f196b01a 100644 (file)
@@ -84,11 +84,10 @@ struct rt {
        rb_node_t               rt_tree;
 };
 
-extern const rb_tree_ops_t rt_rb_tree_ops;
+extern const rb_tree_ops_t rt_compare_list_ops;
 
 void rt_init(struct dhcpcd_ctx *);
 void rt_dispose(struct dhcpcd_ctx *);
-struct rt * rt_find(rb_tree_t *, const struct rt *);
 void rt_free(struct rt *);
 void rt_freeif(struct interface *);
 void rt_headclear0(struct dhcpcd_ctx *, rb_tree_t *, int);