diff options
| author | Donald Sharp <sharpd@cumulusnetworks.com> | 2018-03-17 21:13:09 -0400 | 
|---|---|---|
| committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2018-03-17 21:13:09 -0400 | 
| commit | da11e32521af32b4db39eeb48f2725e9f3db824d (patch) | |
| tree | ba4ef32067ef07174f15ff4f0883b4a93b4a84a3 | |
| parent | 78c16071f99bf3a5df1800a26656c3362eb0ba48 (diff) | |
pimd: Make the rpf scan per vrf.
We know the vrf that we are in when we need to initiate a
rescan of the rpf cache.  So pass it in and use that information.
This should help the rescan at scale with several vrf's cutting
out a lot of unnecessary work.
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
| -rw-r--r-- | pimd/pim_cmd.c | 14 | ||||
| -rw-r--r-- | pimd/pim_instance.h | 3 | ||||
| -rw-r--r-- | pimd/pim_neighbor.c | 4 | ||||
| -rw-r--r-- | pimd/pim_zebra.c | 242 | ||||
| -rw-r--r-- | pimd/pim_zebra.h | 2 | ||||
| -rw-r--r-- | pimd/pimd.c | 1 | ||||
| -rw-r--r-- | pimd/pimd.h | 1 | 
7 files changed, 114 insertions, 153 deletions
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 803e7bb013..a8935bf80d 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2566,8 +2566,8 @@ static void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty,  	}  } -static void show_rpf_refresh_stats(struct vty *vty, time_t now, -				   json_object *json) +static void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim, +				   time_t now, json_object *json)  {  	char refresh_uptime[10]; @@ -2579,7 +2579,7 @@ static void show_rpf_refresh_stats(struct vty *vty, time_t now,  				    qpim_rpf_cache_refresh_delay_msec);  		json_object_int_add(  			json, "rpfCacheRefreshTimer", -			pim_time_timer_remain_msec(qpim_rpf_cache_refresher)); +			pim_time_timer_remain_msec(pim->rpf_cache_refresher));  		json_object_int_add(json, "rpfCacheRefreshRequests",  				    qpim_rpf_cache_refresh_requests);  		json_object_int_add(json, "rpfCacheRefreshEvents", @@ -2600,7 +2600,7 @@ static void show_rpf_refresh_stats(struct vty *vty, time_t now,  			"Nexthop Lookups:            %lld\n"  			"Nexthop Lookups Avoided:    %lld\n",  			qpim_rpf_cache_refresh_delay_msec, -			pim_time_timer_remain_msec(qpim_rpf_cache_refresher), +			pim_time_timer_remain_msec(pim->rpf_cache_refresher),  			(long long)qpim_rpf_cache_refresh_requests,  			(long long)qpim_rpf_cache_refresh_events,  			refresh_uptime, (long long)qpim_nexthop_lookups, @@ -2642,9 +2642,9 @@ static void pim_show_rpf(struct pim_instance *pim, struct vty *vty, u_char uj)  	if (uj) {  		json = json_object_new_object(); -		show_rpf_refresh_stats(vty, now, json); +		show_rpf_refresh_stats(vty, pim, now, json);  	} else { -		show_rpf_refresh_stats(vty, now, json); +		show_rpf_refresh_stats(vty, pim, now, json);  		vty_out(vty, "\n");  		vty_out(vty,  			"Source          Group           RpfIface RpfAddress      RibNextHop      Metric Pref\n"); @@ -4337,7 +4337,7 @@ static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,  	vty_out(vty, "\n"); -	show_rpf_refresh_stats(vty, now, NULL); +	show_rpf_refresh_stats(vty, pim, now, NULL);  	vty_out(vty, "\n"); diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 5422e8fe0d..e672c39fdc 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -94,6 +94,9 @@ struct pim_instance {  	unsigned int keep_alive_time;  	unsigned int rp_keep_alive_time; + +	/* If we need to rescan all our upstreams */ +	struct thread *rpf_cache_refresher;  };  void pim_vrf_init(void); diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 134dbd8712..20a942b4fd 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -545,7 +545,7 @@ pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,  	pim_rp_setup(pim_ifp->pim); -	sched_rpf_cache_refresh(); +	sched_rpf_cache_refresh(pim_ifp->pim);  	return neigh;  } @@ -667,7 +667,7 @@ void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,  	pim_neighbor_free(neigh); -	sched_rpf_cache_refresh(); +	sched_rpf_cache_refresh(pim_ifp->pim);  }  void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 81c0cb6efb..ecb97e8e44 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -394,133 +394,105 @@ static int pim_zebra_if_address_del(int command, struct zclient *client,  	return 0;  } -static void scan_upstream_rpf_cache() +static void scan_upstream_rpf_cache(struct pim_instance *pim)  {  	struct listnode *up_node;  	struct listnode *up_nextnode;  	struct listnode *node;  	struct pim_upstream *up;  	struct interface *ifp; -	struct vrf *vrf; -	struct pim_instance *pim; -	RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { -		pim = vrf->info; -		if (!pim) -			continue; +	for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) { +		enum pim_rpf_result rpf_result; +		struct pim_rpf old; +		struct prefix nht_p; -		for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, -				       up)) { -			enum pim_rpf_result rpf_result; -			struct pim_rpf old; -			struct prefix nht_p; - -			nht_p.family = AF_INET; -			nht_p.prefixlen = IPV4_MAX_BITLEN; -			nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; -			pim_resolve_upstream_nh(pim, &nht_p); +		nht_p.family = AF_INET; +		nht_p.prefixlen = IPV4_MAX_BITLEN; +		nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; +		pim_resolve_upstream_nh(pim, &nht_p); -			old.source_nexthop.interface = -				up->rpf.source_nexthop.interface; -			old.source_nexthop.nbr = up->rpf.source_nexthop.nbr; -			rpf_result = pim_rpf_update(pim, up, &old, 0); +		old.source_nexthop.interface = up->rpf.source_nexthop.interface; +		old.source_nexthop.nbr = up->rpf.source_nexthop.nbr; +		rpf_result = pim_rpf_update(pim, up, &old, 0); -			if (rpf_result == PIM_RPF_FAILURE) -				continue; +		if (rpf_result == PIM_RPF_FAILURE) +			continue; -			if (rpf_result == PIM_RPF_CHANGED) { -				struct pim_neighbor *nbr; +		if (rpf_result == PIM_RPF_CHANGED) { +			struct pim_neighbor *nbr; + +			nbr = pim_neighbor_find(old.source_nexthop.interface, +						old.rpf_addr.u.prefix4); +			if (nbr) +				pim_jp_agg_remove_group(nbr->upstream_jp_agg, +							up); + +			/* +			 * We have detected a case where we might need +			 * to rescan +			 * the inherited o_list so do it. +			 */ +			if (up->channel_oil->oil_inherited_rescan) { +				pim_upstream_inherited_olist_decide(pim, up); +				up->channel_oil->oil_inherited_rescan = 0; +			} -				nbr = pim_neighbor_find( -					old.source_nexthop.interface, -					old.rpf_addr.u.prefix4); -				if (nbr) -					pim_jp_agg_remove_group( -						nbr->upstream_jp_agg, up); +			if (up->join_state == PIM_UPSTREAM_JOINED) { +				/* +				 * If we come up real fast we can be here +				 * where the mroute has not been installed +				 * so install it. +				 */ +				if (!up->channel_oil->installed) +					pim_mroute_add(up->channel_oil, +						       __PRETTY_FUNCTION__);  				/* -				 * We have detected a case where we might need -				 * to rescan -				 * the inherited o_list so do it. +				 * RFC 4601: 4.5.7.  Sending (S,G) +				 * Join/Prune Messages +				 * +				 * Transitions from Joined State +				 * +				 * RPF'(S,G) changes not due to an Assert +				 * +				 * The upstream (S,G) state machine remains +				 * in Joined state. Send Join(S,G) to the new +				 * upstream neighbor, which is the new value +				 * of RPF'(S,G).  Send Prune(S,G) to the old +				 * upstream neighbor, which is the old value +				 * of RPF'(S,G).  Set the Join Timer (JT) to +				 * expire after t_periodic seconds.  				 */ -				if (up->channel_oil->oil_inherited_rescan) { -					pim_upstream_inherited_olist_decide(pim, -									    up); -					up->channel_oil->oil_inherited_rescan = -						0; -				} +				pim_jp_agg_switch_interface(&old, &up->rpf, up); -				if (up->join_state == PIM_UPSTREAM_JOINED) { -					/* -					 * If we come up real fast we can be -					 * here -					 * where the mroute has not been -					 * installed -					 * so install it. -					 */ -					if (!up->channel_oil->installed) -						pim_mroute_add( -							up->channel_oil, -							__PRETTY_FUNCTION__); - -					/* -					 * RFC 4601: 4.5.7.  Sending (S,G) -					 * Join/Prune Messages -					 * -					 * Transitions from Joined State -					 * -					 * RPF'(S,G) changes not due to an -					 * Assert -					 * -					 * The upstream (S,G) state machine -					 * remains in Joined -					 * state. Send Join(S,G) to the new -					 * upstream neighbor, which is -					 * the new value of RPF'(S,G).  Send -					 * Prune(S,G) to the old -					 * upstream neighbor, which is the old -					 * value of RPF'(S,G).  Set -					 * the Join Timer (JT) to expire after -					 * t_periodic seconds. -					 */ -					pim_jp_agg_switch_interface( -						&old, &up->rpf, up); - -					pim_upstream_join_timer_restart(up, -									&old); -				} /* up->join_state == PIM_UPSTREAM_JOINED */ - -				/* FIXME can join_desired actually be changed by -				   pim_rpf_update() -				   returning PIM_RPF_CHANGED ? */ -				pim_upstream_update_join_desired(pim, up); - -			} /* PIM_RPF_CHANGED */ - -		} /* for (qpim_upstream_list) */ -	} +				pim_upstream_join_timer_restart(up, &old); +			} /* up->join_state == PIM_UPSTREAM_JOINED */ -	RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { -		pim = vrf->info; -		if (!pim) -			continue; +			/* FIXME can join_desired actually be changed by +			   pim_rpf_update() +			   returning PIM_RPF_CHANGED ? */ +			pim_upstream_update_join_desired(pim, up); -		FOR_ALL_INTERFACES (pim->vrf, ifp) -			if (ifp->info) { -				struct pim_interface *pim_ifp = ifp->info; -				struct pim_iface_upstream_switch *us; - -				for (ALL_LIST_ELEMENTS_RO( -					     pim_ifp->upstream_switch_list, -					     node, us)) { -					struct pim_rpf rpf; -					rpf.source_nexthop.interface = ifp; -					rpf.rpf_addr.u.prefix4 = us->address; -					pim_joinprune_send(&rpf, us->us); -					pim_jp_agg_clear_group(us->us); -				} +		} /* PIM_RPF_CHANGED */ + +	} /* for (qpim_upstream_list) */ + +	FOR_ALL_INTERFACES (pim->vrf, ifp) +		if (ifp->info) { +			struct pim_interface *pim_ifp = ifp->info; +			struct pim_iface_upstream_switch *us; + +			for (ALL_LIST_ELEMENTS_RO(pim_ifp->upstream_switch_list, +						  node, us)) { +				struct pim_rpf rpf; + +				rpf.source_nexthop.interface = ifp; +				rpf.rpf_addr.u.prefix4 = us->address; +				pim_joinprune_send(&rpf, us->us); +				pim_jp_agg_clear_group(us->us);  			} -	} +		}  }  void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index) @@ -657,53 +629,41 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index)  	}  } -void pim_scan_oil(struct pim_instance *pim_matcher) +void pim_scan_oil(struct pim_instance *pim)  {  	struct listnode *node;  	struct listnode *nextnode;  	struct channel_oil *c_oil;  	ifindex_t ifindex;  	int vif_index = 0; -	struct vrf *vrf; -	struct pim_instance *pim;  	qpim_scan_oil_last = pim_time_monotonic_sec();  	++qpim_scan_oil_events; -	RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { -		pim = vrf->info; -		if (!pim) -			continue; - -		if (pim_matcher && pim != pim_matcher) -			continue; - -		for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, -				       c_oil)) { -			if (c_oil->up -			    && c_oil->up->rpf.source_nexthop.interface) { -				ifindex = c_oil->up->rpf.source_nexthop -						  .interface->ifindex; -				vif_index = pim_if_find_vifindex_by_ifindex( -					pim, ifindex); -				/* Pass Current selected NH vif index to mroute -				 * download */ -				if (vif_index) -					pim_scan_individual_oil(c_oil, -								vif_index); -			} else -				pim_scan_individual_oil(c_oil, 0); -		} +	for (ALL_LIST_ELEMENTS(pim->channel_oil_list, node, nextnode, c_oil)) { +		if (c_oil->up && c_oil->up->rpf.source_nexthop.interface) { +			ifindex = c_oil->up->rpf.source_nexthop +					  .interface->ifindex; +			vif_index = +				pim_if_find_vifindex_by_ifindex(pim, ifindex); +			/* Pass Current selected NH vif index to mroute +			 * download */ +			if (vif_index) +				pim_scan_individual_oil(c_oil, vif_index); +		} else +			pim_scan_individual_oil(c_oil, 0);  	}  }  static int on_rpf_cache_refresh(struct thread *t)  { +	struct pim_instance *pim = THREAD_ARG(t); +  	/* update PIM protocol state */ -	scan_upstream_rpf_cache(); +	scan_upstream_rpf_cache(pim);  	/* update kernel multicast forwarding cache (MFC) */ -	pim_scan_oil(NULL); +	pim_scan_oil(pim);  	qpim_rpf_cache_refresh_last = pim_time_monotonic_sec();  	++qpim_rpf_cache_refresh_events; @@ -713,13 +673,13 @@ static int on_rpf_cache_refresh(struct thread *t)  	return 0;  } -void sched_rpf_cache_refresh(void) +void sched_rpf_cache_refresh(struct pim_instance *pim)  {  	++qpim_rpf_cache_refresh_requests;  	pim_rpf_set_refresh_time(); -	if (qpim_rpf_cache_refresher) { +	if (pim->rpf_cache_refresher) {  		/* Refresh timer is already running */  		return;  	} @@ -731,9 +691,9 @@ void sched_rpf_cache_refresh(void)  			   qpim_rpf_cache_refresh_delay_msec);  	} -	thread_add_timer_msec(master, on_rpf_cache_refresh, 0, +	thread_add_timer_msec(master, on_rpf_cache_refresh, pim,  			      qpim_rpf_cache_refresh_delay_msec, -			      &qpim_rpf_cache_refresher); +			      &pim->rpf_cache_refresher);  }  static void pim_zebra_connected(struct zclient *zclient) diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h index d9b17cb82d..dd8aed0d20 100644 --- a/pimd/pim_zebra.h +++ b/pimd/pim_zebra.h @@ -44,6 +44,6 @@ void igmp_source_forward_reevaluate_all(void);  void pim_forward_start(struct pim_ifchannel *ch);  void pim_forward_stop(struct pim_ifchannel *ch, bool install_it); -void sched_rpf_cache_refresh(void); +void sched_rpf_cache_refresh(struct pim_instance *pim);  struct zclient *pim_zebra_zclient_get(void);  #endif /* PIM_ZEBRA_H */ diff --git a/pimd/pimd.c b/pimd/pimd.c index 52e0920f1f..0532ce873a 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -52,7 +52,6 @@ int qpim_t_periodic =  	PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */  struct pim_assert_metric qpim_infinite_assert_metric;  long qpim_rpf_cache_refresh_delay_msec = 50; -struct thread *qpim_rpf_cache_refresher = NULL;  int64_t qpim_rpf_cache_refresh_requests = 0;  int64_t qpim_rpf_cache_refresh_events = 0;  int64_t qpim_rpf_cache_refresh_last = 0; diff --git a/pimd/pimd.h b/pimd/pimd.h index de7f259319..89582b991e 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -140,7 +140,6 @@ struct in_addr qpim_all_pim_routers_addr;  int qpim_t_periodic; /* Period between Join/Prune Messages */  struct pim_assert_metric qpim_infinite_assert_metric;  long qpim_rpf_cache_refresh_delay_msec; -struct thread *qpim_rpf_cache_refresher;  int64_t qpim_rpf_cache_refresh_requests;  int64_t qpim_rpf_cache_refresh_events;  int64_t qpim_rpf_cache_refresh_last;  | 
