From: Renato Westphal Date: Tue, 13 Dec 2016 17:29:35 +0000 (-0200) Subject: ldpd: use red-black trees to store 'iface' elements X-Git-Tag: frr-3.0-branchpoint~94^2~1^2~6 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=7d3d7491a0bc4b04ee6f65e26ae5f115df5a34f1;p=matthieu%2Ffrr.git ldpd: use red-black trees to store 'iface' elements 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 --- diff --git a/ldpd/interface.c b/ldpd/interface.c index b6472fe5e8..06d36fef72 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -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); } diff --git a/ldpd/lde.c b/ldpd/lde.c index a1309c6448..1e362185d2 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -473,7 +473,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); @@ -489,7 +489,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) diff --git a/ldpd/ldp_debug.c b/ldpd/ldp_debug.c index 15dd06a0f3..86b679d8aa 100644 --- a/ldpd/ldp_debug.c +++ b/ldpd/ldp_debug.c @@ -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 diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index dd70365f3d..689554d857 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -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)); @@ -1641,14 +1641,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); } diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index aa1dc57a7b..14cfaffbb9 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -850,7 +850,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); @@ -954,10 +954,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); } @@ -987,7 +987,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; } @@ -1032,16 +1032,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); @@ -1093,8 +1093,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) { @@ -1236,10 +1236,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: @@ -1254,11 +1254,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); @@ -1271,7 +1271,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); @@ -1770,7 +1770,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); diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 630b192489..2c516c013b 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -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); diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index aef33c8e37..16910a3cc8 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -414,7 +414,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); @@ -430,7 +430,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) @@ -772,7 +772,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) @@ -805,7 +805,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);