]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ldpd: use red-black trees to store 'l2vpn_if' elements
authorRenato Westphal <renato@opensourcerouting.org>
Wed, 14 Dec 2016 14:34:57 +0000 (12:34 -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 6c8ce0396da7a8046cc3aae38f40f86ec424cb94..0382bedf87a6a213ea63a3e23646d2c4fbe43143 100644 (file)
 
 static void             l2vpn_pw_fec(struct l2vpn_pw *, struct fec *);
 static __inline int     l2vpn_compare(struct l2vpn *, struct l2vpn *);
+static __inline int     l2vpn_if_compare(struct l2vpn_if *, struct l2vpn_if *);
 
 RB_GENERATE(l2vpn_head, l2vpn, entry, l2vpn_compare)
+RB_GENERATE(l2vpn_if_head, l2vpn_if, entry, l2vpn_if_compare)
 
 static __inline int
 l2vpn_compare(struct l2vpn *a, struct l2vpn *b)
@@ -51,7 +53,7 @@ l2vpn_new(const char *name)
        l2vpn->mtu = DEFAULT_L2VPN_MTU;
        l2vpn->pw_type = DEFAULT_PW_TYPE;
 
-       LIST_INIT(&l2vpn->if_list);
+       RB_INIT(&l2vpn->if_tree);
        LIST_INIT(&l2vpn->pw_list);
        LIST_INIT(&l2vpn->pw_inactive_list);
 
@@ -72,8 +74,8 @@ l2vpn_del(struct l2vpn *l2vpn)
        struct l2vpn_if         *lif;
        struct l2vpn_pw         *pw;
 
-       while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) {
-               LIST_REMOVE(lif, entry);
+       while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) {
+               RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
                free(lif);
        }
        while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) {
@@ -106,6 +108,12 @@ l2vpn_exit(struct l2vpn *l2vpn)
                l2vpn_pw_exit(pw);
 }
 
+static __inline int
+l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b)
+{
+       return (strcmp(a->ifname, b->ifname));
+}
+
 struct l2vpn_if *
 l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif)
 {
@@ -127,7 +135,7 @@ l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex)
 {
        struct l2vpn_if *lif;
 
-       LIST_FOREACH(lif, &l2vpn->if_list, entry)
+       RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
                if (lif->ifindex == ifindex)
                        return (lif);
 
@@ -137,13 +145,9 @@ l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex)
 struct l2vpn_if *
 l2vpn_if_find_name(struct l2vpn *l2vpn, const char *ifname)
 {
-       struct l2vpn_if *lif;
-
-       LIST_FOREACH(lif, &l2vpn->if_list, entry)
-               if (strcmp(lif->ifname, ifname) == 0)
-                       return (lif);
-
-       return (NULL);
+       struct l2vpn_if  lif;
+       strlcpy(lif.ifname, ifname, sizeof(lif.ifname));
+       return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif));
 }
 
 
index 948aa1b48d6d026a60f09b638ff49f2e5ee05e78..76d56010f51ca1e91742662deb51938ac120853b 100644 (file)
@@ -509,7 +509,7 @@ lde_dispatch_parent(struct thread *thread)
                                fatal(NULL);
                        memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
 
-                       LIST_INIT(&nl2vpn->if_list);
+                       RB_INIT(&nl2vpn->if_tree);
                        LIST_INIT(&nl2vpn->pw_list);
                        LIST_INIT(&nl2vpn->pw_inactive_list);
 
@@ -521,7 +521,7 @@ lde_dispatch_parent(struct thread *thread)
                        memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
 
                        nlif->l2vpn = nl2vpn;
-                       LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry);
+                       RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
                        break;
                case IMSG_RECONF_L2VPN_PW:
                        if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
index 50f5f63bc53db234bf5b0156d9a645af7af45e1e..317fe3f2cb8f4959f0baade0a05bd9e8336395da 100644 (file)
@@ -354,7 +354,7 @@ ldp_l2vpn_config_write(struct vty *vty)
                        vty_out(vty, " bridge %s%s", l2vpn->br_ifname,
                            VTY_NEWLINE);
 
