]> git.puffer.fish Git - mirror/frr.git/commitdiff
ldpd: use red-black trees to store 'l2vpn' elements
authorRenato Westphal <renato@opensourcerouting.org>
Wed, 14 Dec 2016 12:42:45 +0000 (10:42 -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/l2vpn.c
ldpd/lde.c
ldpd/ldp_vty_conf.c
ldpd/ldpd.c
ldpd/ldpd.h
ldpd/ldpe.c

index b8c1728f6361e16623948288e2ab6e660e70f65d..6c8ce0396da7a8046cc3aae38f40f86ec424cb94 100644 (file)
 #include "lde.h"
 #include "log.h"
 
-static void     l2vpn_pw_fec(struct l2vpn_pw *, struct fec *);
+static void             l2vpn_pw_fec(struct l2vpn_pw *, struct fec *);
+static __inline int     l2vpn_compare(struct l2vpn *, struct l2vpn *);
+
+RB_GENERATE(l2vpn_head, l2vpn, entry, l2vpn_compare)
+
+static __inline int
+l2vpn_compare(struct l2vpn *a, struct l2vpn *b)
+{
+       return (strcmp(a->name, b->name));
+}
 
 struct l2vpn *
 l2vpn_new(const char *name)
@@ -52,13 +61,9 @@ l2vpn_new(const char *name)
 struct l2vpn *
 l2vpn_find(struct ldpd_conf *xconf, const char *name)
 {
-       struct l2vpn    *l2vpn;
-
-       LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry)
-               if (strcmp(l2vpn->name, name) == 0)
-                       return (l2vpn);
-
-       return (NULL);
+       struct l2vpn     l2vpn;
+       strlcpy(l2vpn.name, name, sizeof(l2vpn.name));
+       return (RB_FIND(l2vpn_head, &xconf->l2vpn_tree, &l2vpn));
 }
 
 void
@@ -399,7 +404,7 @@ l2vpn_sync_pws(int af, union ldpd_addr *addr)
        struct fec_node         *fn;
        struct fec_nh           *fnh;
 
-       LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) {
+       RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
                LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
                        if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr))
                                continue;
@@ -428,7 +433,7 @@ l2vpn_pw_ctl(pid_t pid)
        struct l2vpn_pw         *pw;
        static struct ctl_pw     pwctl;
 
-       LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry)
+       RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree)
                LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
                        memset(&pwctl, 0, sizeof(pwctl));
                        strlcpy(pwctl.l2vpn_name, pw->l2vpn->name,
index e137c01ddfc24f8e116d2065302d05341fac7083..948aa1b48d6d026a60f09b638ff49f2e5ee05e78 100644 (file)
@@ -475,7 +475,7 @@ lde_dispatch_parent(struct thread *thread)
                        RB_INIT(&nconf->iface_tree);
                        RB_INIT(&nconf->tnbr_tree);
                        RB_INIT(&nconf->nbrp_tree);
-                       LIST_INIT(&nconf->l2vpn_list);
+                       RB_INIT(&nconf->l2vpn_tree);
                        break;
                case IMSG_RECONF_IFACE:
                        if ((niface = malloc(sizeof(struct iface))) == NULL)
@@ -513,7 +513,7 @@ lde_dispatch_parent(struct thread *thread)
                        LIST_INIT(&nl2vpn->pw_list);
                        LIST_INIT(&nl2vpn->pw_inactive_list);
 
-                       LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry);
+                       RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
                        break;
                case IMSG_RECONF_L2VPN_IF:
                        if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
index 0145817d58b491e7c83f517b0ec820b6237272e4..50f5f63bc53db234bf5b0156d9a645af7af45e1e 100644 (file)
@@ -341,7 +341,7 @@ ldp_l2vpn_config_write(struct vty *vty)
        struct l2vpn_if         *lif;
        struct l2vpn_pw         *pw;
 
-       LIST_FOREACH(l2vpn, &ldpd_conf->l2vpn_list, entry) {
+       RB_FOREACH(l2vpn, l2vpn_head, &ldpd_conf->l2vpn_tree) {
                vty_out(vty, "l2vpn %s type vpls%s", l2vpn->name, VTY_NEWLINE);
 
                if (l2vpn->pw_type != DEFAULT_PW_TYPE)
@@ -393,7 +393,7 @@ ldp_iface_is_configured(struct ldpd_conf *xconf, const char *ifname)
        if (if_lookup_name(xconf, ifname))
                return (1);
 
-       LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) {
+       RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
                if (l2vpn_if_find_name(l2vpn, ifname))
                        return (1);
                if (l2vpn_pw_find_name(l2vpn, ifname))
@@ -1235,7 +1235,7 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[])
                if (l2vpn == NULL)
                        goto cancel;
 
-               LIST_REMOVE(l2vpn, entry);
+               RB_REMOVE(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn);
                l2vpn_del(l2vpn);
                ldp_reload(vty_conf);
                return (CMD_SUCCESS);
@@ -1248,7 +1248,7 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[])
 
        l2vpn = l2vpn_new(name_str);
        l2vpn->type = L2VPN_TYPE_VPLS;
