From ad7b74c4f7c8061bccd3b65b85b9fb97becb7cb0 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 31 Jul 2017 12:44:20 -0400 Subject: [PATCH] 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 --- pimd/pim_cmd.c | 36 +++++++++------------- pimd/pim_iface.c | 73 +++++++++++++++++--------------------------- pimd/pim_iface.h | 5 +-- pimd/pim_ifchannel.c | 70 +++++++++++++----------------------------- pimd/pim_ifchannel.h | 10 ++++-- 5 files changed, 75 insertions(+), 119 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 6dfd9c2d60..0cc8f0c87e 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -213,7 +213,6 @@ static void pim_show_assert(struct pim_instance *pim, struct vty *vty) { struct pim_interface *pim_ifp; struct pim_ifchannel *ch; - struct listnode *ch_node; struct listnode *if_node; struct interface *ifp; time_t now; @@ -228,8 +227,7 @@ static void pim_show_assert(struct pim_instance *pim, struct vty *vty) if (!pim_ifp) continue; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, - ch_node, ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { pim_show_assert_helper(vty, pim_ifp, ch, now); } /* 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) { struct pim_interface *pim_ifp; - struct listnode *ch_node; struct listnode *if_node; struct pim_ifchannel *ch; struct interface *ifp; @@ -282,8 +279,7 @@ static void pim_show_assert_internal(struct pim_instance *pim, struct vty *vty) if (!pim_ifp) continue; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, - ch_node, ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { pim_show_assert_internal_helper(vty, pim_ifp, ch); } /* 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) { struct pim_interface *pim_ifp; - struct listnode *ch_node, *if_node; + struct listnode *if_node; struct pim_ifchannel *ch; struct interface *ifp; @@ -332,8 +328,7 @@ static void pim_show_assert_metric(struct pim_instance *pim, struct vty *vty) if (!pim_ifp) continue; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, - ch_node, ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { pim_show_assert_metric_helper(vty, pim_ifp, ch); } /* 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, struct vty *vty) { - struct listnode *ch_node, *if_node; + struct listnode *if_node; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; struct interface *ifp; @@ -396,8 +391,7 @@ static void pim_show_assert_winner_metric(struct pim_instance *pim, if (!pim_ifp) continue; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, - ch_node, ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { pim_show_assert_winner_metric_helper(vty, pim_ifp, ch); } /* 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, u_char uj) { - struct listnode *ch_node, *if_node; + struct listnode *if_node; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; struct interface *ifp; @@ -487,8 +481,7 @@ static void pim_show_membership(struct pim_instance *pim, struct vty *vty, if (!pim_ifp) continue; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, - ch_node, ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { pim_show_membership_helper(vty, pim_ifp, ch, json); } /* scan interface channels */ } @@ -1364,7 +1357,7 @@ static void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, continue; 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; 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) { - struct listnode *ch_node, *if_node; + struct listnode *if_node; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; 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) continue; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, - ch_node, ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { pim_show_join_helper(vty, pim_ifp, ch, json, now, uj); } /* 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, u_char uj) { - struct listnode *ch_node, *if_node; + struct listnode *if_node; struct pim_interface *pim_ifp; struct pim_ifchannel *ch; struct interface *ifp; @@ -2534,8 +2526,8 @@ static void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, if (!pim_ifp) 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 */ pim_show_join_desired_helper(pim, vty, pim_ifp, ch, diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 2fabf37a5e..221ca2f24d 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -66,6 +66,8 @@ void pim_if_terminate(struct pim_instance *pim) static void *if_list_clean(struct pim_interface *pim_ifp) { + struct pim_ifchannel *ch; + if (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) list_delete(pim_ifp->upstream_switch_list); - if (pim_ifp->ifchannel_list) - list_delete(pim_ifp->ifchannel_list); - - if (pim_ifp->pim_ifchannel_hash) - 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); @@ -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_ifp; - char hash_name[64]; zassert(ifp); 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->pim_neighbor_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; /* 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); } - /* list of struct pim_ifchannel */ - 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); + RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb); 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) { struct pim_interface *pim_ifp; + struct pim_ifchannel *ch; zassert(ifp); 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->pim_neighbor_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); @@ -227,15 +211,12 @@ void pim_if_delete(struct interface *ifp) void pim_if_update_could_assert(struct interface *ifp) { struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; struct pim_ifchannel *ch; pim_ifp = ifp->info; zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, node, next_node, - ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { 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) { struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; struct pim_ifchannel *ch; pim_ifp = ifp->info; zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, node, next_node, - ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { 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 pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; struct pim_ifchannel *ch; pim_ifp = ifp->info; zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, node, next_node, - ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { /* Is (S,G,I) assert loser ? */ if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER) 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) { - struct listnode *ch_node; struct pim_ifchannel *ch; /* 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( ch->upstream->flags); } /* 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; 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) { struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; struct pim_ifchannel *ch; pim_ifp = ifp->info; if (!pim_ifp) return; - for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, node, next_node, - ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { pim_ifchannel_update_assert_tracking_desired(ch); } } @@ -1603,3 +1574,15 @@ int pim_if_is_vrf_device(struct interface *ifp) 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; +} diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 7739e3af2b..ed885ff0e3 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -106,8 +106,7 @@ struct pim_interface { uint16_t pim_override_interval_msec; /* config */ struct list *pim_neighbor_list; /* list of struct pim_neighbor */ struct list *upstream_switch_list; - struct list *ifchannel_list; - struct hash *pim_ifchannel_hash; + struct pim_ifchannel_rb ifchannel_rb; /* neighbors without lan_delay */ 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_vrf_device(struct interface *ifp); + +int pim_if_ifchannel_count(struct pim_interface *pim_ifp); #endif /* PIM_IFACE_H */ diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 750dc7f5e9..c91efbd8b6 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -43,7 +43,11 @@ #include "pim_upstream.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_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_ifchannel *child; - struct listnode *ch_node; // Basic Sanity that we are not being silly 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)) return; - for (ALL_LIST_ELEMENTS_RO(pim_ifp->ifchannel_list, ch_node, - child)) { + RB_FOREACH(child, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) { if ((ch->sg.grp.s_addr != INADDR_ANY) && (child->sg.grp.s_addr == ch->sg.grp.s_addr) && (child != ch)) { @@ -189,13 +191,8 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) listnode_delete(ch->parent->sources, ch); ch->parent = NULL; } - /* - notice that listnode_delete() can't be moved - 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); + + RB_REMOVE(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch); if (PIM_DEBUG_PIM_TRACE) 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) { struct pim_interface *pim_ifp; - struct listnode *ifchannel_node; - struct listnode *ifchannel_nextnode; - struct pim_ifchannel *ifchannel; + struct pim_ifchannel *ch; pim_ifp = ifp->info; if (!pim_ifp) return; - for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, ifchannel_node, - ifchannel_nextnode, ifchannel)) { - pim_ifchannel_delete(ifchannel); + while ((ch = RB_ROOT(pim_ifchannel_rb, + &pim_ifp->ifchannel_rb)) != NULL) { + pim_ifchannel_delete(ch); } } @@ -423,7 +418,8 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp, } 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; } @@ -455,30 +451,25 @@ static void ifmembership_set(struct pim_ifchannel *ch, void pim_ifchannel_membership_clear(struct interface *ifp) { struct pim_interface *pim_ifp; - struct listnode *ch_node; struct pim_ifchannel *ch; pim_ifp = ifp->info; 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); } void pim_ifchannel_delete_on_noinfo(struct interface *ifp) { struct pim_interface *pim_ifp; - struct listnode *node; - struct listnode *next_node; - struct pim_ifchannel *ch; + struct pim_ifchannel *ch, *ch_tmp; pim_ifp = ifp->info; zassert(pim_ifp); - for (ALL_LIST_ELEMENTS(pim_ifp->ifchannel_list, node, next_node, - ch)) { + RB_FOREACH_SAFE(ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch_tmp) delete_on_noinfo(ch); - } } /* @@ -552,9 +543,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, ch->t_ifjoin_prune_pending_timer = NULL; ch->ifjoin_creation = 0; - /* Attach to list */ - listnode_add_sort(pim_ifp->ifchannel_list, ch); - ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern); + RB_INSERT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch); up = pim_upstream_add(pim_ifp->pim, sg, NULL, up_flags, __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_ifassert_timer); - listnode_delete(pim_ifp->ifchannel_list, ch); - hash_release(pim_ifp->pim_ifchannel_hash, ch); + RB_REMOVE(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch); XFREE(MTYPE_PIM_IFCHANNEL, ch); 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) { - struct listnode *ifnode; - struct interface *ifp; struct pim_interface *new_pim_ifp = new_ifp->info; 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)) { struct pim_interface *loop_pim_ifp = ifp->info; - struct listnode *ch_node; struct pim_ifchannel *ch; 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) continue; - for (ALL_LIST_ELEMENTS_RO(loop_pim_ifp->ifchannel_list, - ch_node, ch)) { + RB_FOREACH(ch, pim_ifchannel_rb, &loop_pim_ifp->ifchannel_rb) { if (ch->ifjoin_state == PIM_IFJOIN_JOIN) { struct pim_upstream *up = ch->upstream; 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); } - -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; -} diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 3fd717bec8..cef431c30d 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -80,6 +80,8 @@ struct pim_assert_metric { Per-interface (S,G) state */ struct pim_ifchannel { + RB_ENTRY(rb_ifchannel) pim_ifp_rb; + struct pim_ifchannel *parent; struct list *sources; struct prefix_sg sg; @@ -108,6 +110,10 @@ struct pim_ifchannel { 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_delete(struct pim_ifchannel *ch); 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 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); -int pim_ifchannel_equal(const void *arg1, const void *arg2); #endif /* PIM_IFCHANNEL_H */ -- 2.39.5