-               LIST_FOREACH(lif, &l2vpn->if_list, entry)
+               RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
                        vty_out(vty, " member interface %s%s", lif->ifname,
                            VTY_NEWLINE);
 
@@ -1369,7 +1369,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
                if (lif == NULL)
                        goto cancel;
 
-               LIST_REMOVE(lif, entry);
+               RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
                free(lif);
                ldp_reload(vty_conf);
                return (CMD_SUCCESS);
@@ -1392,7 +1392,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
        }
 
        lif = l2vpn_if_new(l2vpn, &kif);
-       LIST_INSERT_HEAD(&l2vpn->if_list, lif, entry);
+       RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
 
        ldp_reload_ref(vty_conf, (void **)&l2vpn);
 
@@ -1723,8 +1723,8 @@ l2vpn_del_api(struct ldpd_conf *conf, struct l2vpn *l2vpn)
        struct l2vpn_if         *lif;
        struct l2vpn_pw         *pw;
 
-       while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) {
-               LIST_REMOVE(lif, entry);
+       while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) {
+               RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
                free(lif);
        }
        while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) {
@@ -1759,14 +1759,14 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
        }
 
        lif = l2vpn_if_new(l2vpn, &kif);
-       LIST_INSERT_HEAD(&l2vpn->if_list, lif, entry);
+       RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
        return (lif);
 }
 
 void
-l2vpn_if_del_api(struct l2vpn_if *lif)
+l2vpn_if_del_api(struct l2vpn *l2vpn, struct l2vpn_if *lif)
 {
-       LIST_REMOVE(lif, entry);
+       RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
        free(lif);
 }
 
index 1375b2672187487b2ba8ae2479a287e4c7e33a4f..dce62801e70aaac0c69ea07640d738272ed7c555 100644 (file)
@@ -914,7 +914,7 @@ main_imsg_send_config(struct ldpd_conf *xconf)
                    sizeof(*l2vpn)) == -1)
                        return (-1);
 
-               LIST_FOREACH(lif, &l2vpn->if_list, entry) {
+               RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) {
                        if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IF, lif,
                            sizeof(*lif)) == -1)
                                return (-1);
