pimd: Convert to using a RB tree for the pim_ifp ifchannel_list

This patch does two things:
1) Converts the pim_ifp->ifchannel_list to a pim_ifp->ifchannel_rb
2) Removes the hashing to use the RB RB_FIND instead.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2017-07-31 12:44:20 -04:00
parent 86b473a7e8
commit ad7b74c4f7
5 changed files with 75 additions and 119 deletions

View File

@ -213,7 +213,6 @@ static void pim_show_assert(struct pim_instance *pim, struct vty *vty)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
struct listnode *ch_node;
struct listnode *if_node; struct listnode *if_node;
struct interface *ifp; struct interface *ifp;
time_t now; time_t now;
@ -228,8 +227,7 @@ static void pim_show_assert(struct pim_instance *pim, struct vty *vty)
if (!pim_ifp) if (!pim_ifp)
continue; continue;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
ch_node, ch)) {
pim_show_assert_helper(vty, pim_ifp, ch, now); pim_show_assert_helper(vty, pim_ifp, ch, now);
} /* scan interface channels */ } /* scan interface channels */
} }
@ -264,7 +262,6 @@ static void pim_show_assert_internal_helper(struct vty *vty,
static void pim_show_assert_internal(struct pim_instance *pim, struct vty *vty) static void pim_show_assert_internal(struct pim_instance *pim, struct vty *vty)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct listnode *ch_node;
struct listnode *if_node; struct listnode *if_node;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
struct interface *ifp; struct interface *ifp;
@ -282,8 +279,7 @@ static void pim_show_assert_internal(struct pim_instance *pim, struct vty *vty)
if (!pim_ifp) if (!pim_ifp)
continue; continue;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
ch_node, ch)) {
pim_show_assert_internal_helper(vty, pim_ifp, ch); pim_show_assert_internal_helper(vty, pim_ifp, ch);
} /* scan interface channels */ } /* scan interface channels */
} }
@ -320,7 +316,7 @@ static void pim_show_assert_metric_helper(struct vty *vty,
static void pim_show_assert_metric(struct pim_instance *pim, struct vty *vty) static void pim_show_assert_metric(struct pim_instance *pim, struct vty *vty)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct listnode *ch_node, *if_node; struct listnode *if_node;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
struct interface *ifp; struct interface *ifp;
@ -332,8 +328,7 @@ static void pim_show_assert_metric(struct pim_instance *pim, struct vty *vty)
if (!pim_ifp) if (!pim_ifp)
continue; continue;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
ch_node, ch)) {
pim_show_assert_metric_helper(vty, pim_ifp, ch); pim_show_assert_metric_helper(vty, pim_ifp, ch);
} /* scan interface channels */ } /* scan interface channels */
} }
@ -383,7 +378,7 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty,
static void pim_show_assert_winner_metric(struct pim_instance *pim, static void pim_show_assert_winner_metric(struct pim_instance *pim,
struct vty *vty) struct vty *vty)
{ {
struct listnode *ch_node, *if_node; struct listnode *if_node;
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
struct interface *ifp; struct interface *ifp;
@ -396,8 +391,7 @@ static void pim_show_assert_winner_metric(struct pim_instance *pim,
if (!pim_ifp) if (!pim_ifp)
continue; continue;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
ch_node, ch)) {
pim_show_assert_winner_metric_helper(vty, pim_ifp, ch); pim_show_assert_winner_metric_helper(vty, pim_ifp, ch);
} /* scan interface channels */ } /* scan interface channels */
} }
@ -472,7 +466,7 @@ static void pim_show_membership_helper(struct vty *vty,
static void pim_show_membership(struct pim_instance *pim, struct vty *vty, static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
u_char uj) u_char uj)
{ {
struct listnode *ch_node, *if_node; struct listnode *if_node;
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
struct interface *ifp; struct interface *ifp;
@ -487,8 +481,7 @@ static void pim_show_membership(struct pim_instance *pim, struct vty *vty,
if (!pim_ifp) if (!pim_ifp)
continue; continue;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
ch_node, ch)) {
pim_show_membership_helper(vty, pim_ifp, ch, json); pim_show_membership_helper(vty, pim_ifp, ch, json);
} /* scan interface channels */ } /* scan interface channels */
} }
@ -1364,7 +1357,7 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty,
continue; continue;
pim_nbrs = pim_ifp->pim_neighbor_list->count; pim_nbrs = pim_ifp->pim_neighbor_list->count;
pim_ifchannels = pim_ifp->ifchannel_list->count; pim_ifchannels = pim_if_ifchannel_count(pim_ifp);
fhr = 0; fhr = 0;
for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up)) for (ALL_LIST_ELEMENTS_RO(pim->upstream_list, upnode, up))
@ -1684,7 +1677,7 @@ static void pim_show_join_helper(struct vty *vty,
static void pim_show_join(struct pim_instance *pim, struct vty *vty, u_char uj) static void pim_show_join(struct pim_instance *pim, struct vty *vty, u_char uj)
{ {
struct listnode *ch_node, *if_node; struct listnode *if_node;
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
struct interface *ifp; struct interface *ifp;
@ -1704,8 +1697,7 @@ static void pim_show_join(struct pim_instance *pim, struct vty *vty, u_char uj)
if (!pim_ifp) if (!pim_ifp)
continue; continue;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
ch_node, ch)) {
pim_show_join_helper(vty, pim_ifp, pim_show_join_helper(vty, pim_ifp,
ch, json, now, uj); ch, json, now, uj);
} /* scan interface channels */ } /* scan interface channels */
@ -2515,7 +2507,7 @@ static void pim_show_join_desired_helper(struct pim_instance *pim,
static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty,
u_char uj) u_char uj)
{ {
struct listnode *ch_node, *if_node; struct listnode *if_node;
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
struct interface *ifp; struct interface *ifp;
@ -2534,8 +2526,8 @@ static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty,
if (!pim_ifp) if (!pim_ifp)
continue; continue;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list,
ch_node, ch)) { RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
/* scan all interfaces */ /* scan all interfaces */
pim_show_join_desired_helper(pim, vty, pim_show_join_desired_helper(pim, vty,
pim_ifp, ch, pim_ifp, ch,

View File

@ -66,6 +66,8 @@ void pim_if_terminate(struct pim_instance *pim)
static void *if_list_clean(struct pim_interface *pim_ifp) static void *if_list_clean(struct pim_interface *pim_ifp)
{ {
struct pim_ifchannel *ch;
if (pim_ifp->igmp_join_list) { if (pim_ifp->igmp_join_list) {
list_delete(pim_ifp->igmp_join_list); list_delete(pim_ifp->igmp_join_list);
} }
@ -81,11 +83,9 @@ static void *if_list_clean(struct pim_interface *pim_ifp)
if (pim_ifp->upstream_switch_list) if (pim_ifp->upstream_switch_list)
list_delete(pim_ifp->upstream_switch_list); list_delete(pim_ifp->upstream_switch_list);
if (pim_ifp->ifchannel_list) while ((ch = RB_ROOT(pim_ifchannel_rb,
list_delete(pim_ifp->ifchannel_list); &pim_ifp->ifchannel_rb)) != NULL)
pim_ifchannel_delete(ch);
if (pim_ifp->pim_ifchannel_hash)
hash_free(pim_ifp->pim_ifchannel_hash);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp); XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
@ -95,7 +95,6 @@ static void *if_list_clean(struct pim_interface *pim_ifp)
struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
char hash_name[64];
zassert(ifp); zassert(ifp);
zassert(!ifp->info); zassert(!ifp->info);
@ -138,8 +137,6 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
pim_ifp->igmp_socket_list = NULL; pim_ifp->igmp_socket_list = NULL;
pim_ifp->pim_neighbor_list = NULL; pim_ifp->pim_neighbor_list = NULL;
pim_ifp->upstream_switch_list = NULL; pim_ifp->upstream_switch_list = NULL;
pim_ifp->ifchannel_list = NULL;
pim_ifp->pim_ifchannel_hash = NULL;
pim_ifp->pim_generation_id = 0; pim_ifp->pim_generation_id = 0;
/* list of struct igmp_sock */ /* list of struct igmp_sock */
@ -167,22 +164,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
return if_list_clean(pim_ifp); return if_list_clean(pim_ifp);
} }
/* list of struct pim_ifchannel */ RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
pim_ifp->ifchannel_list = list_new();
if (!pim_ifp->ifchannel_list) {
zlog_err("%s %s: failure: pim_ifchannel_list=list_new()",
__FILE__, __PRETTY_FUNCTION__);
return if_list_clean(pim_ifp);
}
pim_ifp->ifchannel_list->del = (void (*)(void *))pim_ifchannel_free;
pim_ifp->ifchannel_list->cmp =
(int (*)(void *, void *))pim_ifchannel_compare;
snprintf(hash_name, 64, "Pim Interface %s hash",
ifp->name);
pim_ifp->pim_ifchannel_hash =
hash_create(pim_ifchannel_hash_key, pim_ifchannel_equal,
hash_name);
ifp->info = pim_ifp; ifp->info = pim_ifp;
@ -196,6 +178,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
void pim_if_delete(struct interface *ifp) void pim_if_delete(struct interface *ifp)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
zassert(ifp); zassert(ifp);
pim_ifp = ifp->info; pim_ifp = ifp->info;
@ -215,9 +198,10 @@ void pim_if_delete(struct interface *ifp)
list_delete(pim_ifp->igmp_socket_list); list_delete(pim_ifp->igmp_socket_list);
list_delete(pim_ifp->pim_neighbor_list); list_delete(pim_ifp->pim_neighbor_list);
list_delete(pim_ifp->upstream_switch_list); list_delete(pim_ifp->upstream_switch_list);
list_delete(pim_ifp->ifchannel_list);
hash_free(pim_ifp->pim_ifchannel_hash); while ((ch = RB_ROOT(pim_ifchannel_rb,
&pim_ifp->ifchannel_rb)) != NULL)
pim_ifchannel_delete(ch);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp); XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
@ -227,15 +211,12 @@ void pim_if_delete(struct interface *ifp)
void pim_if_update_could_assert(struct interface *ifp) void pim_if_update_could_assert(struct interface *ifp)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct listnode *node;
struct listnode *next_node;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
pim_ifp = ifp->info; pim_ifp = ifp->info;
zassert(pim_ifp); zassert(pim_ifp);
for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, node, next_node, RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
ch)) {
pim_ifchannel_update_could_assert(ch); pim_ifchannel_update_could_assert(ch);
} }
} }
@ -243,15 +224,12 @@ void pim_if_update_could_assert(struct interface *ifp)
static void pim_if_update_my_assert_metric(struct interface *ifp) static void pim_if_update_my_assert_metric(struct interface *ifp)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct listnode *node;
struct listnode *next_node;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
pim_ifp = ifp->info; pim_ifp = ifp->info;
zassert(pim_ifp); zassert(pim_ifp);
for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, node, next_node, RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
ch)) {
pim_ifchannel_update_my_assert_metric(ch); pim_ifchannel_update_my_assert_metric(ch);
} }
} }
@ -1472,15 +1450,12 @@ void pim_if_assert_on_neighbor_down(struct interface *ifp,
struct in_addr neigh_addr) struct in_addr neigh_addr)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct listnode *node;
struct listnode *next_node;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
pim_ifp = ifp->info; pim_ifp = ifp->info;
zassert(pim_ifp); zassert(pim_ifp);
for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, node, next_node, RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
ch)) {
/* Is (S,G,I) assert loser ? */ /* Is (S,G,I) assert loser ? */
if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
continue; continue;
@ -1494,17 +1469,16 @@ void pim_if_assert_on_neighbor_down(struct interface *ifp,
void pim_if_update_join_desired(struct pim_interface *pim_ifp) void pim_if_update_join_desired(struct pim_interface *pim_ifp)
{ {
struct listnode *ch_node;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
/* clear off flag from interface's upstreams */ /* clear off flag from interface's upstreams */
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, ch_node, ch)) { RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED( PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
ch->upstream->flags); ch->upstream->flags);
} }
/* scan per-interface (S,G,I) state on this I interface */ /* scan per-interface (S,G,I) state on this I interface */
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, ch_node, ch)) { RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
struct pim_upstream *up = ch->upstream; struct pim_upstream *up = ch->upstream;
if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags)) if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags))
@ -1519,16 +1493,13 @@ void pim_if_update_join_desired(struct pim_interface *pim_ifp)
void pim_if_update_assert_tracking_desired(struct interface *ifp) void pim_if_update_assert_tracking_desired(struct interface *ifp)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct listnode *node;
struct listnode *next_node;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
pim_ifp = ifp->info; pim_ifp = ifp->info;
if (!pim_ifp) if (!pim_ifp)
return; return;
for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, node, next_node, RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
ch)) {
pim_ifchannel_update_assert_tracking_desired(ch); pim_ifchannel_update_assert_tracking_desired(ch);
} }
} }
@ -1603,3 +1574,15 @@ int pim_if_is_vrf_device(struct interface *ifp)
return 0; return 0;
} }
int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
{
struct pim_ifchannel *ch;
int count = 0;
RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
count++;
}
return count;
}

