]> git.puffer.fish Git - matthieu/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, 4 Jan 2017 00:07:13 +0000 (22:07 -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 dc9879ef233d4ec66e33841f19187c1b09bae164..b339c9ce6bd6ff95c732d71359f59cc690663eb2 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 80557ed4effd9ad2b72b1ef481e3fe088575a7f2..3feb27d1689fd90146000a400e588e81fd0c62ba 100644 (file)
@@ -476,7 +476,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)
@@ -514,7 +514,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 95b0971e645493edbcc372afef5a926dc23693c6..b66d8d4698d7aab5b77d3a91dc72e0a09144385a 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_ref(vty_conf, (void **)&l2vpn);
        VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn);
@@ -1706,12 +1706,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;
@@ -1728,7 +1728,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 37cc0dec16eccc10eb2de2388c479fdc425603ca..dab761db7f6836ecdf6594aad3ff97c1cd6927b8 100644 (file)
@@ -868,7 +868,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);
@@ -930,7 +930,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;
@@ -1035,7 +1035,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);
@@ -1051,12 +1051,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);
@@ -1105,8 +1105,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);
        }
 
@@ -1469,10 +1469,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:
@@ -1494,11 +1494,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:
@@ -1516,7 +1516,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);
@@ -1773,7 +1773,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 d8f75a0eec9e374a7a4b4fb3a603325dccf3de9e..72e5dc5bcf66961e5c293bf1c372a02acb324e9e 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 e9e45f8fe3a3bea6474d63b27e12ac2f87fc0170..6edd180a43e8e453d2c8394a9f73bd1875f5c33f 100644 (file)
@@ -417,7 +417,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)
@@ -455,7 +455,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)