]> git.puffer.fish Git - mirror/frr.git/commitdiff
ldpd: use red-black trees to store 'iface' elements
authorRenato Westphal <renato@opensourcerouting.org>
Tue, 13 Dec 2016 17:29:35 +0000 (15:29 -0200)
committerRenato Westphal <renato@opensourcerouting.org>
Wed, 15 Feb 2017 09:19:52 +0000 (07:19 -0200)
Using red-black trees instead of linked lists brings the following
benefits:
1 - Elements are naturally ordered (no need to reorder anything before
    outputting data to the user);
2 - Faster lookups/deletes: O(log n) time complexity against O(n).

The insert operation with red-black trees is more expensive though,
but that's not a big issue since lookups are much more frequent.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
ldpd/interface.c
ldpd/lde.c
ldpd/ldp_debug.c
ldpd/ldp_vty_conf.c
ldpd/ldpd.c
ldpd/ldpd.h
ldpd/ldpe.c

index b6472fe5e8c661405c9f40225267466b8416adbe..06d36fef72dea2ee357a84d4ccfaaefd88821db1 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "sockopt.h"
 
+static __inline int     iface_compare(struct iface *, struct iface *);
 static struct if_addr  *if_addr_new(struct kaddr *);
 static struct if_addr  *if_addr_lookup(struct if_addr_head *, struct kaddr *);
 static int              if_start(struct iface *, int);
@@ -39,6 +40,14 @@ static int            if_leave_ipv4_group(struct iface *, struct in_addr *);
 static int              if_join_ipv6_group(struct iface *, struct in6_addr *);
 static int              if_leave_ipv6_group(struct iface *, struct in6_addr *);
 
+RB_GENERATE(iface_head, iface, entry, iface_compare)
+
+static __inline int
+iface_compare(struct iface *a, struct iface *b)
+{
+       return (strcmp(a->name, b->name));
+}
+
 struct iface *
 if_new(struct kif *kif)
 {
@@ -69,18 +78,6 @@ if_new(struct kif *kif)
        return (iface);
 }
 
-struct iface *
-if_lookup(struct ldpd_conf *xconf, unsigned short ifindex)
-{
-       struct iface *iface;
-
-       LIST_FOREACH(iface, &xconf->iface_list, entry)
-               if (iface->ifindex == ifindex)
-                       return (iface);
-
-       return (NULL);
-}
-
 void
 if_exit(struct iface *iface)
 {
@@ -100,17 +97,25 @@ if_exit(struct iface *iface)
 }
 
 struct iface *
-if_lookup_name(struct ldpd_conf *xconf, const char *ifname)
+if_lookup(struct ldpd_conf *xconf, unsigned short ifindex)
 {
        struct iface *iface;
 
-       LIST_FOREACH(iface, &xconf->iface_list, entry)
-               if (strcmp(iface->name, ifname) == 0)
+       RB_FOREACH(iface, iface_head, &xconf->iface_tree)
+               if (iface->ifindex == ifindex)
                        return (iface);
 
        return (NULL);
 }
 
