mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 20:27:03 +00:00
pimd: Convert the channel_oil_list|hash to a rb_tree
The channel_oil_list and hash are taking significant cpu at scale when adding to the sorted list. Replace with a RB_TREE. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
93789698ce
commit
7315ecdabe
@ -1975,7 +1975,6 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
|
||||
const char *src_or_group, const char *group, bool uj)
|
||||
{
|
||||
struct channel_oil *c_oil;
|
||||
struct listnode *node;
|
||||
json_object *json = NULL;
|
||||
json_object *json_group = NULL;
|
||||
json_object *json_ifp_in = NULL;
|
||||
@ -1994,7 +1993,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty,
|
||||
"\nActive Source Group RPT IIF OIL\n");
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
||||
char grp_str[INET_ADDRSTRLEN];
|
||||
char src_str[INET_ADDRSTRLEN];
|
||||
char in_ifname[INTERFACE_NAMSIZ + 1];
|
||||
@ -5420,7 +5419,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
|
||||
now = pim_time_monotonic_sec();
|
||||
|
||||
/* print list of PIM and IGMP routes */
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
||||
found_oif = 0;
|
||||
first = 1;
|
||||
if (!c_oil->installed && !uj)
|
||||
@ -5828,7 +5827,7 @@ DEFUN (clear_ip_mroute_count,
|
||||
return CMD_WARNING;
|
||||
|
||||
pim = vrf->info;
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
|
||||
frr_each(rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
||||
if (!c_oil->installed)
|
||||
continue;
|
||||
|
||||
@ -5863,7 +5862,7 @@ static void show_mroute_count(struct pim_instance *pim, struct vty *vty)
|
||||
"Source Group LastUsed Packets Bytes WrongIf \n");
|
||||
|
||||
/* Print PIM and IGMP route counts */
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
||||
char group_str[INET_ADDRSTRLEN];
|
||||
char source_str[INET_ADDRSTRLEN];
|
||||
|
||||
@ -5968,7 +5967,7 @@ static void show_mroute_summary(struct pim_instance *pim, struct vty *vty)
|
||||
|
||||
vty_out(vty, "Mroute Type Installed/Total\n");
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(pim->channel_oil_list, node, c_oil)) {
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
|
||||
if (!c_oil->installed) {
|
||||
if (c_oil->oil.mfcc_origin.s_addr == INADDR_ANY)
|
||||
starg_sw_mroute_cnt++;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "pim_assert.h"
|
||||
#include "pim_bsm.h"
|
||||
#include "pim_vxlan_instance.h"
|
||||
#include "pim_oil.h"
|
||||
|
||||
#if defined(HAVE_LINUX_MROUTE_H)
|
||||
#include <linux/mroute.h>
|
||||
@ -119,8 +120,7 @@ struct pim_instance {
|
||||
|
||||
int iface_vif_index[MAXVIFS];
|
||||
|
||||
struct list *channel_oil_list;
|
||||
struct hash *channel_oil_hash;
|
||||
struct rb_pim_oil_head channel_oil_head;
|
||||
|
||||
struct pim_msdp msdp;
|
||||
struct pim_vxlan_instance vxlan;
|
||||
|
@ -64,8 +64,8 @@ char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int pim_channel_oil_compare(struct channel_oil *c1,
|
||||
struct channel_oil *c2)
|
||||
int pim_channel_oil_compare(const struct channel_oil *c1,
|
||||
const struct channel_oil *c2)
|
||||
{
|
||||
if (ntohl(c1->oil.mfcc_mcastgrp.s_addr)
|
||||
< ntohl(c2->oil.mfcc_mcastgrp.s_addr))
|
||||
@ -108,26 +108,17 @@ static unsigned int pim_oil_hash_key(const void *arg)
|
||||
|
||||
void pim_oil_init(struct pim_instance *pim)
|
||||
{
|
||||
char hash_name[64];
|
||||
|
||||
snprintf(hash_name, 64, "PIM %s Oil Hash", pim->vrf->name);
|
||||
pim->channel_oil_hash = hash_create_size(8192, pim_oil_hash_key,
|
||||
pim_oil_equal, hash_name);
|
||||
|
||||
pim->channel_oil_list = list_new();
|
||||
pim->channel_oil_list->del = (void (*)(void *))pim_channel_oil_free;
|
||||
pim->channel_oil_list->cmp =
|
||||
(int (*)(void *, void *))pim_channel_oil_compare;
|
||||
rb_pim_oil_init(&pim->channel_oil_head);
|
||||
}
|
||||
|
||||
void pim_oil_terminate(struct pim_instance *pim)
|
||||
{
|
||||
if (pim->channel_oil_list)
|
||||
list_delete(&pim->channel_oil_list);
|
||||
struct channel_oil *c_oil;
|
||||
|
||||
if (pim->channel_oil_hash)
|
||||
hash_free(pim->channel_oil_hash);
|
||||
pim->channel_oil_hash = NULL;
|
||||
while ((c_oil = rb_pim_oil_pop(&pim->channel_oil_head)))
|
||||
pim_channel_oil_free(c_oil);
|
||||
|
||||
rb_pim_oil_fini(&pim->channel_oil_head);
|
||||
}
|
||||
|
||||
void pim_channel_oil_free(struct channel_oil *c_oil)
|
||||
@ -144,7 +135,7 @@ struct channel_oil *pim_find_channel_oil(struct pim_instance *pim,
|
||||
lookup.oil.mfcc_mcastgrp = sg->grp;
|
||||
lookup.oil.mfcc_origin = sg->src;
|
||||
|
||||
c_oil = hash_lookup(pim->channel_oil_hash, &lookup);
|
||||
c_oil = rb_pim_oil_find(&pim->channel_oil_head, &lookup);
|
||||
|
||||
return c_oil;
|
||||
}
|
||||
@ -187,7 +178,6 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
|
||||
|
||||
c_oil->oil.mfcc_mcastgrp = sg->grp;
|
||||
c_oil->oil.mfcc_origin = sg->src;
|
||||
c_oil = hash_get(pim->channel_oil_hash, c_oil, hash_alloc_intern);
|
||||
|
||||
c_oil->oil.mfcc_parent = MAXVIFS;
|
||||
c_oil->oil_ref_count = 1;
|
||||
@ -195,7 +185,7 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
|
||||
c_oil->up = pim_upstream_find(pim, sg);
|
||||
c_oil->pim = pim;
|
||||
|
||||
listnode_add_sort(pim->channel_oil_list, c_oil);
|
||||
rb_pim_oil_add(&pim->channel_oil_head, c_oil);
|
||||
|
||||
if (PIM_DEBUG_MROUTE)
|
||||
zlog_debug("%s(%s): c_oil %s add",
|
||||
@ -224,8 +214,7 @@ struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
|
||||
* called by list_delete_all_node()
|
||||
*/
|
||||
c_oil->up = NULL;
|
||||
listnode_delete(c_oil->pim->channel_oil_list, c_oil);
|
||||
hash_release(c_oil->pim->channel_oil_hash, c_oil);
|
||||
rb_pim_oil_del(&c_oil->pim->channel_oil_head, c_oil);
|
||||
|
||||
pim_channel_oil_free(c_oil);
|
||||
return NULL;
|
||||
|
@ -90,10 +90,13 @@ struct channel_counts {
|
||||
installed: indicate if this entry is installed in the kernel.
|
||||
|
||||
*/
|
||||
PREDECL_RBTREE_UNIQ(rb_pim_oil)
|
||||
|
||||
struct channel_oil {
|
||||
struct pim_instance *pim;
|
||||
|
||||
struct rb_pim_oil_item oil_rb;
|
||||
|
||||
struct mfcctl oil;
|
||||
int installed;
|
||||
int oil_inherited_rescan;
|
||||
@ -106,6 +109,12 @@ struct channel_oil {
|
||||
time_t mroute_creation;
|
||||
};
|
||||
|
||||
extern int pim_channel_oil_compare(const struct channel_oil *c1,
|
||||
const struct channel_oil *c2);
|
||||
DECLARE_RBTREE_UNIQ(rb_pim_oil, struct channel_oil, oil_rb,
|
||||
pim_channel_oil_compare)
|
||||
|
||||
|
||||
extern struct list *pim_channel_oil_list;
|
||||
|
||||
void pim_oil_init(struct pim_instance *pim);
|
||||
|
@ -392,16 +392,13 @@ static void pim_zebra_vxlan_replay(void)
|
||||
|
||||
void pim_scan_oil(struct pim_instance *pim)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct listnode *nextnode;
|
||||
struct channel_oil *c_oil;
|
||||
|
||||
pim->scan_oil_last = pim_time_monotonic_sec();
|
||||
++pim->scan_oil_events;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, c_oil)) {
|
||||
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
|
||||
pim_upstream_mroute_iif_update(c_oil, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static int on_rpf_cache_refresh(struct thread *t)
|
||||
|
Loading…
Reference in New Issue
Block a user