pimd: Make ifchannel lookup a hash lookup

When we are at scale, it is possible that
we have a very large number of ifchannels
per interface.  So make lookup for
that situation to be a hash lookup.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2017-02-12 20:16:08 -05:00
parent 4961e0ad8f
commit a625e9373b
4 changed files with 44 additions and 13 deletions

View File

@ -27,6 +27,7 @@
#include "vrf.h"
#include "linklist.h"
#include "plist.h"
#include "hash.h"
#include "pimd.h"
#include "pim_iface.h"
@ -86,6 +87,9 @@ static void *if_list_clean(struct pim_interface *pim_ifp)
list_delete(pim_ifp->pim_ifchannel_list);
}
if (pim_ifp->pim_ifchannel_hash)
hash_free (pim_ifp->pim_ifchannel_hash);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
return 0;
@ -131,6 +135,7 @@ 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->pim_ifchannel_list = NULL;
pim_ifp->pim_ifchannel_hash = NULL;
pim_ifp->pim_generation_id = 0;
/* list of struct igmp_sock */
@ -161,6 +166,9 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
pim_ifp->pim_ifchannel_list->del = (void (*)(void *)) pim_ifchannel_free;
pim_ifp->pim_ifchannel_list->cmp = (int (*)(void *, void *)) pim_ifchannel_compare;
pim_ifp->pim_ifchannel_hash = hash_create (pim_ifchannel_hash_key,
pim_ifchannel_equal);
ifp->info = pim_ifp;
pim_sock_reset(ifp);
@ -197,6 +205,8 @@ void pim_if_delete(struct interface *ifp)
list_delete(pim_ifp->pim_neighbor_list);
list_delete(pim_ifp->pim_ifchannel_list);
hash_free (pim_ifp->pim_ifchannel_hash);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
ifp->info = NULL;

View File

@ -98,6 +98,7 @@ struct pim_interface {
uint16_t pim_override_interval_msec; /* config */
struct list *pim_neighbor_list; /* list of struct pim_neighbor */
struct list *pim_ifchannel_list; /* list of struct pim_ifchannel */
struct hash *pim_ifchannel_hash;
/* neighbors without lan_delay */
int pim_number_of_nonlandelay_neighbors;

View File

@ -25,6 +25,8 @@
#include "memory.h"
#include "if.h"
#include "vrf.h"
#include "hash.h"
#include "jhash.h"
#include "pimd.h"
#include "pim_str.h"
@ -193,6 +195,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
called by list_delete_all_node()
*/
listnode_delete(pim_ifp->pim_ifchannel_list, ch);
hash_release(pim_ifp->pim_ifchannel_hash, ch);
listnode_delete(pim_ifchannel_list, ch);
pim_ifchannel_free(ch);
@ -373,10 +376,8 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
struct prefix_sg *sg)
{
struct pim_interface *pim_ifp;
struct listnode *ch_node;
struct pim_ifchannel *ch;
zassert(ifp);
struct pim_ifchannel lookup;
pim_ifp = ifp->info;
@ -385,19 +386,13 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
__PRETTY_FUNCTION__,
pim_str_sg_dump (sg),
ifp->name);
return 0;
return NULL;
}
for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
if (
(sg->src.s_addr == ch->sg.src.s_addr) &&
(sg->grp.s_addr == ch->sg.grp.s_addr)
) {
return ch;
}
}
lookup.sg = *sg;
ch = hash_lookup (pim_ifp->pim_ifchannel_hash, &lookup);
return 0;
return ch;
}
static void ifmembership_set(struct pim_ifchannel *ch,
@ -553,6 +548,7 @@ pim_ifchannel_add(struct interface *ifp,
/* Attach to list */
listnode_add_sort(pim_ifp->pim_ifchannel_list, ch);
ch = hash_get (pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern);
listnode_add_sort(pim_ifchannel_list, ch);
return ch;
@ -1228,3 +1224,24 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom)
}
}
}
unsigned int
pim_ifchannel_hash_key (void *arg)
{
struct pim_ifchannel *ch = (struct pim_ifchannel *)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;
}

View File

@ -154,4 +154,7 @@ void pim_ifchannel_scan_forward_start (struct interface *new_ifp);
void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom);
int pim_ifchannel_compare (struct pim_ifchannel *ch1, 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 */