mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 16:04:49 +00:00
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:
parent
4961e0ad8f
commit
a625e9373b
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user