-       LIST_INSERT_HEAD(&vty_conf->l2vpn_list, l2vpn, entry);
+       RB_INSERT(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn);
 
        ldp_reload(vty_conf);
        VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn);
@@ -1713,12 +1713,12 @@ l2vpn_new_api(struct ldpd_conf *conf, const char *name)
 
        l2vpn = l2vpn_new(name);
        l2vpn->type = L2VPN_TYPE_VPLS;
-       LIST_INSERT_HEAD(&conf->l2vpn_list, l2vpn, entry);
+       RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn);
        return (l2vpn);
 }
 
 void
-l2vpn_del_api(struct l2vpn *l2vpn)
+l2vpn_del_api(struct ldpd_conf *conf, struct l2vpn *l2vpn)
 {
        struct l2vpn_if         *lif;
        struct l2vpn_pw         *pw;
@@ -1735,7 +1735,7 @@ l2vpn_del_api(struct l2vpn *l2vpn)
                LIST_REMOVE(pw, entry);
                free(pw);
        }
-       LIST_REMOVE(l2vpn, entry);
+       RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
        free(l2vpn);
 }
 
index c1cef540e009061f9b9c50e1b0d823f722131814..1375b2672187487b2ba8ae2479a287e4c7e33a4f 100644 (file)
@@ -909,7 +909,7 @@ main_imsg_send_config(struct ldpd_conf *xconf)
                        return (-1);
        }
 
-       LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) {
+       RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
                if (main_imsg_compose_both(IMSG_RECONF_L2VPN, l2vpn,
                    sizeof(*l2vpn)) == -1)
                        return (-1);
@@ -971,7 +971,7 @@ ldp_config_normalize(struct ldpd_conf *xconf, void **ref)
                        ldp_config_reset_af(xconf, AF_INET6, ref);
        }
 