+struct iface *
+if_lookup_name(struct ldpd_conf *xconf, const char *ifname)
+{
+       struct iface     iface;
+       strlcpy(iface.name, ifname, sizeof(iface.name));
+       return (RB_FIND(iface_head, &xconf->iface_tree, &iface));
+}
+
 void
 if_update_info(struct iface *iface, struct kif *kif)
 {
@@ -380,7 +385,7 @@ if_update_all(int af)
 {
        struct iface            *iface;
 
-       LIST_FOREACH(iface, &leconf->iface_list, entry)
+       RB_FOREACH(iface, iface_head, &leconf->iface_tree)
                if_update(iface, af);
 }
 
index 47bb326258592f97311dc0652cd2cfc6cac1be8e..29e0fac3277fbc1a1457799a5a27156635a04aae 100644 (file)
@@ -472,7 +472,7 @@ lde_dispatch_parent(struct thread *thread)
                                fatal(NULL);
                        memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
 
-                       LIST_INIT(&nconf->iface_list);
+                       RB_INIT(&nconf->iface_tree);
                        LIST_INIT(&nconf->tnbr_list);
                        LIST_INIT(&nconf->nbrp_list);
                        LIST_INIT(&nconf->l2vpn_list);
@@ -488,7 +488,7 @@ lde_dispatch_parent(struct thread *thread)
                        niface->ipv4.iface = niface;
                        niface->ipv6.iface = niface;
 
-                       LIST_INSERT_HEAD(&nconf->iface_list, niface, entry);
+                       RB_INSERT(iface_head, &nconf->iface_tree, niface);
                        break;
                case IMSG_RECONF_TNBR:
                        if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
index 15dd06a0f3ecf952ea7314b419039ff71e9672c6..86b679d8aa28269c2ec0c0f7669af62f63c9c2df 100644 (file)
@@ -74,7 +74,7 @@ ldp_vty_debug(struct vty *vty, struct vty_arg *args[])
                        DEBUG_OFF(event, EVENT);
                else
                        DEBUG_ON(event, EVENT);
-       } else  if (strcmp(type_str, "messages") == 0) {
+       } else if (strcmp(type_str, "messages") == 0) {
                all = (vty_get_arg_value(args, "all")) ? 1 : 0;
                dir_str = vty_get_arg_value(args, "dir");
                if (dir_str == NULL)
@@ -99,7 +99,7 @@ ldp_vty_debug(struct vty *vty, struct vty_arg *args[])
                                        DEBUG_ON(msg, MSG_SEND_ALL);
                        }
                }
-       } else  if (strcmp(type_str, "zebra") == 0) {
+       } else if (strcmp(type_str, "zebra") == 0) {
                if (disable)
                        DEBUG_OFF(zebra, ZEBRA);
                else
index e5acada1809e30070f7877754427c58856646a1f..e94de950d80f031c7f5516e1c8d5c6cfe9378de2 100644 (file)
@@ -142,7 +142,7 @@ ldp_af_iface_config_write(struct vty *vty, int af)
        struct iface            *iface;
        struct iface_af         *ia;
 
-       LIST_FOREACH(iface, &ldpd_conf->iface_list, entry) {
+       RB_FOREACH(iface, iface_head, &ldpd_conf->iface_tree) {
                ia = iface_af_get(iface, af);
                if (!ia->enabled)
                        continue;
@@ -857,7 +857,7 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[])
 
                ia = iface_af_get(iface, af);
                ia->enabled = 1;
-               LIST_INSERT_HEAD(&vty_conf->iface_list, iface, entry);
+               RB_INSERT(iface_head, &vty_conf->iface_tree, iface);
                ldp_reload_ref(vty_conf, (void **)&iface);
        } else {
                memset(&kif, 0, sizeof(kif));
@@ -1648,14 +1648,14 @@ iface_new_api(struct ldpd_conf *conf, const char *name)
        }
 
        iface = if_new(&kif);
-       LIST_INSERT_HEAD(&conf->iface_list, iface, entry);
+       RB_INSERT(iface_head, &conf->iface_tree, iface);
        return (iface);
 }
 
 void
-iface_del_api(struct iface *iface)
+iface_del_api(struct ldpd_conf *conf, struct iface *iface)
 {
-       LIST_REMOVE(iface, entry);
+       RB_REMOVE(iface_head, &conf->iface_tree, iface);
        free(iface);
 }
 
index 927af682a106e87ef0c8880d7b8761e87a4f0207..21456b4d1ed5f84e6d0ec5ef276ea4aded71ea04 100644 (file)
@@ -891,7 +891,7 @@ main_imsg_send_config(struct ldpd_conf *xconf)
            sizeof(*xconf)) == -1)
                return (-1);
 