@@ -1094,15 +1094,15 @@ ldp_dup_config_ref(struct ldpd_conf *conf, void **ref)
        }
        RB_FOREACH(l2vpn, l2vpn_head, &conf->l2vpn_tree) {
                COPY(xl, l2vpn);
-               LIST_INIT(&xl->if_list);
+               RB_INIT(&xl->if_tree);
                LIST_INIT(&xl->pw_list);
                LIST_INIT(&xl->pw_inactive_list);
                RB_INSERT(l2vpn_head, &xconf->l2vpn_tree, xl);
 
-               LIST_FOREACH(lif, &l2vpn->if_list, entry) {
+               RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) {
                        COPY(xf, lif);
                        xf->l2vpn = xl;
-                       LIST_INSERT_HEAD(&xl->if_list, xf, entry);
+                       RB_INSERT(l2vpn_if_head, &xl->if_tree, xf);
                }
                LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
                        COPY(xp, pw);
@@ -1523,7 +1523,7 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
                                ldpe_l2vpn_exit(l2vpn);
                                break;
                        case PROC_MAIN:
-                               LIST_FOREACH(lif, &l2vpn->if_list, entry)
+                               RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
                                        QOBJ_UNREG (lif);
                                LIST_FOREACH(pw, &l2vpn->pw_list, entry)
                                        QOBJ_UNREG (pw);
@@ -1578,27 +1578,27 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void
        previous_mtu = l2vpn->mtu;
 
        /* merge intefaces */
-       LIST_FOREACH_SAFE(lif, &l2vpn->if_list, entry, ftmp) {
+       RB_FOREACH_SAFE(lif, l2vpn_if_head, &l2vpn->if_tree, ftmp) {
                /* find deleted interfaces */
                if ((xf = l2vpn_if_find_name(xl, lif->ifname)) == NULL) {
                        if (ldpd_process == PROC_MAIN)
                                QOBJ_UNREG (lif);
-                       LIST_REMOVE(lif, entry);
+                       RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
                        free(lif);
                }
        }
-       LIST_FOREACH_SAFE(xf, &xl->if_list, entry, ftmp) {
+       RB_FOREACH_SAFE(xf, l2vpn_if_head, &xl->if_tree, ftmp) {
                /* find new interfaces */
                if ((lif = l2vpn_if_find_name(l2vpn, xf->ifname)) == NULL) {
-                       LIST_REMOVE(xf, entry);
-                       LIST_INSERT_HEAD(&l2vpn->if_list, xf, entry);
+                       RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
+                       RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf);
                        xf->l2vpn = l2vpn;
                        if (ldpd_process == PROC_MAIN)
                                QOBJ_REG (xf, l2vpn_if);
                        continue;
                }
 
-               LIST_REMOVE(xf, entry);
+               RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
                if (ref && *ref == xf)
                        *ref = lif;
                free(xf);
index 6c702287dd5de491bee32ac9aab2f2d0725ba730..9bda8ed218b5b6e9ddb65e819100e3a54c3cc6da 100644 (file)
@@ -325,13 +325,15 @@ DECLARE_QOBJ_TYPE(nbr_params)
 #define F_NBRP_GTSM_HOPS        0x04
 
 struct l2vpn_if {
-       LIST_ENTRY(l2vpn_if)     entry;
+       RB_ENTRY(l2vpn_if)       entry;
        struct l2vpn            *l2vpn;
        char                     ifname[IF_NAMESIZE];
        unsigned int             ifindex;
        uint16_t                 flags;
        QOBJ_FIELDS
 };
+RB_HEAD(l2vpn_if_head, l2vpn_if);
+RB_PROTOTYPE(l2vpn_if_head, l2vpn_if, entry, l2vpn_if_compare);
 DECLARE_QOBJ_TYPE(l2vpn_if)
 
 struct l2vpn_pw {
@@ -365,7 +367,7 @@ struct l2vpn {
        int                      mtu;
        char                     br_ifname[IF_NAMESIZE];
        unsigned int             br_ifindex;
-       LIST_HEAD(, l2vpn_if)    if_list;
+       struct l2vpn_if_head     if_tree;
        LIST_HEAD(, l2vpn_pw)    pw_list;
        LIST_HEAD(, l2vpn_pw)    pw_inactive_list;
        QOBJ_FIELDS
@@ -651,7 +653,8 @@ 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);
+void                    l2vpn_if_del_api(struct l2vpn *l2vpn,
+                          struct l2vpn_if *lif);
 struct l2vpn_pw                *l2vpn_pw_new_api(struct ldpd_conf *conf,
                            struct l2vpn *l2vpn, const char *ifname);
 void                    l2vpn_pw_del_api(struct l2vpn_pw *pw);
index 54f4fef5999a483b3fd4ba993f954cdd0094ef18..103a1ec412e5671d5a786102b33f2876382ddd04 100644 (file)
@@ -452,7 +452,7 @@ ldpe_dispatch_main(struct thread *thread)
                                fatal(NULL);
                        memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
 
-                       LIST_INIT(&nl2vpn->if_list);
+                       RB_INIT(&nl2vpn->if_tree);
                        LIST_INIT(&nl2vpn->pw_list);
                        LIST_INIT(&nl2vpn->pw_inactive_list);
 
@@ -464,7 +464,7 @@ ldpe_dispatch_main(struct thread *thread)
                        memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
 
                        nlif->l2vpn = nl2vpn;
-                       LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry);
+                       RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
                        break;
                case IMSG_RECONF_L2VPN_PW:
                        if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)