-       LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) {
+       RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
                LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
                        if (pw->flags & F_PW_STATIC_NBR_ADDR)
                                continue;
@@ -1076,7 +1076,7 @@ ldp_dup_config_ref(struct ldpd_conf *conf, void **ref)
        RB_INIT(&xconf->iface_tree);
        RB_INIT(&xconf->tnbr_tree);
        RB_INIT(&xconf->nbrp_tree);
-       LIST_INIT(&xconf->l2vpn_list);
+       RB_INIT(&xconf->l2vpn_tree);
 
        RB_FOREACH(iface, iface_head, &conf->iface_tree) {
                COPY(xi, iface);
@@ -1092,12 +1092,12 @@ ldp_dup_config_ref(struct ldpd_conf *conf, void **ref)
                COPY(xn, nbrp);
                RB_INSERT(nbrp_head, &xconf->nbrp_tree, xn);
        }
-       LIST_FOREACH(l2vpn, &conf->l2vpn_list, entry) {
+       RB_FOREACH(l2vpn, l2vpn_head, &conf->l2vpn_tree) {
                COPY(xl, l2vpn);
                LIST_INIT(&xl->if_list);
                LIST_INIT(&xl->pw_list);
                LIST_INIT(&xl->pw_inactive_list);
-               LIST_INSERT_HEAD(&xconf->l2vpn_list, xl, entry);
+               RB_INSERT(l2vpn_head, &xconf->l2vpn_tree, xl);
 
                LIST_FOREACH(lif, &l2vpn->if_list, entry) {
                        COPY(xf, lif);
@@ -1146,8 +1146,8 @@ ldp_clear_config(struct ldpd_conf *xconf)
                RB_REMOVE(nbrp_head, &xconf->nbrp_tree, nbrp);
                free(nbrp);
        }
-       while ((l2vpn = LIST_FIRST(&xconf->l2vpn_list)) != NULL) {
-               LIST_REMOVE(l2vpn, entry);
+       while ((l2vpn = RB_ROOT(&xconf->l2vpn_tree)) != NULL) {
+               RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, l2vpn);
                l2vpn_del(l2vpn);
        }
 
@@ -1510,10 +1510,10 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
        struct l2vpn_if         *lif;
        struct l2vpn_pw         *pw;
 
-       LIST_FOREACH_SAFE(l2vpn, &conf->l2vpn_list, entry, ltmp) {
+       RB_FOREACH_SAFE(l2vpn, l2vpn_head, &conf->l2vpn_tree, ltmp) {
                /* find deleted l2vpns */
                if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) {
-                       LIST_REMOVE(l2vpn, entry);
+                       RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
 
                        switch (ldpd_process) {
                        case PROC_LDE_ENGINE:
@@ -1535,11 +1535,11 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
                        l2vpn_del(l2vpn);
                }
        }
-       LIST_FOREACH_SAFE(xl, &xconf->l2vpn_list, entry, ltmp) {
+       RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) {
                /* find new l2vpns */
                if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) {
-                       LIST_REMOVE(xl, entry);
-                       LIST_INSERT_HEAD(&conf->l2vpn_list, xl, entry);
+                       RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
+                       RB_INSERT(l2vpn_head, &conf->l2vpn_tree, xl);
 
                        switch (ldpd_process) {
                        case PROC_LDE_ENGINE:
@@ -1557,7 +1557,7 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
 
                /* update existing l2vpns */
                merge_l2vpn(conf, l2vpn, xl, ref);
-               LIST_REMOVE(xl, entry);
+               RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
                if (ref && *ref == xl)
                        *ref = l2vpn;
                free(xl);
@@ -1814,7 +1814,7 @@ config_new_empty(void)
        RB_INIT(&xconf->iface_tree);
        RB_INIT(&xconf->tnbr_tree);
        RB_INIT(&xconf->nbrp_tree);
-       LIST_INIT(&xconf->l2vpn_list);
+       RB_INIT(&xconf->l2vpn_tree);
 
        return (xconf);
 }
index 248d9e7f6c1f0dc3b6ff9558a83086c8a793afaa..6c702287dd5de491bee32ac9aab2f2d0725ba730 100644 (file)
@@ -358,7 +358,7 @@ DECLARE_QOBJ_TYPE(l2vpn_pw)
 #define F_PW_STATIC_NBR_ADDR   0x20    /* static neighbor address configured */
 
 struct l2vpn {
-       LIST_ENTRY(l2vpn)        entry;
+       RB_ENTRY(l2vpn)          entry;
        char                     name[L2VPN_NAME_LEN];
        int                      type;
        int                      pw_type;
@@ -370,6 +370,8 @@ struct l2vpn {
        LIST_HEAD(, l2vpn_pw)    pw_inactive_list;
        QOBJ_FIELDS
 };
+RB_HEAD(l2vpn_head, l2vpn);
+RB_PROTOTYPE(l2vpn_head, l2vpn, entry, l2vpn_compare);
 DECLARE_QOBJ_TYPE(l2vpn)
 #define L2VPN_TYPE_VPWS                1
 #define L2VPN_TYPE_VPLS                2
@@ -413,7 +415,7 @@ struct ldpd_conf {
        struct iface_head        iface_tree;
        struct tnbr_head         tnbr_tree;
        struct nbrp_head         nbrp_tree;
-       LIST_HEAD(, l2vpn)       l2vpn_list;
+       struct l2vpn_head        l2vpn_tree;
        uint16_t                 lhello_holdtime;
        uint16_t                 lhello_interval;
        uint16_t                 thello_holdtime;
@@ -644,8 +646,9 @@ struct nbr_params   *nbrp_new_api(struct ldpd_conf *conf,
                            struct in_addr lsr_id);
 void                    nbrp_del_api(struct ldpd_conf *conf,
                            struct nbr_params *nbrp);
-struct l2vpn           *l2vpn_new_api(struct ldpd_conf *cfg, const char *name);
-void                    l2vpn_del_api(struct l2vpn *l2vpn);
+struct l2vpn           *l2vpn_new_api(struct ldpd_conf *conf, const char *name);
+void                    l2vpn_del_api(struct ldpd_conf *conf,
+                           struct l2vpn *l2vpn);
 struct l2vpn_if                *l2vpn_if_new_api(struct ldpd_conf *conf,
                            struct l2vpn *l2vpn, const char *ifname);
 void                    l2vpn_if_del_api(struct l2vpn_if *lif);
index 76988cb7019210ea53fa08e8f07ab0726837c5ec..54f4fef5999a483b3fd4ba993f954cdd0094ef18 100644 (file)
@@ -418,7 +418,7 @@ ldpe_dispatch_main(struct thread *thread)
                        RB_INIT(&nconf->iface_tree);
                        RB_INIT(&nconf->tnbr_tree);
                        RB_INIT(&nconf->nbrp_tree);
-                       LIST_INIT(&nconf->l2vpn_list);
+                       RB_INIT(&nconf->l2vpn_tree);
                        break;
                case IMSG_RECONF_IFACE:
                        if ((niface = malloc(sizeof(struct iface))) == NULL)
@@ -456,7 +456,7 @@ ldpe_dispatch_main(struct thread *thread)
                        LIST_INIT(&nl2vpn->pw_list);
                        LIST_INIT(&nl2vpn->pw_inactive_list);
 
-                       LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry);
+                       RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
                        break;
                case IMSG_RECONF_L2VPN_IF:
                        if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)