View File

@ -106,8 +106,7 @@ struct pim_interface {
uint16_t pim_override_interval_msec; /* config */ uint16_t pim_override_interval_msec; /* config */
struct list *pim_neighbor_list; /* list of struct pim_neighbor */ struct list *pim_neighbor_list; /* list of struct pim_neighbor */
struct list *upstream_switch_list; struct list *upstream_switch_list;
struct list *ifchannel_list; struct pim_ifchannel_rb ifchannel_rb;
struct hash *pim_ifchannel_hash;
/* neighbors without lan_delay */ /* neighbors without lan_delay */
int pim_number_of_nonlandelay_neighbors; int pim_number_of_nonlandelay_neighbors;
@ -208,4 +207,6 @@ int pim_update_source_set(struct interface *ifp, struct in_addr source);
int pim_if_is_loopback(struct pim_instance *pim, struct interface *ifp); int pim_if_is_loopback(struct pim_instance *pim, struct interface *ifp);
int pim_if_is_vrf_device(struct interface *ifp); int pim_if_is_vrf_device(struct interface *ifp);
int pim_if_ifchannel_count(struct pim_interface *pim_ifp);
#endif /* PIM_IFACE_H */ #endif /* PIM_IFACE_H */

View File

@ -43,7 +43,11 @@
#include "pim_upstream.h" #include "pim_upstream.h"
#include "pim_ssm.h" #include "pim_ssm.h"
int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2) RB_GENERATE(pim_ifchannel_rb, pim_ifchannel,
pim_ifp_rb, pim_ifchannel_compare);
int pim_ifchannel_compare(const struct pim_ifchannel *ch1,
const struct pim_ifchannel *ch2)
{ {
struct pim_interface *pim_ifp1; struct pim_interface *pim_ifp1;
struct pim_interface *pim_ifp2; struct pim_interface *pim_ifp2;
@ -100,7 +104,6 @@ static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch)
{ {
struct pim_interface *pim_ifp = ch->interface->info; struct pim_interface *pim_ifp = ch->interface->info;
struct pim_ifchannel *child; struct pim_ifchannel *child;
struct listnode *ch_node;
// Basic Sanity that we are not being silly // Basic Sanity that we are not being silly
if ((ch->sg.src.s_addr != INADDR_ANY) if ((ch->sg.src.s_addr != INADDR_ANY)
@ -111,8 +114,7 @@ static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch)
&& (ch->sg.grp.s_addr == INADDR_ANY)) && (ch->sg.grp.s_addr == INADDR_ANY))
return; return;
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, ch_node, RB_FOREACH(child, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
child)) {
if ((ch->sg.grp.s_addr != INADDR_ANY) if ((ch->sg.grp.s_addr != INADDR_ANY)
&& (child->sg.grp.s_addr == ch->sg.grp.s_addr) && (child->sg.grp.s_addr == ch->sg.grp.s_addr)
&& (child != ch)) { && (child != ch)) {
@ -189,13 +191,8 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
listnode_delete(ch->parent->sources, ch); listnode_delete(ch->parent->sources, ch);
ch->parent = NULL; ch->parent = NULL;
} }
/*
notice that listnode_delete() can't be moved RB_REMOVE(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch);
into pim_ifchannel_free() because the later is
called by list_delete_all_node()
*/
listnode_delete(pim_ifp->ifchannel_list, ch);
hash_release(pim_ifp->pim_ifchannel_hash, ch);
if (PIM_DEBUG_PIM_TRACE) if (PIM_DEBUG_PIM_TRACE)
zlog_debug("%s: ifchannel entry %s is deleted ", zlog_debug("%s: ifchannel entry %s is deleted ",
@ -207,17 +204,15 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
void pim_ifchannel_delete_all(struct interface *ifp) void pim_ifchannel_delete_all(struct interface *ifp)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct listnode *ifchannel_node; struct pim_ifchannel *ch;
struct listnode *ifchannel_nextnode;
struct pim_ifchannel *ifchannel;
pim_ifp = ifp->info; pim_ifp = ifp->info;
if (!pim_ifp) if (!pim_ifp)
return; return;
for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, ifchannel_node, while ((ch = RB_ROOT(pim_ifchannel_rb,
ifchannel_nextnode, ifchannel)) { &pim_ifp->ifchannel_rb)) != NULL) {
pim_ifchannel_delete(ifchannel); pim_ifchannel_delete(ch);
} }
} }
@ -423,7 +418,8 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
} }
lookup.sg = *sg; lookup.sg = *sg;
ch = hash_lookup(pim_ifp->pim_ifchannel_hash, &lookup); lookup.interface = ifp;
ch = RB_FIND(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, &lookup);
return ch; return ch;
} }
@ -455,31 +451,26 @@ static void ifmembership_set(struct pim_ifchannel *ch,
void pim_ifchannel_membership_clear(struct interface *ifp) void pim_ifchannel_membership_clear(struct interface *ifp)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct listnode *ch_node;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
pim_ifp = ifp->info; pim_ifp = ifp->info;
zassert(pim_ifp); zassert(pim_ifp);
for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, ch_node, ch)) RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb)
ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO); ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO);
} }
void pim_ifchannel_delete_on_noinfo(struct interface *ifp) void pim_ifchannel_delete_on_noinfo(struct interface *ifp)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct listnode *node; struct pim_ifchannel *ch, *ch_tmp;
struct listnode *next_node;
struct pim_ifchannel *ch;
pim_ifp = ifp->info; pim_ifp = ifp->info;
zassert(pim_ifp); zassert(pim_ifp);
for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, node, next_node, RB_FOREACH_SAFE(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch_tmp)
ch)) {
delete_on_noinfo(ch); delete_on_noinfo(ch);
} }
}
/* /*
* For a given Interface, if we are given a S,G * For a given Interface, if we are given a S,G
@ -552,9 +543,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
ch->t_ifjoin_prune_pending_timer = NULL; ch->t_ifjoin_prune_pending_timer = NULL;
ch->ifjoin_creation = 0; ch->ifjoin_creation = 0;
/* Attach to list */ RB_INSERT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch);
listnode_add_sort(pim_ifp->ifchannel_list, ch);
ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern);
up = pim_upstream_add(pim_ifp->pim, sg, NULL, up_flags, up = pim_upstream_add(pim_ifp->pim, sg, NULL, up_flags,
__PRETTY_FUNCTION__, ch); __PRETTY_FUNCTION__, ch);
@ -572,8 +561,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
THREAD_OFF(ch->t_ifjoin_prune_pending_timer); THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
THREAD_OFF(ch->t_ifassert_timer); THREAD_OFF(ch->t_ifassert_timer);
listnode_delete(pim_ifp->ifchannel_list, ch); RB_REMOVE(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch);
hash_release(pim_ifp->pim_ifchannel_hash, ch);
XFREE(MTYPE_PIM_IFCHANNEL, ch); XFREE(MTYPE_PIM_IFCHANNEL, ch);
return NULL; return NULL;
} }
@ -1285,14 +1273,13 @@ void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch)
*/ */
void pim_ifchannel_scan_forward_start(struct interface *new_ifp) void pim_ifchannel_scan_forward_start(struct interface *new_ifp)
{ {
struct listnode *ifnode;
struct interface *ifp;
struct pim_interface *new_pim_ifp = new_ifp->info; struct pim_interface *new_pim_ifp = new_ifp->info;
struct pim_instance *pim = new_pim_ifp->pim; struct pim_instance *pim = new_pim_ifp->pim;
struct listnode *ifnode;
struct interface *ifp;
for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode, ifp)) { for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), ifnode, ifp)) {
struct pim_interface *loop_pim_ifp = ifp->info; struct pim_interface *loop_pim_ifp = ifp->info;
struct listnode *ch_node;
struct pim_ifchannel *ch; struct pim_ifchannel *ch;
if (!loop_pim_ifp) if (!loop_pim_ifp)
@ -1301,8 +1288,7 @@ void pim_ifchannel_scan_forward_start(struct interface *new_ifp)
if (new_pim_ifp == loop_pim_ifp) if (new_pim_ifp == loop_pim_ifp)
continue; continue;
for (ALL_LIST_ELEMENTS_RO(loop_pim_ifp->ifchannel_list, RB_FOREACH(ch, pim_ifchannel_rb, &loop_pim_ifp->ifchannel_rb) {
ch_node, ch)) {
if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { if (ch->ifjoin_state == PIM_IFJOIN_JOIN) {
struct pim_upstream *up = ch->upstream; struct pim_upstream *up = ch->upstream;
if ((!up->channel_oil) if ((!up->channel_oil)
@ -1395,15 +1381,3 @@ unsigned int pim_ifchannel_hash_key(void *arg)
return jhash_2words(ch->sg.src.s_addr, ch->sg.grp.s_addr, 0); return jhash_2words(ch->sg.src.s_addr, ch->sg.grp.s_addr, 0);
} }
int pim_ifchannel_equal(const void *arg1, const void *arg2)
{
const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1;
const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2;
if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr)
&& (ch1->sg.src.s_addr == ch2->sg.src.s_addr))
return 1;
return 0;
}

View File

@ -80,6 +80,8 @@ struct pim_assert_metric {
Per-interface (S,G) state Per-interface (S,G) state
*/ */
struct pim_ifchannel { struct pim_ifchannel {
RB_ENTRY(rb_ifchannel) pim_ifp_rb;
struct pim_ifchannel *parent; struct pim_ifchannel *parent;
struct list *sources; struct list *sources;
struct prefix_sg sg; struct prefix_sg sg;
@ -108,6 +110,10 @@ struct pim_ifchannel {
struct pim_upstream *upstream; struct pim_upstream *upstream;
}; };
RB_HEAD(pim_ifchannel_rb, pim_ifchannel);
RB_PROTOTYPE(pim_ifchannel_rb, pim_ifchannel,
pim_ifp_rb, pim_ifchannel_compare);
void pim_ifchannel_free(struct pim_ifchannel *ch); void pim_ifchannel_free(struct pim_ifchannel *ch);
void pim_ifchannel_delete(struct pim_ifchannel *ch); void pim_ifchannel_delete(struct pim_ifchannel *ch);
void pim_ifchannel_delete_all(struct interface *ifp); void pim_ifchannel_delete_all(struct interface *ifp);
@ -148,8 +154,8 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
uint8_t source_flags, uint8_t join, uint8_t source_flags, uint8_t join,
uint8_t starg_alone); uint8_t starg_alone);
int pim_ifchannel_compare(struct pim_ifchannel *ch1, struct pim_ifchannel *ch2); int pim_ifchannel_compare(const struct pim_ifchannel *ch1,
const struct pim_ifchannel *ch2);
unsigned int pim_ifchannel_hash_key(void *arg); unsigned int pim_ifchannel_hash_key(void *arg);
int pim_ifchannel_equal(const void *arg1, const void *arg2);
#endif /* PIM_IFCHANNEL_H */ #endif /* PIM_IFCHANNEL_H */