diff options
| author | mobash-rasool <mrasool@vmware.com> | 2023-08-15 22:26:21 +0530 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-15 22:26:21 +0530 | 
| commit | 2b4e03871166265ee82003b89d5e82a378478a97 (patch) | |
| tree | ff8a601398e8df2a6954ae834e57f2a2fa591f7f /pimd | |
| parent | 77014daf3a88f4a4e2874db93e4b3915937f20ee (diff) | |
| parent | 538520239951422ac88791a8516a293fd1d3504c (diff) | |
Merge pull request #14193 from donaldsharp/pim_vxlan_weirdness
Do not look into pim's eyes, pim gets mad
Diffstat (limited to 'pimd')
| -rw-r--r-- | pimd/pim_msg.c | 27 | ||||
| -rw-r--r-- | pimd/pim_nht.c | 41 | ||||
| -rw-r--r-- | pimd/pim_upstream.c | 1 | ||||
| -rw-r--r-- | pimd/pim_vxlan.c | 36 | ||||
| -rw-r--r-- | pimd/pim_vxlan.h | 3 | 
5 files changed, 98 insertions, 10 deletions
diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 5d1f08314b..6814798bf5 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -196,7 +196,32 @@ size_t pim_msg_get_jp_group_size(struct list *sources)  				__func__, up->sg_str);  		for (ALL_LIST_ELEMENTS_RO(up->sources, up_node, child)) { -			if (!PIM_UPSTREAM_FLAG_TEST_USE_RPT(child->flags)) { +			/* +			 * PIM VXLAN is weird +			 * It auto creates the S,G and populates a bunch +			 * of flags that make it look like a SPT prune should +			 * be sent.  But this regularly scheduled join +			 * for the *,G in the VXLAN setup can happen at +			 * scheduled times *before* the null register +			 * is received by the RP to cause it to initiate +			 * the S,G joins toward the source.  Let's just +			 * assume that if this is a SRC VXLAN ORIG route +			 * and no actual ifchannels( joins ) have been +			 * created then do not send the embedded prune +			 * Why you may ask?  Well if the prune is S,G +			 * RPT Prune is received *before* the join +			 * from the RP( if it flows to this routers +			 * upstream interface ) then we'll just wisely +			 * create a mroute with an empty oil on +			 * the upstream intermediate router preventing +			 * packets from flowing to the RP +			 */ +			if (PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(child->flags) && +			    listcount(child->ifchannels) == 0) { +				if (PIM_DEBUG_PIM_PACKETS) +					zlog_debug("%s: %s Vxlan originated S,G route with no ifchannels, not adding prune to compound message", +						   __func__, child->sg_str); +			} else if (!PIM_UPSTREAM_FLAG_TEST_USE_RPT(child->flags)) {  				/* If we are using SPT and the SPT and RPT IIFs  				 * are different we can prune the source off  				 * of the RPT. diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 5f0f2a5933..4e8e5f0df7 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -31,6 +31,8 @@  #include "pim_zlookup.h"  #include "pim_rp.h"  #include "pim_addr.h" +#include "pim_register.h" +#include "pim_vxlan.h"  /**   * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister @@ -399,17 +401,28 @@ static void pim_update_rp_nh(struct pim_instance *pim,  {  	struct listnode *node = NULL;  	struct rp_info *rp_info = NULL; +	struct interface *ifp;  	/*Traverse RP list and update each RP Nexthop info */  	for (ALL_LIST_ELEMENTS_RO(pnc->rp_list, node, rp_info)) {  		if (pim_rpf_addr_is_inaddr_any(&rp_info->rp))  			continue; +		ifp = rp_info->rp.source_nexthop.interface;  		// Compute PIM RPF using cached nexthop  		if (!pim_ecmp_nexthop_lookup(pim, &rp_info->rp.source_nexthop,  					     rp_info->rp.rpf_addr,  					     &rp_info->group, 1))  			pim_rp_nexthop_del(rp_info); + +		/* +		 * If we transition from no path to a path +		 * we need to search through all the vxlan's +		 * that use this rp and send NULL registers +		 * for all the vxlan S,G streams +		 */ +		if (!ifp && rp_info->rp.source_nexthop.interface) +			pim_vxlan_rp_info_is_alive(pim, &rp_info->rp);  	}  } @@ -436,17 +449,27 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg)  		(rpf_result == PIM_RPF_FAILURE && old.source_nexthop.interface))  		pim_zebra_upstream_rpf_changed(pim, up, &old); +	/* +	 * If we are a VXLAN source and we are transitioning from not +	 * having an outgoing interface to having an outgoing interface +	 * let's immediately send the null pim register +	 */ +	if (!old.source_nexthop.interface && up->rpf.source_nexthop.interface && +	    PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(up->flags) && +	    (up->reg_state == PIM_REG_NOINFO || up->reg_state == PIM_REG_JOIN)) { +		pim_null_register_send(up); +	}  	if (PIM_DEBUG_PIM_NHT) { -		zlog_debug( -			"%s: NHT upstream %s(%s) old ifp %s new ifp %s", -			__func__, up->sg_str, pim->vrf->name, -			old.source_nexthop.interface ? old.source_nexthop -							       .interface->name -						     : "Unknown", -			up->rpf.source_nexthop.interface ? up->rpf.source_nexthop -								   .interface->name -							 : "Unknown"); +		zlog_debug("%s: NHT upstream %s(%s) old ifp %s new ifp %s rpf_result: %d", +			   __func__, up->sg_str, pim->vrf->name, +			   old.source_nexthop.interface ? old.source_nexthop +								  .interface->name +							: "Unknown", +			   up->rpf.source_nexthop.interface ? up->rpf.source_nexthop +								      .interface->name +							    : "Unknown", +			   rpf_result);  	}  	return HASHWALK_CONTINUE; diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index a8d087bf49..fd99e77761 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -912,6 +912,7 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,  				false /*update_mroute*/);  		rpf_result = pim_rpf_update(pim, up, NULL, __func__);  		if (rpf_result == PIM_RPF_FAILURE) { +			up->channel_oil->oil_inherited_rescan = 1;  			if (PIM_DEBUG_PIM_TRACE)  				zlog_debug(  					"%s: Attempting to create upstream(%s), Unable to RPF for source", diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c index 8df3c90f00..9650da89a8 100644 --- a/pimd/pim_vxlan.c +++ b/pimd/pim_vxlan.c @@ -32,6 +32,41 @@ static void pim_vxlan_work_timer_setup(bool start);  static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,  			struct interface *ifp); +/* + * The rp info has gone from no path to having a + * path.  Let's immediately send out the null pim register + * as that else we will be sitting for up to 60 seconds waiting + * for it too pop.  Which is not cool. + */ +void pim_vxlan_rp_info_is_alive(struct pim_instance *pim, +				struct pim_rpf *rpg_changed) +{ +	struct listnode *listnode; +	struct pim_vxlan_sg *vxlan_sg; +	struct pim_rpf *rpg; + +	/* +	 * No vxlan here, move along, nothing to see +	 */ +	if (!vxlan_info.work_list) +		return; + +	for (listnode = vxlan_info.work_list->head; listnode; +	     listnode = listnode->next) { +		vxlan_sg = listgetdata(listnode); + +		rpg = RP(pim, vxlan_sg->up->sg.grp); + +		/* +		 * If the rp is the same we should send +		 */ +		if (rpg == rpg_changed) { +			zlog_debug("VXLAN RP INFO is alive sending"); +			pim_null_register_send(vxlan_sg->up); +		} +	} +} +  /*************************** vxlan work list **********************************   * A work list is maintained for staggered generation of pim null register   * messages for vxlan SG entries that are in a reg_join state. @@ -66,6 +101,7 @@ static void pim_vxlan_do_reg_work(void)  	for (; listnode; listnode = listnode->next) {  		vxlan_sg = (struct pim_vxlan_sg *)listnode->data; +  		if (vxlan_sg->up && (vxlan_sg->up->reg_state == PIM_REG_JOIN)) {  			if (PIM_DEBUG_VXLAN)  				zlog_debug("vxlan SG %s periodic NULL register", diff --git a/pimd/pim_vxlan.h b/pimd/pim_vxlan.h index 9a135ca6b8..5039bf6540 100644 --- a/pimd/pim_vxlan.h +++ b/pimd/pim_vxlan.h @@ -135,6 +135,9 @@ extern bool pim_vxlan_do_mlag_reg(void);  extern void pim_vxlan_inherit_mlag_flags(struct pim_instance *pim,  		struct pim_upstream *up, bool inherit); +extern void pim_vxlan_rp_info_is_alive(struct pim_instance *pim, +				       struct pim_rpf *rpg_changed); +  /* Shutdown of PIM stop the thread */  extern void pim_vxlan_terminate(void);  #endif /* PIM_VXLAN_H */  | 
