mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-03 23:47:16 +00:00 
			
		
		
		
	zebra: Create depends after initial lookup
Create any depends only after the initial hash lookup fails. Should reduce hashing cpu cycles significantly. Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com>
This commit is contained in:
		
							parent
							
								
									6e72876478
								
							
						
					
					
						commit
						6384cbcb0e
					
				@ -439,48 +439,6 @@ static void zebra_nhg_process_grp(struct nexthop_group *nhg,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id,
 | 
			
		||||
			   struct nexthop_group *nhg,
 | 
			
		||||
			   struct nhg_connected_tree_head *nhg_depends,
 | 
			
		||||
			   vrf_id_t vrf_id, afi_t afi, int type)
 | 
			
		||||
{
 | 
			
		||||
	struct nhg_hash_entry lookup = {};
 | 
			
		||||
 | 
			
		||||
	uint32_t old_id_counter = id_counter;
 | 
			
		||||
 | 
			
		||||
	bool created = false;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If it has an id at this point, we must have gotten it from the kernel
 | 
			
		||||
	 */
 | 
			
		||||
	lookup.id = id ? id : ++id_counter;
 | 
			
		||||
 | 
			
		||||
	lookup.afi = afi;
 | 
			
		||||
	lookup.vrf_id = vrf_id;
 | 
			
		||||
	lookup.type = type ? type : ZEBRA_ROUTE_NHG;
 | 
			
		||||
	lookup.nhg = nhg;
 | 
			
		||||
 | 
			
		||||
	if (nhg_depends)
 | 
			
		||||
		lookup.nhg_depends = *nhg_depends;
 | 
			
		||||
 | 
			
		||||
	if (id)
 | 
			
		||||
		(*nhe) = zebra_nhg_lookup_id(id);
 | 
			
		||||
	else
 | 
			
		||||
		(*nhe) = hash_lookup(zrouter.nhgs, &lookup);
 | 
			
		||||
 | 
			
		||||
	/* If it found an nhe in our tables, this new ID is unused */
 | 
			
		||||
	if (*nhe)
 | 
			
		||||
		id_counter = old_id_counter;
 | 
			
		||||
 | 
			
		||||
	if (!(*nhe)) {
 | 
			
		||||
		(*nhe) = hash_get(zrouter.nhgs, &lookup, zebra_nhg_hash_alloc);
 | 
			
		||||
		created = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return created;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends,
 | 
			
		||||
				    struct nexthop *nh, afi_t afi)
 | 
			
		||||
{
 | 
			
		||||
@ -493,30 +451,97 @@ static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends,
 | 
			
		||||
	depends_add(nhg_depends, depend);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find/create a single nexthop */
 | 
			
		||||
static bool zebra_nhg_find_nexthop(struct nhg_hash_entry **nhe, uint32_t id,
 | 
			
		||||
				   struct nexthop *nh, afi_t afi, int type)
 | 
			
		||||
static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id,
 | 
			
		||||
			   struct nexthop_group *nhg,
 | 
			
		||||
			   struct nhg_connected_tree_head *nhg_depends,
 | 
			
		||||
			   vrf_id_t vrf_id, afi_t afi, int type)
 | 
			
		||||
{
 | 
			
		||||
	struct nhg_hash_entry lookup = {};
 | 
			
		||||
 | 
			
		||||
	uint32_t old_id_counter = id_counter;
 | 
			
		||||
 | 
			
		||||
	bool created = false;
 | 
			
		||||
	bool recursive = false;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If it has an id at this point, we must have gotten it from the kernel
 | 
			
		||||
	 */
 | 
			
		||||
	lookup.id = id ? id : ++id_counter;
 | 
			
		||||
 | 
			
		||||
	lookup.type = type ? type : ZEBRA_ROUTE_NHG;
 | 
			
		||||
	lookup.nhg = nhg;
 | 
			
		||||
 | 
			
		||||
	if (lookup.nhg->nexthop->next) {
 | 
			
		||||
		/* Groups can have all vrfs and AF's in them */
 | 
			
		||||
		lookup.afi = AFI_UNSPEC;
 | 
			
		||||
		lookup.vrf_id = 0;
 | 
			
		||||
	} else {
 | 
			
		||||
		lookup.afi = afi;
 | 
			
		||||
		lookup.vrf_id = vrf_id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (id)
 | 
			
		||||
		(*nhe) = zebra_nhg_lookup_id(id);
 | 
			
		||||
	else
 | 
			
		||||
		(*nhe) = hash_lookup(zrouter.nhgs, &lookup);
 | 
			
		||||
 | 
			
		||||
	/* If it found an nhe in our tables, this new ID is unused */
 | 
			
		||||
	if (*nhe)
 | 
			
		||||
		id_counter = old_id_counter;
 | 
			
		||||
 | 
			
		||||
	if (!(*nhe)) {
 | 
			
		||||
		/* Only hash/lookup the depends if the first lookup
 | 
			
		||||
		 * fails to find something. This should hopefully save a
 | 
			
		||||
		 * lot of cycles for larger ecmp sizes.
 | 
			
		||||
		 */
 | 
			
		||||
		if (nhg_depends)
 | 
			
		||||
			/* If you don't want to hash on each nexthop in the
 | 
			
		||||
			 * nexthop group struct you can pass the depends
 | 
			
		||||
			 * directly. Kernel-side we do this since it just looks
 | 
			
		||||
			 * them up via IDs.
 | 
			
		||||
			 */
 | 
			
		||||
			lookup.nhg_depends = *nhg_depends;
 | 
			
		||||
		else {
 | 
			
		||||
			if (nhg->nexthop->next) {
 | 
			
		||||
				nhg_connected_tree_init(&lookup.nhg_depends);
 | 
			
		||||
 | 
			
		||||
				/* If its a group, create a dependency tree */
 | 
			
		||||
				struct nexthop *nh = NULL;
 | 
			
		||||
 | 
			
		||||
				for (nh = nhg->nexthop; nh; nh = nh->next)
 | 
			
		||||
					depends_find_add(&lookup.nhg_depends,
 | 
			
		||||
							 nh, afi);
 | 
			
		||||
			} else if (CHECK_FLAG(nhg->nexthop->flags,
 | 
			
		||||
					      NEXTHOP_FLAG_RECURSIVE)) {
 | 
			
		||||
				nhg_connected_tree_init(&lookup.nhg_depends);
 | 
			
		||||
				handle_recursive_depend(&lookup.nhg_depends,
 | 
			
		||||
							nhg->nexthop->resolved,
 | 
			
		||||
							afi);
 | 
			
		||||
				recursive = true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		(*nhe) = hash_get(zrouter.nhgs, &lookup, zebra_nhg_hash_alloc);
 | 
			
		||||
		created = true;
 | 
			
		||||
 | 
			
		||||
		if (recursive)
 | 
			
		||||
			SET_FLAG((*nhe)->flags, NEXTHOP_GROUP_RECURSIVE);
 | 
			
		||||
	}
 | 
			
		||||
	return created;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find/create a single nexthop */
 | 
			
		||||
static struct nhg_hash_entry *
 | 
			
		||||
zebra_nhg_find_nexthop(uint32_t id, struct nexthop *nh, afi_t afi, int type)
 | 
			
		||||
{
 | 
			
		||||
	struct nhg_hash_entry *nhe = NULL;
 | 
			
		||||
	struct nexthop_group nhg = {};
 | 
			
		||||
	struct nhg_connected_tree_head nhg_depends = {};
 | 
			
		||||
	bool created = true;
 | 
			
		||||
 | 
			
		||||
	_nexthop_group_add_sorted(&nhg, nh);
 | 
			
		||||
 | 
			
		||||
	if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)) {
 | 
			
		||||
		nhg_connected_tree_init(&nhg_depends);
 | 
			
		||||
		handle_recursive_depend(&nhg_depends, nh->resolved, afi);
 | 
			
		||||
	}
 | 
			
		||||
	zebra_nhg_find(&nhe, id, &nhg, NULL, nh->vrf_id, afi, 0);
 | 
			
		||||
 | 
			
		||||
	if (!zebra_nhg_find(nhe, id, &nhg, &nhg_depends, nh->vrf_id, afi, 0)) {
 | 
			
		||||
		created = false;
 | 
			
		||||
		depends_decrement_free(&nhg_depends);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (zebra_nhg_depends_count(*nhe))
 | 
			
		||||
			SET_FLAG((*nhe)->flags, NEXTHOP_GROUP_RECURSIVE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return created;
 | 
			
		||||
	return nhe;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct nhg_ctx *nhg_ctx_new()
 | 
			
		||||
@ -682,8 +707,8 @@ static int nhg_ctx_process_new(struct nhg_ctx *ctx)
 | 
			
		||||
		/* These got copied over in zebra_nhg_alloc() */
 | 
			
		||||
		nexthop_group_free_delete(&nhg);
 | 
			
		||||
	} else
 | 
			
		||||
		zebra_nhg_find_nexthop(&nhe, ctx->id, &ctx->u.nh, ctx->afi,
 | 
			
		||||
				       ctx->type);
 | 
			
		||||
		nhe = zebra_nhg_find_nexthop(ctx->id, &ctx->u.nh, ctx->afi,
 | 
			
		||||
					     ctx->type);
 | 
			
		||||
 | 
			
		||||
	if (nhe) {
 | 
			
		||||
		if (ctx->id != nhe->id) {
 | 
			
		||||
@ -858,7 +883,7 @@ static struct nhg_hash_entry *depends_find(struct nexthop *nh, afi_t afi)
 | 
			
		||||
	lookup->next = NULL;
 | 
			
		||||
	lookup->prev = NULL;
 | 
			
		||||
 | 
			
		||||
	zebra_nhg_find_nexthop(&nhe, 0, lookup, afi, 0);
 | 
			
		||||
	nhe = zebra_nhg_find_nexthop(0, lookup, afi, 0);
 | 
			
		||||
 | 
			
		||||
	nexthops_free(lookup);
 | 
			
		||||
 | 
			
		||||
@ -906,11 +931,7 @@ struct nhg_hash_entry *
 | 
			
		||||
zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi)
 | 
			
		||||
{
 | 
			
		||||
	struct nhg_hash_entry *nhe = NULL;
 | 
			
		||||
	struct nhg_connected_tree_head nhg_depends = {};
 | 
			
		||||
	bool recursive = false;
 | 
			
		||||
 | 
			
		||||
	/* Defualt the nhe to the afi and vrf of the route */
 | 
			
		||||
	afi_t nhg_afi = rt_afi;
 | 
			
		||||
	vrf_id_t nhg_vrf_id = nhg->nexthop->vrf_id;
 | 
			
		||||
 | 
			
		||||
	if (!nhg) {
 | 
			
		||||
@ -919,30 +940,7 @@ zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (nhg->nexthop->next) {
 | 
			
		||||
		nhg_connected_tree_init(&nhg_depends);
 | 
			
		||||
 | 
			
		||||
		/* If its a group, create a dependency tree */
 | 
			
		||||
		struct nexthop *nh = NULL;
 | 
			
		||||
 | 
			
		||||
		for (nh = nhg->nexthop; nh; nh = nh->next)
 | 
			
		||||
			depends_find_add(&nhg_depends, nh, rt_afi);
 | 
			
		||||
 | 
			
		||||
		/* change the afi/vrf_id since its a group */
 | 
			
		||||
		nhg_afi = AFI_UNSPEC;
 | 
			
		||||
		nhg_vrf_id = 0;
 | 
			
		||||
	} else if (CHECK_FLAG(nhg->nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) {
 | 
			
		||||
		nhg_connected_tree_init(&nhg_depends);
 | 
			
		||||
		handle_recursive_depend(&nhg_depends, nhg->nexthop->resolved,
 | 
			
		||||
					rt_afi);
 | 
			
		||||
		recursive = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!zebra_nhg_find(&nhe, id, nhg, &nhg_depends, nhg_vrf_id, nhg_afi,
 | 
			
		||||
			    0))
 | 
			
		||||
		depends_decrement_free(&nhg_depends);
 | 
			
		||||
	else if (recursive)
 | 
			
		||||
		SET_FLAG(nhe->flags, NEXTHOP_GROUP_RECURSIVE);
 | 
			
		||||
	zebra_nhg_find(&nhe, id, nhg, NULL, nhg_vrf_id, rt_afi, 0);
 | 
			
		||||
 | 
			
		||||
	return nhe;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user