From: Donald Sharp Date: Sat, 21 Dec 2019 04:00:31 +0000 (-0500) Subject: pimd: Convert the upstream_list and hash to a rb tree X-Git-Tag: base_7.3~39^2~1 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=dd3364cb1aa265ec0310e8ed8adffac16f6fb24e;p=matthieu%2Ffrr.git pimd: Convert the upstream_list and hash to a rb tree Convert the upstream_list and hash to a rb tree, Significant time was being spent in the listnode_add_sort. This reduces this time greatly. Signed-off-by: Donald Sharp --- diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 4f5ad89f8f..01bebebd29 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -914,7 +914,6 @@ static void pim_show_interfaces_single(struct pim_instance *pim, struct in_addr ifaddr; struct interface *ifp; struct listnode *neighnode; - struct listnode *upnode; struct pim_interface *pim_ifp; struct pim_neighbor *neigh; struct pim_upstream *up; @@ -1052,8 +1051,7 @@ static void pim_show_interfaces_single(struct pim_instance *pim, pim_ifp->pim_dr_election_changes); // FHR - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, - up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (ifp != up->rpf.source_nexthop.interface) continue; @@ -1215,8 +1213,7 @@ static void pim_show_interfaces_single(struct pim_instance *pim, // FHR print_header = 1; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, - up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (!up->rpf.source_nexthop.interface) continue; @@ -1386,7 +1383,6 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool uj) { struct interface *ifp; - struct listnode *upnode; struct pim_interface *pim_ifp; struct pim_upstream *up; int fhr = 0; @@ -1408,7 +1404,7 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, pim_ifchannels = pim_if_ifchannel_count(pim_ifp); fhr = 0; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) + frr_each (rb_pim_upstream, &pim->upstream_head, up) if (ifp == up->rpf.source_nexthop.interface) if (up->flags & PIM_UPSTREAM_FLAG_MASK_FHR) fhr++; @@ -2428,7 +2424,6 @@ static const char *pim_reg_state2brief_str(enum pim_reg_state reg_state, static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, struct prefix_sg *sg, bool uj) { - struct listnode *upnode; struct pim_upstream *up; time_t now; json_object *json = NULL; @@ -2443,7 +2438,7 @@ static void pim_show_upstream(struct pim_instance *pim, struct vty *vty, vty_out(vty, "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n"); - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { char src_str[INET_ADDRSTRLEN]; char grp_str[INET_ADDRSTRLEN]; char uptime[10]; @@ -2715,7 +2710,6 @@ static void pim_show_join_desired_helper(struct pim_instance *pim, static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj) { - struct listnode *upnode; struct pim_upstream *up; json_object *json = NULL; @@ -2726,7 +2720,7 @@ static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, vty_out(vty, "Source Group EvalJD\n"); - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { /* scan all interfaces */ pim_show_join_desired_helper(pim, vty, up, json, uj); @@ -2742,7 +2736,6 @@ static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj) { - struct listnode *upnode; struct pim_upstream *up; json_object *json = NULL; json_object *json_group = NULL; @@ -2754,7 +2747,7 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, vty_out(vty, "Source Group RpfIface RibNextHop RpfAddress \n"); - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { char src_str[INET_ADDRSTRLEN]; char grp_str[INET_ADDRSTRLEN]; char rpf_nexthop_str[PREFIX_STRLEN]; @@ -2875,7 +2868,6 @@ static void show_scan_oil_stats(struct pim_instance *pim, struct vty *vty, static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) { - struct listnode *up_node; struct pim_upstream *up; time_t now = pim_time_monotonic_sec(); json_object *json = NULL; @@ -2892,7 +2884,7 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, bool uj) "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n"); } - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, up_node, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { char src_str[INET_ADDRSTRLEN]; char grp_str[INET_ADDRSTRLEN]; char rpf_addr_str[PREFIX_STRLEN]; @@ -3932,11 +3924,8 @@ static void clear_mroute(struct pim_instance *pim) } /* clean up all upstreams*/ - if (pim->upstream_list) { - while (pim->upstream_list->count) { - up = listnode_head(pim->upstream_list); - pim_upstream_del(pim, up, __PRETTY_FUNCTION__); - } + while ((up = rb_pim_upstream_first(&pim->upstream_head))) { + pim_upstream_del(pim, up, __PRETTY_FUNCTION__); } } diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 5a95043df9..da0c75decb 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -29,6 +29,7 @@ #include "pim_bsm.h" #include "pim_vxlan_instance.h" #include "pim_oil.h" +#include "pim_upstream.h" #if defined(HAVE_LINUX_MROUTE_H) #include @@ -108,8 +109,7 @@ struct pim_instance { struct list *static_routes; // Upstream vrf specific information - struct list *upstream_list; - struct hash *upstream_hash; + struct rb_pim_upstream_head upstream_head; struct timer_wheel *upstream_sg_wheel; /* diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 8a18594fd7..58ebc6ce67 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -565,11 +565,9 @@ void pim_msdp_sa_local_update(struct pim_upstream *up) static void pim_msdp_sa_local_setup(struct pim_instance *pim) { struct pim_upstream *up; - struct listnode *up_node; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, up_node, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) pim_msdp_sa_local_update(up); - } } /* whenever the RP changes we need to re-evaluate the "local" SA-cache */ diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index bd8424b3e4..5cb9492ec3 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -177,7 +177,6 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr, struct pim_nexthop_cache *pnc = NULL; struct pim_nexthop_cache lookup; struct zclient *zclient = NULL; - struct listnode *upnode = NULL; struct pim_upstream *upstream = NULL; zclient = pim_zebra_zclient_get(); @@ -190,8 +189,8 @@ void pim_delete_tracked_nexthop(struct pim_instance *pim, struct prefix *addr, /* Release the (*, G)upstream from pnc->upstream_hash, * whose Group belongs to the RP getting deleted */ - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, - upstream)) { + frr_each (rb_pim_upstream, &pim->upstream_head, + upstream) { struct prefix grp; struct rp_info *trp_info; diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 5af3328a1a..598988f88f 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -86,26 +86,6 @@ int pim_channel_oil_compare(const struct channel_oil *c1, return 0; } -static bool pim_oil_equal(const void *arg1, const void *arg2) -{ - const struct channel_oil *c1 = (const struct channel_oil *)arg1; - const struct channel_oil *c2 = (const struct channel_oil *)arg2; - - if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) - && (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) - return true; - - return false; -} - -static unsigned int pim_oil_hash_key(const void *arg) -{ - const struct channel_oil *oil = arg; - - return jhash_2words(oil->oil.mfcc_mcastgrp.s_addr, - oil->oil.mfcc_origin.s_addr, 0); -} - void pim_oil_init(struct pim_instance *pim) { rb_pim_oil_init(&pim->channel_oil_head); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index bd295b0fef..2db39bac4b 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -446,7 +446,6 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, struct prefix nht_p; struct route_node *rn; struct pim_upstream *up; - struct listnode *upnode; if (rp_addr.s_addr == INADDR_ANY || rp_addr.s_addr == INADDR_NONE) @@ -554,8 +553,7 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, __PRETTY_FUNCTION__, buf, buf1); } - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, - up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { /* Find (*, G) upstream whose RP is not * configured yet */ @@ -650,7 +648,7 @@ int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr, rn->lock); } - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->sg.src.s_addr == INADDR_ANY) { struct prefix grp; struct rp_info *trp_info; @@ -723,7 +721,6 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, bool was_plist = false; struct rp_info *trp_info; struct pim_upstream *up; - struct listnode *upnode; struct bsgrp_node *bsgrp = NULL; struct bsm_rpinfo *bsrp = NULL; char grp_str[PREFIX2STR_BUFFER]; @@ -800,7 +797,7 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, rp_all = pim_rp_find_match_group(pim, &g_all); if (rp_all == rp_info) { - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { /* Find the upstream (*, G) whose upstream address is * same as the deleted RP */ @@ -852,7 +849,7 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr, pim_rp_refresh_group_to_rp_mapping(pim); - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { /* Find the upstream (*, G) whose upstream address is same as * the deleted RP */ @@ -893,7 +890,6 @@ int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr, int result = 0; struct rp_info *rp_info = NULL; struct pim_upstream *up; - struct listnode *upnode; rn = route_node_lookup(pim->rp_table, &group); if (!rn) { @@ -942,7 +938,7 @@ int pim_rp_change(struct pim_instance *pim, struct in_addr new_rp_addr, listnode_add_sort(pim->rp_list, rp_info); - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->sg.src.s_addr == INADDR_ANY) { struct prefix grp; struct rp_info *trp_info; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index a0387cdd4a..afd10bd3db 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -98,7 +98,6 @@ static void pim_upstream_find_new_children(struct pim_instance *pim, struct pim_upstream *up) { struct pim_upstream *child; - struct listnode *ch_node; if ((up->sg.src.s_addr != INADDR_ANY) && (up->sg.grp.s_addr != INADDR_ANY)) @@ -108,7 +107,7 @@ static void pim_upstream_find_new_children(struct pim_instance *pim, && (up->sg.grp.s_addr == INADDR_ANY)) return; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, ch_node, child)) { + frr_each (rb_pim_upstream, &pim->upstream_head, child) { if ((up->sg.grp.s_addr != INADDR_ANY) && (child->sg.grp.s_addr == up->sg.grp.s_addr) && (child != up)) { @@ -191,9 +190,8 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim, return up; if (PIM_DEBUG_TRACE) - zlog_debug( - "pim_upstream free vrf:%s %s flags 0x%x", - pim->vrf->name, up->sg_str, up->flags); + zlog_debug("pim_upstream free vrf:%s %s flags 0x%x", + pim->vrf->name, up->sg_str, up->flags); THREAD_OFF(up->t_ka_timer); THREAD_OFF(up->t_rs_timer); @@ -235,8 +233,7 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim, listnode_delete(up->parent->sources, up); up->parent = NULL; - listnode_delete(pim->upstream_list, up); - hash_release(pim->upstream_hash, up); + rb_pim_upstream_del(&pim->upstream_head, up); if (notify_msdp) { pim_msdp_up_del(pim, &up->sg); @@ -533,10 +530,9 @@ static int pim_upstream_could_register(struct pim_upstream *up) * we re-revaluate register setup for existing upstream entries */ void pim_upstream_register_reevaluate(struct pim_instance *pim) { - struct listnode *upnode; struct pim_upstream *up; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { /* If FHR is set CouldRegister is True. Also check if the flow * is actually active; if it is not kat setup will trigger * source @@ -639,9 +635,8 @@ void pim_upstream_update_use_rpt(struct pim_upstream *up, void pim_upstream_reeval_use_rpt(struct pim_instance *pim) { struct pim_upstream *up; - struct listnode *node; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, node, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->sg.src.s_addr == INADDR_ANY) continue; @@ -756,11 +751,9 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up, } } -int pim_upstream_compare(void *arg1, void *arg2) +int pim_upstream_compare(const struct pim_upstream *up1, + const struct pim_upstream *up2) { - const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; - const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; - if (ntohl(up1->sg.grp.s_addr) < ntohl(up2->sg.grp.s_addr)) return -1; @@ -811,7 +804,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, if (ch) ch->upstream = up; - up = hash_get(pim->upstream_hash, up, hash_alloc_intern); + rb_pim_upstream_add(&pim->upstream_head, up); /* Set up->upstream_addr as INADDR_ANY, if RP is not * configured and retain the upstream data structure */ @@ -825,7 +818,8 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, up->parent = pim_upstream_find_parent(pim, up); if (up->sg.src.s_addr == INADDR_ANY) { up->sources = list_new(); - up->sources->cmp = pim_upstream_compare; + up->sources->cmp = + (int (*)(void *, void *))pim_upstream_compare; } else up->sources = NULL; @@ -889,8 +883,6 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, } } - listnode_add_sort(pim->upstream_list, up); - if (PIM_DEBUG_PIM_TRACE) { zlog_debug( "%s: Created Upstream %s upstream_addr %s ref count %d increment", @@ -908,7 +900,7 @@ struct pim_upstream *pim_upstream_find(struct pim_instance *pim, struct pim_upstream *up = NULL; lookup.sg = *sg; - up = hash_lookup(pim->upstream_hash, &lookup); + up = rb_pim_upstream_find(&pim->upstream_head, &lookup); return up; } @@ -1168,15 +1160,12 @@ void pim_upstream_update_join_desired(struct pim_instance *pim, void pim_upstream_rpf_genid_changed(struct pim_instance *pim, struct in_addr neigh_addr) { - struct listnode *up_node; - struct listnode *up_nextnode; struct pim_upstream *up; /* * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr */ - for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) { - + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (PIM_DEBUG_PIM_TRACE) { char neigh_str[INET_ADDRSTRLEN]; char rpf_addr_str[PREFIX_STRLEN]; @@ -1788,8 +1777,6 @@ int pim_upstream_empty_inherited_olist(struct pim_upstream *up) */ void pim_upstream_find_new_rpf(struct pim_instance *pim) { - struct listnode *up_node; - struct listnode *up_nextnode; struct pim_upstream *up; struct pim_rpf old; enum pim_rpf_result rpf_result; @@ -1797,7 +1784,7 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim) /* * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr */ - for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->upstream_addr.s_addr == INADDR_ANY) { if (PIM_DEBUG_PIM_TRACE) zlog_debug( @@ -1837,18 +1824,11 @@ void pim_upstream_terminate(struct pim_instance *pim) { struct pim_upstream *up; - if (pim->upstream_list) { - while (pim->upstream_list->count) { - up = listnode_head(pim->upstream_list); - pim_upstream_del(pim, up, __PRETTY_FUNCTION__); - } - - list_delete(&pim->upstream_list); + while ((up = rb_pim_upstream_first(&pim->upstream_head))) { + pim_upstream_del(pim, up, __PRETTY_FUNCTION__); } - if (pim->upstream_hash) - hash_free(pim->upstream_hash); - pim->upstream_hash = NULL; + rb_pim_upstream_fini(&pim->upstream_head); if (pim->upstream_sg_wheel) wheel_delete(pim->upstream_sg_wheel); @@ -1991,9 +1971,8 @@ static void pim_upstream_sg_running(void *arg) void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim) { struct pim_upstream *up; - struct listnode *node; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, node, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->sg.src.s_addr != INADDR_ANY) continue; @@ -2031,7 +2010,6 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim, const char *nlist) { struct pim_upstream *up; - struct listnode *node; struct prefix_list *np; struct prefix g; enum prefix_list_type apply_new; @@ -2041,7 +2019,7 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim, g.family = AF_INET; g.prefixlen = IPV4_MAX_PREFIXLEN; - for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, node, up)) { + frr_each (rb_pim_upstream, &pim->upstream_head, up) { if (up->sg.src.s_addr != INADDR_ANY) continue; @@ -2075,11 +2053,5 @@ void pim_upstream_init(struct pim_instance *pim) wheel_init(router->master, 31000, 100, pim_upstream_hash_key, pim_upstream_sg_running, name); - snprintf(name, 64, "PIM %s Upstream Hash", - pim->vrf->name); - pim->upstream_hash = hash_create_size(8192, pim_upstream_hash_key, - pim_upstream_equal, name); - - pim->upstream_list = list_new(); - pim->upstream_list->cmp = pim_upstream_compare; + rb_pim_upstream_init(&pim->upstream_head); } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index ab50820518..1eb2052bb3 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -169,6 +169,7 @@ enum pim_upstream_sptbit { PIM_UPSTREAM_SPTBIT_TRUE }; +PREDECL_RBTREE_UNIQ(rb_pim_upstream); /* Upstream (S,G) channel in Joined state (S,G) in the "Not Joined" state is not represented @@ -198,6 +199,7 @@ enum pim_upstream_sptbit { */ struct pim_upstream { struct pim_instance *pim; + struct rb_pim_upstream_item upstream_rb; struct pim_upstream *parent; struct in_addr upstream_addr; /* Who we are talking to */ struct in_addr upstream_register; /*Who we received a register from*/ @@ -326,7 +328,11 @@ void pim_upstream_init(struct pim_instance *pim); void pim_upstream_terminate(struct pim_instance *pim); void join_timer_start(struct pim_upstream *up); -int pim_upstream_compare(void *arg1, void *arg2); +int pim_upstream_compare(const struct pim_upstream *up1, + const struct pim_upstream *up2); +DECLARE_RBTREE_UNIQ(rb_pim_upstream, struct pim_upstream, upstream_rb, + pim_upstream_compare) + void pim_upstream_register_reevaluate(struct pim_instance *pim); void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim);