diff options
| author | Satheesh Kumar K <sathk@cumulusnetworks.com> | 2019-08-19 02:06:00 -0700 | 
|---|---|---|
| committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2020-03-06 16:03:36 -0500 | 
| commit | 22c35834ea43ebec121c0c042bbb2ef3b6e25591 (patch) | |
| tree | 2deced58e8cd0934d6d4c005824b5c21359b4756 /pimd | |
| parent | ec85b101e6ba032c17981b9f354f358a0bc67c01 (diff) | |
pimd: Use PIM EVPN MLAG Infra for syncing PIM MLAG Entries
Initially, MLAG Sync is happened at pim_ifchannel, this is mainly to
support even config mismatches(missing configuration of dual active).
But this causes more syncs for each entry.
and also it is not In-line with PIM EVPN. to avoid that moving to
pm_upstream based syncing.
Signed-off-by: Satheesh Kumar K <sathk@cumulusnetworks.com>
Diffstat (limited to 'pimd')
| -rw-r--r-- | pimd/pim_iface.h | 1 | ||||
| -rw-r--r-- | pimd/pim_ifchannel.c | 34 | ||||
| -rw-r--r-- | pimd/pim_mlag.c | 95 | ||||
| -rw-r--r-- | pimd/pim_mlag.h | 11 | ||||
| -rw-r--r-- | pimd/pim_upstream.c | 25 | ||||
| -rw-r--r-- | pimd/pim_upstream.h | 2 | 
6 files changed, 158 insertions, 10 deletions
diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index 1b76b52305..570bf5eac3 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -55,6 +55,7 @@  #define PIM_IF_DONT_PIM_CAN_DISABLE_JOIN_SUPRESSION(options) ((options) &= ~PIM_IF_MASK_PIM_CAN_DISABLE_JOIN_SUPRESSION)  #define PIM_I_am_DR(pim_ifp) (pim_ifp)->pim_dr_addr.s_addr == (pim_ifp)->primary_address.s_addr +#define PIM_I_am_DualActive(pim_ifp) (pim_ifp)->activeactive == true  struct pim_iface_upstream_switch {  	struct in_addr address; diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 528c93ce16..e23d3dc3da 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -43,6 +43,7 @@  #include "pim_upstream.h"  #include "pim_ssm.h"  #include "pim_rp.h" +#include "pim_mlag.h"  RB_GENERATE(pim_ifchannel_rb, pim_ifchannel, pim_ifp_rb, pim_ifchannel_compare); @@ -130,6 +131,21 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)  	pim_ifp = ch->interface->info; +	if (PIM_I_am_DualActive(pim_ifp)) { +		if (PIM_DEBUG_MLAG) +			zlog_debug( +				"%s: if-chnanel-%s is deleted from a Dual " +				"active Interface", +				__func__, ch->sg_str); +		/* Post Delete only if it is the last Dual-active Interface */ +		if (ch->upstream->dualactive_ifchannel_count == 1) { +			pim_mlag_up_local_del(pim_ifp->pim, ch->upstream); +			PIM_UPSTREAM_FLAG_UNSET_MLAG_INTERFACE( +				ch->upstream->flags); +		} +		ch->upstream->dualactive_ifchannel_count--; +	} +  	if (ch->upstream->channel_oil) {  		uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;  		if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) @@ -586,6 +602,24 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,  	else  		PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags); +	/* +	 * advertise MLAG Data to MLAG peer +	 */ +	if (PIM_I_am_DualActive(pim_ifp)) { +		up->dualactive_ifchannel_count++; +		/* Sync once for upstream */ +		if (up->dualactive_ifchannel_count == 1) { +			PIM_UPSTREAM_FLAG_SET_MLAG_INTERFACE(up->flags); +			pim_mlag_up_local_add(pim_ifp->pim, up); +		} +		if (PIM_DEBUG_MLAG) +			zlog_debug( +				"%s: New Dual active if-chnanel is added to upstream:%s " +				"count:%d, flags:0x%x", +				__func__, up->sg_str, +				up->dualactive_ifchannel_count, up->flags); +	} +  	if (PIM_DEBUG_PIM_TRACE)  		zlog_debug("%s: ifchannel %s is created ", __func__,  			   ch->sg_str); diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c index defe41674c..321745590d 100644 --- a/pimd/pim_mlag.c +++ b/pimd/pim_mlag.c @@ -32,6 +32,76 @@ extern struct zclient *zclient;  #define PIM_MLAG_METADATA_LEN 4 +/*********************ACtual Data processing *****************************/ +/* TBD: There can be duplicate updates to FIB***/ +#define PIM_MLAG_ADD_OIF_TO_OIL(ch, ch_oil)                                    \ +	do {                                                                   \ +		if (PIM_DEBUG_MLAG)                                            \ +			zlog_debug(                                            \ +				"%s: add Dual-active Interface to %s "         \ +				"to oil:%s",                                   \ +				__func__, ch->interface->name, ch->sg_str);    \ +		pim_channel_add_oif(ch_oil, ch->interface,                     \ +				    PIM_OIF_FLAG_PROTO_IGMP, __func__);        \ +	} while (0) + +#define PIM_MLAG_DEL_OIF_TO_OIL(ch, ch_oil)                                    \ +	do {                                                                   \ +		if (PIM_DEBUG_MLAG)                                            \ +			zlog_debug(                                            \ +				"%s: del Dual-active Interface to %s "         \ +				"to oil:%s",                                   \ +				__func__, ch->interface->name, ch->sg_str);    \ +		pim_channel_del_oif(ch_oil, ch->interface,                     \ +				    PIM_OIF_FLAG_PROTO_IGMP, __func__);        \ +	} while (0) + + +static void pim_mlag_calculate_df_for_ifchannels(struct pim_upstream *up, +						 bool is_df) +{ +	struct listnode *chnode; +	struct listnode *chnextnode; +	struct pim_ifchannel *ch; +	struct pim_interface *pim_ifp = NULL; +	struct channel_oil *ch_oil = NULL; + +	ch_oil = (up) ? up->channel_oil : NULL; + +	if (!ch_oil) +		return; + +	if (PIM_DEBUG_MLAG) +		zlog_debug("%s: Calculating DF for Dual active if-channel%s", +			   __func__, up->sg_str); + +	for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) { +		pim_ifp = (ch->interface) ? ch->interface->info : NULL; +		if (!pim_ifp || !PIM_I_am_DualActive(pim_ifp)) +			continue; + +		if (is_df) +			PIM_MLAG_ADD_OIF_TO_OIL(ch, ch_oil); +		else +			PIM_MLAG_DEL_OIF_TO_OIL(ch, ch_oil); +	} +} + +static void pim_mlag_inherit_mlag_flags(struct pim_upstream *up, bool is_df) +{ +	struct listnode *listnode; +	struct pim_upstream *child; + +	for (ALL_LIST_ELEMENTS_RO(up->sources, listnode, child)) { +		PIM_UPSTREAM_FLAG_SET_MLAG_PEER(child->flags); +		if (is_df) +			PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF(child->flags); +		else +			PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(child->flags); +		pim_mlag_calculate_df_for_ifchannels(child, is_df); +	} +} +  /******************************* pim upstream sync **************************/  /* Update DF role for the upstream entry and return true on role change */  bool pim_mlag_up_df_role_update(struct pim_instance *pim, @@ -59,6 +129,15 @@ bool pim_mlag_up_df_role_update(struct pim_instance *pim,  		PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(up->flags); +	/* +	 * This Upstream entry synced to peer Because of Dual-active +	 * Interface configuration +	 */ +	if (PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags)) { +		pim_mlag_calculate_df_for_ifchannels(up, is_df); +		pim_mlag_inherit_mlag_flags(up, is_df); +	} +  	/* If the DF role has changed check if ipmr-lo needs to be  	 * muted/un-muted. Active-Active devices and vxlan termination  	 * devices (ipmr-lo) are suppressed on the non-DF. @@ -91,7 +170,8 @@ static bool pim_mlag_up_df_role_elect(struct pim_instance *pim,  	uint32_t local_cost;  	bool rv; -	if (!pim_up_mlag_is_local(up)) +	if (!pim_up_mlag_is_local(up) +	    && !PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags))  		return false;  	/* We are yet to rx a status update from the local MLAG daemon so @@ -417,7 +497,8 @@ static void pim_mlag_up_local_replay(void)  	RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {  		pim = vrf->info;  		frr_each (rb_pim_upstream, &pim->upstream_head, up) { -			if (pim_up_mlag_is_local(up)) +			if (pim_up_mlag_is_local(up) +			    || PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags))  				pim_mlag_up_local_add_send(pim, up);  		}  	} @@ -438,7 +519,9 @@ static void pim_mlag_up_local_reeval(bool mlagd_send, const char *reason_code)  	RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {  		pim = vrf->info;  		frr_each (rb_pim_upstream, &pim->upstream_head, up) { -			if (!pim_up_mlag_is_local(up)) +			if (!pim_up_mlag_is_local(up) +			    && !PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE( +				    up->flags))  				continue;  			/* if role changes re-send to peer */  			if (pim_mlag_up_df_role_elect(pim, up) && @@ -772,6 +855,12 @@ int pim_zebra_mlag_process_up(void)  	if (PIM_DEBUG_MLAG)  		zlog_debug("%s: Received Process-Up from Mlag", __func__); +	/* +	 * Incase of local MLAG restart, PIM needs to replay all the data +	 * since MLAG is empty. +	 */ +	router->connected_to_mlag = true; +	router->mlag_flags |= PIM_MLAGF_LOCAL_CONN_UP;  	return 0;  } diff --git a/pimd/pim_mlag.h b/pimd/pim_mlag.h index 4639f56826..eb316695f7 100644 --- a/pimd/pim_mlag.h +++ b/pimd/pim_mlag.h @@ -32,8 +32,6 @@ extern void pim_instance_mlag_init(struct pim_instance *pim);  extern void pim_instance_mlag_terminate(struct pim_instance *pim);  extern void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp);  extern void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp); -extern void pim_mlag_register(void); -extern void pim_mlag_deregister(void);  extern int pim_zebra_mlag_process_up(void);  extern int pim_zebra_mlag_process_down(void);  extern int pim_zebra_mlag_handle_msg(struct stream *msg, int len); @@ -43,10 +41,13 @@ extern int pim_mlag_signal_zpthread(void);  extern void pim_zpthread_init(void);  extern void pim_zpthread_terminate(void); +extern void pim_mlag_register(void); +extern void pim_mlag_deregister(void);  extern void pim_mlag_up_local_add(struct pim_instance *pim, -		struct pim_upstream *upstream); +				  struct pim_upstream *upstream);  extern void pim_mlag_up_local_del(struct pim_instance *pim, -		struct pim_upstream *upstream); +				  struct pim_upstream *upstream);  extern bool pim_mlag_up_df_role_update(struct pim_instance *pim, -		struct pim_upstream *up, bool is_df, const char *reason); +				       struct pim_upstream *up, bool is_df, +				       const char *reason);  #endif diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index c905dd146a..998720e8f6 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -141,6 +141,18 @@ static struct pim_upstream *pim_upstream_find_parent(struct pim_instance *pim,  		if (up)  			listnode_add(up->sources, child); +		/* +		 * In case parent is MLAG entry copy the data to child +		 */ +		if (up && PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags)) { +			PIM_UPSTREAM_FLAG_SET_MLAG_INTERFACE(child->flags); +			if (PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags)) +				PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(child->flags); +			else +				PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF( +					child->flags); +		} +  		return up;  	} @@ -903,7 +915,8 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,  	/* XXX - duplicate send is possible here if pim_rpf_update  	 * successfully resolved the nexthop  	 */ -	if (pim_up_mlag_is_local(up)) +	if (pim_up_mlag_is_local(up) +	    || PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags))  		pim_mlag_up_local_add(pim, up);  	if (PIM_DEBUG_PIM_TRACE) { @@ -918,7 +931,8 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,  uint32_t pim_up_mlag_local_cost(struct pim_upstream *up)  { -	if (!(pim_up_mlag_is_local(up))) +	if (!(pim_up_mlag_is_local(up)) +	    && !(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE))  		return router->infinite_assert_metric.route_metric;  	if ((up->rpf.source_nexthop.interface == @@ -1752,6 +1766,7 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,  				   up->sg_str);  	FOR_ALL_INTERFACES (pim->vrf, ifp) { +		struct pim_interface *pim_ifp;  		if (!ifp->info)  			continue; @@ -1765,6 +1780,12 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,  		if (!ch && !starch)  			continue; +		pim_ifp = ifp->info; +		if (PIM_I_am_DualActive(pim_ifp) +		    && PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(up->flags) +		    && (PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags) +			|| !PIM_UPSTREAM_FLAG_TEST_MLAG_PEER(up->flags))) +			continue;  		if (pim_upstream_evaluate_join_desired_interface(up, ch,  								 starch)) {  			int flag = PIM_OIF_FLAG_PROTO_PIM; diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 4d693b8b64..ca693ee73f 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -237,6 +237,8 @@ struct pim_upstream {  	struct channel_oil *channel_oil;  	struct list *sources;  	struct list *ifchannels; +	/* Counter for Dual active ifchannels*/ +	uint32_t dualactive_ifchannel_count;  	enum pim_upstream_state join_state;  	enum pim_reg_state reg_state;  | 
