diff options
| author | Donatas Abraitis <donatas@opensourcerouting.org> | 2022-09-18 22:18:13 +0300 | 
|---|---|---|
| committer | Donatas Abraitis <donatas@opensourcerouting.org> | 2022-10-12 17:48:43 +0300 | 
| commit | 46dbf9d0c0b99f60767793ef3b688f95175edc6e (patch) | |
| tree | caa2b86397dc6c9dec7969e9ea3a91119e211293 /bgpd | |
| parent | 984eb32b588186ac946733c5c3fe8032bae28ebc (diff) | |
bgpd: Implement ACCEPT_OWN extended community
TL;DR: rfc7611.
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
Diffstat (limited to 'bgpd')
| -rw-r--r-- | bgpd/bgp_community.h | 27 | ||||
| -rw-r--r-- | bgpd/bgp_mplsvpn.c | 84 | ||||
| -rw-r--r-- | bgpd/bgp_mplsvpn.h | 3 | ||||
| -rw-r--r-- | bgpd/bgp_nht.c | 3 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 147 | ||||
| -rw-r--r-- | bgpd/bgp_route.h | 5 | ||||
| -rw-r--r-- | bgpd/bgp_table.h | 1 | ||||
| -rw-r--r-- | bgpd/bgp_vty.c | 34 | ||||
| -rw-r--r-- | bgpd/bgpd.c | 1 | ||||
| -rw-r--r-- | bgpd/bgpd.h | 1 | 
10 files changed, 274 insertions, 32 deletions
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h index 616ddb4405..05a5d4486a 100644 --- a/bgpd/bgp_community.h +++ b/bgpd/bgp_community.h @@ -23,6 +23,7 @@  #include "lib/json.h"  #include "bgpd/bgp_route.h" +#include "bgpd/bgp_attr.h"  /* Communities attribute.  */  struct community { @@ -109,4 +110,30 @@ extern void bgp_remove_comm_from_aggregate_hash(struct bgp_aggregate *aggregate,  						struct community *community);  extern void bgp_aggr_community_remove(void *arg); +/* This implies that when propagating routes into a VRF, the ACCEPT_OWN + * community SHOULD NOT be propagated. + */ +static inline void community_strip_accept_own(struct attr *attr) +{ +	struct community *old_com = bgp_attr_get_community(attr); +	struct community *new_com = NULL; +	uint32_t val = COMMUNITY_ACCEPT_OWN; + +	if (old_com && community_include(old_com, val)) { +		new_com = community_dup(old_com); +		val = htonl(val); +		community_del_val(new_com, &val); + +		if (!old_com->refcnt) +			community_free(&old_com); + +		if (!new_com->size) { +			community_free(&new_com); +			bgp_attr_set_community(attr, NULL); +		} else { +			bgp_attr_set_community(attr, new_com); +		} +	} +} +  #endif /* _QUAGGA_BGP_COMMUNITY_H */ diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 08748d2eba..66eef1aa52 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -42,6 +42,7 @@  #include "bgpd/bgp_packet.h"  #include "bgpd/bgp_vty.h"  #include "bgpd/bgp_vpn.h" +#include "bgpd/bgp_community.h"  #include "bgpd/bgp_ecommunity.h"  #include "bgpd/bgp_zebra.h"  #include "bgpd/bgp_nexthop.h" @@ -996,6 +997,9 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,  		if (nexthop_self_flag)  			bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF); +		if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN)) +			bgp_path_info_set_flag(bn, bpi, BGP_PATH_ACCEPT_OWN); +  		if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi,  					      source_bpi, bpi, bgp_orig, p,  					      debug)) @@ -1036,6 +1040,9 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,  	if (nexthop_self_flag)  		bgp_path_info_set_flag(bn, new, BGP_PATH_ANNC_NH_SELF); +	if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN)) +		bgp_path_info_set_flag(bn, new, BGP_PATH_ACCEPT_OWN); +  	bgp_path_info_extra_get(new);  	/* @@ -1217,6 +1224,8 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp,	     /* to */  		XFREE(MTYPE_ECOMMUNITY_STR, s);  	} +	community_strip_accept_own(&static_attr); +  	/* Nexthop */  	/* if policy nexthop not set, use 0 */  	if (CHECK_FLAG(from_bgp->vpn_policy[afi].flags, @@ -1362,7 +1371,7 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp,	     /* to */  	 * because of loop checking.  	 */  	if (new_info) -		vpn_leak_to_vrf_update(from_bgp, new_info); +		vpn_leak_to_vrf_update(from_bgp, new_info, NULL);  }  void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp,		/* to */ @@ -1518,10 +1527,40 @@ void vpn_leak_from_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,  	}  } -static bool -vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp,	     /* to */ -			      struct bgp *from_bgp,	   /* from */ -			      struct bgp_path_info *path_vpn) /* route */ +static struct bgp *bgp_lookup_by_rd(struct bgp_path_info *bpi, +				    struct prefix_rd *rd, afi_t afi) +{ +	struct listnode *node, *nnode; +	struct bgp *bgp; + +	if (!rd) +		return NULL; + +	/* If ACCEPT_OWN is not enabled for this path - return. */ +	if (!CHECK_FLAG(bpi->flags, BGP_PATH_ACCEPT_OWN)) +		return NULL; + +	for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { +		if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF) +			continue; + +		if (!CHECK_FLAG(bgp->vpn_policy[afi].flags, +				BGP_VPN_POLICY_TOVPN_RD_SET)) +			continue; + +		/* Check if we have source VRF by RD value */ +		if (memcmp(&bgp->vpn_policy[afi].tovpn_rd.val, rd->val, +			   ECOMMUNITY_SIZE) == 0) +			return bgp; +	} + +	return NULL; +} + +static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp,   /* to */ +					  struct bgp *from_bgp, /* from */ +					  struct bgp_path_info *path_vpn, +					  struct prefix_rd *prd)  {  	const struct prefix *p = bgp_dest_get_prefix(path_vpn->net);  	afi_t afi = family2afi(p->family); @@ -1558,9 +1597,22 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp,	     /* to */  		return false;  	} +	/* A route MUST NOT ever be accepted back into its source VRF, even if +	 * it carries one or more RTs that match that VRF. +	 */ +	if (prd && memcmp(&prd->val, &to_bgp->vpn_policy[afi].tovpn_rd.val, +			  ECOMMUNITY_SIZE) == 0) { +		if (debug) +			zlog_debug( +				"%s: skipping import, match RD (%pRD) of src VRF (%s) and the prefix (%pFX)", +				__func__, prd, to_bgp->name_pretty, p); + +		return false; +	} +  	if (debug) -		zlog_debug("%s: updating %pFX to vrf %s", __func__, p, -			   to_bgp->name_pretty); +		zlog_debug("%s: updating RD %pRD, %pFX to vrf %s", __func__, +			   prd, p, to_bgp->name_pretty);  	/* shallow copy */  	static_attr = *path_vpn->attr; @@ -1585,6 +1637,8 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp,	     /* to */  			ecommunity_free(&old_ecom);  	} +	community_strip_accept_own(&static_attr); +  	/*  	 * Nexthop: stash and clear  	 * @@ -1711,9 +1765,16 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp,	     /* to */  	/*  	 * For VRF-2-VRF route-leaking,  	 * the source will be the originating VRF. +	 * +	 * If ACCEPT_OWN mechanism is enabled, then we SHOULD(?) +	 * get the source VRF (BGP) by looking at the RD.  	 */ +	struct bgp *src_bgp = bgp_lookup_by_rd(path_vpn, prd, afi); +  	if (path_vpn->extra && path_vpn->extra->bgp_orig)  		src_vrf = path_vpn->extra->bgp_orig; +	else if (src_bgp) +		src_vrf = src_bgp;  	else  		src_vrf = from_bgp; @@ -1723,8 +1784,9 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp,	     /* to */  	return true;  } -bool vpn_leak_to_vrf_update(struct bgp *from_bgp,	   /* from */ -			    struct bgp_path_info *path_vpn) /* route */ +bool vpn_leak_to_vrf_update(struct bgp *from_bgp, +			    struct bgp_path_info *path_vpn, +			    struct prefix_rd *prd)  {  	struct listnode *mnode, *mnnode;  	struct bgp *bgp; @@ -1741,7 +1803,7 @@ bool vpn_leak_to_vrf_update(struct bgp *from_bgp,	   /* from */  		if (!path_vpn->extra  		    || path_vpn->extra->bgp_orig != bgp) { /* no loop */  			leak_success |= vpn_leak_to_vrf_update_onevrf( -				bgp, from_bgp, path_vpn); +				bgp, from_bgp, path_vpn, prd);  		}  	}  	return leak_success; @@ -1897,7 +1959,7 @@ void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *vpn_from,  					continue;  				vpn_leak_to_vrf_update_onevrf(to_bgp, vpn_from, -							      bpi); +							      bpi, NULL);  			}  		}  	} diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 46607a38c4..9af4cdf3a2 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -72,7 +72,8 @@ extern void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,  				       afi_t afi);  extern bool vpn_leak_to_vrf_update(struct bgp *from_bgp, -				   struct bgp_path_info *path_vpn); +				   struct bgp_path_info *path_vpn, +				   struct prefix_rd *prd);  extern void vpn_leak_to_vrf_withdraw(struct bgp *from_bgp,  				     struct bgp_path_info *path_vpn); diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 7274bcdb21..7eeab373a0 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -139,7 +139,8 @@ static int bgp_isvalid_nexthop_for_mpls(struct bgp_nexthop_cache *bnc,  	 */  	return (bgp_zebra_num_connects() == 0 ||  		(bnc && (bnc->nexthop_num > 0 && -			 (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) || +			 (CHECK_FLAG(path->flags, BGP_PATH_ACCEPT_OWN) || +			  CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) ||  			  bnc->bgp->srv6_enabled ||  			  bgp_isvalid_nexthop_for_ebgp(bnc, path) ||  			  bgp_isvalid_nexthop_for_mplsovergre(bnc, path))))); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0b411d0ec1..f6b6cb93db 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -103,10 +103,6 @@ DEFINE_HOOK(bgp_rpki_prefix_status,  	     const struct prefix *prefix),  	    (peer, attr, prefix)); -/* Render dest to prefix_rd based on safi */ -static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest, -						safi_t safi); -  /* Extern from bgp_dump.c */  extern const char *bgp_origin_str[];  extern const char *bgp_origin_long_str[]; @@ -881,6 +877,49 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,  		return 0;  	} +	/* If a BGP speaker supports ACCEPT_OWN and is configured for the +	 * extensions defined in this document, the following step is inserted +	 * after the LOCAL_PREF comparison step in the BGP decision process: +	 *	When comparing a pair of routes for a BGP destination, the +	 *	route with the ACCEPT_OWN community attached is preferred over +	 *	the route that does not have the community. +	 * This extra step MUST only be invoked during the best path selection +	 * process of VPN-IP routes. +	 */ +	if (safi == SAFI_MPLS_VPN && +	    (CHECK_FLAG(new->peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN) || +	     CHECK_FLAG(exist->peer->af_flags[afi][safi], +			PEER_FLAG_ACCEPT_OWN))) { +		bool new_accept_own = false; +		bool exist_accept_own = false; +		uint32_t accept_own = COMMUNITY_ACCEPT_OWN; + +		if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) +			new_accept_own = community_include( +				bgp_attr_get_community(newattr), accept_own); +		if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) +			exist_accept_own = community_include( +				bgp_attr_get_community(existattr), accept_own); + +		if (new_accept_own && !exist_accept_own) { +			*reason = bgp_path_selection_accept_own; +			if (debug) +				zlog_debug( +					"%s: %s wins over %s due to accept-own", +					pfx_buf, new_buf, exist_buf); +			return 1; +		} + +		if (!new_accept_own && exist_accept_own) { +			*reason = bgp_path_selection_accept_own; +			if (debug) +				zlog_debug( +					"%s: %s loses to %s due to accept-own", +					pfx_buf, new_buf, exist_buf); +			return 0; +		} +	} +  	/* 3. Local route check. We prefer:  	 *  - BGP_ROUTE_STATIC  	 *  - BGP_ROUTE_AGGREGATE @@ -3883,6 +3922,60 @@ static void bgp_attr_add_no_export_community(struct attr *attr)  	bgp_attr_set_community(attr, new);  } +static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi, +			   struct attr *attr, const struct prefix *prefix, +			   int *sub_type) +{ +	struct listnode *node, *nnode; +	struct bgp *bgp; +	bool accept_own_found = false; + +	if (safi != SAFI_MPLS_VPN) +		return false; + +	/* Processing of the ACCEPT_OWN community is enabled by configuration */ +	if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ACCEPT_OWN)) +		return false; + +	/* The route in question carries the ACCEPT_OWN community */ +	if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) { +		struct community *comm = bgp_attr_get_community(attr); + +		if (community_include(comm, COMMUNITY_ACCEPT_OWN)) +			accept_own_found = true; +	} + +	/* The route in question is targeted to one or more destination VRFs +	 * on the router (as determined by inspecting the Route Target(s)). +	 */ +	for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { +		if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF) +			continue; + +		if (accept_own_found && +		    ecommunity_include( +			    bgp->vpn_policy[afi] +				    .rtlist[BGP_VPN_POLICY_DIR_TOVPN], +			    bgp_attr_get_ecommunity(attr))) { +			if (bgp_debug_update(peer, prefix, NULL, 1)) +				zlog_debug( +					"%pBP prefix %pFX has ORIGINATOR_ID, but it's accepted due to ACCEPT_OWN", +					peer, prefix); + +			/* Treat this route as imported, because it's leaked +			 * already from another VRF, and we got an updated +			 * version from route-reflector with ACCEPT_OWN +			 * community. +			 */ +			*sub_type = BGP_ROUTE_IMPORTED; + +			return true; +		} +	} + +	return false; +} +  int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,  	       struct attr *attr, afi_t afi, safi_t safi, int type,  	       int sub_type, struct prefix_rd *prd, mpls_label_t *label, @@ -3996,12 +4089,20 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,  		}  	} -	/* Route reflector originator ID check.  */ +	/* Route reflector originator ID check. If ACCEPT_OWN mechanism is +	 * enabled, then take care of that too. +	 */ +	bool accept_own = false; +  	if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)  	    && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) { -		peer->stat_pfx_originator_loop++; -		reason = "originator is us;"; -		goto filtered; +		accept_own = +			bgp_accept_own(peer, afi, safi, attr, p, &sub_type); +		if (!accept_own) { +			peer->stat_pfx_originator_loop++; +			reason = "originator is us;"; +			goto filtered; +		}  	}  	/* Route reflector cluster ID check.  */ @@ -4499,8 +4600,13 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,  				bgp_path_info_unset_flag(dest, pi,  							 BGP_PATH_VALID);  			} -		} else +		} else { +			if (accept_own) +				bgp_path_info_set_flag(dest, pi, +						       BGP_PATH_ACCEPT_OWN); +  			bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID); +		}  #ifdef ENABLE_BGP_VNC  		if (safi == SAFI_MPLS_VPN) { @@ -4550,8 +4656,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,  		}  		if ((SAFI_MPLS_VPN == safi)  		    && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { - -			leak_success = vpn_leak_to_vrf_update(bgp, pi); +			leak_success = vpn_leak_to_vrf_update(bgp, pi, prd);  		}  #ifdef ENABLE_BGP_VNC @@ -4659,8 +4764,12 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,  			}  			bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);  		} -	} else +	} else { +		if (accept_own) +			bgp_path_info_set_flag(dest, new, BGP_PATH_ACCEPT_OWN); +  		bgp_path_info_set_flag(dest, new, BGP_PATH_VALID); +	}  	/* Addpath ID */  	new->addpath_rx_id = addpath_id; @@ -4706,7 +4815,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,  	}  	if ((SAFI_MPLS_VPN == safi)  	    && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { -		leak_success = vpn_leak_to_vrf_update(bgp, new); +		leak_success = vpn_leak_to_vrf_update(bgp, new, prd);  	}  #ifdef ENABLE_BGP_VNC  	if (SAFI_MPLS_VPN == safi) { @@ -6427,7 +6536,8 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,  			if (SAFI_MPLS_VPN == safi  			    && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) { -				vpn_leak_to_vrf_update(bgp, pi); +				vpn_leak_to_vrf_update(bgp, pi, +						       &bgp_static->prd);  			}  #ifdef ENABLE_BGP_VNC  			rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd, @@ -6467,7 +6577,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,  	if (SAFI_MPLS_VPN == safi  	    && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) { -		vpn_leak_to_vrf_update(bgp, new); +		vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);  	}  #ifdef ENABLE_BGP_VNC  	rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi, @@ -8826,6 +8936,8 @@ const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)  		return "Weight";  	case bgp_path_selection_local_pref:  		return "Local Pref"; +	case bgp_path_selection_accept_own: +		return "Accept Own";  	case bgp_path_selection_local_route:  		return "Local Route";  	case bgp_path_selection_confed_as_path: @@ -11902,8 +12014,8 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd,  /*   * Return rd based on safi   */ -static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest, -						safi_t safi) +const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest, +					 safi_t safi)  {  	switch (safi) {  	case SAFI_MPLS_VPN: @@ -11912,7 +12024,6 @@ static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,  		return (struct prefix_rd *)(bgp_dest_get_prefix(dest));  	default:  		return NULL; -  	}  } diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index ddef4ca1bb..22d28ecd00 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -289,7 +289,7 @@ struct bgp_path_info {  	int lock;  	/* BGP information status.  */ -	uint16_t flags; +	uint32_t flags;  #define BGP_PATH_IGP_CHANGED (1 << 0)  #define BGP_PATH_DAMPED (1 << 1)  #define BGP_PATH_HISTORY (1 << 2) @@ -306,6 +306,7 @@ struct bgp_path_info {  #define BGP_PATH_RIB_ATTR_CHG (1 << 13)  #define BGP_PATH_ANNC_NH_SELF (1 << 14)  #define BGP_PATH_LINK_BW_CHG (1 << 15) +#define BGP_PATH_ACCEPT_OWN (1 << 16)  	/* BGP route type.  This can be static, RIP, OSPF, BGP etc.  */  	uint8_t type; @@ -852,4 +853,6 @@ extern void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr);  const char *  bgp_path_selection_reason2str(enum bgp_path_selection_reason reason);  extern bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi); +extern const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest, +						safi_t safi);  #endif /* _QUAGGA_BGP_ROUTE_H */ diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 86cd4f3da1..91d92ebd6d 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -63,6 +63,7 @@ enum bgp_path_selection_reason {  	bgp_path_selection_evpn_lower_ip,  	bgp_path_selection_weight,  	bgp_path_selection_local_pref, +	bgp_path_selection_accept_own,  	bgp_path_selection_local_route,  	bgp_path_selection_confed_as_path,  	bgp_path_selection_as_path, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 10396b8b4f..b85f3707b6 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -8327,6 +8327,32 @@ ALIAS_HIDDEN(  	"Only give warning message when limit is exceeded\n"  	"Force checking all received routes not only accepted\n") +/* "neighbor accept-own" */ +DEFPY (neighbor_accept_own, +       neighbor_accept_own_cmd, +       "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor accept-own", +       NO_STR +       NEIGHBOR_STR +       NEIGHBOR_ADDR_STR2 +       "Enable handling of self-originated VPN routes containing ACCEPT_OWN community\n") +{ +	struct peer *peer; +	afi_t afi = bgp_node_afi(vty); +	safi_t safi = bgp_node_safi(vty); +	int ret; + +	peer = peer_and_group_lookup_vty(vty, neighbor); +	if (!peer) +		return CMD_WARNING_CONFIG_FAILED; + +	if (no) +		ret = peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ACCEPT_OWN); +	else +		ret = peer_af_flag_set(peer, afi, safi, PEER_FLAG_ACCEPT_OWN); + +	return bgp_vty_return(vty, ret); +} +  /* "neighbor soo" */  DEFPY (neighbor_soo,         neighbor_soo_cmd, @@ -17362,6 +17388,10 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,  		}  	} +	/* accept-own */ +	if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ACCEPT_OWN)) +		vty_out(vty, "  neighbor %s accept-own\n", addr); +  	/* soo */  	if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOO)) {  		char *soo_str = ecommunity_ecom2str( @@ -19571,6 +19601,10 @@ void bgp_vty_init(void)  	install_element(BGP_EVPN_NODE, &neighbor_allowas_in_cmd);  	install_element(BGP_EVPN_NODE, &no_neighbor_allowas_in_cmd); +	/* neighbor accept-own */ +	install_element(BGP_VPNV4_NODE, &neighbor_accept_own_cmd); +	install_element(BGP_VPNV6_NODE, &neighbor_accept_own_cmd); +  	/* "neighbor soo" */  	install_element(BGP_IPV4_NODE, &neighbor_soo_cmd);  	install_element(BGP_IPV4_NODE, &no_neighbor_soo_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 188402d0b4..40e6c90dfc 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -4313,6 +4313,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] = {  	{PEER_FLAG_WEIGHT, 0, peer_change_reset_in},  	{PEER_FLAG_DISABLE_ADDPATH_RX, 0, peer_change_reset},  	{PEER_FLAG_SOO, 0, peer_change_reset}, +	{PEER_FLAG_ACCEPT_OWN, 0, peer_change_reset},  	{0, 0, 0}};  /* Proper action set. */ diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index b9d24969e3..44e225b043 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1462,6 +1462,7 @@ struct peer {  #define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 29)  #define PEER_FLAG_SOO (1ULL << 30)  #define PEER_FLAG_ORR_GROUP (1ULL << 31) /* Optimal-Route-Reflection */ +#define PEER_FLAG_ACCEPT_OWN (1ULL << 32)  	/* BGP Optimal Route Reflection Group name */  	char *orr_group_name[AFI_MAX][SAFI_MAX];  | 