-       LIST_FOREACH(iface, &xconf->iface_list, entry) {
+       RB_FOREACH(iface, iface_head, &xconf->iface_tree) {
                if (main_imsg_compose_both(IMSG_RECONF_IFACE, iface,
                    sizeof(*iface)) == -1)
                        return (-1);
@@ -995,10 +995,10 @@ ldp_config_reset_main(struct ldpd_conf *conf, void **ref)
        struct iface            *iface;
        struct nbr_params       *nbrp;
 
-       while ((iface = LIST_FIRST(&conf->iface_list)) != NULL) {
+       while ((iface = RB_ROOT(&conf->iface_tree)) != NULL) {
                if (ref && *ref == iface)
                        *ref = NULL;
-               LIST_REMOVE(iface, entry);
+               RB_REMOVE(iface_head, &conf->iface_tree, iface);
                free(iface);
        }
 
@@ -1028,7 +1028,7 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af, void **ref)
        struct iface_af         *ia;
        struct tnbr             *tnbr, *ttmp;
 
-       LIST_FOREACH(iface, &conf->iface_list, entry) {
+       RB_FOREACH(iface, iface_head, &conf->iface_tree) {
                ia = iface_af_get(iface, af);
                ia->enabled = 0;
        }
@@ -1073,16 +1073,16 @@ ldp_dup_config_ref(struct ldpd_conf *conf, void **ref)
        } while (0)
 
        COPY(xconf, conf);
-       LIST_INIT(&xconf->iface_list);
+       RB_INIT(&xconf->iface_tree);
        LIST_INIT(&xconf->tnbr_list);
        LIST_INIT(&xconf->nbrp_list);
        LIST_INIT(&xconf->l2vpn_list);
 
-       LIST_FOREACH(iface, &conf->iface_list, entry) {
+       RB_FOREACH(iface, iface_head, &conf->iface_tree) {
                COPY(xi, iface);
                xi->ipv4.iface = xi;
                xi->ipv6.iface = xi;
-               LIST_INSERT_HEAD(&xconf->iface_list, xi, entry);
+               RB_INSERT(iface_head, &xconf->iface_tree, xi);
        }
        LIST_FOREACH(tnbr, &conf->tnbr_list, entry) {
                COPY(xt, tnbr);
@@ -1134,8 +1134,8 @@ ldp_clear_config(struct ldpd_conf *xconf)
        struct nbr_params       *nbrp;
        struct l2vpn            *l2vpn;
 
-       while ((iface = LIST_FIRST(&xconf->iface_list)) != NULL) {
-               LIST_REMOVE(iface, entry);
+       while ((iface = RB_ROOT(&xconf->iface_tree)) != NULL) {
+               RB_REMOVE(iface_head, &xconf->iface_tree, iface);
                free(iface);
        }
        while ((tnbr = LIST_FIRST(&xconf->tnbr_list)) != NULL) {
@@ -1277,10 +1277,10 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
 {
        struct iface            *iface, *itmp, *xi;
 
-       LIST_FOREACH_SAFE(iface, &conf->iface_list, entry, itmp) {
+       RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) {
                /* find deleted interfaces */
                if ((xi = if_lookup_name(xconf, iface->name)) == NULL) {
-                       LIST_REMOVE(iface, entry);
+                       RB_REMOVE(iface_head, &conf->iface_tree, iface);
 
                        switch (ldpd_process) {
                        case PROC_LDE_ENGINE:
@@ -1295,11 +1295,11 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
                        free(iface);
                }
        }
-       LIST_FOREACH_SAFE(xi, &xconf->iface_list, entry, itmp) {
+       RB_FOREACH_SAFE(xi, iface_head, &xconf->iface_tree, itmp) {
                /* find new interfaces */
                if ((iface = if_lookup_name(conf, xi->name)) == NULL) {
-                       LIST_REMOVE(xi, entry);
-                       LIST_INSERT_HEAD(&conf->iface_list, xi, entry);
+                       RB_REMOVE(iface_head, &xconf->iface_tree, xi);
+                       RB_INSERT(iface_head, &conf->iface_tree, xi);
 
                        if (ldpd_process == PROC_MAIN) {
                                QOBJ_REG (xi, iface);
@@ -1312,7 +1312,7 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
                /* update existing interfaces */
                merge_iface_af(&iface->ipv4, &xi->ipv4);
                merge_iface_af(&iface->ipv6, &xi->ipv6);
-               LIST_REMOVE(xi, entry);
+               RB_REMOVE(iface_head, &xconf->iface_tree, xi);
                if (ref && *ref == xi)
                        *ref = iface;
                free(xi);
@@ -1811,7 +1811,7 @@ config_new_empty(void)
        if (xconf == NULL)
                fatal(NULL);
 
-       LIST_INIT(&xconf->iface_list);
+       RB_INIT(&xconf->iface_tree);
        LIST_INIT(&xconf->tnbr_list);
        LIST_INIT(&xconf->nbrp_list);
        LIST_INIT(&xconf->l2vpn_list);
index e58d8e4852c5706336e97562e9b0ced2c48cc99d..3e046447f2fc65a22a7534a6fed1c3cfa0f044bd 100644 (file)
@@ -264,7 +264,7 @@ struct iface_af {
 };
 
 struct iface {
-       LIST_ENTRY(iface)        entry;
+       RB_ENTRY(iface)          entry;
        char                     name[IF_NAMESIZE];
        unsigned int             ifindex;
        struct if_addr_head      addr_list;
@@ -275,6 +275,8 @@ struct iface {
        struct iface_af          ipv6;
        QOBJ_FIELDS
 };
+RB_HEAD(iface_head, iface);
+RB_PROTOTYPE(iface_head, iface, entry, iface_compare);
 DECLARE_QOBJ_TYPE(iface)
 
 /* source of targeted hellos */
@@ -404,7 +406,7 @@ struct ldpd_conf {
        struct in_addr           rtr_id;
        struct ldpd_af_conf      ipv4;
        struct ldpd_af_conf      ipv6;
-       LIST_HEAD(, iface)       iface_list;
+       struct iface_head        iface_tree;
        LIST_HEAD(, tnbr)        tnbr_list;
        LIST_HEAD(, nbr_params)  nbrp_list;
        LIST_HEAD(, l2vpn)       l2vpn_list;
@@ -627,9 +629,10 @@ void                        config_clear(struct ldpd_conf *);
 
 /* ldp_vty_conf.c */
 /* NOTE: the parameters' names should be preserved because of codegen */
-struct iface           *iface_new_api(struct ldpd_conf *cfg,
+struct iface           *iface_new_api(struct ldpd_conf *conf,
                            const char *name);
-void                    iface_del_api(struct iface *iface);
+void                    iface_del_api(struct ldpd_conf *conf,
+                           struct iface *iface);
 struct tnbr            *tnbr_new_api(struct ldpd_conf *cfg, int af,
                            union ldpd_addr *addr);
 void                    tnbr_del_api(struct tnbr *tnbr);
index 0d0fe5c9e92ab271fc78339f03c9738d83ccce3f..284d4cb35a33699345bac46a2b3304e3e8482bfb 100644 (file)
@@ -415,7 +415,7 @@ ldpe_dispatch_main(struct thread *thread)
                                fatal(NULL);
                        memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
 
-                       LIST_INIT(&nconf->iface_list);
+                       RB_INIT(&nconf->iface_tree);
                        LIST_INIT(&nconf->tnbr_list);
                        LIST_INIT(&nconf->nbrp_list);
                        LIST_INIT(&nconf->l2vpn_list);
@@ -431,7 +431,7 @@ ldpe_dispatch_main(struct thread *thread)
                        niface->ipv4.iface = niface;
                        niface->ipv6.iface = niface;
 
-                       LIST_INSERT_HEAD(&nconf->iface_list, niface, entry);
+                       RB_INSERT(iface_head, &nconf->iface_tree, niface);
                        break;
                case IMSG_RECONF_TNBR:
                        if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
@@ -773,7 +773,7 @@ ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
        struct iface_af         *ia;
        struct ctl_iface        *ictl;
 
-       LIST_FOREACH(iface, &leconf->iface_list, entry) {
+       RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
                if (idx == 0 || idx == iface->ifindex) {
                        ia = iface_af_get(iface, af);
                        if (!ia->enabled)
@@ -806,7 +806,7 @@ ldpe_adj_ctl(struct ctl_conn *c)
 
        imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
 
-       LIST_FOREACH(iface, &leconf->iface_list, entry) {
+       RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
                memset(&ictl, 0, sizeof(ictl));
                ictl.active_v4 = (iface->ipv4.state == IF_STA_ACTIVE);
                ictl.active_v6 = (iface->ipv6.state == IF_STA_ACTIVE);