diff options
| author | Russ White <russ@riw.us> | 2023-02-21 08:01:03 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-02-21 08:01:03 -0500 | 
| commit | ba755d35e508c2452e5459bdd7c0dd67a70a88a4 (patch) | |
| tree | adc08f46788b8012240faec23ae7e7271bb0d40d | |
| parent | 39c664c4ea530a9460efa1a78fe669ae56c85f83 (diff) | |
| parent | 616e9f0d9f0458788adf4b30707016c8db383b02 (diff) | |
Merge pull request #12248 from pguibert6WIND/bgpasdot
lib, bgp: add initial support for asdot format
76 files changed, 7247 insertions, 473 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 584f524f05..2cc7e46573 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -287,9 +287,13 @@ static struct assegment *assegment_normalise(struct assegment *head)  	return head;  } -static struct aspath *aspath_new(void) +static struct aspath *aspath_new(enum asnotation_mode asnotation)  { -	return XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath)); +	struct aspath *as; + +	as = XCALLOC(MTYPE_AS_PATH, sizeof(struct aspath)); +	as->asnotation = asnotation; +	return as;  }  /* Free AS path structure. */ @@ -537,8 +541,10 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)   *   * This was changed to 10 after the well-known BGP assertion, which   * had hit some parts of the Internet in May of 2009. + * plain format : '4294967295 ' : 10 + 1 + * astod format : '65535.65535 ': 11 + 1   */ -#define ASN_STR_LEN (10 + 1) +#define ASN_STR_LEN (11 + 1)  	str_size = MAX(assegment_count_asns(seg, 0) * ASN_STR_LEN + 2 + 1,  		       ASPATH_STR_DEFAULT_LEN);  	str_buf = XMALLOC(MTYPE_AS_STR, str_size); @@ -569,7 +575,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)  /* We might need to increase str_buf, particularly if path has   * differing segments types, our initial guesstimate above will - * have been wrong. Need 10 chars for ASN, a separator each and + * have been wrong. Need 11 chars for ASN, a separator each and   * potentially two segment delimiters, plus a space between each   * segment and trailing zero.   * @@ -595,12 +601,11 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)  		/* write out the ASNs, with their separators, bar the last one*/  		for (i = 0; i < seg->length; i++) {  			if (make_json) -				json_object_array_add( -					jseg_list, -					json_object_new_int64(seg->as[i])); - -			len += snprintf(str_buf + len, str_size - len, "%u", -					seg->as[i]); +				asn_asn2json_array(jseg_list, seg->as[i], +						   as->asnotation); +			len += snprintfrr(str_buf + len, str_size - len, +					  ASN_FORMAT(as->asnotation), +					  &seg->as[i]);  			if (i < (seg->length - 1))  				len += snprintf(str_buf + len, str_size - len, @@ -691,6 +696,7 @@ struct aspath *aspath_dup(struct aspath *aspath)  	new->str = XMALLOC(MTYPE_AS_STR, buflen);  	new->str_len = aspath->str_len; +	new->asnotation = aspath->asnotation;  	/* copy the string data */  	if (aspath->str_len > 0) @@ -718,6 +724,7 @@ static void *aspath_hash_alloc(void *arg)  	new->str = aspath->str;  	new->str_len = aspath->str_len;  	new->json = aspath->json; +	new->asnotation = aspath->asnotation;  	return new;  } @@ -825,7 +832,8 @@ static int assegments_parse(struct stream *s, size_t length,     On error NULL is returned.   */ -struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit) +struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit, +			    enum asnotation_mode asnotation)  {  	struct aspath as;  	struct aspath *find; @@ -840,6 +848,7 @@ struct aspath *aspath_parse(struct stream *s, size_t length, int use32bit)  		return NULL;  	memset(&as, 0, sizeof(as)); +	as.asnotation = asnotation;  	if (assegments_parse(s, length, &as.segments, use32bit) < 0)  		return NULL; @@ -1057,7 +1066,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)  			seg = assegment_append_asns(seg, seg1->as, match);  			if (!aspath) { -				aspath = aspath_new(); +				aspath = aspath_new(as1->asnotation);  				aspath->segments = seg;  			} else  				prevseg->next = seg; @@ -1077,7 +1086,7 @@ struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2)  	}  	if (!aspath) -		aspath = aspath_new(); +		aspath = aspath_new(as1->asnotation);  	/* Make as-set using rest of all information. */  	from = match; @@ -1521,7 +1530,7 @@ struct aspath *aspath_filter_exclude(struct aspath *source,  	struct assegment *srcseg, *exclseg, *lastseg;  	struct aspath *newpath; -	newpath = aspath_new(); +	newpath = aspath_new(source->asnotation);  	lastseg = NULL;  	for (srcseg = source->segments; srcseg; srcseg = srcseg->next) { @@ -1751,7 +1760,7 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath,  		newseg = assegment_append_asns(newseg, seg->as, cpasns);  		if (!newpath) { -			newpath = aspath_new(); +			newpath = aspath_new(aspath->asnotation);  			newpath->segments = newseg;  		} else  			prevseg->next = newseg; @@ -1880,16 +1889,16 @@ static void aspath_segment_add(struct aspath *as, int type)  		as->segments = new;  } -struct aspath *aspath_empty(void) +struct aspath *aspath_empty(enum asnotation_mode asnotation)  { -	return aspath_parse(NULL, 0, 1); /* 32Bit ;-) */ +	return aspath_parse(NULL, 0, 1, asnotation); /* 32Bit ;-) */  }  struct aspath *aspath_empty_get(void)  {  	struct aspath *aspath; -	aspath = aspath_new(); +	aspath = aspath_new(bgp_get_asnotation(NULL));  	aspath_make_str_count(aspath, false);  	return aspath;  } @@ -1925,6 +1934,8 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,  				   unsigned long *asno)  {  	const char *p = buf; +	as_t asval; +	bool found = false;  	/* Skip separators (space for sequences, ',' for sets). */  	while (isspace((unsigned char)*p) || *p == ',') @@ -1961,30 +1972,18 @@ static const char *aspath_gettoken(const char *buf, enum as_token *token,  		return p;  	} -	/* Check actual AS value. */ -	if (isdigit((unsigned char)*p)) { -		as_t asval; - -		*token = as_token_asval; -		asval = (*p - '0'); -		p++; - -		while (isdigit((unsigned char)*p)) { -			asval *= 10; -			asval += (*p - '0'); -			p++; -		} +	asval = 0; +	p = asn_str2asn_parse(p, &asval, &found); +	if (found) {  		*asno = asval; -		return p; -	} - -	/* There is no match then return unknown token. */ -	*token = as_token_unknown; -	p++; +		*token = as_token_asval; +	} else +		*token = as_token_unknown;  	return p;  } -struct aspath *aspath_str2aspath(const char *str) +struct aspath *aspath_str2aspath(const char *str, +				 enum asnotation_mode asnotation)  {  	enum as_token token = as_token_unknown;  	unsigned short as_type; @@ -1992,7 +1991,7 @@ struct aspath *aspath_str2aspath(const char *str)  	struct aspath *aspath;  	int needtype; -	aspath = aspath_new(); +	aspath = aspath_new(asnotation);  	/* We start default type as AS_SEQUENCE. */  	as_type = AS_SEQUENCE; @@ -2066,6 +2065,10 @@ bool aspath_cmp(const void *arg1, const void *arg2)  	const struct assegment *seg1 = ((const struct aspath *)arg1)->segments;  	const struct assegment *seg2 = ((const struct aspath *)arg2)->segments; +	if (((const struct aspath *)arg1)->asnotation != +	    ((const struct aspath *)arg2)->asnotation) +		return false; +  	while (seg1 || seg2) {  		int i;  		if ((!seg1 && seg2) || (seg1 && !seg2)) diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index dd65b423a7..18af375c13 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -57,6 +57,9 @@ struct aspath {  	   and AS path regular expression match.  */  	char *str;  	unsigned short str_len; + +	/* AS notation used by string expression of AS path */ +	enum asnotation_mode asnotation;  };  #define ASPATH_STR_DEFAULT_LEN 32 @@ -65,7 +68,9 @@ struct aspath {  extern void aspath_init(void);  extern void aspath_finish(void);  extern struct aspath *aspath_parse(struct stream *s, size_t length, -				   int use32bit); +				   int use32bit, +				   enum asnotation_mode asnotation); +  extern struct aspath *aspath_dup(struct aspath *aspath);  extern struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2);  extern struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2); @@ -81,9 +86,10 @@ extern bool aspath_cmp_left(const struct aspath *aspath1,  extern bool aspath_cmp_left_confed(const struct aspath *as1,  				   const struct aspath *as2);  extern struct aspath *aspath_delete_confed_seq(struct aspath *aspath); -extern struct aspath *aspath_empty(void); +extern struct aspath *aspath_empty(enum asnotation_mode asnotation);  extern struct aspath *aspath_empty_get(void); -extern struct aspath *aspath_str2aspath(const char *str); +extern struct aspath *aspath_str2aspath(const char *str, +					enum asnotation_mode asnotation);  extern void aspath_str_update(struct aspath *as, bool make_json);  extern void aspath_free(struct aspath *aspath);  extern struct aspath *aspath_intern(struct aspath *aspath); diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index fe918a3e03..19c65ce4d2 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1054,7 +1054,7 @@ struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp,  	attr->origin = origin;  	attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN); -	attr->aspath = aspath_empty(); +	attr->aspath = aspath_empty(bgp->asnotation);  	attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);  	attr->weight = BGP_ATTR_DEFAULT_WEIGHT;  	attr->tag = 0; @@ -1092,7 +1092,7 @@ struct attr *bgp_attr_aggregate_intern(  	if (aspath)  		attr.aspath = aspath_intern(aspath);  	else -		attr.aspath = aspath_empty(); +		attr.aspath = aspath_empty(bgp->asnotation);  	attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);  	/* Next hop attribute.  */ @@ -1590,15 +1590,19 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)  	struct attr *const attr = args->attr;  	struct peer *const peer = args->peer;  	const bgp_size_t length = args->length; +	enum asnotation_mode asnotation; +	asnotation = bgp_get_asnotation( +		args->peer && args->peer->bgp ? args->peer->bgp : NULL);  	/*  	 * peer with AS4 => will get 4Byte ASnums  	 * otherwise, will get 16 Bit  	 */ -	attr->aspath = aspath_parse( -		peer->curr, length, -		CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) -			&& CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV)); +	attr->aspath = +		aspath_parse(peer->curr, length, +			     CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV) && +				     CHECK_FLAG(peer->cap, PEER_CAP_AS4_ADV), +			     asnotation);  	/* In case of IBGP, length will be zero. */  	if (!attr->aspath) { @@ -1614,7 +1618,8 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)  	 * such messages, conformant BGP speakers SHOULD use the "Treat-as-  	 * withdraw" error handling behavior as per [RFC7606].  	 */ -	if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) { +	if (peer->bgp && peer->bgp->reject_as_sets && +	    aspath_check_as_sets(attr->aspath)) {  		flog_err(EC_BGP_ATTR_MAL_AS_PATH,  			 "AS_SET and AS_CONFED_SET are deprecated from %pBP",  			 peer); @@ -1690,8 +1695,11 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,  	struct peer *const peer = args->peer;  	struct attr *const attr = args->attr;  	const bgp_size_t length = args->length; +	enum asnotation_mode asnotation; + +	asnotation = bgp_get_asnotation(peer->bgp); -	*as4_path = aspath_parse(peer->curr, length, 1); +	*as4_path = aspath_parse(peer->curr, length, 1, asnotation);  	/* In case of IBGP, length will be zero. */  	if (!*as4_path) { diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c index b410a4b896..fc3363b098 100644 --- a/bgpd/bgp_btoa.c +++ b/bgpd/bgp_btoa.c @@ -86,7 +86,8 @@ static void attr_parse(struct stream *s, uint16_t len)  		case BGP_ATTR_AS_PATH: {  			struct aspath *aspath; -			aspath = aspath_parse(s, length, 1); +			aspath = aspath_parse(s, length, 1, +					      bgp_get_asnotation(NULL));  			printf("ASPATH: %s\n", aspath->str);  			aspath_free(aspath);  		} break; diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 2dec1ca46d..782245e512 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -2635,6 +2635,7 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,  	char tag_buf[30];  	char overlay_index_buf[INET6_ADDRSTRLEN + 14];  	const struct prefix_evpn *evp; +	int len = 0;  	/* ' with addpath ID '          17  	 * max strlen of uint32       + 10 @@ -2688,11 +2689,15 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,  		}  	} -	if (prd) -		snprintfrr(str, size, "RD %pRD %pFX%s%s%s %s %s", prd, pu.p, +	if (prd) { +		len += snprintfrr(str + len, size - len, "RD "); +		len += snprintfrr(str + len, size - len, +				  BGP_RD_AS_FORMAT(bgp_get_asnotation(NULL)), +				  prd); +		snprintfrr(str + len, size - len, " %pFX%s%s%s %s %s", pu.p,  			   overlay_index_buf, tag_buf, pathid_buf, afi2str(afi),  			   safi2str(safi)); -	else if (safi == SAFI_FLOWSPEC) { +	} else if (safi == SAFI_FLOWSPEC) {  		char return_string[BGP_FLOWSPEC_NLRI_STRING_MAX];  		const struct prefix_fs *fs = pu.fs; diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 4758cd98ec..51b44a9e78 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -5923,6 +5923,8 @@ void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn)  	vpn->prd.prefixlen = 64;  	snprintfrr(buf, sizeof(buf), "%pI4:%hu", &bgp->router_id, vpn->rd_id);  	(void)str2prefix_rd(buf, &vpn->prd); +	if (vpn->prd_pretty) +		XFREE(MTYPE_BGP, vpn->prd_pretty);  	UNSET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);  } @@ -6027,6 +6029,8 @@ void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn)  	bf_release_index(bm->rd_idspace, vpn->rd_id);  	hash_release(bgp->vni_svi_hash, vpn);  	hash_release(bgp->vnihash, vpn); +	if (vpn->prd_pretty) +		XFREE(MTYPE_BGP, vpn->prd_pretty);  	QOBJ_UNREG(vpn);  	XFREE(MTYPE_BGP_EVPN, vpn);  } @@ -6238,13 +6242,14 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id,  		ret = bgp_get_vty(&bgp_vrf, &as, vrf_id_to_name(vrf_id),  				  vrf_id == VRF_DEFAULT -				  ? BGP_INSTANCE_TYPE_DEFAULT -				  : BGP_INSTANCE_TYPE_VRF); +					  ? BGP_INSTANCE_TYPE_DEFAULT +					  : BGP_INSTANCE_TYPE_VRF, +				  NULL, ASNOTATION_UNDEFINED);  		switch (ret) {  		case BGP_ERR_AS_MISMATCH:  			flog_err(EC_BGP_EVPN_AS_MISMATCH, -				 "BGP instance is already running; AS is %u", -				 as); +				 "BGP instance is already running; AS is %s", +				 bgp_vrf->as_pretty);  			return -1;  		case BGP_ERR_INSTANCE_MISMATCH:  			flog_err(EC_BGP_EVPN_INSTANCE_MISMATCH, @@ -6660,6 +6665,9 @@ void bgp_evpn_cleanup(struct bgp *bgp)  	list_delete(&bgp->vrf_import_rtl);  	list_delete(&bgp->vrf_export_rtl);  	list_delete(&bgp->l2vnis); + +	if (bgp->vrf_prd_pretty) +		XFREE(MTYPE_BGP, bgp->vrf_prd_pretty);  }  /* diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index fa913016fb..391ca4cd19 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -2395,7 +2395,8 @@ static void bgp_evpn_es_json_frag_fill(json_object *json_frags,  	for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) {  		json_frag = json_object_new_object(); -		json_object_string_addf(json_frag, "rd", "%pRD", &es_frag->prd); +		json_object_string_addf(json_frag, "rd", "%pRDP", +					&es_frag->prd);  		json_object_int_add(json_frag, "eviCount",  				    listcount(es_frag->es_evi_frag_list)); @@ -2410,7 +2411,7 @@ static void bgp_evpn_es_frag_show_detail(struct vty *vty,  	struct bgp_evpn_es_frag *es_frag;  	for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) { -		vty_out(vty, "  %pRD EVIs: %d\n", &es_frag->prd, +		vty_out(vty, "  %pRDP EVIs: %d\n", &es_frag->prd,  			listcount(es_frag->es_evi_frag_list));  	}  } @@ -2524,7 +2525,7 @@ static void bgp_evpn_es_show_entry(struct vty *vty,  		json_object_string_add(json, "esi", es->esi_str);  		if (es->es_base_frag) -			json_object_string_addf(json, "rd", "%pRD", +			json_object_string_addf(json, "rd", "%pRDP",  						&es->es_base_frag->prd);  		if (es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) { @@ -2562,7 +2563,7 @@ static void bgp_evpn_es_show_entry(struct vty *vty,  		bgp_evpn_es_vteps_str(vtep_str, es, sizeof(vtep_str)); -		vty_out(vty, "%-30s %-5s %-21pRD %-8d %s\n", es->esi_str, +		vty_out(vty, "%-30s %-5s %-21pRDP %-8d %s\n", es->esi_str,  			type_str, &es->es_base_frag->prd,  			listcount(es->es_evi_list), vtep_str);  	} @@ -2639,7 +2640,7 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,  		vty_out(vty, "ESI: %s\n", es->esi_str);  		vty_out(vty, " Type: %s\n", type_str); -		vty_out(vty, " RD: %pRD\n", &es->es_base_frag->prd); +		vty_out(vty, " RD: %pRDP\n", &es->es_base_frag->prd);  		vty_out(vty, " Originator-IP: %pI4\n", &es->originator_ip);  		if (es->flags & BGP_EVPNES_LOCAL)  			vty_out(vty, " Local ES DF preference: %u\n", @@ -3958,7 +3959,8 @@ static void bgp_evpn_es_evi_show_entry(struct vty *vty,  		json_object *json_types;  		json_object_string_add(json, "esi", es_evi->es->esi_str); -		json_object_int_add(json, "vni", es_evi->vpn->vni); +		if (es_evi->vpn) +			json_object_int_add(json, "vni", es_evi->vpn->vni);  		if (es_evi->flags & (BGP_EVPNES_EVI_LOCAL |  					BGP_EVPNES_EVI_REMOTE)) { @@ -4002,13 +4004,18 @@ static void bgp_evpn_es_evi_show_entry(struct vty *vty,  static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty,  		struct bgp_evpn_es_evi *es_evi, json_object *json)  { +	enum asnotation_mode mode; + +	mode = bgp_get_asnotation(es_evi->vpn->bgp_vrf); +  	if (json) {  		json_object *json_flags;  		/* Add the "brief" info first */  		bgp_evpn_es_evi_show_entry(vty, es_evi, json);  		if (es_evi->es_frag) -			json_object_string_addf(json, "esFragmentRd", "%pRD", +			json_object_string_addf(json, "esFragmentRd", +						BGP_RD_AS_FORMAT(mode),  						&es_evi->es_frag->prd);  		if (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) {  			json_flags = json_object_new_array(); @@ -4032,9 +4039,12 @@ static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty,  		vty_out(vty, "VNI: %d ESI: %s\n",  				es_evi->vpn->vni, es_evi->es->esi_str);  		vty_out(vty, " Type: %s\n", type_str); -		if (es_evi->es_frag) -			vty_out(vty, " ES fragment RD: %pRD\n", +		if (es_evi->es_frag) { +			vty_out(vty, " ES fragment RD: "); +			vty_out(vty, BGP_RD_AS_FORMAT(mode),  				&es_evi->es_frag->prd); +			vty_out(vty, "\n"); +		}  		vty_out(vty, " Inconsistencies: %s\n",  			(es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) ?  			"es-vtep-mismatch":"-"); diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index d63e7a1a16..fbf3b19c37 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -76,6 +76,7 @@ struct bgpevpn {  	/* RD for this VNI. */  	struct prefix_rd prd; +	char *prd_pretty;  	/* Route type 3 field */  	struct in_addr originator_ip; diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 33c202c3d7..59986102a5 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -374,7 +374,9 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,  		json_object_int_add(json, "vni", bgp_vrf->l3vni);  		json_object_string_add(json, "type", "L3");  		json_object_string_add(json, "inKernel", "True"); -		json_object_string_addf(json, "rd", "%pRD", &bgp_vrf->vrf_prd); +		json_object_string_addf(json, "rd", +					BGP_RD_AS_FORMAT(bgp_vrf->asnotation), +					&bgp_vrf->vrf_prd);  		json_object_string_addf(json, "originatorIp", "%pI4",  					&bgp_vrf->originator_ip);  		json_object_string_add(json, "advertiseGatewayMacip", "n/a"); @@ -398,7 +400,10 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,  		vty_out(vty, "  Type: %s\n", "L3");  		vty_out(vty, "  Tenant VRF: %s\n",  			vrf_id_to_name(bgp_vrf->vrf_id)); -		vty_out(vty, "  RD: %pRD\n", &bgp_vrf->vrf_prd); +		vty_out(vty, "  RD: "); +		vty_out(vty, BGP_RD_AS_FORMAT(bgp_vrf->asnotation), +			&bgp_vrf->vrf_prd); +		vty_out(vty, "\n");  		vty_out(vty, "  Originator IP: %pI4\n",  			&bgp_vrf->originator_ip);  		vty_out(vty, "  Advertise-gw-macip : %s\n", "n/a"); @@ -461,8 +466,10 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)  	json_object *json_import_rtl = NULL;  	json_object *json_export_rtl = NULL;  	struct bgp *bgp_evpn; +	enum asnotation_mode asnotation;  	bgp_evpn = bgp_get_evpn(); +	asnotation = bgp_get_asnotation(bgp_evpn);  	if (json) {  		json_import_rtl = json_object_new_array(); @@ -471,7 +478,8 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)  		json_object_string_add(json, "type", "L2");  		json_object_string_add(json, "inKernel",  				       is_vni_live(vpn) ? "True" : "False"); -		json_object_string_addf(json, "rd", "%pRD", &vpn->prd); +		json_object_string_addf( +			json, "rd", BGP_RD_AS_FORMAT(asnotation), &vpn->prd);  		json_object_string_addf(json, "originatorIp", "%pI4",  					&vpn->originator_ip);  		json_object_string_addf(json, "mcastGroup", "%pI4", @@ -512,7 +520,9 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)  		vty_out(vty, "  Type: %s\n", "L2");  		vty_out(vty, "  Tenant-Vrf: %s\n",  			vrf_id_to_name(vpn->tenant_vrf_id)); -		vty_out(vty, "  RD: %pRD\n", &vpn->prd); +		vty_out(vty, "  RD: "); +		vty_out(vty, BGP_RD_AS_FORMAT(asnotation), &vpn->prd); +		vty_out(vty, "\n");  		vty_out(vty, "  Originator IP: %pI4\n", &vpn->originator_ip);  		vty_out(vty, "  Mcast group: %pI4\n", &vpn->mcast_grp);  		if (!vpn->advertise_gw_macip && @@ -991,7 +1001,9 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,  		json_object_string_add(json_vni, "inKernel", "True");  		json_object_string_addf(json_vni, "originatorIp", "%pI4",  					&bgp->originator_ip); -		json_object_string_addf(json_vni, "rd", "%pRD", &bgp->vrf_prd); +		json_object_string_addf(json_vni, "rd", +					BGP_RD_AS_FORMAT(bgp->asnotation), +					&bgp->vrf_prd);  		json_object_string_add(json_vni, "advertiseGatewayMacip",  				       "n/a");  		json_object_string_add(json_vni, "advertiseSviMacIp", "n/a"); @@ -1007,7 +1019,8 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,  			json_vni, "rmac",  			prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2)));  	} else { -		vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, bgp->l3vni, "L3", +		vty_out(vty, "%-1s %-10u %-4s ", buf1, bgp->l3vni, "L3"); +		vty_out(vty, BGP_RD_AS_FORMAT_SPACE(bgp->asnotation),  			&bgp->vrf_prd);  	} @@ -1091,11 +1104,13 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])  	struct listnode *node, *nnode;  	struct ecommunity *ecom;  	struct bgp *bgp_evpn; +	enum asnotation_mode asnotation;  	vty = args[0];  	json = args[1];  	bgp_evpn = bgp_get_evpn(); +	asnotation = bgp_get_asnotation(bgp_evpn);  	if (json) {  		json_vni = json_object_new_object(); @@ -1112,7 +1127,9 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])  		json_object_string_add(json_vni, "type", "L2");  		json_object_string_add(json_vni, "inKernel",  				       is_vni_live(vpn) ? "True" : "False"); -		json_object_string_addf(json_vni, "rd", "%pRD", &vpn->prd); +		json_object_string_addf(json_vni, "rd", +					BGP_RD_AS_FORMAT(asnotation), +					&vpn->prd);  		json_object_string_addf(json_vni, "originatorIp", "%pI4",  					&vpn->originator_ip);  		json_object_string_addf(json_vni, "mcastGroup", "%pI4", @@ -1142,8 +1159,8 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])  			json_object_string_add(json_vni, "advertiseSviMacIp",  					       "Disabled");  	} else { -		vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, vpn->vni, "L2", -			&vpn->prd); +		vty_out(vty, "%-1s %-10u %-4s ", buf1, vpn->vni, "L2"); +		vty_out(vty, BGP_RD_AS_FORMAT_SPACE(asnotation), &vpn->prd);  	}  	for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) { @@ -1332,9 +1349,9 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,  							json,  							"defaultLocPrf",  							bgp->default_local_pref); -						json_object_int_add( -							json, "localAS", -							bgp->as); +						asn_asn2json(json, "localAS", +							     bgp->as, +							     bgp->asnotation);  					} else {  						if (option == SHOW_DISPLAY_TAGS)  							vty_out(vty, @@ -2203,7 +2220,8 @@ static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,  /*   * Configure RD for VRF   */ -static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd) +static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd, +				  const char *rd_pretty)  {  	/* If we have already advertise type-5 routes with a diffrent RD, we  	 * have to delete and withdraw them firs @@ -2212,6 +2230,7 @@ static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd)  	/* update RD */  	memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd)); +	bgp_vrf->vrf_prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty);  	SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);  	/* We have a new RD for VRF. @@ -2233,7 +2252,8 @@ static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)  	/* fall back to default RD */  	bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);  	UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD); - +	if (bgp_vrf->vrf_prd_pretty) +		XFREE(MTYPE_BGP, bgp_vrf->vrf_prd_pretty);  	/* We have a new RD for VRF.  	 * Advertise all type-5 routes again with the new RD  	 */ @@ -2244,7 +2264,7 @@ static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)   * Configure RD for a VNI (vty handler)   */  static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn, -			      struct prefix_rd *rd) +			      struct prefix_rd *rd, const char *rd_pretty)  {  	/* If the VNI is "live", we need to delete and withdraw this VNI's  	 * local routes with the prior RD first. Then, after updating RD, @@ -2255,6 +2275,7 @@ static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,  	/* update RD */  	memcpy(&vpn->prd, rd, sizeof(struct prefix_rd)); +	vpn->prd_pretty = XSTRDUP(MTYPE_BGP, rd_pretty);  	SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);  	if (is_vni_live(vpn)) @@ -2778,7 +2799,8 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,  	if (json) {  		json_rd = json_object_new_object(); -		json_object_string_addf(json_rd, "rd", "%pRD", prd); +		json_object_string_addf(json_rd, "rd", +					BGP_RD_AS_FORMAT(bgp->asnotation), prd);  	}  	bgp_dest_unlock_node(rd_dest); @@ -2861,7 +2883,9 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,  	if (json) {  		if (add_rd_to_json) -			json_object_object_addf(json, json_rd, "%pRD", prd); +			json_object_object_addf( +				json, json_rd, +				BGP_RD_AS_FORMAT(bgp->asnotation), prd);  		else {  			json_object_free(json_rd);  			json_rd = NULL; @@ -2916,7 +2940,7 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,  			continue;  		prefix_rd2str((struct prefix_rd *)rd_destp, rd_str, -			      sizeof(rd_str)); +			      sizeof(rd_str), bgp->asnotation);  		/* Construct an RT-2 from the user-supplied mac(ip),  		 * then search the l2vpn evpn table for it. @@ -3043,7 +3067,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,  		tbl_ver = table->version;  		prefix_rd2str((struct prefix_rd *)rd_destp, rd_str, -			      sizeof(rd_str)); +			      sizeof(rd_str), bgp->asnotation);  		if (json)  			json_rd = json_object_new_object(); @@ -3460,7 +3484,7 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)  	if (is_vni_configured(vpn)) {  		vty_out(vty, "  vni %u\n", vpn->vni);  		if (is_rd_configured(vpn)) -			vty_out(vty, "   rd %pRD\n", &vpn->prd); +			vty_out(vty, "   rd %s\n", vpn->prd_pretty);  		if (is_import_rt_configured(vpn)) {  			for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, @@ -6111,7 +6135,7 @@ DEFUN (bgp_evpn_vrf_rd,  		return CMD_SUCCESS;  	/* Configure or update the RD. */ -	evpn_configure_vrf_rd(bgp_vrf, &prd); +	evpn_configure_vrf_rd(bgp_vrf, &prd, argv[1]->arg);  	return CMD_SUCCESS;  } @@ -6203,7 +6227,7 @@ DEFUN (bgp_evpn_vni_rd,  		return CMD_SUCCESS;  	/* Configure or update the RD. */ -	evpn_configure_rd(bgp, vpn, &prd); +	evpn_configure_rd(bgp, vpn, &prd, argv[1]->arg);  	return CMD_SUCCESS;  } @@ -6388,7 +6412,9 @@ DEFUN (show_bgp_vrf_l3vni_info,  		for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))  			vty_out(vty, "%s  ", ecommunity_str(l3rt->ecom));  		vty_out(vty, "\n"); -		vty_out(vty, "  RD: %pRD\n", &bgp->vrf_prd); +		vty_out(vty, "  RD: "); +		vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), &bgp->vrf_prd); +		vty_out(vty, "\n");  	} else {  		json_object_string_add(json, "vrf", name);  		json_object_string_addf(json, "local-ip", "%pI4", @@ -6424,7 +6450,9 @@ DEFUN (show_bgp_vrf_l3vni_info,  				json_object_new_string(  					ecommunity_str(l3rt->ecom)));  		json_object_object_add(json, "import-rts", json_import_rts); -		json_object_string_addf(json, "rd", "%pRD", &bgp->vrf_prd); +		json_object_string_addf(json, "rd", +					BGP_RD_AS_FORMAT(bgp->asnotation), +					&bgp->vrf_prd);  	}  	if (uj) @@ -7251,7 +7279,7 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,  		}  	}  	if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD)) -		vty_out(vty, "  rd %pRD\n", &bgp->vrf_prd); +		vty_out(vty, "  rd %s\n", bgp->vrf_prd_pretty);  	/* import route-target */  	if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) { diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index bd8ce54775..ab02170183 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -1853,7 +1853,7 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp,   /* to */  	int origin_local = 0;  	struct bgp *src_vrf;  	struct interface *ifp; - +	char rd_buf[RD_ADDRSTRLEN];  	int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);  	if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) { @@ -1892,6 +1892,10 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp,   /* to */  		return false;  	} +	rd_buf[0] = '\0'; +	if (debug && prd) +		prefix_rd2str(prd, rd_buf, sizeof(rd_buf), to_bgp->asnotation); +  	/* A route MUST NOT ever be accepted back into its source VRF, even if  	 * it carries one or more RTs that match that VRF.  	 */ @@ -1900,15 +1904,14 @@ static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp,   /* to */  		   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); - +				"%s: skipping import, match RD (%s) of src VRF (%s) and the prefix (%pFX)", +				__func__, rd_buf, to_bgp->name_pretty, p);  		return false;  	}  	if (debug) -		zlog_debug("%s: updating RD %pRD, %pFX to %s", __func__, prd, p, -			   to_bgp->name_pretty); +		zlog_debug("%s: updating RD %s, %pFX to %s", __func__, rd_buf, +			   p, to_bgp->name_pretty);  	/* shallow copy */  	static_attr = *path_vpn->attr; @@ -2403,7 +2406,7 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,  				     &bgp->vrf_prd_auto);  			bgp->vpn_policy[afi].tovpn_rd = bgp->vrf_prd_auto;  			prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf, -				      sizeof(buf)); +				      sizeof(buf), bgp->asnotation);  			/* free up pre-existing memory if any and allocate  			 *  the ecommunity attribute with new RD/RT @@ -2538,8 +2541,8 @@ void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,  		from_bgp->vpn_policy[afi].tovpn_rd = from_bgp->vrf_prd_auto;  		SET_FLAG(from_bgp->vpn_policy[afi].flags,  			 BGP_VPN_POLICY_TOVPN_RD_SET); -		prefix_rd2str(&from_bgp->vpn_policy[afi].tovpn_rd, -			      buf, sizeof(buf)); +		prefix_rd2str(&from_bgp->vpn_policy[afi].tovpn_rd, buf, +			      sizeof(buf), from_bgp->asnotation);  		from_bgp->vpn_policy[afi].rtlist[edir] =  			ecommunity_str2com(buf, ECOMMUNITY_ROUTE_TARGET, 0);  		SET_FLAG(from_bgp->af_flags[afi][safi], diff --git a/bgpd/bgp_mplsvpn_snmp.c b/bgpd/bgp_mplsvpn_snmp.c index 95a7bb8117..9b2ab66806 100644 --- a/bgpd/bgp_mplsvpn_snmp.c +++ b/bgpd/bgp_mplsvpn_snmp.c @@ -942,11 +942,13 @@ static uint8_t *mplsL3vpnVrfTable(struct variable *v, oid name[],  		if (CHECK_FLAG(l3vpn_bgp->vpn_policy[AFI_IP].flags,  			       BGP_VPN_POLICY_TOVPN_RD_SET))  			prefix_rd2str(&l3vpn_bgp->vpn_policy[AFI_IP].tovpn_rd, -				      rd_buf, sizeof(rd_buf)); +				      rd_buf, sizeof(rd_buf), +				      bgp_get_asnotation(l3vpn_bgp));  		else if (CHECK_FLAG(l3vpn_bgp->vpn_policy[AFI_IP6].flags,  				    BGP_VPN_POLICY_TOVPN_RD_SET))  			prefix_rd2str(&l3vpn_bgp->vpn_policy[AFI_IP6].tovpn_rd, -				      rd_buf, sizeof(rd_buf)); +				      rd_buf, sizeof(rd_buf), +				      bgp_get_asnotation(l3vpn_bgp));  		*var_len = strnlen(rd_buf, RD_ADDRSTRLEN);  		return (uint8_t *)rd_buf; diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index da89c594c8..df67e2a72c 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -538,7 +538,7 @@ static void bgp_accept(struct thread *thread)  				peer1->host);  	peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as, -			   peer1->as, peer1->as_type, NULL, false); +			   peer1->as, peer1->as_type, NULL, false, NULL);  	peer_xfer_config(peer, peer1);  	bgp_peer_gr_flags_update(peer); diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index a3014c0c6d..00a0bc8402 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -802,6 +802,7 @@ static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp,  		safi = table->safi;  		bgp_path = table->bgp; +  		if (json) {  			json_path = json_object_new_object();  			json_object_string_add(json_path, "afi", afi2str(afi)); @@ -811,7 +812,8 @@ static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp,  						dest);  			if (dest->pdest)  				json_object_string_addf( -					json_path, "rd", "%pRD", +					json_path, "rd", +					BGP_RD_AS_FORMAT(bgp->asnotation),  					(struct prefix_rd *)bgp_dest_get_prefix(  						dest->pdest));  			json_object_string_add( @@ -821,13 +823,14 @@ static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp,  			json_object_array_add(paths, json_path);  			continue;  		} -		if (dest->pdest) -			vty_out(vty, "    %d/%d %pBD RD %pRD %s flags 0x%x\n", -				afi, safi, dest, +		if (dest->pdest) { +			vty_out(vty, "    %d/%d %pBD RD ", afi, safi, dest); +			vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),  				(struct prefix_rd *)bgp_dest_get_prefix( -					dest->pdest), -				bgp_path->name_pretty, path->flags); -		else +					dest->pdest)); +			vty_out(vty, " %s flags 0x%x\n", bgp_path->name_pretty, +				path->flags); +		} else  			vty_out(vty, "    %d/%d %pBD %s flags 0x%x\n",  				afi, safi, dest, bgp_path->name_pretty, path->flags);  	} diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 4f42766b9f..25b458a8e5 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -1190,14 +1190,20 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)  		}  		if (BGP_DEBUG(nht, NHT)) { -			if (dest->pdest) -				zlog_debug( -					"... eval path %d/%d %pBD RD %pRD %s flags 0x%x", -					afi, safi, dest, + +			if (dest->pdest) { +				char rd_buf[RD_ADDRSTRLEN]; + +				prefix_rd2str(  					(struct prefix_rd *)bgp_dest_get_prefix(  						dest->pdest), +					rd_buf, sizeof(rd_buf), +					bgp_get_asnotation(bnc->bgp)); +				zlog_debug( +					"... eval path %d/%d %pBD RD %s %s flags 0x%x", +					afi, safi, dest, rd_buf,  					bgp_path->name_pretty, path->flags); -			else +			} else  				zlog_debug(  					"... eval path %d/%d %pBD %s flags 0x%x",  					afi, safi, dest, bgp_path->name_pretty, diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c index 6e73ab8d1e..bb9f76b8a3 100644 --- a/bgpd/bgp_rd.c +++ b/bgpd/bgp_rd.c @@ -83,12 +83,12 @@ void decode_rd_vnc_eth(const uint8_t *pnt, struct rd_vnc_eth *rd_vnc_eth)  int str2prefix_rd(const char *str, struct prefix_rd *prd)  { -	int ret = 0; -	char *p; -	char *p2; +	int ret = 0, type = RD_TYPE_UNDEFINED; +	char *p, *p2;  	struct stream *s = NULL;  	char *half = NULL;  	struct in_addr addr; +	as_t as_val;  	prd->family = AF_UNSPEC;  	prd->prefixlen = 64; @@ -97,41 +97,55 @@ int str2prefix_rd(const char *str, struct prefix_rd *prd)  	if (!p)  		goto out; +	/* a second ':' is accepted */ +	p2 = strchr(p + 1, ':'); +	if (p2) { +		/* type is in first part */ +		half = XMALLOC(MTYPE_TMP, (p - str) + 1); +		memcpy(half, str, (p - str)); +		half[p - str] = '\0'; +		type = atoi(half); +		if (type != RD_TYPE_AS && type != RD_TYPE_IP && +		    type != RD_TYPE_AS4) +			goto out; +		XFREE(MTYPE_TMP, half); +		half = XMALLOC(MTYPE_TMP, (p2 - p)); +		memcpy(half, p + 1, (p2 - p - 1)); +		half[p2 - p - 1] = '\0'; +		p = p2 + 1; +	} else { +		half = XMALLOC(MTYPE_TMP, (p - str) + 1); +		memcpy(half, str, (p - str)); +		half[p - str] = '\0'; +	}  	if (!all_digit(p + 1))  		goto out;  	s = stream_new(RD_BYTES); -	half = XMALLOC(MTYPE_TMP, (p - str) + 1); -	memcpy(half, str, (p - str)); -	half[p - str] = '\0'; - -	p2 = strchr(str, '.'); - -	if (!p2) { -		unsigned long as_val; - -		if (!all_digit(half)) -			goto out; - -		as_val = atol(half); -		if (as_val > 0xffff) { +	/* if it is an AS format or an IP */ +	if (asn_str2asn(half, &as_val)) { +		if (as_val > UINT16_MAX) {  			stream_putw(s, RD_TYPE_AS4);  			stream_putl(s, as_val);  			stream_putw(s, atol(p + 1)); +			if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_AS4) +				goto out;  		} else {  			stream_putw(s, RD_TYPE_AS);  			stream_putw(s, as_val);  			stream_putl(s, atol(p + 1)); +			if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_AS) +				goto out;  		} -	} else { -		if (!inet_aton(half, &addr)) -			goto out; - +	} else if (inet_aton(half, &addr)) {  		stream_putw(s, RD_TYPE_IP);  		stream_put_in_addr(s, &addr);  		stream_putw(s, atol(p + 1)); -	} +		if (type != RD_TYPE_UNDEFINED && type != RD_TYPE_IP) +			goto out; +	} else +		goto out;  	memcpy(prd->val, s->data, 8);  	ret = 1; @@ -142,12 +156,14 @@ out:  	return ret;  } -char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size) +char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size, +		    enum asnotation_mode asnotation)  {  	const uint8_t *pnt;  	uint16_t type;  	struct rd_as rd_as;  	struct rd_ip rd_ip; +	int len = 0;  	assert(size >= RD_ADDRSTRLEN); @@ -157,11 +173,15 @@ char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size)  	if (type == RD_TYPE_AS) {  		decode_rd_as(pnt + 2, &rd_as); -		snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val); +		len += snprintfrr(buf + len, size - len, ASN_FORMAT(asnotation), +				  &rd_as.as); +		snprintfrr(buf + len, size - len, ":%u", rd_as.val);  		return buf;  	} else if (type == RD_TYPE_AS4) {  		decode_rd_as4(pnt + 2, &rd_as); -		snprintf(buf, size, "%u:%u", rd_as.as, rd_as.val); +		len += snprintfrr(buf + len, size - len, ASN_FORMAT(asnotation), +				  &rd_as.as); +		snprintfrr(buf + len, size - len, ":%u", rd_as.val);  		return buf;  	} else if (type == RD_TYPE_IP) {  		decode_rd_ip(pnt + 2, &rd_ip); @@ -196,16 +216,38 @@ void form_auto_rd(struct in_addr router_id,  	(void)str2prefix_rd(buf, prd);  } -printfrr_ext_autoreg_p("RD", printfrr_prd); -static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea, -			    const void *ptr) +static ssize_t printfrr_prd_asnotation(struct fbuf *buf, +				       struct printfrr_eargs *ea, +				       const void *ptr, +				       enum asnotation_mode asnotation)  {  	char rd_buf[RD_ADDRSTRLEN];  	if (!ptr)  		return bputs(buf, "(null)"); -	prefix_rd2str(ptr, rd_buf, sizeof(rd_buf)); +	prefix_rd2str(ptr, rd_buf, sizeof(rd_buf), asnotation);  	return bputs(buf, rd_buf);  } + +printfrr_ext_autoreg_p("RDP", printfrr_prd); +static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea, +			    const void *ptr) +{ +	return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_PLAIN); +} + +printfrr_ext_autoreg_p("RDD", printfrr_prd_dot); +static ssize_t printfrr_prd_dot(struct fbuf *buf, struct printfrr_eargs *ea, +				const void *ptr) +{ +	return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_DOT); +} + +printfrr_ext_autoreg_p("RDE", printfrr_prd_dotplus); +static ssize_t printfrr_prd_dotplus(struct fbuf *buf, struct printfrr_eargs *ea, +				    const void *ptr) +{ +	return printfrr_prd_asnotation(buf, ea, ptr, ASNOTATION_DOTPLUS); +} diff --git a/bgpd/bgp_rd.h b/bgpd/bgp_rd.h index 44173b7a24..e38c2fad3b 100644 --- a/bgpd/bgp_rd.h +++ b/bgpd/bgp_rd.h @@ -7,7 +7,11 @@  #ifndef _QUAGGA_BGP_RD_H  #define _QUAGGA_BGP_RD_H +#include "asn.h" +#include "prefix.h" +  /* RD types */ +#define RD_TYPE_UNDEFINED (-1)  #define RD_TYPE_AS      0  #define RD_TYPE_IP      1  #define RD_TYPE_AS4     2 @@ -19,6 +23,16 @@  #define RD_ADDRSTRLEN  28  #define RD_BYTES  8 +#define BGP_RD_AS_FORMAT(mode)                                                 \ +	((mode == ASNOTATION_DOT)                                              \ +		 ? "%pRDD"                                                     \ +		 : ((mode == ASNOTATION_DOTPLUS) ? "%pRDE" : "%pRDP")) + +#define BGP_RD_AS_FORMAT_SPACE(mode)                                           \ +	((mode == ASNOTATION_DOT)                                              \ +		 ? "%-21pRDD"                                                  \ +		 : ((mode == ASNOTATION_DOTPLUS) ? "%-21pRDE" : "%-21pRDP")) +  struct rd_as {  	uint16_t type;  	as_t as; @@ -51,7 +65,8 @@ extern void decode_rd_vnc_eth(const uint8_t *pnt,  #endif  extern int str2prefix_rd(const char *, struct prefix_rd *); -extern char *prefix_rd2str(const struct prefix_rd *, char *, size_t); +extern char *prefix_rd2str(const struct prefix_rd *prd, char *buf, size_t size, +			   enum asnotation_mode asnotation);  extern void form_auto_rd(struct in_addr router_id, uint16_t rd_id,  			 struct prefix_rd *prd); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0d93abc12f..977dca13dc 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -6078,6 +6078,8 @@ static void bgp_static_free(struct bgp_static *bgp_static)  	XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);  	route_map_counter_decrement(bgp_static->rmap.map); +	if (bgp_static->prd_pretty) +		XFREE(MTYPE_BGP, bgp_static->prd_pretty);  	XFREE(MTYPE_ATTR, bgp_static->eth_s_id);  	XFREE(MTYPE_BGP_STATIC, bgp_static);  } @@ -6981,6 +6983,8 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,  		bgp_static->label = label;  		bgp_static->prd = prd; +		if (rd_str) +			bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP, rd_str);  		if (rmap_str) {  			XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);  			route_map_counter_decrement(bgp_static->rmap.map); @@ -7243,7 +7247,7 @@ static bool aggr_suppress_map_test(struct bgp *bgp,  		return false;  	/* Call route map matching and return result. */ -	attr.aspath = aspath_empty(); +	attr.aspath = aspath_empty(bgp->asnotation);  	rmap_path.peer = bgp->peer_self;  	rmap_path.attr = &attr; @@ -7337,9 +7341,12 @@ static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,  				    struct lcommunity *lcomm)  {  	static struct aspath *ae = NULL; +	enum asnotation_mode asnotation; + +	asnotation = bgp_get_asnotation(NULL);  	if (!ae) -		ae = aspath_empty(); +		ae = aspath_empty(asnotation);  	if (!pi)  		return false; @@ -10254,10 +10261,11 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,  		if (dest && dest->pdest) {  			pdest = dest->pdest;  			if (is_pi_family_evpn(parent_ri)) { -				vty_out(vty, -					"  Imported from %pRD:%pFX, VNI %s", +				vty_out(vty, "  Imported from "); +				vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),  					(struct prefix_rd *)bgp_dest_get_prefix( -						pdest), +						pdest)); +				vty_out(vty, ":%pFX, VNI %s",  					(struct prefix_evpn *)  						bgp_dest_get_prefix(dest),  					tag_buf); @@ -10270,12 +10278,15 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,  							: "inactive");  				vty_out(vty, "\n"); -			} else -				vty_out(vty, "  Imported from %pRD:%pFX\n", +			} else { +				vty_out(vty, "  Imported from "); +				vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),  					(struct prefix_rd *)bgp_dest_get_prefix( -						pdest), +						pdest)); +				vty_out(vty, ":%pFX\n",  					(struct prefix_evpn *)  						bgp_dest_get_prefix(dest)); +			}  		}  	} @@ -11184,17 +11195,26 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,  			vty_out(vty, "{\n");  			*json_header_depth = 2;  		} -  		vty_out(vty,  			" \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64  			",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n" -			" \"localAS\": %u,\n \"routes\": { ", +			" \"localAS\": ",  			bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,  			bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT  				? VRF_DEFAULT_NAME  				: bgp->name,  			table->version, &bgp->router_id, -			bgp->default_local_pref, bgp->as); +			bgp->default_local_pref); +		if ((bgp->asnotation == ASNOTATION_PLAIN) || +		    ((bgp->asnotation == ASNOTATION_DOT) && +		     (bgp->as < UINT16_MAX))) +			vty_out(vty, "%u", bgp->as); +		else { +			vty_out(vty, "\""); +			vty_out(vty, ASN_FORMAT(bgp->asnotation), &bgp->as); +			vty_out(vty, "\""); +		} +		vty_out(vty, ",\n \"routes\": { ");  		if (rd) {  			vty_out(vty, " \"routeDistinguishers\" : {");  			++*json_header_depth; @@ -11468,7 +11488,10 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,  				vty_out(vty, "\n");  				vty_out(vty, "Default local pref %u, ",  					bgp->default_local_pref); -				vty_out(vty, "local AS %u\n", bgp->as); +				vty_out(vty, "local AS "); +				vty_out(vty, ASN_FORMAT(bgp->asnotation), +					&bgp->as); +				vty_out(vty, "\n");  				if (!detail_routes) {  					vty_out(vty, BGP_SHOW_SCODE_HEADER);  					vty_out(vty, BGP_SHOW_NCODE_HEADER); @@ -11665,7 +11688,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,  			char rd[RD_ADDRSTRLEN];  			memcpy(&prd, dest_p, sizeof(struct prefix_rd)); -			prefix_rd2str(&prd, rd, sizeof(rd)); +			prefix_rd2str(&prd, rd, sizeof(rd), bgp->asnotation);  			bgp_show_table(vty, bgp, safi, itable, type, output_arg,  				       rd, next == NULL, &output_cum,  				       &total_cum, &json_header_depth, @@ -11816,13 +11839,16 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,  	if (safi == SAFI_EVPN) {  		if (!json) {  			vty_out(vty, "BGP routing table entry for %s%s%pFX\n", -				prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) +				prd ? prefix_rd2str(prd, buf1, sizeof(buf1), +						    bgp->asnotation)  				    : "",  				prd ? ":" : "", (struct prefix_evpn *)p);  		} else { -			json_object_string_add(json, "rd", -				prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) : -				""); +			json_object_string_add( +				json, "rd", +				prd ? prefix_rd2str(prd, buf1, sizeof(buf1), +						    bgp->asnotation) +				    : "");  			bgp_evpn_route2json((struct prefix_evpn *)p, json);  		}  	} else { @@ -11832,7 +11858,8 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,  				"\n",  				((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)  					 ? prefix_rd2str(prd, buf1, -							 sizeof(buf1)) +							 sizeof(buf1), +							 bgp->asnotation)  					 : ""),  				safi == SAFI_MPLS_VPN ? ":" : "", p,  				dest->version); @@ -12055,8 +12082,9 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd,  		json_object_object_add(json_header, "paths", json_paths);  		if (pfx_rd) -			json_object_object_addf(json, json_header, "%pRD", -						pfx_rd); +			json_object_object_addf( +				json, json_header, +				BGP_RD_AS_FORMAT(bgp->asnotation), pfx_rd);  	}  } @@ -14465,7 +14493,8 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")  			prd = (const struct prefix_rd *)bgp_dest_get_prefix(  				dest); -			prefix_rd2str(prd, rd_str, sizeof(rd_str)); +			prefix_rd2str(prd, rd_str, sizeof(rd_str), +				      bgp->asnotation);  			show_adj_route(  				vty, peer, table, afi, safi, type, rmap_name, @@ -15594,7 +15623,6 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,  	struct bgp_dest *dest;  	struct bgp_table *table;  	const struct prefix *p; -	const struct prefix_rd *prd;  	struct bgp_static *bgp_static;  	mpls_label_t label; @@ -15612,13 +15640,12 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,  				continue;  			p = bgp_dest_get_prefix(dest); -			prd = (const struct prefix_rd *)bgp_dest_get_prefix( -				pdest);  			/* "network" configuration display.  */  			label = decode_label(&bgp_static->label); -			vty_out(vty, "  network %pFX rd %pRD", p, prd); +			vty_out(vty, "  network %pFX rd %s", p, +				bgp_static->prd_pretty);  			if (safi == SAFI_MPLS_VPN)  				vty_out(vty, " label %u", label); @@ -15641,7 +15668,6 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,  	struct bgp_dest *dest;  	struct bgp_table *table;  	const struct prefix *p; -	const struct prefix_rd *prd;  	struct bgp_static *bgp_static;  	char buf[PREFIX_STRLEN * 2];  	char buf2[SU_ADDRSTRLEN]; @@ -15669,7 +15695,6 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,  				esi_to_str(bgp_static->eth_s_id,  						esi_buf, sizeof(esi_buf));  			p = bgp_dest_get_prefix(dest); -			prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);  			/* "network" configuration display.  */  			if (p->u.prefix_evpn.route_type == 5) { @@ -15696,8 +15721,9 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,  					  &bgp_static->gatewayIp.u.prefix, buf2,  					  sizeof(buf2));  			vty_out(vty, -				"  network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n", -				buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag, +				"  network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n", +				buf, bgp_static->prd_pretty, +				p->u.prefix_evpn.prefix_addr.eth_tag,  				decode_label(&bgp_static->label), esi_buf, buf2,  				macrouter); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index d449152c21..bd4191bfd9 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -355,6 +355,7 @@ struct bgp_static {  	/* Route Distinguisher */  	struct prefix_rd prd; +	char *prd_pretty;  	/* MPLS label.  */  	mpls_label_t label; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index dbffecee30..4b6f290c71 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -213,7 +213,7 @@ static void *route_aspath_compile(const char *arg)  {  	struct aspath *aspath; -	aspath = aspath_str2aspath(arg); +	aspath = aspath_str2aspath(arg, bgp_get_asnotation(NULL));  	if (!aspath)  		return NULL;  	return aspath; @@ -5663,15 +5663,16 @@ DEFUN_YANG (no_set_label_index,  DEFUN_YANG (set_aspath_prepend_asn,  	    set_aspath_prepend_asn_cmd, -	    "set as-path prepend (1-4294967295)...", +	    "set as-path prepend ASNUM...",  	    SET_STR  	    "Transform BGP AS_PATH attribute\n"  	    "Prepend to the as-path\n" -	    "AS number\n") +	    AS_STR)  {  	int idx_asn = 3;  	int ret;  	char *str; +	struct aspath *aspath;  	str = argv_concat(argv, argc, idx_asn); @@ -5679,6 +5680,12 @@ DEFUN_YANG (set_aspath_prepend_asn,  		"./set-action[action='frr-bgp-route-map:as-path-prepend']";  	char xpath_value[XPATH_MAXLEN]; +	aspath = route_aspath_compile(str); +	if (!aspath) { +		vty_out(vty, "%% Invalid AS path value %s\n", str); +		return CMD_WARNING_CONFIG_FAILED; +	} +	route_aspath_free(aspath);  	nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);  	snprintf(xpath_value, sizeof(xpath_value),  		 "%s/rmap-set-action/frr-bgp-route-map:prepend-as-path", xpath); @@ -5713,16 +5720,22 @@ DEFUN_YANG (set_aspath_prepend_lastas,  DEFPY_YANG (set_aspath_replace_asn,  	    set_aspath_replace_asn_cmd, -	    "set as-path replace <any|(1-4294967295)>$replace", +	    "set as-path replace <any|ASNUM>$replace",  	    SET_STR  	    "Transform BGP AS_PATH attribute\n"  	    "Replace AS number to local AS number\n"  	    "Replace any AS number to local AS number\n" -	    "Replace a specific AS number to local AS number\n") +	    "Replace a specific AS number in plain or dotted format to local AS number\n")  {  	const char *xpath =  		"./set-action[action='frr-bgp-route-map:as-path-replace']";  	char xpath_value[XPATH_MAXLEN]; +	as_t as_value; + +	if (!strmatch(replace, "any") && !asn_str2asn(replace, &as_value)) { +		vty_out(vty, "%% Invalid AS value %s\n", replace); +		return CMD_WARNING_CONFIG_FAILED; +	}  	nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);  	snprintf(xpath_value, sizeof(xpath_value), @@ -5733,13 +5746,13 @@ DEFPY_YANG (set_aspath_replace_asn,  DEFPY_YANG (no_set_aspath_replace_asn,  	    no_set_aspath_replace_asn_cmd, -	    "no set as-path replace [<any|(1-4294967295)>]", +	    "no set as-path replace [<any|ASNUM>]",  	    NO_STR  	    SET_STR  	    "Transform BGP AS_PATH attribute\n"  	    "Replace AS number to local AS number\n"  	    "Replace any AS number to local AS number\n" -	    "Replace a specific AS number to local AS number\n") +	    "Replace a specific AS number in plain or dotted format to local AS number\n")  {  	const char *xpath =  		"./set-action[action='frr-bgp-route-map:as-path-replace']"; @@ -5750,12 +5763,12 @@ DEFPY_YANG (no_set_aspath_replace_asn,  DEFUN_YANG (no_set_aspath_prepend,  	    no_set_aspath_prepend_cmd, -	    "no set as-path prepend [(1-4294967295)]", +	    "no set as-path prepend [ASNUM]",  	    NO_STR  	    SET_STR  	    "Transform BGP AS_PATH attribute\n"  	    "Prepend to the as-path\n" -	    "AS number\n") +	    AS_STR)  {  	const char *xpath =  		"./set-action[action='frr-bgp-route-map:as-path-prepend']"; @@ -5783,15 +5796,16 @@ DEFUN_YANG (no_set_aspath_prepend_lastas,  DEFUN_YANG (set_aspath_exclude,  	    set_aspath_exclude_cmd, -	    "set as-path exclude (1-4294967295)...", +	    "set as-path exclude ASNUM...",  	    SET_STR  	    "Transform BGP AS-path attribute\n"  	    "Exclude from the as-path\n" -	    "AS number\n") +	    AS_STR)  {  	int idx_asn = 3;  	int ret;  	char *str; +	struct aspath *aspath;  	str = argv_concat(argv, argc, idx_asn); @@ -5799,6 +5813,12 @@ DEFUN_YANG (set_aspath_exclude,  		"./set-action[action='frr-bgp-route-map:as-path-exclude']";  	char xpath_value[XPATH_MAXLEN]; +	aspath = route_aspath_compile(str); +	if (!aspath) { +		vty_out(vty, "%% Invalid AS path value %s\n", str); +		return CMD_WARNING_CONFIG_FAILED; +	} +	route_aspath_free(aspath);  	nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);  	snprintf(xpath_value, sizeof(xpath_value),  		 "%s/rmap-set-action/frr-bgp-route-map:exclude-as-path", xpath); @@ -5810,7 +5830,7 @@ DEFUN_YANG (set_aspath_exclude,  DEFUN_YANG (no_set_aspath_exclude,  	    no_set_aspath_exclude_cmd, -	    "no set as-path exclude (1-4294967295)...", +	    "no set as-path exclude ASNUM...",  	    NO_STR  	    SET_STR  	    "Transform BGP AS_PATH attribute\n" @@ -6496,11 +6516,11 @@ DEFPY_YANG (no_set_aigp_metric,  DEFUN_YANG (set_aggregator_as,  	    set_aggregator_as_cmd, -	    "set aggregator as (1-4294967295) A.B.C.D", +	    "set aggregator as ASNUM A.B.C.D",  	    SET_STR  	    "BGP aggregator attribute\n"  	    "AS number of aggregator\n" -	    "AS number\n" +	    AS_STR  	    "IP address of aggregator\n")  {  	int idx_number = 3; @@ -6509,6 +6529,12 @@ DEFUN_YANG (set_aggregator_as,  	char xpath_addr[XPATH_MAXLEN];  	const char *xpath =  		"./set-action[action='frr-bgp-route-map:aggregator']"; +	as_t as_value; + +	if (!asn_str2asn(argv[idx_number]->arg, &as_value)) { +		vty_out(vty, "%% Invalid AS value %s\n", argv[idx_number]->arg); +		return CMD_WARNING_CONFIG_FAILED; +	}  	nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); @@ -6531,12 +6557,12 @@ DEFUN_YANG (set_aggregator_as,  DEFUN_YANG (no_set_aggregator_as,  	    no_set_aggregator_as_cmd, -	    "no set aggregator as [(1-4294967295) A.B.C.D]", +	    "no set aggregator as [ASNUM A.B.C.D]",  	    NO_STR  	    SET_STR  	    "BGP aggregator attribute\n"  	    "AS number of aggregator\n" -	    "AS number\n" +	    AS_STR  	    "IP address of aggregator\n")  {  	const char *xpath = diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 61b8b4edce..d7e1a6341b 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -81,6 +81,7 @@ struct rpki_for_each_record_arg {  	unsigned int *prefix_amount;  	as_t as;  	json_object *json; +	enum asnotation_mode asnotation;  };  static int start(void); @@ -105,7 +106,7 @@ static void rpki_delete_all_cache_nodes(void);  static int add_tcp_cache(const char *host, const char *port,  			 const uint8_t preference, const char *bindaddr);  static void print_record(const struct pfx_record *record, struct vty *vty, -			 json_object *json); +			 json_object *json, enum asnotation_mode asnotation);  static bool is_synchronized(void);  static bool is_running(void);  static bool is_stopping(void); @@ -270,7 +271,7 @@ static void rpki_delete_all_cache_nodes(void)  }  static void print_record(const struct pfx_record *record, struct vty *vty, -			 json_object *json) +			 json_object *json, enum asnotation_mode asnotation)  {  	char ip[INET6_ADDRSTRLEN];  	json_object *json_record = NULL; @@ -278,8 +279,10 @@ static void print_record(const struct pfx_record *record, struct vty *vty,  	lrtr_ip_addr_to_str(&record->prefix, ip, sizeof(ip));  	if (!json) { -		vty_out(vty, "%-40s   %3u - %3u   %10u\n", ip, record->min_len, -			record->max_len, record->asn); +		vty_out(vty, "%-40s   %3u - %3u   ", ip, record->min_len, +			record->max_len); +		vty_out(vty, ASN_FORMAT(asnotation), &record->asn); +		vty_out(vty, "\n");  	} else {  		json_record = json_object_new_object();  		json_object_string_add(json_record, "prefix", ip); @@ -287,7 +290,7 @@ static void print_record(const struct pfx_record *record, struct vty *vty,  				    record->min_len);  		json_object_int_add(json_record, "prefixLenMax",  				    record->max_len); -		json_object_int_add(json_record, "asn", record->asn); +		asn_asn2json(json_record, "asn", record->asn, asnotation);  		json_object_array_add(json, json_record);  	}  } @@ -299,7 +302,7 @@ static void print_record_by_asn(const struct pfx_record *record, void *data)  	if (record->asn == arg->as) {  		(*arg->prefix_amount)++; -		print_record(record, vty, arg->json); +		print_record(record, vty, arg->json, arg->asnotation);  	}  } @@ -310,7 +313,7 @@ static void print_record_cb(const struct pfx_record *record, void *data)  	(*arg->prefix_amount)++; -	print_record(record, vty, arg->json); +	print_record(record, vty, arg->json, arg->asnotation);  }  static struct rtr_mgr_group *get_groups(void) @@ -728,6 +731,7 @@ static void print_prefix_table_by_asn(struct vty *vty, as_t as,  	arg.vty = vty;  	arg.as = as;  	arg.json = NULL; +	arg.asnotation = bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT));  	if (!group) {  		if (!json) @@ -780,6 +784,7 @@ static void print_prefix_table(struct vty *vty, json_object *json)  	arg.vty = vty;  	arg.json = NULL; +	arg.asnotation = bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT));  	if (!group) {  		if (!json) @@ -1337,7 +1342,7 @@ DEFPY (show_rpki_prefix_table,  DEFPY (show_rpki_as_number,         show_rpki_as_number_cmd, -       "show rpki as-number (1-4294967295)$by_asn [json$uj]", +       "show rpki as-number ASNUM$by_asn [json$uj]",         SHOW_STR         RPKI_OUTPUT_STRING         "Lookup by ASN in prefix table\n" @@ -1345,23 +1350,28 @@ DEFPY (show_rpki_as_number,         JSON_STR)  {  	struct json_object *json = NULL; +	as_t as;  	if (!is_synchronized()) {  		if (!uj)  			vty_out(vty, "No Connection to RPKI cache server.\n");  		return CMD_WARNING;  	} - +	if (!asn_str2asn(by_asn, &as)) { +		if (!uj) +			vty_out(vty, "Invalid AS value: %s.\n", by_asn); +		return CMD_WARNING; +	}  	if (uj)  		json = json_object_new_object(); -	print_prefix_table_by_asn(vty, by_asn, json); +	print_prefix_table_by_asn(vty, as, json);  	return CMD_SUCCESS;  }  DEFPY (show_rpki_prefix,         show_rpki_prefix_cmd, -       "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn] [json$uj]", +       "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [ASNUM$asn] [json$uj]",         SHOW_STR         RPKI_OUTPUT_STRING         "Lookup IP prefix and optionally ASN in prefix table\n" @@ -1372,6 +1382,8 @@ DEFPY (show_rpki_prefix,  {  	json_object *json = NULL;  	json_object *json_records = NULL; +	as_t as; +	enum asnotation_mode asnotation;  	if (!is_synchronized()) {  		if (!uj) @@ -1392,13 +1404,19 @@ DEFPY (show_rpki_prefix,  		return CMD_WARNING;  	} +	if (asn && !asn_str2asn(asn, &as)) { +		if (!uj) +			vty_out(vty, "Invalid AS value: %s.\n", asn); +		return CMD_WARNING; +	} +  	struct pfx_record *matches = NULL;  	unsigned int match_count = 0;  	enum pfxv_state result;  	if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count, -				 asn, &addr, prefix->prefixlen, &result) -	    != PFX_SUCCESS) { +				 as, &addr, prefix->prefixlen, +				 &result) != PFX_SUCCESS) {  		if (!json)  			vty_out(vty, "Prefix lookup failed\n");  		return CMD_WARNING; @@ -1415,13 +1433,14 @@ DEFPY (show_rpki_prefix,  		json_object_object_add(json, "prefixes", json_records);  	} +	asnotation = bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT));  	for (size_t i = 0; i < match_count; ++i) {  		const struct pfx_record *record = &matches[i]; -		if (record->max_len >= prefix->prefixlen -		    && ((asn != 0 && (uint32_t)asn == record->asn) -			|| asn == 0)) { -			print_record(&matches[i], vty, json_records); +		if (record->max_len >= prefix->prefixlen && +		    ((as != 0 && (uint32_t)as == record->asn) || as == 0)) { +			print_record(&matches[i], vty, json_records, +				     asnotation);  		}  	} diff --git a/bgpd/bgp_script.c b/bgpd/bgp_script.c index 6cc75494ed..f4ab233524 100644 --- a/bgpd/bgp_script.c +++ b/bgpd/bgp_script.c @@ -149,7 +149,8 @@ void lua_decode_attr(lua_State *L, int idx, struct attr *attr)  	attr->nh_ifindex = lua_tointeger(L, -1);  	lua_pop(L, 1);  	lua_getfield(L, idx, "aspath"); -	attr->aspath = aspath_str2aspath(lua_tostring(L, -1)); +	attr->aspath = aspath_str2aspath(lua_tostring(L, -1), +					 bgp_get_asnotation(NULL));  	lua_pop(L, 1);  	lua_getfield(L, idx, "localpref");  	attr->local_pref = lua_tointeger(L, -1); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index b858d9c4b4..8ef18a34d0 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -24,6 +24,7 @@  #include "queue.h"  #include "filter.h"  #include "frrstr.h" +#include "asn.h"  #include "bgpd/bgpd.h"  #include "bgpd/bgp_attr_evpn.h" @@ -579,9 +580,10 @@ static const char *get_bgp_default_af_flag(afi_t afi, safi_t safi)  }  int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name, -		enum bgp_instance_type inst_type) +		enum bgp_instance_type inst_type, const char *as_pretty, +		enum asnotation_mode asnotation)  { -	int ret = bgp_get(bgp, as, name, inst_type); +	int ret = bgp_get(bgp, as, name, inst_type, as_pretty, asnotation);  	if (ret == BGP_CREATED) {  		bgp_timers_set(*bgp, DFLT_BGP_KEEPALIVE, DFLT_BGP_HOLDTIME, @@ -1222,7 +1224,12 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,  	/* Clear all neighbors belonging to a specific AS. */  	if (sort == clear_as) { -		as_t as = strtoul(arg, NULL, 10); +		as_t as; + +		if (!asn_str2asn(arg, &as)) { +			vty_out(vty, "%% BGP: No such AS %s\n", arg); +			return CMD_WARNING; +		}  		for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {  			if (peer->as != as) @@ -1460,16 +1467,23 @@ DEFUN (no_auto_summary,  /* "router bgp" commands. */  DEFUN_NOSH (router_bgp,         router_bgp_cmd, -       "router bgp [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]", +       "router bgp [ASNUM$instasn [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]",         ROUTER_STR         BGP_STR         AS_STR -       BGP_INSTANCE_HELP_STR) +       BGP_INSTANCE_HELP_STR +       "Force the AS notation output\n" +       "use 'AA.BB' format for AS 4 byte values\n" +       "use 'AA.BB' format for all AS values\n" +       "use plain format for all AS values\n")  {  	int idx_asn = 2;  	int idx_view_vrf = 3;  	int idx_vrf = 4;  	int is_new_bgp = 0; +	int idx_asnotation = 3; +	int idx_asnotation_kind = 4; +	enum asnotation_mode asnotation = ASNOTATION_UNDEFINED;  	int ret;  	as_t as;  	struct bgp *bgp; @@ -1494,39 +1508,62 @@ DEFUN_NOSH (router_bgp,  	// "router bgp X"  	else { -		as = strtoul(argv[idx_asn]->arg, NULL, 10); +		if (!asn_str2asn(argv[idx_asn]->arg, &as)) { +			vty_out(vty, "%% BGP: No such AS %s\n", +				argv[idx_asn]->arg); +			return CMD_WARNING_CONFIG_FAILED; +		}  		if (as == BGP_PRIVATE_AS_MAX || as == BGP_AS4_MAX)  			vty_out(vty, "Reserved AS used (%u|%u); AS is %u\n",  				BGP_PRIVATE_AS_MAX, BGP_AS4_MAX, as);  		inst_type = BGP_INSTANCE_TYPE_DEFAULT; -		if (argc > 3) { -			name = argv[idx_vrf]->arg; -			if (!strcmp(argv[idx_view_vrf]->text, "vrf")) { -				if (strmatch(name, VRF_DEFAULT_NAME)) -					name = NULL; -				else -					inst_type = BGP_INSTANCE_TYPE_VRF; -			} else if (!strcmp(argv[idx_view_vrf]->text, "view")) -				inst_type = BGP_INSTANCE_TYPE_VIEW; +		if (argv_find(argv, argc, "VIEWVRFNAME", &idx_vrf)) { +			idx_view_vrf = idx_vrf - 1; +			if (argv[idx_view_vrf]->text) { +				name = argv[idx_vrf]->arg; + +				if (!strcmp(argv[idx_view_vrf]->text, "vrf")) { +					if (strmatch(name, VRF_DEFAULT_NAME)) +						name = NULL; +					else +						inst_type = +							BGP_INSTANCE_TYPE_VRF; +				} else if (!strcmp(argv[idx_view_vrf]->text, +						   "view")) +					inst_type = BGP_INSTANCE_TYPE_VIEW; +			} +		} +		if (argv_find(argv, argc, "as-notation", &idx_asnotation)) { +			idx_asnotation_kind = idx_asnotation + 1; +			if (strmatch(argv[idx_asnotation_kind]->text, "dot+")) +				asnotation = ASNOTATION_DOTPLUS; +			else if (strmatch(argv[idx_asnotation_kind]->text, +					  "dot")) +				asnotation = ASNOTATION_DOT; +			else if (strmatch(argv[idx_asnotation_kind]->text, +					  "plain")) +				asnotation = ASNOTATION_PLAIN;  		}  		if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)  			is_new_bgp = (bgp_lookup(as, name) == NULL); -		ret = bgp_get_vty(&bgp, &as, name, inst_type); +		ret = bgp_get_vty(&bgp, &as, name, inst_type, +				  argv[idx_asn]->arg, asnotation);  		switch (ret) {  		case BGP_ERR_AS_MISMATCH: -			vty_out(vty, "BGP is already running; AS is %u\n", as); +			vty_out(vty, "BGP is already running; AS is %s\n", +				bgp->as_pretty);  			return CMD_WARNING_CONFIG_FAILED;  		case BGP_ERR_INSTANCE_MISMATCH:  			vty_out(vty,  				"BGP instance name and AS number mismatch\n");  			vty_out(vty, -				"BGP instance is already running; AS is %u\n", -				as); +				"BGP instance is already running; AS is %s\n", +				bgp->as_pretty);  			return CMD_WARNING_CONFIG_FAILED;  		} @@ -1542,6 +1579,19 @@ DEFUN_NOSH (router_bgp,  			bgp_vpn_leak_export(bgp);  		/* Pending: handle when user tries to change a view to vrf n vv.  		 */ +		/* for pre-existing bgp instance, +		 * - update as_pretty +		 * - update asnotation if explicitly mentioned +		 */ +		if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO)) { +			XFREE(MTYPE_BGP, bgp->as_pretty); +			bgp->as_pretty = XSTRDUP(MTYPE_BGP, argv[idx_asn]->arg); +			if (!CHECK_FLAG(bgp->config, BGP_CONFIG_ASNOTATION) && +			    asnotation != ASNOTATION_UNDEFINED) { +				SET_FLAG(bgp->config, BGP_CONFIG_ASNOTATION); +				bgp->asnotation = asnotation; +			} +		}  	}  	/* unset the auto created flag as the user config is now present */ @@ -1554,12 +1604,16 @@ DEFUN_NOSH (router_bgp,  /* "no router bgp" commands. */  DEFUN (no_router_bgp,         no_router_bgp_cmd, -       "no router bgp [(1-4294967295)$instasn [<view|vrf> VIEWVRFNAME]]", +       "no router bgp [ASNUM$instasn [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]",         NO_STR         ROUTER_STR         BGP_STR         AS_STR -       BGP_INSTANCE_HELP_STR) +       BGP_INSTANCE_HELP_STR +       "Force the AS notation output\n" +       "use 'AA.BB' format for AS 4 byte values\n" +       "use 'AA.BB' format for all AS values\n" +       "use plain format for all AS values\n")  {  	int idx_asn = 3;  	int idx_vrf = 5; @@ -1588,8 +1642,11 @@ DEFUN (no_router_bgp,  			return CMD_WARNING_CONFIG_FAILED;  		}  	} else { -		as = strtoul(argv[idx_asn]->arg, NULL, 10); - +		if (!asn_str2asn(argv[idx_asn]->arg, &as)) { +			vty_out(vty, "%% BGP: No such AS %s\n", +				argv[idx_asn]->arg); +			return CMD_WARNING_CONFIG_FAILED; +		}  		if (argc > 4) {  			name = argv[idx_vrf]->arg;  			if (strmatch(argv[idx_vrf - 1]->text, "vrf") @@ -1821,7 +1878,6 @@ DEFPY (bgp_suppress_fib_pending,  	return CMD_SUCCESS;  } -  /* BGP Cluster ID.  */  DEFUN (bgp_cluster_id,         bgp_cluster_id_cmd, @@ -1917,30 +1973,33 @@ DEFPY (no_bgp_send_extra_data,  DEFUN (bgp_confederation_identifier,         bgp_confederation_identifier_cmd, -       "bgp confederation identifier (1-4294967295)", +       "bgp confederation identifier ASNUM",         BGP_STR         "AS confederation parameters\n" -       "AS number\n" +       AS_STR         "Set routing domain confederation AS\n")  {  	VTY_DECLVAR_CONTEXT(bgp, bgp);  	int idx_number = 3;  	as_t as; -	as = strtoul(argv[idx_number]->arg, NULL, 10); +	if (!asn_str2asn(argv[idx_number]->arg, &as)) { +		vty_out(vty, "%% BGP: No such AS %s\n", argv[idx_number]->arg); +		return CMD_WARNING_CONFIG_FAILED; +	} -	bgp_confederation_id_set(bgp, as); +	bgp_confederation_id_set(bgp, as, argv[idx_number]->arg);  	return CMD_SUCCESS;  }  DEFUN (no_bgp_confederation_identifier,         no_bgp_confederation_identifier_cmd, -       "no bgp confederation identifier [(1-4294967295)]", +       "no bgp confederation identifier [ASNUM]",         NO_STR         BGP_STR         "AS confederation parameters\n" -       "AS number\n" +       AS_STR         "Set routing domain confederation AS\n")  {  	VTY_DECLVAR_CONTEXT(bgp, bgp); @@ -1951,7 +2010,7 @@ DEFUN (no_bgp_confederation_identifier,  DEFUN (bgp_confederation_peers,         bgp_confederation_peers_cmd, -       "bgp confederation peers (1-4294967295)...", +       "bgp confederation peers ASNUM...",         BGP_STR         "AS confederation parameters\n"         "Peer ASs in BGP confederation\n" @@ -1963,15 +2022,20 @@ DEFUN (bgp_confederation_peers,  	int i;  	for (i = idx_asn; i < argc; i++) { -		as = strtoul(argv[i]->arg, NULL, 10); -		bgp_confederation_peers_add(bgp, as); +		if (!asn_str2asn(argv[i]->arg, &as)) { +			vty_out(vty, "%% Invalid confed peer AS value: %s\n", +				argv[i]->arg); +			continue; +		} + +		bgp_confederation_peers_add(bgp, as, argv[i]->arg);  	}  	return CMD_SUCCESS;  }  DEFUN (no_bgp_confederation_peers,         no_bgp_confederation_peers_cmd, -       "no bgp confederation peers (1-4294967295)...", +       "no bgp confederation peers ASNUM...",         NO_STR         BGP_STR         "AS confederation parameters\n" @@ -1984,8 +2048,11 @@ DEFUN (no_bgp_confederation_peers,  	int i;  	for (i = idx_asn; i < argc; i++) { -		as = strtoul(argv[i]->arg, NULL, 10); - +		if (!asn_str2asn(argv[i]->arg, &as)) { +			vty_out(vty, "%% Invalid confed peer AS value: %s\n", +				argv[i]->arg); +			continue; +		}  		bgp_confederation_peers_remove(bgp, as);  	}  	return CMD_SUCCESS; @@ -4489,11 +4556,13 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,  	} else if (as_str[0] == 'e') {  		as = 0;  		as_type = AS_EXTERNAL; -	} else { -		/* Get AS number.  */ -		as = strtoul(as_str, NULL, 10); -	} +	} else if (!asn_str2asn(as_str, &as)) +		as_type = AS_UNSPECIFIED; +	if (as_type == AS_UNSPECIFIED) { +		vty_out(vty, "%% Invalid peer AS: %s\n", as_str); +		return CMD_WARNING_CONFIG_FAILED; +	}  	/* If peer is peer group or interface peer, call proper function. */  	ret = str2sockunion(peer_str, &su);  	if (ret < 0) { @@ -4502,11 +4571,12 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,  		/* Check if existing interface peer */  		peer = peer_lookup_by_conf_if(bgp, peer_str); -		ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type); +		ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type, as_str);  		/* if not interface peer, check peer-group settings */  		if (ret < 0 && !peer) { -			ret = peer_group_remote_as(bgp, peer_str, &as, as_type); +			ret = peer_group_remote_as(bgp, peer_str, &as, as_type, +						   as_str);  			if (ret < 0) {  				vty_out(vty,  					"%% Create the peer-group or interface first\n"); @@ -4520,7 +4590,7 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,  				"%% Can not configure the local system as neighbor\n");  			return CMD_WARNING_CONFIG_FAILED;  		} -		ret = peer_remote_as(bgp, &su, NULL, &as, as_type); +		ret = peer_remote_as(bgp, &su, NULL, &as, as_type, as_str);  	}  	return bgp_vty_return(vty, ret); @@ -4591,7 +4661,7 @@ ALIAS(no_bgp_shutdown, no_bgp_shutdown_msg_cmd,  DEFUN (neighbor_remote_as,         neighbor_remote_as_cmd, -       "neighbor <A.B.C.D|X:X::X:X|WORD> remote-as <(1-4294967295)|internal|external>", +       "neighbor <A.B.C.D|X:X::X:X|WORD> remote-as <ASNUM|internal|external>",         NEIGHBOR_STR         NEIGHBOR_ADDR_STR2         "Specify a BGP neighbor\n" @@ -4671,18 +4741,19 @@ static int peer_conf_interface_get(struct vty *vty, const char *conf_if,  			as_type = AS_EXTERNAL;  		} else {  			/* Get AS number.  */ -			as = strtoul(as_str, NULL, 10); -			as_type = AS_SPECIFIED; +			if (asn_str2asn(as_str, &as)) +				as_type = AS_SPECIFIED;  		}  	}  	peer = peer_lookup_by_conf_if(bgp, conf_if);  	if (peer) {  		if (as_str) -			ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type); +			ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type, +					     as_str);  	} else {  		peer = peer_create(NULL, conf_if, bgp, bgp->as, as, as_type, -				   NULL, true); +				   NULL, true, as_str);  		if (!peer) {  			vty_out(vty, "%% BGP failed to create peer\n"); @@ -4784,7 +4855,7 @@ DEFUN (neighbor_interface_config_v6only,  DEFUN (neighbor_interface_config_remote_as,         neighbor_interface_config_remote_as_cmd, -       "neighbor WORD interface remote-as <(1-4294967295)|internal|external>", +       "neighbor WORD interface remote-as <ASNUM|internal|external>",         NEIGHBOR_STR         "Interface name or neighbor tag\n"         "Enable BGP on interface\n" @@ -4801,7 +4872,7 @@ DEFUN (neighbor_interface_config_remote_as,  DEFUN (neighbor_interface_v6only_config_remote_as,         neighbor_interface_v6only_config_remote_as_cmd, -       "neighbor WORD interface v6only remote-as <(1-4294967295)|internal|external>", +       "neighbor WORD interface v6only remote-as <ASNUM|internal|external>",         NEIGHBOR_STR         "Interface name or neighbor tag\n"         "Enable BGP with v6 link-local only\n" @@ -4970,7 +5041,7 @@ DEFUN (no_neighbor_peer_group,  DEFUN (no_neighbor_interface_peer_group_remote_as,         no_neighbor_interface_peer_group_remote_as_cmd, -       "no neighbor WORD remote-as <(1-4294967295)|internal|external>", +       "no neighbor WORD remote-as <ASNUM|internal|external>",         NO_STR         NEIGHBOR_STR         "Interface name or neighbor tag\n" @@ -4987,7 +5058,7 @@ DEFUN (no_neighbor_interface_peer_group_remote_as,  	/* look up for neighbor by interface name config. */  	peer = peer_lookup_by_conf_if(bgp, argv[idx_word]->arg);  	if (peer) { -		peer_as_change(peer, 0, AS_UNSPECIFIED); +		peer_as_change(peer, 0, AS_UNSPECIFIED, NULL);  		return CMD_SUCCESS;  	} @@ -5003,11 +5074,11 @@ DEFUN (no_neighbor_interface_peer_group_remote_as,  DEFUN (neighbor_local_as,         neighbor_local_as_cmd, -       "neighbor <A.B.C.D|X:X::X:X|WORD> local-as (1-4294967295)", +       "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM",         NEIGHBOR_STR         NEIGHBOR_ADDR_STR2         "Specify a local-as number\n" -       "AS number used as local AS\n") +       "AS number expressed in dotted or plain format used as local AS\n")  {  	int idx_peer = 1;  	int idx_number = 3; @@ -5019,18 +5090,23 @@ DEFUN (neighbor_local_as,  	if (!peer)  		return CMD_WARNING_CONFIG_FAILED; -	as = strtoul(argv[idx_number]->arg, NULL, 10); -	ret = peer_local_as_set(peer, as, 0, 0); +	if (!asn_str2asn(argv[idx_number]->arg, &as)) { +		vty_out(vty, "%% Invalid neighbor local-as value: %s\n", +			argv[idx_number]->arg); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	ret = peer_local_as_set(peer, as, 0, 0, argv[idx_number]->arg);  	return bgp_vty_return(vty, ret);  }  DEFUN (neighbor_local_as_no_prepend,         neighbor_local_as_no_prepend_cmd, -       "neighbor <A.B.C.D|X:X::X:X|WORD> local-as (1-4294967295) no-prepend", +       "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM no-prepend",         NEIGHBOR_STR         NEIGHBOR_ADDR_STR2         "Specify a local-as number\n" -       "AS number used as local AS\n" +       "AS number expressed in dotted or plain format used as local AS\n"         "Do not prepend local-as to updates from ebgp peers\n")  {  	int idx_peer = 1; @@ -5043,18 +5119,23 @@ DEFUN (neighbor_local_as_no_prepend,  	if (!peer)  		return CMD_WARNING_CONFIG_FAILED; -	as = strtoul(argv[idx_number]->arg, NULL, 10); -	ret = peer_local_as_set(peer, as, 1, 0); +	if (!asn_str2asn(argv[idx_number]->arg, &as)) { +		vty_out(vty, "%% Invalid neighbor local-as value: %s\n", +			argv[idx_number]->arg); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	ret = peer_local_as_set(peer, as, 1, 0, argv[idx_number]->arg);  	return bgp_vty_return(vty, ret);  }  DEFUN (neighbor_local_as_no_prepend_replace_as,         neighbor_local_as_no_prepend_replace_as_cmd, -       "neighbor <A.B.C.D|X:X::X:X|WORD> local-as (1-4294967295) no-prepend replace-as", +       "neighbor <A.B.C.D|X:X::X:X|WORD> local-as ASNUM no-prepend replace-as",         NEIGHBOR_STR         NEIGHBOR_ADDR_STR2         "Specify a local-as number\n" -       "AS number used as local AS\n" +       "AS number expressed in dotted or plain format used as local AS\n"         "Do not prepend local-as to updates from ebgp peers\n"         "Do not prepend local-as to updates from ibgp peers\n")  { @@ -5068,19 +5149,24 @@ DEFUN (neighbor_local_as_no_prepend_replace_as,  	if (!peer)  		return CMD_WARNING_CONFIG_FAILED; -	as = strtoul(argv[idx_number]->arg, NULL, 10); -	ret = peer_local_as_set(peer, as, 1, 1); +	if (!asn_str2asn(argv[idx_number]->arg, &as)) { +		vty_out(vty, "%% Invalid neighbor local-as value: %s\n", +			argv[idx_number]->arg); +		return CMD_WARNING_CONFIG_FAILED; +	} + +	ret = peer_local_as_set(peer, as, 1, 1, argv[idx_number]->arg);  	return bgp_vty_return(vty, ret);  }  DEFUN (no_neighbor_local_as,         no_neighbor_local_as_cmd, -       "no neighbor <A.B.C.D|X:X::X:X|WORD> local-as [(1-4294967295) [no-prepend [replace-as]]]", +       "no neighbor <A.B.C.D|X:X::X:X|WORD> local-as [ASNUM [no-prepend [replace-as]]]",         NO_STR         NEIGHBOR_STR         NEIGHBOR_ADDR_STR2         "Specify a local-as number\n" -       "AS number used as local AS\n" +       "AS number expressed in dotted or plain format used as local AS\n"         "Do not prepend local-as to updates from ebgp peers\n"         "Do not prepend local-as to updates from ibgp peers\n")  { @@ -9020,10 +9106,13 @@ DEFPY (af_rd_vpn_export,  			   bgp_get_default(), bgp);  	if (yes) { +		bgp->vpn_policy[afi].tovpn_rd_pretty = +			XSTRDUP(MTYPE_BGP, rd_str);  		bgp->vpn_policy[afi].tovpn_rd = prd;  		SET_FLAG(bgp->vpn_policy[afi].flags,  			 BGP_VPN_POLICY_TOVPN_RD_SET);  	} else { +		XFREE(MTYPE_BGP, bgp->vpn_policy[afi].tovpn_rd_pretty);  		UNSET_FLAG(bgp->vpn_policy[afi].flags,  			   BGP_VPN_POLICY_TOVPN_RD_SET);  	} @@ -9548,7 +9637,8 @@ DEFPY(af_import_vrf_route_map, af_import_vrf_route_map_cmd,  		/* Auto-create assuming the same AS */  		ret = bgp_get_vty(&bgp_default, &as, NULL, -				  BGP_INSTANCE_TYPE_DEFAULT); +				  BGP_INSTANCE_TYPE_DEFAULT, NULL, +				  ASNOTATION_UNDEFINED);  		if (ret) {  			vty_out(vty, @@ -9660,7 +9750,8 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,  	if (!bgp_default) {  		/* Auto-create assuming the same AS */  		ret = bgp_get_vty(&bgp_default, &as, NULL, -				  BGP_INSTANCE_TYPE_DEFAULT); +				  BGP_INSTANCE_TYPE_DEFAULT, NULL, +				  ASNOTATION_UNDEFINED);  		if (ret) {  			vty_out(vty, @@ -9675,8 +9766,8 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,  			vrf_bgp = bgp_default;  		else  			/* Auto-create assuming the same AS */ -			ret = bgp_get_vty(&vrf_bgp, &as, import_name, bgp_type); - +			ret = bgp_get_vty(&vrf_bgp, &as, import_name, bgp_type, +					  NULL, ASNOTATION_UNDEFINED);  		if (ret) {  			vty_out(vty,  				"VRF %s is not configured as a bgp instance\n", @@ -10144,7 +10235,7 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,  /* one clear bgp command to rule them all */  DEFUN (clear_ip_bgp_all,         clear_ip_bgp_all_cmd, -       "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|(1-4294967295)|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats>]", +       "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|ASNUM|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats>]",         CLEAR_STR         IP_STR         BGP_STR @@ -10157,7 +10248,7 @@ DEFUN (clear_ip_bgp_all,         "BGP IPv4 neighbor to clear\n"         "BGP IPv6 neighbor to clear\n"         "BGP neighbor on interface to clear\n" -       "Clear peers with the AS number\n" +       "Clear peers with the AS number in plain or dotted format\n"         "Clear all external peers\n"         "Clear all members of peer-group\n"         "BGP peer-group name\n" @@ -10198,7 +10289,7 @@ DEFUN (clear_ip_bgp_all,  	if (argv_find_and_parse_afi(argv, argc, &idx, &afi))  		argv_find_and_parse_safi(argv, argc, &idx, &safi); -	/* <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group PGNAME> */ +	/* <*|A.B.C.D|X:X::X:X|WORD|ASNUM|external|peer-group PGNAME> */  	if (argv_find(argv, argc, "*", &idx)) {  		clr_sort = clear_all;  	} else if (argv_find(argv, argc, "A.B.C.D", &idx)) { @@ -10217,7 +10308,7 @@ DEFUN (clear_ip_bgp_all,  	} else if (argv_find(argv, argc, "WORD", &idx)) {  		clr_sort = clear_peer;  		clr_arg = argv[idx]->arg; -	} else if (argv_find(argv, argc, "(1-4294967295)", &idx)) { +	} else if (argv_find(argv, argc, "ASNUM", &idx)) {  		clr_sort = clear_as;  		clr_arg = argv[idx]->arg;  	} else if (argv_find(argv, argc, "external", &idx)) { @@ -10355,8 +10446,8 @@ DEFUN (show_bgp_views,  		/* Skip VRFs. */  		if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)  			continue; -		vty_out(vty, "\t%s (AS%u)\n", bgp->name ? bgp->name : "(null)", -			bgp->as); +		vty_out(vty, "\t%s (AS%s)\n", bgp->name ? bgp->name : "(null)", +			bgp->as_pretty);  	}  	return CMD_SUCCESS; @@ -11142,7 +11233,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,  				json_object_string_addf(json, "routerId",  							"%pI4",  							&bgp->router_id); -				json_object_int_add(json, "as", bgp->as); +				asn_asn2json(json, "as", bgp->as, +					     bgp->asnotation);  				json_object_int_add(json, "vrfId", vrf_id_ui);  				json_object_string_add(  					json, "vrfName", @@ -11152,8 +11244,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,  						: bgp->name);  			} else {  				vty_out(vty, -					"BGP router identifier %pI4, local AS number %u vrf-id %d", -					&bgp->router_id, bgp->as, +					"BGP router identifier %pI4, local AS number %s vrf-id %d", +					&bgp->router_id, bgp->as_pretty,  					bgp->vrf_id == VRF_UNKNOWN  						? -1  						: (int)bgp->vrf_id); @@ -11387,12 +11479,13 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,  					json_object_string_add(json_peer, "domainname",  							       peer->domainname); -				json_object_int_add(json_peer, "remoteAs", peer->as); -				json_object_int_add( -					json_peer, "localAs", -					peer->change_local_as -						? peer->change_local_as -						: peer->local_as); +				asn_asn2json(json_peer, "remoteAs", peer->as, +					     bgp->asnotation); +				asn_asn2json(json_peer, "localAs", +					     peer->change_local_as +						     ? peer->change_local_as +						     : peer->local_as, +					     bgp->asnotation);  				json_object_int_add(json_peer, "version", 4);  				json_object_int_add(json_peer, "msgRcvd",  						    PEER_TOTAL_RX(peer)); @@ -11572,14 +11665,19 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,  					&peer->ibuf->count,  					memory_order_relaxed); -				if (show_wide) +				vty_out(vty, "4 "); +				vty_out(vty, ASN_FORMAT_SPACE(bgp->asnotation), +					&peer->as); +				if (show_wide) {  					vty_out(vty, -						"4 %10u %10u %9u %9u %8" PRIu64 -						" %4zu %4zu %8s", -						peer->as, +						ASN_FORMAT_SPACE( +							bgp->asnotation),  						peer->change_local_as -							? peer->change_local_as -							: peer->local_as, +							? &peer->change_local_as +							: &peer->local_as); +					vty_out(vty, +						" %9u %9u %8" PRIu64 +						" %4zu %4zu %8s",  						PEER_TOTAL_RX(peer),  						PEER_TOTAL_TX(peer),  						peer->version[afi][safi], @@ -11588,10 +11686,11 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,  							    timebuf,  							    BGP_UPTIME_LEN, 0,  							    NULL)); -				else -					vty_out(vty, "4 %10u %9u %9u %8" PRIu64 -						     " %4zu %4zu %8s", -						peer->as, PEER_TOTAL_RX(peer), +				} else { +					vty_out(vty, +						" %9u %9u %8" PRIu64 +						" %4zu %4zu %8s", +						PEER_TOTAL_RX(peer),  						PEER_TOTAL_TX(peer),  						peer->version[afi][safi],  						inq_count, outq_count, @@ -11599,7 +11698,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,  							    timebuf,  							    BGP_UPTIME_LEN, 0,  							    NULL)); - +				}  				if (peer_established(peer)) {  					if (peer->afc_recv[afi][safi]) {  						if (CHECK_FLAG( @@ -11892,7 +11991,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,  DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd,        "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR        " [" BGP_SAFI_WITH_LABEL_CMD_STR -      "]] [all$all] summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json$uj]", +      "]] [all$all] summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <ASNUM|internal|external>>] [terse] [wide] [json$uj]",        SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR  	      BGP_SAFI_WITH_LABEL_HELP_STR        "Display the entries for all address families\n" @@ -11903,8 +12002,7 @@ DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd,        "Neighbor to display information about\n"        "Neighbor to display information about\n"        "Neighbor on BGP configured interface\n" -      "Show only the specified remote AS sessions\n" -      "AS number\n" +      "Show only the specified remote AS sessions\n" AS_STR        "Internal (iBGP) AS sessions\n"        "External (eBGP) AS sessions\n"        "Shorten the information on BGP instances\n" @@ -11946,8 +12044,12 @@ DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd,  			as_type = AS_INTERNAL;  		else if (argv[idx + 1]->arg[0] == 'e')  			as_type = AS_EXTERNAL; -		else -			as = (as_t)atoi(argv[idx + 1]->arg); +		else if (!asn_str2asn(argv[idx + 1]->arg, &as)) { +			vty_out(vty, +				"%% Invalid neighbor remote-as value: %s\n", +				argv[idx + 1]->arg); +			return CMD_SUCCESS; +		}  	}  	if (argv_find(argv, argc, "terse", &idx)) @@ -13082,13 +13184,14 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,  			json_object_string_addf(json_neigh, "bgpNeighborAddr",  						"%pSU", &p->su); -		json_object_int_add(json_neigh, "remoteAs", p->as); +		asn_asn2json(json_neigh, "remoteAs", p->as, bgp->asnotation);  		if (p->change_local_as) -			json_object_int_add(json_neigh, "localAs", -					    p->change_local_as); +			asn_asn2json(json_neigh, "localAs", p->change_local_as, +				     bgp->asnotation);  		else -			json_object_int_add(json_neigh, "localAs", p->local_as); +			asn_asn2json(json_neigh, "localAs", p->local_as, +				     bgp->asnotation);  		if (CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))  			json_object_boolean_true_add(json_neigh, @@ -13098,13 +13201,19 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,  			json_object_boolean_true_add(json_neigh,  						     "localAsReplaceAs");  	} else { -		if ((p->as_type == AS_SPECIFIED) || (p->as_type == AS_EXTERNAL) -		    || (p->as_type == AS_INTERNAL)) -			vty_out(vty, "remote AS %u, ", p->as); -		else +		if ((p->as_type == AS_SPECIFIED) || +		    (p->as_type == AS_EXTERNAL) || +		    (p->as_type == AS_INTERNAL)) { +			vty_out(vty, "remote AS "); +			vty_out(vty, ASN_FORMAT(bgp->asnotation), &p->as); +			vty_out(vty, ", "); +		} else  			vty_out(vty, "remote AS Unspecified, "); -		vty_out(vty, "local AS %u%s%s, ", -			p->change_local_as ? p->change_local_as : p->local_as, +		vty_out(vty, "local AS "); +		vty_out(vty, ASN_FORMAT(bgp->asnotation), +			p->change_local_as ? &p->change_local_as +					   : &p->local_as); +		vty_out(vty, "%s%s, ",  			CHECK_FLAG(p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)  				? " no-prepend"  				: "", @@ -15577,10 +15686,9 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,  						json_object_new_string(vname));  			json_object_object_add(json, "exportToVrfs",  					       json_export_vrfs); -			json_object_string_addf(json, "routeDistinguisher", -						"%pRD", -						&bgp->vpn_policy[afi].tovpn_rd); - +			json_object_string_addf( +				json, "routeDistinguisher", "%s", +				bgp->vpn_policy[afi].tovpn_rd_pretty);  			dir = BGP_VPN_POLICY_DIR_TOVPN;  			if (bgp->vpn_policy[afi].rtlist[dir]) {  				ecom_str = ecommunity_ecom2str( @@ -15648,8 +15756,10 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,  						node, vname))  				vty_out(vty, "  %s\n", vname); -			vty_out(vty, "RD: %pRD\n", +			vty_out(vty, "RD: "); +			vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),  				&bgp->vpn_policy[afi].tovpn_rd); +			vty_out(vty, "\n");  			dir = BGP_VPN_POLICY_DIR_TOVPN;  			if (bgp->vpn_policy[afi].rtlist[dir]) { @@ -16014,18 +16124,22 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group,  	if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) {  		if (json) -			json_object_int_add(json_peer_group, "remoteAs", -					    conf->as); -		else -			vty_out(vty, "\nBGP peer-group %s, remote AS %u\n", -				group->name, conf->as); +			asn_asn2json(json_peer_group, "remoteAs", conf->as, +				     bgp_get_asnotation(conf->bgp)); +		else { +			vty_out(vty, "\nBGP peer-group %s, remote AS ", +				group->name); +			vty_out(vty, ASN_FORMAT(bgp_get_asnotation(conf->bgp)), +				&conf->as); +			vty_out(vty, "\n"); +		}  	} else if (conf->as_type == AS_INTERNAL) {  		if (json) -			json_object_int_add(json_peer_group, "remoteAs", -					    group->bgp->as); +			asn_asn2json(json, "remoteAs", group->bgp->as, +				     group->bgp->asnotation);  		else -			vty_out(vty, "\nBGP peer-group %s, remote AS %u\n", -				group->name, group->bgp->as); +			vty_out(vty, "\nBGP peer-group %s, remote AS %s\n", +				group->name, group->bgp->as_pretty);  	} else {  		if (!json)  			vty_out(vty, "\nBGP peer-group %s\n", group->name); @@ -17148,8 +17262,8 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,  	}  	if (CHECK_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET)) -		vty_out(vty, "%*srd vpn export %pRD\n", indent, "", -			&bgp->vpn_policy[afi].tovpn_rd); +		vty_out(vty, "%*srd vpn export %s\n", indent, "", +			bgp->vpn_policy[afi].tovpn_rd_pretty);  	if (CHECK_FLAG(bgp->vpn_policy[afi].flags,  		       BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) { @@ -17319,7 +17433,7 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,  			vty_out(vty, " peer-group %s", peer->group->name);  			if_pg_printed = true;  		} else if (peer->as_type == AS_SPECIFIED) { -			vty_out(vty, " remote-as %u", peer->as); +			vty_out(vty, " remote-as %s", peer->as_pretty);  			if_ras_printed = true;  		} else if (peer->as_type == AS_INTERNAL) {  			vty_out(vty, " remote-as internal"); @@ -17339,8 +17453,8 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,  		if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) {  			if (peer->as_type == AS_SPECIFIED) { -				vty_out(vty, " neighbor %s remote-as %u\n", -					addr, peer->as); +				vty_out(vty, " neighbor %s remote-as %s\n", +					addr, peer->as_pretty);  			} else if (peer->as_type == AS_INTERNAL) {  				vty_out(vty,  					" neighbor %s remote-as internal\n", @@ -17368,8 +17482,8 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,  		if (!if_ras_printed) {  			if (peer->as_type == AS_SPECIFIED) { -				vty_out(vty, " neighbor %s remote-as %u\n", -					addr, peer->as); +				vty_out(vty, " neighbor %s remote-as %s\n", +					addr, peer->as_pretty);  			} else if (peer->as_type == AS_INTERNAL) {  				vty_out(vty,  					" neighbor %s remote-as internal\n", @@ -17384,8 +17498,8 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,  	/* local-as */  	if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS)) { -		vty_out(vty, " neighbor %s local-as %u", addr, -			peer->change_local_as); +		vty_out(vty, " neighbor %s local-as %s", addr, +			peer->change_local_as_pretty);  		if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND))  			vty_out(vty, " no-prepend");  		if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS)) @@ -18066,12 +18180,16 @@ int bgp_config_write(struct vty *vty)  			continue;  		/* Router bgp ASN */ -		vty_out(vty, "router bgp %u", bgp->as); +		vty_out(vty, "router bgp %s", bgp->as_pretty);  		if (bgp->name)  			vty_out(vty, " %s %s",  				(bgp->inst_type  == BGP_INSTANCE_TYPE_VIEW)  				? "view" : "vrf", bgp->name); +		if (CHECK_FLAG(bgp->config, BGP_CONFIG_ASNOTATION)) +			vty_out(vty, " as-notation %s", +				asn_mode2str(bgp->asnotation)); +  		vty_out(vty, "\n");  		/* BGP fast-external-failover. */ @@ -18189,8 +18307,8 @@ int bgp_config_write(struct vty *vty)  		/* Confederation identifier*/  		if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) -			vty_out(vty, " bgp confederation identifier %u\n", -				bgp->confed_id); +			vty_out(vty, " bgp confederation identifier %s\n", +				bgp->confed_id_pretty);  		/* Confederation peer */  		if (bgp->confed_peers_cnt > 0) { @@ -18199,7 +18317,8 @@ int bgp_config_write(struct vty *vty)  			vty_out(vty, " bgp confederation peers");  			for (i = 0; i < bgp->confed_peers_cnt; i++) -				vty_out(vty, " %u", bgp->confed_peers[i]); +				vty_out(vty, " %s", +					bgp->confed_peers[i].as_pretty);  			vty_out(vty, "\n");  		} diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 56485035e8..1c5adff68d 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -135,7 +135,8 @@ extern void bgp_vty_init(void);  extern void community_alias_vty(void);  extern const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);  extern int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name, -		       enum bgp_instance_type inst_type); +		       enum bgp_instance_type inst_type, const char *as_pretty, +		       enum asnotation_mode asnotation);  extern void bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp);  extern void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);  extern void bgp_config_write_rpkt_quanta(struct vty *vty, struct bgp *bgp); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 9ea5a92adc..09d7944aec 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -553,7 +553,7 @@ void bgp_tcp_keepalive_unset(struct bgp *bgp)  }  /* BGP confederation configuration.  */ -void bgp_confederation_id_set(struct bgp *bgp, as_t as) +void bgp_confederation_id_set(struct bgp *bgp, as_t as, const char *as_str)  {  	struct peer *peer;  	struct listnode *node, *nnode; @@ -565,6 +565,9 @@ void bgp_confederation_id_set(struct bgp *bgp, as_t as)  	/* Remember - were we doing confederation before? */  	already_confed = bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION);  	bgp->confed_id = as; +	if (bgp->confed_id_pretty) +		XFREE(MTYPE_BGP, bgp->confed_id_pretty); +	bgp->confed_id_pretty = XSTRDUP(MTYPE_BGP, as_str);  	bgp_config_set(bgp, BGP_CONFIG_CONFEDERATION);  	/* If we were doing confederation already, this is just an external @@ -617,6 +620,7 @@ void bgp_confederation_id_unset(struct bgp *bgp)  	struct listnode *node, *nnode;  	bgp->confed_id = 0; +	XFREE(MTYPE_BGP, bgp->confed_id_pretty);  	bgp_config_unset(bgp, BGP_CONFIG_CONFEDERATION);  	for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { @@ -644,14 +648,14 @@ bool bgp_confederation_peers_check(struct bgp *bgp, as_t as)  		return false;  	for (i = 0; i < bgp->confed_peers_cnt; i++) -		if (bgp->confed_peers[i] == as) +		if (bgp->confed_peers[i].as == as)  			return true;  	return false;  }  /* Add an AS to the confederation set.  */ -void bgp_confederation_peers_add(struct bgp *bgp, as_t as) +void bgp_confederation_peers_add(struct bgp *bgp, as_t as, const char *as_str)  {  	struct peer *peer;  	struct listnode *node, *nnode; @@ -662,11 +666,13 @@ void bgp_confederation_peers_add(struct bgp *bgp, as_t as)  	if (bgp_confederation_peers_check(bgp, as))  		return; -	bgp->confed_peers = -		XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers, -			 (bgp->confed_peers_cnt + 1) * sizeof(as_t)); +	bgp->confed_peers = XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers, +				     (bgp->confed_peers_cnt + 1) * +					     sizeof(struct as_confed)); -	bgp->confed_peers[bgp->confed_peers_cnt] = as; +	bgp->confed_peers[bgp->confed_peers_cnt].as = as; +	bgp->confed_peers[bgp->confed_peers_cnt].as_pretty = +		XSTRDUP(MTYPE_BGP, as_str);  	bgp->confed_peers_cnt++;  	if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) { @@ -703,9 +709,15 @@ void bgp_confederation_peers_remove(struct bgp *bgp, as_t as)  		return;  	for (i = 0; i < bgp->confed_peers_cnt; i++) -		if (bgp->confed_peers[i] == as) -			for (j = i + 1; j < bgp->confed_peers_cnt; j++) -				bgp->confed_peers[j - 1] = bgp->confed_peers[j]; +		if (bgp->confed_peers[i].as == as) { +			XFREE(MTYPE_BGP, bgp->confed_peers[i].as_pretty); +			for (j = i + 1; j < bgp->confed_peers_cnt; j++) { +				bgp->confed_peers[j - 1].as = +					bgp->confed_peers[j].as; +				bgp->confed_peers[j - 1].as_pretty = +					bgp->confed_peers[j].as_pretty; +			} +		}  	bgp->confed_peers_cnt--; @@ -714,9 +726,9 @@ void bgp_confederation_peers_remove(struct bgp *bgp, as_t as)  			XFREE(MTYPE_BGP_CONFED_LIST, bgp->confed_peers);  		bgp->confed_peers = NULL;  	} else -		bgp->confed_peers = -			XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers, -				 bgp->confed_peers_cnt * sizeof(as_t)); +		bgp->confed_peers = XREALLOC( +			MTYPE_BGP_CONFED_LIST, bgp->confed_peers, +			bgp->confed_peers_cnt * sizeof(struct as_confed));  	/* Now reset any peer who's remote AS has just been removed from the  	   CONFED */ @@ -1172,6 +1184,11 @@ static void peer_free(struct peer *peer)  	FOREACH_AFI_SAFI (afi, safi)  		bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_NONE); +	if (peer->change_local_as_pretty) +		XFREE(MTYPE_BGP, peer->change_local_as_pretty); +	if (peer->as_pretty) +		XFREE(MTYPE_BGP, peer->as_pretty); +  	bgp_unlock(peer->bgp);  	memset(peer, 0, sizeof(struct peer)); @@ -1753,7 +1770,7 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp)  struct peer *peer_create(union sockunion *su, const char *conf_if,  			 struct bgp *bgp, as_t local_as, as_t remote_as,  			 int as_type, struct peer_group *group, -			 bool config_node) +			 bool config_node, const char *as_str)  {  	int active;  	struct peer *peer; @@ -1778,6 +1795,9 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,  	}  	peer->local_as = local_as;  	peer->as = remote_as; +	/* internal and external values do not use as_pretty */ +	if (as_str && asn_str2asn(as_str, NULL)) +		peer->as_pretty = XSTRDUP(MTYPE_BGP, as_str);  	peer->as_type = as_type;  	peer->local_id = bgp->router_id;  	peer->v_holdtime = bgp->default_holdtime; @@ -1881,7 +1901,8 @@ bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)  }  /* Change peer's AS number.  */ -void peer_as_change(struct peer *peer, as_t as, int as_specified) +void peer_as_change(struct peer *peer, as_t as, int as_specified, +		    const char *as_str)  {  	enum bgp_peer_sort origtype, newtype; @@ -1896,6 +1917,12 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)  	}  	origtype = peer_sort_lookup(peer);  	peer->as = as; +	if (as_specified == AS_SPECIFIED && as_str) { +		if (peer->as_pretty) +			XFREE(MTYPE_BGP, peer->as_pretty); +		peer->as_pretty = XSTRDUP(MTYPE_BGP, as_str); +	} else if (peer->as_type == AS_UNSPECIFIED && peer->as_pretty) +		XFREE(MTYPE_BGP, peer->as_pretty);  	peer->as_type = as_specified;  	if (bgp_config_check(peer->bgp, BGP_CONFIG_CONFEDERATION) @@ -1953,7 +1980,7 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)  /* If peer does not exist, create new one.  If peer already exists,     set AS number to the peer.  */  int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if, -		   as_t *as, int as_type) +		   as_t *as, int as_type, const char *as_str)  {  	struct peer *peer;  	as_t local_as; @@ -2007,7 +2034,7 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,  		/* Existing peer's AS number change. */  		if (((peer->as_type == AS_SPECIFIED) && peer->as != *as)  		    || (peer->as_type != as_type)) -			peer_as_change(peer, *as, as_type); +			peer_as_change(peer, *as, as_type, as_str);  	} else {  		if (conf_if)  			return BGP_ERR_NO_INTERFACE_CONFIG; @@ -2022,7 +2049,7 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,  			local_as = bgp->as;  		peer_create(su, conf_if, bgp, local_as, *as, as_type, NULL, -			    true); +			    true, as_str);  	}  	return 0; @@ -2047,6 +2074,13 @@ const char *bgp_get_name_by_role(uint8_t role)  	return "unknown";  } +enum asnotation_mode bgp_get_asnotation(struct bgp *bgp) +{ +	if (!bgp) +		return ASNOTATION_PLAIN; +	return bgp->asnotation; +} +  static void peer_group2peer_config_copy_af(struct peer_group *group,  					   struct peer *peer, afi_t afi,  					   safi_t safi) @@ -2804,7 +2838,7 @@ static void peer_group2peer_config_copy(struct peer_group *group,  /* Peer group's remote AS configuration.  */  int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as, -			 int as_type) +			 int as_type, const char *as_str)  {  	struct peer_group *group;  	struct peer *peer; @@ -2820,12 +2854,12 @@ int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as,  	/* When we setup peer-group AS number all peer group member's AS  	   number must be updated to same number.  */ -	peer_as_change(group->conf, *as, as_type); +	peer_as_change(group->conf, *as, as_type, as_str);  	for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {  		if (((peer->as_type == AS_SPECIFIED) && peer->as != *as)  		    || (peer->as_type != as_type)) -			peer_as_change(peer, *as, as_type); +			peer_as_change(peer, *as, as_type, as_str);  	}  	return 0; @@ -3132,7 +3166,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,  		}  		peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as, -				   group->conf->as_type, group, true); +				   group->conf->as_type, group, true, NULL);  		peer = peer_lock(peer); /* group->peer list reference */  		listnode_add(group->peer, peer); @@ -3184,23 +3218,37 @@ static void bgp_vrf_string_name_delete(void *data)  /* BGP instance creation by `router bgp' commands. */  static struct bgp *bgp_create(as_t *as, const char *name, -			      enum bgp_instance_type inst_type) +			      enum bgp_instance_type inst_type, +			      const char *as_pretty, +			      enum asnotation_mode asnotation)  {  	struct bgp *bgp;  	afi_t afi;  	safi_t safi;  	bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp)); +	bgp->as = *as; +	if (as_pretty) +		bgp->as_pretty = XSTRDUP(MTYPE_BGP, as_pretty); +	else +		bgp->as_pretty = XSTRDUP(MTYPE_BGP, asn_asn2asplain(*as)); + +	if (asnotation != ASNOTATION_UNDEFINED) { +		bgp->asnotation = asnotation; +		SET_FLAG(bgp->config, BGP_CONFIG_ASNOTATION); +	} else +		asn_str2asn_notation(bgp->as_pretty, NULL, &bgp->asnotation);  	if (BGP_DEBUG(zebra, ZEBRA)) {  		if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) -			zlog_debug("Creating Default VRF, AS %u", *as); +			zlog_debug("Creating Default VRF, AS %s", +				   bgp->as_pretty);  		else -			zlog_debug("Creating %s %s, AS %u", +			zlog_debug("Creating %s %s, AS %s",  				   (inst_type == BGP_INSTANCE_TYPE_VRF)  					   ? "VRF"  					   : "VIEW", -				   name, *as); +				   name, bgp->as_pretty);  	}  	/* Default the EVPN VRF to the default one */ @@ -3277,7 +3325,6 @@ static struct bgp *bgp_create(as_t *as, const char *name,  	bgp->condition_check_period = DEFAULT_CONDITIONAL_ROUTES_POLL_TIME;  	bgp_addpath_init_bgp_data(&bgp->tx_addpath);  	bgp->fast_convergence = false; -	bgp->as = *as;  	bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME;  #ifdef ENABLE_BGP_VNC @@ -3514,7 +3561,8 @@ int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, const char *name,  /* Called from VTY commands. */  int bgp_get(struct bgp **bgp_val, as_t *as, const char *name, -	    enum bgp_instance_type inst_type) +	    enum bgp_instance_type inst_type, const char *as_pretty, +	    enum asnotation_mode asnotation)  {  	struct bgp *bgp;  	struct vrf *vrf = NULL; @@ -3524,7 +3572,7 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,  	if (ret || *bgp_val)  		return ret; -	bgp = bgp_create(as, name, inst_type); +	bgp = bgp_create(as, name, inst_type, as_pretty, asnotation);  	/*  	 * view instances will never work inside of a vrf @@ -3918,8 +3966,13 @@ void bgp_free(struct bgp *bgp)  		dir = BGP_VPN_POLICY_DIR_TOVPN;  		if (bgp->vpn_policy[afi].rtlist[dir])  			ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]); +		if (bgp->vpn_policy[afi].tovpn_rd_pretty) +			XFREE(MTYPE_BGP, bgp->vpn_policy[afi].tovpn_rd_pretty);  	} +	bgp_confederation_id_unset(bgp); + +	XFREE(MTYPE_BGP, bgp->as_pretty);  	XFREE(MTYPE_BGP, bgp->name);  	XFREE(MTYPE_BGP, bgp->name_pretty);  	XFREE(MTYPE_BGP, bgp->snmp_stats); @@ -4024,7 +4077,7 @@ struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp,  	/* Create peer first; we've already checked group config is valid. */  	peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as, -			   group->conf->as_type, group, true); +			   group->conf->as_type, group, true, NULL);  	if (!peer)  		return NULL; @@ -6228,7 +6281,7 @@ int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi)  }  int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend, -		      bool replace_as) +		      bool replace_as, const char *as_str)  {  	bool old_no_prepend, old_replace_as;  	struct bgp *bgp = peer->bgp; @@ -6253,6 +6306,9 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,  	    && old_replace_as == replace_as)  		return 0;  	peer->change_local_as = as; +	if (as_str) +		peer->change_local_as_pretty = XSTRDUP(MTYPE_BGP, as_str); +  	(void)peer_sort(peer);  	/* Check if handling a regular peer. */ @@ -6286,6 +6342,9 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,  		COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS,  			  replace_as);  		member->change_local_as = as; +		if (as_str) +			member->change_local_as_pretty = +				XSTRDUP(MTYPE_BGP, as_str);  	}  	return 0; @@ -6311,6 +6370,7 @@ int peer_local_as_unset(struct peer *peer)  		peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);  		peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);  		peer->change_local_as = 0; +		XFREE(MTYPE_BGP, peer->change_local_as_pretty);  	}  	/* Check if handling a regular peer. */ @@ -6341,6 +6401,7 @@ int peer_local_as_unset(struct peer *peer)  		UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);  		UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);  		member->change_local_as = 0; +		XFREE(MTYPE_BGP, member->change_local_as_pretty);  		/* Send notification or stop peer depending on state. */  		if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) { @@ -8024,7 +8085,7 @@ static void bgp_instasn_autocomplete(vector comps, struct cmd_token *token)  {  	struct listnode *next, *next2;  	struct bgp *bgp, *bgp2; -	char buf[11]; +	char buf[ASN_STRING_MAX_SIZE];  	for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {  		/* deduplicate */ @@ -8037,7 +8098,7 @@ static void bgp_instasn_autocomplete(vector comps, struct cmd_token *token)  		if (bgp2 != bgp)  			continue; -		snprintf(buf, sizeof(buf), "%u", bgp->as); +		snprintf(buf, sizeof(buf), "%s", bgp->as_pretty);  		vector_set(comps, XSTRDUP(MTYPE_COMPLETION, buf));  	}  } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 91f0de0cea..2a7c7a3143 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -16,6 +16,7 @@  #include "vty.h"  #include "srv6.h"  #include "iana_afi.h" +#include "asn.h"  /* For union sockunion.  */  #include "queue.h" @@ -62,7 +63,6 @@ enum zebra_gr_mode {  };  /* Typedef BGP specific types.  */ -typedef uint32_t as_t;  typedef uint16_t as16_t; /* we may still encounter 16 Bit asnums */  typedef uint16_t bgp_size_t; @@ -203,6 +203,7 @@ struct vpn_policy {  	/* should be mpls_label_t? */  	uint32_t tovpn_label; /* may be MPLS_LABEL_NONE */  	uint32_t tovpn_zebra_vrf_label_last_sent; +	char *tovpn_rd_pretty;  	struct prefix_rd tovpn_rd;  	struct prefix tovpn_nexthop; /* unset => set to 0 */  	uint32_t flags; @@ -324,10 +325,16 @@ struct bgp_srv6_function {  	char locator_name[SRV6_LOCNAME_SIZE];  }; +struct as_confed { +	as_t as; +	char *as_pretty; +}; +  /* BGP instance structure.  */  struct bgp {  	/* AS number of this BGP instance.  */  	as_t as; +	char *as_pretty;  	/* Name of this BGP instance.  */  	char *name; @@ -383,6 +390,7 @@ struct bgp {  	uint16_t config;  #define BGP_CONFIG_CLUSTER_ID             (1 << 0)  #define BGP_CONFIG_CONFEDERATION          (1 << 1) +#define BGP_CONFIG_ASNOTATION             (1 << 2)  	/* BGP router identifier.  */  	struct in_addr router_id; @@ -394,7 +402,8 @@ struct bgp {  	/* BGP confederation information.  */  	as_t confed_id; -	as_t *confed_peers; +	char *confed_id_pretty; +	struct as_confed *confed_peers;  	int confed_peers_cnt;  	struct thread @@ -728,6 +737,7 @@ struct bgp {  	/* RD for this VRF */  	struct prefix_rd vrf_prd; +	char *vrf_prd_pretty;  	/* import rt list for the vrf instance */  	struct list *vrf_import_rtl; @@ -782,6 +792,8 @@ struct bgp {  	bool allow_martian; +	enum asnotation_mode asnotation; +  	QOBJ_FIELDS;  };  DECLARE_QOBJ_TYPE(bgp); @@ -1105,6 +1117,8 @@ struct peer {  	/* Peer's remote AS number. */  	int as_type;  	as_t as; +	/* for vty as format */ +	char *as_pretty;  	/* Peer's local AS number. */  	as_t local_as; @@ -1113,6 +1127,8 @@ struct peer {  	/* Peer's Change local AS number. */  	as_t change_local_as; +	/* for vty as format */ +	char *change_local_as_pretty;  	/* Remote router ID. */  	struct in_addr remote_id; @@ -2131,7 +2147,7 @@ extern void bgp_recalculate_all_bestpaths(struct bgp *bgp);  extern struct peer *peer_create(union sockunion *su, const char *conf_if,  				struct bgp *bgp, as_t local_as, as_t remote_as,  				int as_type, struct peer_group *group, -				bool config_node); +				bool config_node, const char *as_str);  extern struct peer *peer_create_accept(struct bgp *);  extern void peer_xfer_config(struct peer *dst, struct peer *src);  extern char *peer_uptime(time_t uptime2, char *buf, size_t len, bool use_json, @@ -2158,7 +2174,9 @@ extern void bgp_option_norib_set_runtime(void);  /* unset the bgp no-rib option during runtime and reset all peers */  extern void bgp_option_norib_unset_runtime(void); -extern int bgp_get(struct bgp **, as_t *, const char *, enum bgp_instance_type); +extern int bgp_get(struct bgp **bgp, as_t *as, const char *name, +		   enum bgp_instance_type kind, const char *as_pretty, +		   enum asnotation_mode asnotation);  extern void bgp_instance_up(struct bgp *);  extern void bgp_instance_down(struct bgp *);  extern int bgp_delete(struct bgp *); @@ -2174,11 +2192,13 @@ extern void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set);  extern void bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id);  extern void bgp_cluster_id_unset(struct bgp *bgp); -extern void bgp_confederation_id_set(struct bgp *bgp, as_t as); +extern void bgp_confederation_id_set(struct bgp *bgp, as_t as, +				     const char *as_str);  extern void bgp_confederation_id_unset(struct bgp *bgp);  extern bool bgp_confederation_peers_check(struct bgp *, as_t); -extern void bgp_confederation_peers_add(struct bgp *bgp, as_t as); +extern void bgp_confederation_peers_add(struct bgp *bgp, as_t as, +					const char *as_str);  extern void bgp_confederation_peers_remove(struct bgp *bgp, as_t as);  extern void bgp_timers_set(struct bgp *, uint32_t keepalive, uint32_t holdtime, @@ -2199,10 +2219,13 @@ extern void bgp_listen_limit_unset(struct bgp *bgp);  extern bool bgp_update_delay_active(struct bgp *);  extern bool bgp_update_delay_configured(struct bgp *);  extern bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi); -extern void peer_as_change(struct peer *, as_t, int); -extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *, -			  int); -extern int peer_group_remote_as(struct bgp *, const char *, as_t *, int); +extern void peer_as_change(struct peer *peer, as_t as, int as_type, +			   const char *as_str); +extern int peer_remote_as(struct bgp *bgp, union sockunion *su, +			  const char *conf_if, as_t *as, int as_type, +			  const char *as_str); +extern int peer_group_remote_as(struct bgp *bgp, const char *peer_str, as_t *as, +				int as_type, const char *as_str);  extern int peer_delete(struct peer *peer);  extern void peer_notify_unconfig(struct peer *peer);  extern int peer_group_delete(struct peer_group *); @@ -2281,8 +2304,8 @@ extern int peer_distribute_unset(struct peer *, afi_t, safi_t, int);  extern int peer_allowas_in_set(struct peer *, afi_t, safi_t, int, int);  extern int peer_allowas_in_unset(struct peer *, afi_t, safi_t); -extern int peer_local_as_set(struct peer *, as_t, bool no_prepend, -			     bool replace_as); +extern int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend, +			     bool replace_as, const char *as_str);  extern int peer_local_as_unset(struct peer *);  extern int peer_prefix_list_set(struct peer *, afi_t, safi_t, int, @@ -2341,6 +2364,7 @@ extern void peer_tx_shutdown_message_unset(struct peer *);  extern void bgp_route_map_update_timer(struct thread *thread);  extern const char *bgp_get_name_by_role(uint8_t role); +extern enum asnotation_mode bgp_get_asnotation(struct bgp *bgp);  extern void bgp_route_map_terminate(void); diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index 40cb8f8d5a..5b6961d18a 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -410,6 +410,7 @@ DEFUN (vnc_defaults_rd,  	} else { +		/* TODO: save RD format */  		ret = str2prefix_rd(argv[1]->arg, &prd);  		if (!ret) {  			vty_out(vty, "%% Malformed rd\n"); @@ -2874,6 +2875,7 @@ DEFUN (vnc_nve_group_rd,  	} else { +		/* TODO: save RD format */  		ret = str2prefix_rd(argv[1]->arg, &prd);  		if (!ret) {  			vty_out(vty, "%% Malformed rd\n"); @@ -3346,6 +3348,7 @@ DEFUN (vnc_vrf_policy_rd,  	} else { +		/* TODO: save RD format */  		ret = str2prefix_rd(argv[1]->arg, &prd);  		if (!ret) {  			vty_out(vty, "%% Malformed rd\n"); @@ -3924,7 +3927,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)  						value);  				} else -					vty_out(vty, "  rd %pRD\n", &rfg->rd); +					vty_out(vty, "  rd %pRDP\n", &rfg->rd);  			}  			if (rfg->rt_import_list && rfg->rt_export_list @@ -4144,7 +4147,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)  						value);  				} else -					vty_out(vty, "  rd %pRD\n", +					vty_out(vty, "  rd %pRDP\n",  						&hc->default_rd);  			}  			if (hc->default_response_lifetime @@ -4224,7 +4227,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)  							value);  					} else -						vty_out(vty, "  rd %pRD\n", +						vty_out(vty, "  rd %pRDP\n",  							&rfg->rd);  				}  				if (rfg->flags & RFAPI_RFG_RESPONSE_LIFETIME) { diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 0c8fdc72e0..8d6db9d775 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -363,7 +363,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd,  	bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);  	vnc_zlog_debug_verbose( -		"%s: peer=%p, prefix=%pFX, prd=%pRD afi=%d, safi=%d bn=%p, bn->info=%p", +		"%s: peer=%p, prefix=%pFX, prd=%pRDP afi=%d, safi=%d bn=%p, bn->info=%p",  		__func__, peer, p, prd, afi, safi, bn,  		(bn ? bgp_dest_get_bgp_path_info(bn) : NULL)); @@ -1053,7 +1053,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */  	bgp_process(bgp, bn, afi, safi);  	vnc_zlog_debug_any( -		"%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRD)", +		"%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRDP)",  		__func__, safi2str(safi), buf, bn, prd);  done: @@ -3712,7 +3712,7 @@ int rfapi_set_autord_from_vn(struct prefix_rd *rd, struct rfapi_ip_addr *vn)  		memcpy(rd->val + 2, &vn->addr.v6.s6_addr32[3],  		       4); /* low order 4 bytes */  	} -	vnc_zlog_debug_verbose("%s: auto-RD is set to %pRD", __func__, rd); +	vnc_zlog_debug_verbose("%s: auto-RD is set to %pRDP", __func__, rd);  	return 0;  } diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 6d4fc53f83..a504405361 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -2082,7 +2082,7 @@ static void rfapiItBiIndexAdd(struct agg_node *rn, /* Import table VPN node */  	assert(bpi);  	assert(bpi->extra); -	vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRD", __func__, bpi, +	vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRDP", __func__, bpi,  			       bpi->peer, &bpi->extra->vnc.import.rd);  	sl = RFAPI_RDINDEX_W_ALLOC(rn); @@ -2120,7 +2120,9 @@ static void rfapiItBiIndexDump(struct agg_node *rn)  		char buf[RD_ADDRSTRLEN];  		char buf_aux_pfx[PREFIX_STRLEN]; -		prefix_rd2str(&k->extra->vnc.import.rd, buf, sizeof(buf)); +		prefix_rd2str( +			&k->extra->vnc.import.rd, buf, sizeof(buf), +			bgp_get_asnotation(k->peer ? k->peer->bgp : NULL));  		if (k->extra->vnc.import.aux_prefix.family) {  			prefix2str(&k->extra->vnc.import.aux_prefix,  				   buf_aux_pfx, sizeof(buf_aux_pfx)); @@ -2158,7 +2160,7 @@ static struct bgp_path_info *rfapiItBiIndexSearch(  			strlcpy(buf_aux_pfx, "(nil)", sizeof(buf_aux_pfx));  		vnc_zlog_debug_verbose( -			"%s want prd=%pRD, peer=%p, aux_prefix=%s", __func__, +			"%s want prd=%pRDP, peer=%p, aux_prefix=%s", __func__,  			prd, peer, buf_aux_pfx);  		rfapiItBiIndexDump(rn);  	} @@ -2174,7 +2176,7 @@ static struct bgp_path_info *rfapiItBiIndexSearch(  		     bpi_result = bpi_result->next) {  #ifdef DEBUG_BI_SEARCH  			vnc_zlog_debug_verbose( -				"%s: bpi has prd=%pRD, peer=%p", __func__, +				"%s: bpi has prd=%pRDP, peer=%p", __func__,  				&bpi_result->extra->vnc.import.rd,  				bpi_result->peer);  #endif @@ -2238,7 +2240,7 @@ static void rfapiItBiIndexDel(struct agg_node *rn, /* Import table VPN node */  	struct skiplist *sl;  	int rc; -	vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRD", __func__, bpi, +	vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRDP", __func__, bpi,  			       bpi->peer, &bpi->extra->vnc.import.rd);  	sl = RFAPI_RDINDEX(rn); diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index b15620741b..f727f24f1d 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -1114,7 +1114,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,  				skiplist_insert(slRibPt, &ori->rk, ori);  				vnc_zlog_debug_verbose( -					"%s:   nomatch lPendCost item %p in slRibPt, added (rd=%pRD)", +					"%s:   nomatch lPendCost item %p in slRibPt, added (rd=%pRDP)",  					__func__, ri, &ori->rk.rd);  			} @@ -1356,7 +1356,7 @@ callback:  					ri->last_sent_time = monotime(NULL);  #if DEBUG_RIB_SL_RD  					vnc_zlog_debug_verbose( -						"%s: move route to recently deleted list, rd=%pRD", +						"%s: move route to recently deleted list, rd=%pRDP",  						__func__, &ri->rk.rd);  #endif @@ -2252,7 +2252,7 @@ static int print_rib_sl(int (*fp)(void *, const char *, ...), struct vty *vty,  		}  #endif -		fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %pRD\n", +		fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %pRDP\n",  		   deleted ? 'r' : ' ', *printedprefix ? "" : str_pfx, str_vn,  		   str_un, ri->cost, str_lifetime, str_age, &ri->rk.rd); diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 0144c28d58..2b768b8f8d 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -1589,7 +1589,7 @@ void rfapiPrintDescriptor(struct vty *vty, struct rfapi_descriptor *rfd)  	vty_out(vty, " ");  	rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr);  	vty_out(vty, " %p %p ", rfd->response_cb, rfd->cookie); -	vty_out(vty, "%pRD", &rfd->rd); +	vty_out(vty, "%pRDP", &rfd->rd);  	vty_out(vty, " %d", rfd->response_lifetime);  	vty_out(vty, " %s", (rfd->rfg ? rfd->rfg->name : "<orphaned>"));  	vty_out(vty, "%s", HVTYNL); @@ -4709,6 +4709,7 @@ static int vnc_add_vrf_prefix(struct vty *vty, const char *arg_vrf,  	if (arg_rd) {  		opt = &optary[cur_opt++];  		opt->type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD; +		/* TODO: save RD format */  		if (!str2prefix_rd(arg_rd, &opt->v.internal_rd)) {  			vty_out(vty, "Malformed RD \"%s\"\n", arg_rd);  			return CMD_WARNING_CONFIG_FAILED; diff --git a/doc/developer/cli.rst b/doc/developer/cli.rst index 5d1dda06df..2a08531bd7 100644 --- a/doc/developer/cli.rst +++ b/doc/developer/cli.rst @@ -151,6 +151,7 @@ by the parser.                           : RANGE                           : MAC                           : MAC_PREFIX +                         : ASNUM     selector: "<" `selector_seq_seq` ">" `varname_token`             : "{" `selector_seq_seq` "}" `varname_token`             : "[" `selector_seq_seq` "]" `varname_token` @@ -176,27 +177,29 @@ parser, but this is merely a dumb copy job.  Here is a brief summary of the various token types along with examples. -+-----------------+-------------------+-------------------------------------------------------------+ -| Token type      | Syntax            | Description                                                 | -+=================+===================+=============================================================+ -| ``WORD``        | ``show ip bgp``   | Matches itself. In the given example every token is a WORD. | -+-----------------+-------------------+-------------------------------------------------------------+ -| ``IPV4``        | ``A.B.C.D``       | Matches an IPv4 address.                                    | -+-----------------+-------------------+-------------------------------------------------------------+ -| ``IPV6``        | ``X:X::X:X``      | Matches an IPv6 address.                                    | -+-----------------+-------------------+-------------------------------------------------------------+ -| ``IPV4_PREFIX`` | ``A.B.C.D/M``     | Matches an IPv4 prefix in CIDR notation.                    | -+-----------------+-------------------+-------------------------------------------------------------+ -| ``IPV6_PREFIX`` | ``X:X::X:X/M``    | Matches an IPv6 prefix in CIDR notation.                    | -+-----------------+-------------------+-------------------------------------------------------------+ -| ``MAC``         | ``X:X:X:X:X:X``   | Matches a 48-bit mac address.                               | -+-----------------+-------------------+-------------------------------------------------------------+ -| ``MAC_PREFIX``  | ``X:X:X:X:X:X/M`` | Matches a 48-bit mac address with a mask.                   | -+-----------------+-------------------+-------------------------------------------------------------+ -| ``VARIABLE``    | ``FOOBAR``        | Matches anything.                                           | -+-----------------+-------------------+-------------------------------------------------------------+ -| ``RANGE``       | ``(X-Y)``         | Matches numbers in the range X..Y inclusive.                | -+-----------------+-------------------+-------------------------------------------------------------+ ++-----------------+-------------------------+-------------------------------------------------------+ +| Token type      | Syntax                  | Description                                           | ++=================+=========================+=======================================================+ +| ``WORD``        | ``show ip bgp``         | Matches itself. In the example every token is a WORD. | ++-----------------+-------------------------+-------------------------------------------------------+ +| ``IPV4``        | ``A.B.C.D``             | Matches an IPv4 address.                              | ++-----------------+-------------------------+-------------------------------------------------------+ +| ``IPV6``        | ``X:X::X:X``            | Matches an IPv6 address.                              | ++-----------------+-------------------------+-------------------------------------------------------+ +| ``IPV4_PREFIX`` | ``A.B.C.D/M``           | Matches an IPv4 prefix in CIDR notation.              | ++-----------------+-------------------------+-------------------------------------------------------+ +| ``IPV6_PREFIX`` | ``X:X::X:X/M``          | Matches an IPv6 prefix in CIDR notation.              | ++-----------------+-------------------------+-------------------------------------------------------+ +| ``MAC``         | ``X:X:X:X:X:X``         | Matches a 48-bit mac address.                         | ++-----------------+-------------------------+-------------------------------------------------------+ +| ``MAC_PREFIX``  | ``X:X:X:X:X:X/M``       | Matches a 48-bit mac address with a mask.             | ++-----------------+-------------------------+-------------------------------------------------------+ +| ``VARIABLE``    | ``FOOBAR``              | Matches anything.                                     | ++-----------------+-------------------------+-------------------------------------------------------+ +| ``RANGE``       | ``(X-Y)``               | Matches numbers in the range X..Y inclusive.          | ++-----------------+-------------------------+-------------------------------------------------------+ +| ``ASNUM``       | ``<A.B|(1-4294967295>`` | Matches an AS in plain or dot format.                 | ++-----------------+-------------------------+-------------------------------------------------------+  When presented with user input, the parser will search over all defined  commands in the current context to find a match. It is aware of the various diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index c5319a8e88..e0f1c6266a 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -254,8 +254,9 @@ ASN and Router ID  -----------------  First of all you must configure BGP router with the :clicmd:`router bgp ASN` -command. The AS number is an identifier for the autonomous system. The BGP -protocol uses the AS number for detecting whether the BGP connection is +command. The AS number is an identifier for the autonomous system. The AS +identifier can either be a number or two numbers separated by a period. The +BGP protocol uses the AS identifier for detecting whether the BGP connection is  internal or external.  .. clicmd:: router bgp ASN @@ -4301,6 +4302,26 @@ Segment-Routing IPv6       vpn_policy[AFI_IP].tovpn_sid: none       vpn_policy[AFI_IP6].tovpn_sid: 2001:db8:1:1::200 +AS-notation support +------------------- + +By default, the ASN value output follows how the BGP ASN instance is +expressed in the configuration. Three as-notation outputs are available: + +- plain output: both AS4B and AS2B use a single number. +  ` router bgp 65536`. + +- dot output: AS4B values are using two numbers separated by a period. +  `router bgp 1.1` means that the AS number is 65536. + +- dot+ output: AS2B and AS4B values are using two numbers separated by a +  period. `router bgp 0.5` means that the AS number is 5. + +The below option permits forcing the as-notation output: + +.. clicmd:: router bgp ASN as-notation dot|dot+|plain + +   The chosen as-notation format will override the BGP ASN output.  .. _bgp-route-reflector: diff --git a/lib/asn.c b/lib/asn.c new file mode 100644 index 0000000000..c64666375d --- /dev/null +++ b/lib/asn.c @@ -0,0 +1,260 @@ +/* + * ASN functions + * + * Copyright 2022 6WIND + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <zebra.h> +#include "log.h" +#include "asn.h" + +static bool relax_as_zero; + +static const struct message asnotation_mode_msg[] = { +	{ASNOTATION_PLAIN, "plain"}, +	{ASNOTATION_DOT, "dot"}, +	{ASNOTATION_DOTPLUS, "dot+"}, +	{ASNOTATION_UNDEFINED, "undefined"}, +	{0} +}; + +/* converts a string into an Autonomous system number + * "1.1" => 65536 + * "65500" => 65500 + */ +static bool asn_str2asn_internal(const char *asstring, as_t *asn, +				 const char **next, bool *partial, +				 enum asnotation_mode *mode) +{ +	uint32_t high = 0, low = 0; +	uint64_t temp_val; +	const char *p = asstring; +	bool ret = false; +	uint32_t digit; +	enum asnotation_mode val = ASNOTATION_PLAIN; + +	if (!asstring) +		goto end; + +	if  (!isdigit((unsigned char)*p)) +		goto end; + +	temp_val = 0; +	while (isdigit((unsigned char)*p)) { +		digit = (*p) - '0'; +		temp_val *= 10; +		temp_val += digit; +		if (temp_val > UINT32_MAX) +			/* overflow */ +			goto end; +		p++; +	} +	high = (uint32_t)temp_val; +	if (*p == '.') { /* dot format */ +		p++; +		temp_val = 0; +		if (*p == '\0' && partial) { +			*partial = true; +			goto end; +		} +		while (isdigit((unsigned char)*p)) { +			digit = (*p) - '0'; +			temp_val *= 10; +			temp_val += digit; +			if (temp_val > UINT16_MAX) +				/* overflow */ +				goto end; +			p++; +		} +		low = (uint32_t)temp_val; + +		if (!next && *p != '\0' && !isdigit((unsigned char)*p)) +			goto end; +		/* AS <AS4B>.<AS4B> is forbidden */ +		if (high > UINT16_MAX) +			goto end; +		/* AS 0.0 is authorised for some case only */ +		if (!relax_as_zero && high == 0 && low == 0) { +			if (partial) +				*partial = true; +			goto end; +		} +		if (asn) +			*asn = (high << 16) + low; +		ret = true; +		if (high == 0) +			val = ASNOTATION_DOTPLUS; +		else +			val = ASNOTATION_DOT; +		goto end; +	} +	/* AS 0 is forbidden */ +	if (!relax_as_zero && high == 0) +		goto end; +	if (!asn) { +		ret = true; +		goto end; +	} +	*asn = high; +	ret = true; + end: +	if (next) +		*next = p; +	if (mode) +		*mode = val; +	return ret; +} + +static void asn_asn2asdot(as_t asn, char *asstring, size_t len) +{ +	uint16_t low, high; + +	high = (asn >> 16) & 0xffff; +	low = asn & 0xffff; +	snprintf(asstring, len, "%hu.%hu", high, low); +} + +bool asn_str2asn(const char *asstring, as_t *asn) +{ +	return asn_str2asn_internal(asstring, asn, NULL, NULL, NULL); +} + +const char *asn_asn2asplain(as_t asn) +{ +	static char buf[ASN_STRING_MAX_SIZE]; + +	snprintf(buf, sizeof(buf), "%u", asn); +	return buf; +} + +const char *asn_str2asn_parse(const char *asstring, as_t *asn, bool *found_ptr) +{ +	const char *p = NULL; +	const char **next = &p; +	bool found; + +	found = asn_str2asn_internal(asstring, asn, next, NULL, NULL); +	if (found_ptr) +		*found_ptr = found; +	return *next; +} + +void asn_relax_as_zero(bool relax) +{ +	relax_as_zero = relax; +} + +enum match_type asn_str2asn_match(const char *str) +{ +	bool found, partial = false; + +	found = asn_str2asn_internal(str, NULL, NULL, &partial, NULL); +	if (found && !partial) +		return exact_match; + +	if (partial) +		return partly_match; + +	return no_match; +} + +bool asn_str2asn_notation(const char *asstring, as_t *asn, +			  enum asnotation_mode *asnotation) +{ +	return asn_str2asn_internal(asstring, asn, NULL, NULL, asnotation); +} + +const char *asn_mode2str(enum asnotation_mode asnotation) +{ +	return lookup_msg(asnotation_mode_msg, asnotation, +			  "Unrecognized AS notation mode"); +} + +void asn_asn2json(json_object *json, const char *attr, +		  as_t asn, enum asnotation_mode asnotation) +{ +	static char as_str[ASN_STRING_MAX_SIZE]; + +	if ((asnotation == ASNOTATION_PLAIN) || +	    ((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX)) +		json_object_int_add(json, attr, asn); +	else { +		asn_asn2asdot(asn, as_str, sizeof(as_str)); +		json_object_string_add(json, attr, as_str); +	} +} + +void asn_asn2json_array(json_object *jseg_list, as_t asn, +			enum asnotation_mode asnotation) +{ +	static char as_str[ASN_STRING_MAX_SIZE]; + +	if ((asnotation == ASNOTATION_PLAIN) || +	    ((asnotation == ASNOTATION_DOT) && asn < UINT16_MAX)) +		json_object_array_add(jseg_list, +				      json_object_new_int64(asn)); +	else { +		asn_asn2asdot(asn, as_str, sizeof(as_str)); +		json_array_string_add(jseg_list, as_str); +	} +} + +char *asn_asn2string(const as_t *asn, char *buf, size_t len, +		     enum asnotation_mode asnotation) +{ +	if ((asnotation == ASNOTATION_PLAIN) || +	    ((asnotation == ASNOTATION_DOT) && *asn < UINT16_MAX)) +		snprintf(buf, len, "%u", *asn); +	else +		asn_asn2asdot(*asn, buf, len); +	return buf; +} + +static ssize_t printfrr_asnotation(struct fbuf *buf, struct printfrr_eargs *ea, +				   const void *ptr, +				   enum asnotation_mode asnotation) +{ +	/* for alignemnt up to 33 chars - %33pASD for instance - */ +	char as_str[ASN_STRING_MAX_SIZE*3]; +	const as_t *asn; + +	if (!ptr) +		return bputs(buf, "(null)"); +	asn = ptr; +	asn_asn2string(asn, as_str, sizeof(as_str), asnotation); +	return bputs(buf, as_str); +} + +printfrr_ext_autoreg_p("ASP", printfrr_asplain); +static ssize_t printfrr_asplain(struct fbuf *buf, struct printfrr_eargs *ea, +				const void *ptr) +{ +	return printfrr_asnotation(buf, ea, ptr, ASNOTATION_PLAIN); +} + +printfrr_ext_autoreg_p("ASD", printfrr_asdot); +static ssize_t printfrr_asdot(struct fbuf *buf, struct printfrr_eargs *ea, +				const void *ptr) +{ +	return printfrr_asnotation(buf, ea, ptr, ASNOTATION_DOT); +} + +printfrr_ext_autoreg_p("ASE", printfrr_asdotplus); +static ssize_t printfrr_asdotplus(struct fbuf *buf, struct printfrr_eargs *ea, +				  const void *ptr) +{ +	return printfrr_asnotation(buf, ea, ptr, ASNOTATION_DOTPLUS); +} diff --git a/lib/asn.h b/lib/asn.h new file mode 100644 index 0000000000..81a42c658d --- /dev/null +++ b/lib/asn.h @@ -0,0 +1,81 @@ +/* + * AS number structure + * Copyright 2022 6WIND + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRR_ASN_H +#define _FRR_ASN_H + +#include "zebra.h" +#include "command_match.h" +#include "json.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ASN_STRING_MAX_SIZE	12 + +enum asnotation_mode { +	ASNOTATION_PLAIN = 0, +	ASNOTATION_DOT, +	ASNOTATION_DOTPLUS, +	ASNOTATION_UNDEFINED, +}; + +typedef uint32_t as_t; + +extern bool asn_str2asn(const char *asstring, as_t *asn); +extern const char *asn_asn2asplain(as_t asn); +extern const char *asn_str2asn_parse(const char *asstring, as_t *asn, +				     bool *found_ptr); +extern enum match_type asn_str2asn_match(const char *str); +extern bool asn_str2asn_notation(const char *asstring, as_t *asn, +				 enum asnotation_mode *asnotation); +extern const char *asn_mode2str(enum asnotation_mode asnotation); +void asn_asn2json_array(json_object *jseg_list, as_t asn, +			enum asnotation_mode asnotation); +void asn_asn2json(json_object *jseg_list, const char *attr, +		  as_t asn, enum asnotation_mode asnotation); +extern char *asn_asn2string(const as_t *as, char *buf, size_t len, +			    enum asnotation_mode asnotation); +/* display AS in appropriate format */ +#ifdef _FRR_ATTRIBUTE_PRINTFRR +#pragma FRR printfrr_ext "%pASP"  (as_t *) +#pragma FRR printfrr_ext "%pASD"  (as_t *) +#pragma FRR printfrr_ext "%pASE"  (as_t *) +#endif + +#define ASN_FORMAT(mode)  \ +	((mode == ASNOTATION_DOT) ? "%pASD" :	    \ +	 ((mode == ASNOTATION_DOTPLUS) ? "%pASE" :	\ +	  "%pASP")) +#define ASN_FORMAT_SPACE(mode)		    \ +	((mode == ASNOTATION_DOT) ? "%10pASD" :	    \ +	 ((mode == ASNOTATION_DOTPLUS) ? "%10pASE" :	\ +	  "%10pASP")) + +/* for test */ +extern void asn_relax_as_zero(bool relax); + +#ifdef __cplusplus +} +#endif + +#endif /* _FRR_ASN_H */ diff --git a/lib/command.c b/lib/command.c index cf96df6f95..ee5a3889e8 100644 --- a/lib/command.c +++ b/lib/command.c @@ -56,6 +56,7 @@ const struct message tokennames[] = {  	item(IPV6_PREFIX_TKN),  	item(MAC_TKN),  	item(MAC_PREFIX_TKN), +	item(ASNUM_TKN),  	item(FORK_TKN),  	item(JOIN_TKN),  	item(START_TKN), diff --git a/lib/command.h b/lib/command.h index 2121bfd623..6538e56588 100644 --- a/lib/command.h +++ b/lib/command.h @@ -391,7 +391,8 @@ struct cmd_node {  #define DEBUG_STR "Debugging functions\n"  #define UNDEBUG_STR "Disable debugging functions (see also 'debug')\n"  #define ROUTER_STR "Enable a routing process\n" -#define AS_STR "AS number\n" +#define AS_STR                                                                 \ +	"AS number in plain  <1-4294967295> or dotted <0-65535>.<0-65535> format\n"  #define MAC_STR "MAC address\n"  #define MBGP_STR "MBGP information\n"  #define MATCH_STR "Match values from routing table\n" diff --git a/lib/command_graph.c b/lib/command_graph.c index 850fdeafcd..ff3c11db69 100644 --- a/lib/command_graph.c +++ b/lib/command_graph.c @@ -266,6 +266,7 @@ static bool cmd_nodes_equal(struct graph_node *ga, struct graph_node *gb)  	case END_TKN:  	case NEG_ONLY_TKN:  	case WORD_TKN: +	case ASNUM_TKN:  		return true;  	} @@ -535,6 +536,7 @@ void cmd_graph_node_print_cb(struct graph_node *gn, struct buffer *buf)  	case MAC_PREFIX_TKN:  	case END_TKN:  	case VARIABLE_TKN: +	case ASNUM_TKN:  		color = "#ffffff";  		break;  	} diff --git a/lib/command_graph.h b/lib/command_graph.h index 8e84fa928d..25aa47db7b 100644 --- a/lib/command_graph.h +++ b/lib/command_graph.h @@ -45,6 +45,7 @@ enum cmd_token_type {  	IPV6_PREFIX_TKN, // IPV6 network prefixes  	MAC_TKN,         // Ethernet address  	MAC_PREFIX_TKN,  // Ethernet address w/ CIDR mask +	ASNUM_TKN,       // AS dot format  	/* plumbing types */  	FORK_TKN,  // marks subgraph beginning diff --git a/lib/command_lex.l b/lib/command_lex.l index 64f74498b8..dc89191c13 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -38,6 +38,7 @@ VARIABLE        [A-Z][-_A-Z:0-9]+  WORD            (\-|\+)?[a-zA-Z0-9\*][-+_a-zA-Z0-9\*]*  NUMBER          (\-|\+)?[0-9]{1,20}  RANGE           \({NUMBER}[ ]?\-[ ]?{NUMBER}\) +ASNUM           ASNUM  /* yytext shall be a pointer */  %pointer @@ -57,6 +58,7 @@ RANGE           \({NUMBER}[ ]?\-[ ]?{NUMBER}\)  %}  [ \t]+          LOC_STEP /* ignore whitespace */; +{ASNUM}         {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return ASNUM;}  {IPV4}          {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV4;}  {IPV4_PREFIX}   {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV4_PREFIX;}  {IPV6}          {yylval->string = XSTRDUP(MTYPE_LEX, yytext); return IPV6;} diff --git a/lib/command_match.c b/lib/command_match.c index 5ed643bc91..ff3c48fc31 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -10,6 +10,7 @@  #include "command_match.h"  #include "memory.h" +#include "asn.h"  DEFINE_MTYPE_STATIC(LIB, CMD_MATCHSTACK, "Command Match Stack"); @@ -541,6 +542,7 @@ static enum match_type min_match_level(enum cmd_token_type type)  	case END_TKN:  	case NEG_ONLY_TKN:  	case VARIABLE_TKN: +	case ASNUM_TKN:  		return exact_match;  	} @@ -564,6 +566,7 @@ static int score_precedence(enum cmd_token_type type)  	case IPV6_PREFIX_TKN:  	case MAC_TKN:  	case MAC_PREFIX_TKN: +	case ASNUM_TKN:  	case RANGE_TKN:  		return 2;  	case WORD_TKN: @@ -698,6 +701,8 @@ static enum match_type match_token(struct cmd_token *token, char *input_token)  		return match_mac(input_token, false);  	case MAC_PREFIX_TKN:  		return match_mac(input_token, true); +	case ASNUM_TKN: +		return asn_str2asn_match(input_token);  	case END_TKN:  	case FORK_TKN:  	case JOIN_TKN: @@ -840,7 +845,6 @@ static enum match_type match_ipv4_prefix(const char *str)  	return exact_match;  } -  #define IPV6_ADDR_STR   "0123456789abcdefABCDEF:."  #define IPV6_PREFIX_STR "0123456789abcdefABCDEF:./"  #define STATE_START     1 diff --git a/lib/command_parse.y b/lib/command_parse.y index a29e090ef0..8867e98ccc 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -88,6 +88,7 @@  %token <string> RANGE  %token <string> MAC  %token <string> MAC_PREFIX +%token <string> ASNUM  /* special syntax, value is irrelevant */  %token <string> EXCL_BRACKET @@ -277,6 +278,11 @@ placeholder_token_real:    $$ = new_token_node (ctx, MAC_PREFIX_TKN, $1, doc_next(ctx));    XFREE (MTYPE_LEX, $1);  } +| ASNUM +{ +  $$ = new_token_node (ctx, ASNUM_TKN, $1, doc_next(ctx)); +  XFREE (MTYPE_LEX, $1); +}  placeholder_token:    placeholder_token_real varname_token diff --git a/lib/command_py.c b/lib/command_py.c index ceea5883d5..f8abcf8ef4 100644 --- a/lib/command_py.c +++ b/lib/command_py.c @@ -201,6 +201,7 @@ static PyObject *graph_to_pyobj(struct wrap_graph *wgraph,  			item(IPV6_PREFIX_TKN); // IPV6 network prefixes  			item(MAC_TKN);	       // MAC address  			item(MAC_PREFIX_TKN);  // MAC address with mask +			item(ASNUM_TKN);       // ASNUM  			/* plumbing types */  			item(FORK_TKN); diff --git a/lib/prefix.h b/lib/prefix.h index 1fd652507f..a6435be1b4 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -644,7 +644,10 @@ static inline bool ipv4_mcast_ssm(const struct in_addr *addr)  #pragma FRR printfrr_ext "%pFX"  (struct prefix_eth *)  #pragma FRR printfrr_ext "%pFX"  (struct prefix_evpn *)  #pragma FRR printfrr_ext "%pFX"  (struct prefix_fs *) -#pragma FRR printfrr_ext "%pRD"  (struct prefix_rd *) +#pragma FRR printfrr_ext "%pRDP"  (struct prefix_rd *) +/* RD with AS4B with dot and dot+ format */ +#pragma FRR printfrr_ext "%pRDD"  (struct prefix_rd *) +#pragma FRR printfrr_ext "%pRDE"  (struct prefix_rd *)  #pragma FRR printfrr_ext "%pPSG4" (struct prefix_sg *)  #endif diff --git a/lib/subdir.am b/lib/subdir.am index 8d00668c8c..beef8675aa 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -13,6 +13,7 @@ lib_libfrr_la_SOURCES = \  	lib/affinitymap_northbound.c \  	lib/agg_table.c \  	lib/atomlist.c \ +	lib/asn.c \  	lib/base64.c \  	lib/bfd.c \  	lib/buffer.c \ @@ -169,6 +170,7 @@ pkginclude_HEADERS += \  	lib/admin_group.h \  	lib/affinitymap.h \  	lib/agg_table.h \ +	lib/asn.h \  	lib/atomlist.h \  	lib/base64.h \  	lib/bfd.h \ diff --git a/python/clidef.py b/python/clidef.py index d71b482a99..244a8205bf 100644 --- a/python/clidef.py +++ b/python/clidef.py @@ -51,6 +51,12 @@ _fail = (_end == argv[_i]->arg) || (*_end != '\\0');"""      ) +class AsDotHandler(RenderHandler): +    argtype = "as_t" +    decl = Template("as_t $varname = 0;") +    code = Template("_fail = !asn_str2asn(argv[_i]->arg, &$varname);") + +  # A.B.C.D/M (prefix_ipv4) and  # X:X::X:X/M (prefix_ipv6) are "compatible" and can merge into a  # struct prefix: @@ -152,6 +158,7 @@ handlers = {      "IPV6_PREFIX_TKN": Prefix6Handler,      "MAC_TKN": PrefixEthHandler,      "MAC_PREFIX_TKN": PrefixEthHandler, +    "ASNUM_TKN": AsDotHandler,  }  # core template invoked for each occurence of DEFPY. diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c index 8806bcd8fc..926097f571 100644 --- a/tests/bgpd/test_aspath.c +++ b/tests/bgpd/test_aspath.c @@ -55,6 +55,7 @@ static struct test_segment {  	const uint8_t asdata[1024];  	int len;  	struct test_spec sp; +	enum asnotation_mode asnotation;  } test_segments[] = {  	{  		/* 0 */ @@ -64,6 +65,7 @@ static struct test_segment {  		10,  		{"8466 3 52737 4096", "8466 3 52737 4096", 4, 0,  		 NOT_ALL_PRIVATE, 4096, 4, 8466}, +		0,  	},  	{  		/* 1 */ @@ -72,8 +74,16 @@ static struct test_segment {  		{0x2, 0x1, 0x22, 0x12, 0x2, 0x1, 0x00, 0x04},  		8,  		{ -			"8722 4", "8722 4", 2, 0, NOT_ALL_PRIVATE, 4, 5, 8722, +			"8722 4", +			"8722 4", +			2, +			0, +			NOT_ALL_PRIVATE, +			4, +			5, +			8722,  		}, +		0,  	},  	{  		/* 2 */ @@ -84,6 +94,7 @@ static struct test_segment {  		14,  		{"8466 3 52737 4096 8722 4", "8466 3 52737 4096 8722 4", 6, 0,  		 NOT_ALL_PRIVATE, 3, 5, 8466}, +		0,  	},  	{  		/* 3 */ @@ -93,6 +104,7 @@ static struct test_segment {  		10,  		{"8482 51457 {5204}", "8482 51457 {5204}", 3, 0,  		 NOT_ALL_PRIVATE, 5204, 51456, 8482}, +		0,  	},  	{  		/* 4 */ @@ -104,6 +116,7 @@ static struct test_segment {  		{"8467 59649 {4196,48658} {17322,30745}",  		 "8467 59649 {4196,48658} {17322,30745}", 4, 0, NOT_ALL_PRIVATE,  		 48658, 1, 8467}, +		0,  	},  	{  		/* 5 */ @@ -116,6 +129,7 @@ static struct test_segment {  		{"6435 59408 21665 {2457,4369,61697} 1842 41590 51793",  		 "6435 59408 21665 {2457,4369,61697} 1842 41590 51793", 7, 0,  		 NOT_ALL_PRIVATE, 51793, 1, 6435}, +		0,  	},  	{  		/* 6 */ @@ -124,6 +138,7 @@ static struct test_segment {  		{0x3, 0x3, 0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15},  		8,  		{"(123 456 789)", "", 0, 3, NOT_ALL_PRIVATE, 789, 1, NULL_ASN}, +		0,  	},  	{  		/* 7 */ @@ -134,6 +149,7 @@ static struct test_segment {  		14,  		{"(123 456 789) (111 222)", "", 0, 5, NOT_ALL_PRIVATE, 111, 1,  		 NULL_ASN}, +		0,  	},  	{  		/* 8 */ @@ -142,6 +158,7 @@ static struct test_segment {  		{0x4, 0x3, 0x01, 0xc8, 0x00, 0x7b, 0x03, 0x15},  		8,  		{"[123,456,789]", "", 0, 1, NOT_ALL_PRIVATE, 123, 1, NULL_ASN}, +		0,  	},  	{  		/* 9 */ @@ -153,6 +170,7 @@ static struct test_segment {  		24,  		{"(123 456 789) [111,222] 8722 {4196,48658}",  		 "8722 {4196,48658}", 2, 4, NOT_ALL_PRIVATE, 123, 1, NULL_ASN}, +		0,  	},  	{  		/* 10 */ @@ -163,6 +181,7 @@ static struct test_segment {  		14,  		{"8466 2 52737 4096 8722 4", "8466 2 52737 4096 8722 4", 6, 0,  		 NOT_ALL_PRIVATE, 4096, 1, 8466}, +		0,  	},  	{  		/* 11 */ @@ -174,6 +193,7 @@ static struct test_segment {  		{"8466 2 52737 4096 8722 4 8722",  		 "8466 2 52737 4096 8722 4 8722", 7, 0, NOT_ALL_PRIVATE, 4096,  		 1, 8466}, +		0,  	},  	{  		/* 12 */ @@ -183,6 +203,7 @@ static struct test_segment {  		10,  		{"8466 64512 52737 65535", "8466 64512 52737 65535", 4, 0,  		 NOT_ALL_PRIVATE, 65535, 4, 8466}, +		0,  	},  	{  		/* 13 */ @@ -192,6 +213,7 @@ static struct test_segment {  		10,  		{"65534 64512 64513 65535", "65534 64512 64513 65535", 4, 0,  		 ALL_PRIVATE, 65534, 4, 65534}, +		0,  	},  	{  		/* 14 */ @@ -260,6 +282,7 @@ static struct test_segment {  		 "8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285 8466 3 52737 4096 34285",  		 250, 0, NOT_ALL_PRIVATE, 4096, 4, 8466}, +		0,  	},  	{  		/* 15 */ @@ -270,6 +293,7 @@ static struct test_segment {  		12,  		{"8466 3 52737 4096 3456", "8466 3 52737 4096 3456", 5, 0,  		 NOT_ALL_PRIVATE, 4096, 4, 8466}, +		0,  	},  	{  		/* 16 */ @@ -278,6 +302,7 @@ static struct test_segment {  		{},  		0,  		{"", "", 0, 0, 0, 0, 0, 0}, +		0,  	},  	{  		/* 17 */ @@ -293,6 +318,7 @@ static struct test_segment {  		 "8466 3 52737 4096 3456 {7099,8153}",  		 "8466 3 52737 4096 3456 {7099,8153}", 6, 0, NOT_ALL_PRIVATE,  		 4096, 4, 8466}, +		0,  	},  	{  		/* 18 */ @@ -305,6 +331,7 @@ static struct test_segment {  		{"6435 59408 21665 {23456} 23456 23456 23456",  		 "6435 59408 21665 {23456} 23456 23456 23456", 7, 0,  		 NOT_ALL_PRIVATE, 23456, 1, 6435}, +		0,  	},  	{  		/* 19 */ @@ -316,6 +343,7 @@ static struct test_segment {  		{"{2457,4369,61697} 1842 41591 51793",  		 "{2457,4369,61697} 1842 41591 51793", 4, 0, NOT_ALL_PRIVATE,  		 51793, 1, 2457}, +		0,  	},  	{  		/* 20 */ @@ -329,44 +357,88 @@ static struct test_segment {  		{"(123 456 789) [124,456,788] 6435 59408 21665 {23456} 23456 23456 23456",  		 "6435 59408 21665 {23456} 23456 23456 23456", 7, 4,  		 NOT_ALL_PRIVATE, 23456, 1, 6435}, +		0,  	},  	{  		/* 21 */  		"reconcile_start_trans",  		"seq(23456,23456,23456) seq(6435,59408,21665)",  		{ -			0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0, 0x2, 0x3, -			0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, +			0x2, +			0x3, +			0x5b, +			0xa0, +			0x5b, +			0xa0, +			0x5b, +			0xa0, +			0x2, +			0x3, +			0x19, +			0x23, +			0xe8, +			0x10, +			0x54, +			0xa1,  		},  		16,  		{"23456 23456 23456 6435 59408 21665",  		 "23456 23456 23456 6435 59408 21665", 6, 0, NOT_ALL_PRIVATE,  		 21665, 1, 23456}, +		0,  	},  	{  		/* 22 */  		"reconcile_start_trans4",  		"seq(1842,41591,51793) seq(6435,59408,21665)",  		{ -			0x2, 0x3, 0x07, 0x32, 0xa2, 0x77, 0xca, 0x51, 0x2, 0x3, -			0x19, 0x23, 0xe8, 0x10, 0x54, 0xa1, +			0x2, +			0x3, +			0x07, +			0x32, +			0xa2, +			0x77, +			0xca, +			0x51, +			0x2, +			0x3, +			0x19, +			0x23, +			0xe8, +			0x10, +			0x54, +			0xa1,  		},  		16,  		{"1842 41591 51793 6435 59408 21665",  		 "1842 41591 51793 6435 59408 21665", 6, 0, NOT_ALL_PRIVATE,  		 41591, 1, 1842}, +		0,  	},  	{  		/* 23 */  		"reconcile_start_trans_error",  		"seq(23456,23456,23456) seq(6435,59408)",  		{ -			0x2, 0x3, 0x5b, 0xa0, 0x5b, 0xa0, 0x5b, 0xa0, 0x2, 0x2, -			0x19, 0x23, 0xe8, 0x10, +			0x2, +			0x3, +			0x5b, +			0xa0, +			0x5b, +			0xa0, +			0x5b, +			0xa0, +			0x2, +			0x2, +			0x19, +			0x23, +			0xe8, +			0x10,  		},  		14,  		{"23456 23456 23456 6435 59408", "23456 23456 23456 6435 59408",  		 5, 0, NOT_ALL_PRIVATE, 59408, 1, 23456}, +		0,  	},  	{  		/* 24 */ @@ -382,6 +454,7 @@ static struct test_segment {  		 "8466 3 52737 4096 3456 {7099,8153}",  		 "8466 3 52737 4096 3456 {7099,8153}", 6, 0, NOT_ALL_PRIVATE,  		 4096, 4, 8466}, +		0,  	},  	{  		/* 25 */ @@ -391,6 +464,7 @@ static struct test_segment {  		 0x80},  		12,  		{NULL, NULL, 0, 0, 0, 0, 0, 0}, +		0,  	},  	{  		/* 26  */ @@ -400,6 +474,7 @@ static struct test_segment {  		 0x00, 0x0d, 0x80},  		14,  		{NULL, NULL, 0, 0, 0, 0, 0, 0}, +		0,  	},  	{  		/* 27  */ @@ -408,20 +483,66 @@ static struct test_segment {  		{0x8, 0x2, 0x10, 0x00, 0x0d, 0x80},  		14,  		{NULL, NULL, 0, 0, 0, 0, 0, 0}, +		0,  	},  	{  		/* 28 */  		"BGP_AS_ZERO",  		"seq(8466,3,52737,0,4096)", -		{0x2, 0x5, -		0x21, 0x12, -		0x00, 0x03, -		0xce, 0x01, -		0x00, 0x00, -		0x10, 0x00}, +		{0x2, 0x5, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x00, 0x00, 0x10, +		 0x00},  		12,  		{"8466 3 52737 0 4096", "8466 3 52737 0 4096", 5, 0,  		 NOT_ALL_PRIVATE, 4096, 4, 8466}, +		0, +	}, +	{ +		/* 29 */ +		"seq3_asdot+", +		"seq(0.8466,0.3,0.52737,0.4096,0.8722,0.4)", +		{0x2, 0x6, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x10, 0x00, 0x22, +		 0x12, 0x00, 0x04}, +		14, +		{"0.8466 0.3 0.52737 0.4096 0.8722 0.4", +		 "0.8466 0.3 0.52737 0.4096 0.8722 0.4", 6, 0, NOT_ALL_PRIVATE, +		 3, 5, 8466}, +		ASNOTATION_DOTPLUS, +	}, +	{ +		/* 30 */ +		"confmulti_asdot+", +		"confseq(0.123,0.456,0.789) confset(0.222,0.111) seq(0.8722) set(0.4196,0.48658)", +		{0x3,  0x3,  0x00, 0x7b, 0x01, 0xc8, 0x03, 0x15, +		 0x4,  0x2,  0x00, 0xde, 0x00, 0x6f, 0x2,  0x1, +		 0x22, 0x12, 0x1,  0x2,  0x10, 0x64, 0xbe, 0x12}, +		24, +		{"(0.123 0.456 0.789) [0.111,0.222] 0.8722 {0.4196,0.48658}", +		 "0.8722 {0.4196,0.48658}", 2, 4, NOT_ALL_PRIVATE, 123, 1, +		 NULL_ASN}, +		ASNOTATION_DOTPLUS, +	}, +	{ +		/* 31 */ +		"someprivate asdot+", +		"seq(0.8466,0.64512,0.52737,0.65535)", +		{0x2, 0x4, 0x21, 0x12, 0xfc, 0x00, 0xce, 0x01, 0xff, 0xff}, +		10, +		{"0.8466 0.64512 0.52737 0.65535", +		 "0.8466 0.64512 0.52737 0.65535", 4, 0, NOT_ALL_PRIVATE, 65535, +		 4, 8466}, +		ASNOTATION_DOTPLUS, +	}, +	{ +		/* 32 */ +		"BGP_AS_ZERO asdot+", +		"seq(0.8466,0.3,0.52737,0.0,0.4096)", +		{0x2, 0x5, 0x21, 0x12, 0x00, 0x03, 0xce, 0x01, 0x00, 0x00, 0x10, +		 0x00}, +		12, +		{"0.8466 0.3 0.52737 0.0 0.4096", +		 "0.8466 0.3 0.52737 0.0 0.4096", 5, 0, NOT_ALL_PRIVATE, 4096, +		 4, 8466}, +		ASNOTATION_DOTPLUS,  	},  	{NULL, NULL, {0}, 0, {NULL, 0, 0}}}; @@ -856,16 +977,16 @@ struct compare_tests {  };  /* make an aspath from a data stream */ -static struct aspath *make_aspath(const uint8_t *data, size_t len, int use32bit) +static struct aspath *make_aspath(const uint8_t *data, size_t len, int use32bit, +				  enum asnotation_mode asnotation)  {  	struct stream *s = NULL;  	struct aspath *as; -  	if (len) {  		s = stream_new(len);  		stream_put(s, data, len);  	} -	as = aspath_parse(s, len, use32bit); +	as = aspath_parse(s, len, use32bit, asnotation);  	if (s)  		stream_free(s); @@ -901,15 +1022,16 @@ static int validate(struct aspath *as, const struct test_spec *sp)  	}  	out = aspath_snmp_pathseg(as, &bytes); -	asinout = make_aspath(out, bytes, 0); - +	asinout = make_aspath(out, bytes, 0, as->asnotation);  	/* Excercise AS4 parsing a bit, with a dogfood test */  	if (!s)  		s = stream_new(BGP_MAX_PACKET_SIZE);  	bytes4 = aspath_put(s, as, 1); -	as4 = make_aspath(STREAM_DATA(s), bytes4, 1); +	as4 = make_aspath(STREAM_DATA(s), bytes4, 1, as->asnotation); -	asstr = aspath_str2aspath(sp->shouldbe); +	asn_relax_as_zero(true); +	asstr = aspath_str2aspath(sp->shouldbe, as->asnotation); +	asn_relax_as_zero(false);  	asconfeddel = aspath_delete_confed_seq(aspath_dup(asinout)); @@ -1036,7 +1158,7 @@ static void parse_test(struct test_segment *t)  	printf("%s: %s\n", t->name, t->desc); -	asp = make_aspath(t->asdata, t->len, 0); +	asp = make_aspath(t->asdata, t->len, 0, t->asnotation);  	printf("aspath: %s\nvalidating...:\n", aspath_print(asp)); @@ -1058,8 +1180,10 @@ static void prepend_test(struct tests *t)  	printf("prepend %s: %s\n", t->test1->name, t->test1->desc);  	printf("to %s: %s\n", t->test2->name, t->test2->desc); -	asp1 = make_aspath(t->test1->asdata, t->test1->len, 0); -	asp2 = make_aspath(t->test2->asdata, t->test2->len, 0); +	asp1 = make_aspath(t->test1->asdata, t->test1->len, 0, +			   ASNOTATION_PLAIN); +	asp2 = make_aspath(t->test2->asdata, t->test2->len, 0, +			   ASNOTATION_PLAIN);  	ascratch = aspath_dup(asp2);  	aspath_unintern(&asp2); @@ -1085,8 +1209,8 @@ static void empty_prepend_test(struct test_segment *t)  	printf("empty prepend %s: %s\n", t->name, t->desc); -	asp1 = make_aspath(t->asdata, t->len, 0); -	asp2 = aspath_empty(); +	asp1 = make_aspath(t->asdata, t->len, 0, t->asnotation); +	asp2 = aspath_empty(t->asnotation);  	ascratch = aspath_dup(asp2);  	aspath_unintern(&asp2); @@ -1113,8 +1237,10 @@ static void as4_reconcile_test(struct tests *t)  	printf("reconciling %s:\n  %s\n", t->test1->name, t->test1->desc);  	printf("with %s:\n  %s\n", t->test2->name, t->test2->desc); -	asp1 = make_aspath(t->test1->asdata, t->test1->len, 0); -	asp2 = make_aspath(t->test2->asdata, t->test2->len, 0); +	asp1 = make_aspath(t->test1->asdata, t->test1->len, 0, +			   ASNOTATION_PLAIN); +	asp2 = make_aspath(t->test2->asdata, t->test2->len, 0, +			   ASNOTATION_PLAIN);  	ascratch = aspath_reconcile_as4(asp1, asp2); @@ -1138,8 +1264,10 @@ static void aggregate_test(struct tests *t)  	printf("aggregate %s: %s\n", t->test1->name, t->test1->desc);  	printf("with %s: %s\n", t->test2->name, t->test2->desc); -	asp1 = make_aspath(t->test1->asdata, t->test1->len, 0); -	asp2 = make_aspath(t->test2->asdata, t->test2->len, 0); +	asp1 = make_aspath(t->test1->asdata, t->test1->len, 0, +			   ASNOTATION_PLAIN); +	asp2 = make_aspath(t->test2->asdata, t->test2->len, 0, +			   ASNOTATION_PLAIN);  	ascratch = aspath_aggregate(asp1, asp2); @@ -1171,8 +1299,8 @@ static void cmp_test(void)  		printf("left cmp %s: %s\n", t1->name, t1->desc);  		printf("and %s: %s\n", t2->name, t2->desc); -		asp1 = make_aspath(t1->asdata, t1->len, 0); -		asp2 = make_aspath(t2->asdata, t2->len, 0); +		asp1 = make_aspath(t1->asdata, t1->len, 0, ASNOTATION_PLAIN); +		asp2 = make_aspath(t2->asdata, t2->len, 0, ASNOTATION_PLAIN);  		if (aspath_cmp_left(asp1, asp2) != left_compare[i].shouldbe_cmp  		    || aspath_cmp_left(asp2, asp1) @@ -1210,7 +1338,9 @@ static int handle_attr_test(struct aspath_tests *t)  	struct aspath *asp;  	size_t datalen; -	asp = make_aspath(t->segment->asdata, t->segment->len, 0); +	asp = make_aspath(t->segment->asdata, t->segment->len, 0, +			  t->segment->asnotation); +	bgp.asnotation = t->segment->asnotation;  	peer.curr = stream_new(BGP_MAX_PACKET_SIZE);  	peer.obuf = stream_fifo_new(); @@ -1286,8 +1416,8 @@ int main(void)  		parse_test(&test_segments[i]);  		empty_prepend_test(&test_segments[i++]);  	} -  	i = 0; +  	while (prepend_tests[i].test1) {  		printf("prepend test %u\n", i);  		prepend_test(&prepend_tests[i++]); diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c index 01b0740b87..8ef5748671 100644 --- a/tests/bgpd/test_capability.c +++ b/tests/bgpd/test_capability.c @@ -937,7 +937,8 @@ int main(void)  	if (fileno(stdout) >= 0)  		tty = isatty(fileno(stdout)); -	if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT) < 0) +	if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT, NULL, +		    ASNOTATION_PLAIN) < 0)  		return -1;  	peer = peer_create_accept(bgp); diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c index 3abf7bd141..b1f3314f1f 100644 --- a/tests/bgpd/test_mp_attr.c +++ b/tests/bgpd/test_mp_attr.c @@ -1079,7 +1079,8 @@ int main(void)  	if (fileno(stdout) >= 0)  		tty = isatty(fileno(stdout)); -	if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT) < 0) +	if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT, NULL, +		    ASNOTATION_PLAIN) < 0)  		return -1;  	peer = peer_create_accept(bgp); diff --git a/tests/bgpd/test_packet.c b/tests/bgpd/test_packet.c index 1a2d21ad22..aeebbd9a35 100644 --- a/tests/bgpd/test_packet.c +++ b/tests/bgpd/test_packet.c @@ -50,7 +50,8 @@ int main(int argc, char *argv[])  	vrf_init(NULL, NULL, NULL, NULL);  	bgp_option_set(BGP_OPT_NO_LISTEN); -	if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT) < 0) +	if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT, NULL, +		    ASNOTATION_PLAIN) < 0)  		return -1;  	peer = peer_create_accept(bgp); diff --git a/tests/lib/test_printfrr.c b/tests/lib/test_printfrr.c index 9cabae8f20..0ab40b2ecd 100644 --- a/tests/lib/test_printfrr.c +++ b/tests/lib/test_printfrr.c @@ -12,6 +12,7 @@  #include "lib/memory.h"  #include "lib/prefix.h"  #include "lib/nexthop.h" +#include "lib/asn.h"  static int errors; @@ -145,6 +146,7 @@ int main(int argc, char **argv)  	struct in_addr ip;  	char *p;  	char buf[256]; +	as_t asn;  	printcmp("%d %u %d %u", 123, 123, -456, -456);  	printcmp("%lld %llu %lld %llu", 123LL, 123LL, -456LL, -456LL); @@ -392,6 +394,13 @@ int main(int argc, char **argv)  	printchk("-00:09", "%pTSIm", &ts);  	printchk("--:--", "%pTVImx", &tv);  	printchk("--:--", "%pTTImx", &tt); +	/* ASN checks */ +	asn = 65536; +	printchk("1.0", "%pASD", &asn); +	asn = 65400; +	printchk("65400", "%pASP", &asn); +	printchk("0.65400", "%pASE", &asn); +	printchk("65400", "%pASD", &asn);  	return !!errors;  } diff --git a/tests/topotests/bgp_asdot_regex/__init__.py b/tests/topotests/bgp_asdot_regex/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_asdot_regex/__init__.py diff --git a/tests/topotests/bgp_asdot_regex/r1/bgpd.conf b/tests/topotests/bgp_asdot_regex/r1/bgpd.conf new file mode 100644 index 0000000000..4dd95dd8b7 --- /dev/null +++ b/tests/topotests/bgp_asdot_regex/r1/bgpd.conf @@ -0,0 +1,27 @@ +router bgp 1.1 +  no bgp ebgp-requires-policy +  no bgp network import-check +  neighbor 192.168.255.2 remote-as 1.2 +  address-family ipv4 unicast +   network 172.31.1.0/24 route-map rmapout +   network 172.31.2.0/24 route-map rmapout +   neighbor 192.168.255.2 route-map rmapin in +   neighbor 192.168.255.2 activate +  exit-address-family +exit +bgp as-path access-list only1_4 permit _1.4_ +bgp as-path access-list only65540 permit _65540_ +access-list 172313 permit 172.31.3.0/24 +access-list 172314 permit 172.31.4.0/24 +route-map rmapout permit 1 + set as-path prepend 1.4 +exit +route-map rmapin permit 1 + match ip address 172313 + match as-path only1_4  +exit +route-map rmapin permit 2 + match ip address 172314 + match as-path only65540 +exit + diff --git a/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json b/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json new file mode 100644 index 0000000000..e3703bf953 --- /dev/null +++ b/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json @@ -0,0 +1,80 @@ +{    + "vrfId": 0, + "vrfName": "default", + "tableVersion": 3, + "routerId": "192.168.255.1", + "defaultLocPrf": 100, + "localAS": "1.1", + "routes": { "172.31.1.0/24": [ +  {  +    "valid":true, +    "bestpath":true, +    "selectionReason":"First path received", +    "pathFrom":"external", +    "prefix":"172.31.1.0", +    "prefixLen":24, +    "network":"172.31.1.0/24", +    "metric":0, +    "weight":32768, +    "peerId":"(unspec)", +    "path":"1.4", +    "origin":"IGP", +    "nexthops":[ +      { +        "ip":"0.0.0.0", +        "hostname":"r1", +        "afi":"ipv4", +        "used":true +      } +    ] +  }  +]    +,"172.31.2.0/24": [ +  {  +    "valid":true, +    "bestpath":true, +    "selectionReason":"First path received", +    "pathFrom":"external", +    "prefix":"172.31.2.0", +    "prefixLen":24, +    "network":"172.31.2.0/24", +    "metric":0, +    "weight":32768, +    "peerId":"(unspec)", +    "path":"1.4", +    "origin":"IGP", +    "nexthops":[ +      { +        "ip":"0.0.0.0", +        "hostname":"r1", +        "afi":"ipv4", +        "used":true +      } +    ] +  } +] +,"172.31.3.0/24": [ +  { +    "valid":true, +    "bestpath":true, +    "selectionReason":"First path received", +    "pathFrom":"external", +    "prefix":"172.31.3.0", +    "prefixLen":24, +    "network":"172.31.3.0/24", +    "metric":0, +    "weight":0, +    "peerId":"192.168.255.2", +    "path":"1.2 1.4", +    "origin":"IGP", +    "nexthops":[ +      { +        "ip":"192.168.255.2", +        "hostname":"r2", +        "afi":"ipv4", +        "used":true +      } +    ] +  } +] + }  }  diff --git a/tests/topotests/bgp_asdot_regex/r1/zebra.conf b/tests/topotests/bgp_asdot_regex/r1/zebra.conf new file mode 100644 index 0000000000..6e9b0b4a7e --- /dev/null +++ b/tests/topotests/bgp_asdot_regex/r1/zebra.conf @@ -0,0 +1,6 @@ +! +interface r1-eth0 +  ip address 192.168.255.1/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_asdot_regex/r2/bgpd.conf b/tests/topotests/bgp_asdot_regex/r2/bgpd.conf new file mode 100644 index 0000000000..216dbd19ef --- /dev/null +++ b/tests/topotests/bgp_asdot_regex/r2/bgpd.conf @@ -0,0 +1,26 @@ +router bgp 65538 +  no bgp ebgp-requires-policy +  no bgp network import-check +  neighbor 192.168.255.1 remote-as 65537 +  address-family ipv4 unicast +   network 172.31.3.0/24 route-map rmapout +   network 172.31.4.0/24 route-map rmapout +   neighbor 192.168.255.1 route-map rmapin in +   neighbor 192.168.255.1 activate +  exit-address-family +exit +bgp as-path access-list only65540 permit _65540_ +bgp as-path access-list only1_4 permit _1.4_ +access-list 172311 permit 172.31.1.0/24 +access-list 172312 permit 172.31.2.0/24 +route-map rmapout permit 1 + set as-path prepend 65540 +exit +route-map rmapin permit 1 + match ip address 172311 + match as-path only65540  +exit +route-map rmapin permit 2 + match ip address 172312 + match as-path only1_4  +exit diff --git a/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json b/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json new file mode 100644 index 0000000000..1af4ff7e3d --- /dev/null +++ b/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json @@ -0,0 +1,80 @@ +{ + "vrfId": 0, + "vrfName": "default", + "tableVersion": 3, + "routerId": "192.168.255.2", + "defaultLocPrf": 100, + "localAS": 65538, + "routes": { "172.31.1.0/24": [ +  { +    "valid":true, +    "bestpath":true, +    "selectionReason":"First path received", +    "pathFrom":"external", +    "prefix":"172.31.1.0", +    "prefixLen":24, +    "network":"172.31.1.0/24", +    "metric":0, +    "weight":0, +    "peerId":"192.168.255.1", +    "path":"65537 65540", +    "origin":"IGP", +    "nexthops":[ +      { +        "ip":"192.168.255.1", +        "hostname":"r1", +        "afi":"ipv4", +        "used":true +      } +    ] +  } +] +,"172.31.3.0/24": [ +  { +    "valid":true, +    "bestpath":true, +    "selectionReason":"First path received", +    "pathFrom":"external", +    "prefix":"172.31.3.0", +    "prefixLen":24, +    "network":"172.31.3.0/24", +    "metric":0, +    "weight":32768, +    "peerId":"(unspec)", +    "path":"65540", +    "origin":"IGP", +    "nexthops":[ +      { +        "ip":"0.0.0.0", +        "hostname":"r2", +        "afi":"ipv4", +        "used":true +      } +    ] +  } +] +,"172.31.4.0/24": [ +  { +    "valid":true, +    "bestpath":true, +    "selectionReason":"First path received", +    "pathFrom":"external", +    "prefix":"172.31.4.0", +    "prefixLen":24, +    "network":"172.31.4.0/24", +    "metric":0, +    "weight":32768, +    "peerId":"(unspec)", +    "path":"65540", +    "origin":"IGP", +    "nexthops":[ +      { +        "ip":"0.0.0.0", +        "hostname":"r2", +        "afi":"ipv4", +        "used":true +      } +    ] +  } +] + }  }  diff --git a/tests/topotests/bgp_asdot_regex/r2/zebra.conf b/tests/topotests/bgp_asdot_regex/r2/zebra.conf new file mode 100644 index 0000000000..6c14de583b --- /dev/null +++ b/tests/topotests/bgp_asdot_regex/r2/zebra.conf @@ -0,0 +1,6 @@ +! +interface r2-eth0 +  ip address 192.168.255.2/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py b/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py new file mode 100644 index 0000000000..5d5f1659e9 --- /dev/null +++ b/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python + +# +# test_bgp_asdot_regex.py +# Part of Topotests +# +# Copyright 2022 6WIND S.A. +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +test_bgp_asdot_regex.py: + +Test how regex applies when asnotation to forge bgp config is based on dot or not. +""" + +import os +import sys +import json +import pytest +from functools import partial + +# add after imports, before defining classes or functions: +pytestmark = [pytest.mark.bgpd] + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): +    for routern in range(1, 3): +        tgen.add_router("r{}".format(routern)) + +    switch = tgen.add_switch("s1") +    switch.add_link(tgen.gears["r1"]) +    switch.add_link(tgen.gears["r2"]) + + +def setup_module(mod): +    tgen = Topogen(build_topo, mod.__name__) +    tgen.start_topology() + +    router_list = tgen.routers() + +    for i, (rname, router) in enumerate(router_list.items(), 1): +        router.load_config( +            TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) +        ) +        router.load_config( +            TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) +        ) + +    tgen.start_router() + + +def teardown_module(mod): +    tgen = get_topogen() +    tgen.stop_topology() + + +def test_bgp_asdot_regex(): +    tgen = get_topogen() + +    if tgen.routers_have_failure(): +        pytest.skip(tgen.errors) + +    router1 = tgen.gears["r1"] +    router2 = tgen.gears["r2"] + +    def _bgp_converge(router): +        output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.2 json")) +        expected = { +            "192.168.255.2": { +                "bgpState": "Established", +                "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 1}}, +            } +        } +        return topotest.json_cmp(output, expected) + +    logger.info("Check if neighbor sessions are up in {}".format(router1.name)) +    test_func = partial(_bgp_converge, router1) +    success, result = topotest.run_and_expect(test_func, None, count=15, wait=0.5) +    assert result is None, 'Failed to see BGP convergence in "{}"'.format(router1.name) + +    logger.info("BGP neighbor session is up in {}".format(router1.name)) + +    logger.info("waiting for bgp peers exchanging UPDATES") + +    for router in tgen.routers().values(): +        ref_file = "{}/{}/show_bgp_ipv4.json".format(CWD, router.name) +        expected = json.loads(open(ref_file).read()) +        test_func = partial( +            topotest.router_json_cmp, router, "show bgp ipv4 unicast json", expected +        ) +        _, res = topotest.run_and_expect(test_func, None, count=40, wait=2.5) +        assertmsg = "{}: BGP UPDATE exchange failure".format(router.name) +        assert res is None, assertmsg + + +if __name__ == "__main__": +    args = ["-s"] + sys.argv[1:] +    sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_local_as_dotplus_private_remove/__init__.py b/tests/topotests/bgp_local_as_dotplus_private_remove/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_local_as_dotplus_private_remove/__init__.py diff --git a/tests/topotests/bgp_local_as_dotplus_private_remove/r1/bgpd.conf b/tests/topotests/bgp_local_as_dotplus_private_remove/r1/bgpd.conf new file mode 100644 index 0000000000..1846df24f3 --- /dev/null +++ b/tests/topotests/bgp_local_as_dotplus_private_remove/r1/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 0.65000 as-notation dot+ +  no bgp ebgp-requires-policy +  neighbor 192.168.255.2 remote-as 0.1000 +  neighbor 192.168.255.2 timers 3 10 +  neighbor 192.168.255.2 local-as 0.500 +  address-family ipv4 unicast +    neighbor 192.168.255.2 remove-private-AS +    redistribute connected diff --git a/tests/topotests/bgp_local_as_dotplus_private_remove/r1/zebra.conf b/tests/topotests/bgp_local_as_dotplus_private_remove/r1/zebra.conf new file mode 100644 index 0000000000..0a283c06d5 --- /dev/null +++ b/tests/topotests/bgp_local_as_dotplus_private_remove/r1/zebra.conf @@ -0,0 +1,9 @@ +! +interface lo + ip address 172.16.255.254/32 +! +interface r1-eth0 + ip address 192.168.255.1/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_local_as_dotplus_private_remove/r2/bgpd.conf b/tests/topotests/bgp_local_as_dotplus_private_remove/r2/bgpd.conf new file mode 100644 index 0000000000..c9adfa4671 --- /dev/null +++ b/tests/topotests/bgp_local_as_dotplus_private_remove/r2/bgpd.conf @@ -0,0 +1,5 @@ +router bgp 0.1000 as-notation dot+ +  no bgp ebgp-requires-policy +  neighbor 192.168.255.1 remote-as 0.500 +  neighbor 192.168.255.1 timers 3 10 +! diff --git a/tests/topotests/bgp_local_as_dotplus_private_remove/r2/zebra.conf b/tests/topotests/bgp_local_as_dotplus_private_remove/r2/zebra.conf new file mode 100644 index 0000000000..606c17bec9 --- /dev/null +++ b/tests/topotests/bgp_local_as_dotplus_private_remove/r2/zebra.conf @@ -0,0 +1,6 @@ +! +interface r2-eth0 + ip address 192.168.255.2/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_local_as_dotplus_private_remove/r3/bgpd.conf b/tests/topotests/bgp_local_as_dotplus_private_remove/r3/bgpd.conf new file mode 100644 index 0000000000..9a831270b4 --- /dev/null +++ b/tests/topotests/bgp_local_as_dotplus_private_remove/r3/bgpd.conf @@ -0,0 +1,8 @@ +router bgp 3000 +  no bgp ebgp-requires-policy +  neighbor 192.168.255.2 remote-as 1000 +  neighbor 192.168.255.2 timers 3 10 +  neighbor 192.168.255.2 local-as 500 +  address-family ipv4 unicast +    neighbor 192.168.255.2 remove-private-AS +    redistribute connected diff --git a/tests/topotests/bgp_local_as_dotplus_private_remove/r3/zebra.conf b/tests/topotests/bgp_local_as_dotplus_private_remove/r3/zebra.conf new file mode 100644 index 0000000000..39499a198d --- /dev/null +++ b/tests/topotests/bgp_local_as_dotplus_private_remove/r3/zebra.conf @@ -0,0 +1,9 @@ +! +interface lo + ip address 172.16.255.254/32 +! +interface r3-eth0 + ip address 192.168.255.1/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_local_as_dotplus_private_remove/r4/bgpd.conf b/tests/topotests/bgp_local_as_dotplus_private_remove/r4/bgpd.conf new file mode 100644 index 0000000000..c9adfa4671 --- /dev/null +++ b/tests/topotests/bgp_local_as_dotplus_private_remove/r4/bgpd.conf @@ -0,0 +1,5 @@ +router bgp 0.1000 as-notation dot+ +  no bgp ebgp-requires-policy +  neighbor 192.168.255.1 remote-as 0.500 +  neighbor 192.168.255.1 timers 3 10 +! diff --git a/tests/topotests/bgp_local_as_dotplus_private_remove/r4/zebra.conf b/tests/topotests/bgp_local_as_dotplus_private_remove/r4/zebra.conf new file mode 100644 index 0000000000..b85911504e --- /dev/null +++ b/tests/topotests/bgp_local_as_dotplus_private_remove/r4/zebra.conf @@ -0,0 +1,6 @@ +! +interface r4-eth0 + ip address 192.168.255.2/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp_local_as_dotplus_private_remove/test_bgp_local_as_dotplus_private_remove.py b/tests/topotests/bgp_local_as_dotplus_private_remove/test_bgp_local_as_dotplus_private_remove.py new file mode 100644 index 0000000000..efecad3eb2 --- /dev/null +++ b/tests/topotests/bgp_local_as_dotplus_private_remove/test_bgp_local_as_dotplus_private_remove.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python + +# +# bgp_local_as_private_remove.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2019 by +# Network Device Education Foundation, Inc. ("NetDEF") +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +bgp_local_as_private_remove.py: +Test if primary AS number is not removed in cases when `local-as` +used together with `remove-private-AS`. +""" + +import os +import sys +import json +import time +import pytest + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib.topogen import Topogen, TopoRouter, get_topogen + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): +    for routern in range(1, 5): +        tgen.add_router("r{}".format(routern)) + +    switch = tgen.add_switch("s1") +    switch.add_link(tgen.gears["r1"]) +    switch.add_link(tgen.gears["r2"]) + +    switch = tgen.add_switch("s2") +    switch.add_link(tgen.gears["r3"]) +    switch.add_link(tgen.gears["r4"]) + + +def setup_module(mod): +    tgen = Topogen(build_topo, mod.__name__) +    tgen.start_topology() + +    router_list = tgen.routers() + +    for i, (rname, router) in enumerate(router_list.items(), 1): +        router.load_config( +            TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) +        ) +        router.load_config( +            TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) +        ) + +    tgen.start_router() + + +def teardown_module(mod): +    tgen = get_topogen() +    tgen.stop_topology() + + +def test_bgp_remove_private_as(): +    tgen = get_topogen() + +    if tgen.routers_have_failure(): +        pytest.skip(tgen.errors) + +    def _bgp_converge(router): +        while True: +            output = json.loads( +                tgen.gears[router].vtysh_cmd("show ip bgp neighbor 192.168.255.1 json") +            ) +            if output["192.168.255.1"]["bgpState"] == "Established": +                time.sleep(1) +                return True + +    def _bgp_as_path(router): +        output = json.loads( +            tgen.gears[router].vtysh_cmd("show ip bgp 172.16.255.254/32 json") +        ) +        if output["prefix"] == "172.16.255.254/32": +            return output["paths"][0]["aspath"]["segments"][0]["list"] + +    if _bgp_converge("r2"): +        assert len(_bgp_as_path("r2")) == 1 +        assert '0.65000' not in _bgp_as_path("r2") + +    if _bgp_converge("r4"): +        assert len(_bgp_as_path("r4")) == 2 +        assert '0.3000' in _bgp_as_path("r4") + + +if __name__ == "__main__": +    args = ["-s"] + sys.argv[1:] +    sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_local_asn_dot/bgp_local_asn_dot_agg.json b/tests/topotests/bgp_local_asn_dot/bgp_local_asn_dot_agg.json new file mode 100644 index 0000000000..b481932449 --- /dev/null +++ b/tests/topotests/bgp_local_asn_dot/bgp_local_asn_dot_agg.json @@ -0,0 +1,147 @@ +{ +    "address_types": ["ipv4", "ipv6"], +    "ipv4base": "10.0.0.0", +    "ipv4mask": 30, +    "ipv6base": "fd00::", +    "ipv6mask": 64, +    "link_ip_start": {"ipv4": "10.0.0.0", "v4mask": 30, "ipv6": "fd00::", "v6mask": 64}, +    "lo_prefix": {"ipv4": "1.0.", "v4mask": 32, "ipv6": "2001:db8:f::", "v6mask": 128}, +    "routers": { +        "r1": { +            "links": { +                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"}, +                "r3": {"ipv4": "auto", "ipv6": "auto"} +            }, +            "bgp": { +                "local_as": "1.100", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "redistribute": [ +                                {"redist_type": "static"} +                             ], +                            "neighbor": { +                                "r3": {"dest_link": {"r1": {}}} +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "redistribute": [ +                                {"redist_type": "static"} +                             ], +                            "neighbor": { +                                "r3": {"dest_link": {"r1": {}}} +                            } +                        } +                    } +                } +            }, +            "static_routes":[ +                { +                "network":"10.1.1.0/32", +                "next_hop":"Null0" +                }, +                { +                "network":"10:1::1:0/128", +                "next_hop":"Null0" +                }] +            }, +        "r2": { +            "links": { +                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"}, +                "r3": {"ipv4": "auto", "ipv6": "auto"} +            }, +            "bgp": { +                "local_as": "1.200", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "redistribute": [ +                                {"redist_type": "static"} +                            ], +                            "neighbor": { +                                "r3": {"dest_link": {"r2": {}}} +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "redistribute": [ +                                {"redist_type": "static"} +                            ], +                            "neighbor": { +                                "r3": {"dest_link": {"r2": {}}} +                            } +                        } +                    } +                } +            }, +            "static_routes":[ +                { +                "network":"10.1.2.0/32", +                "next_hop":"Null0" +                }, +                { +                "network":"10:1::2:0/128", +                "next_hop":"Null0" +                }] +            }, +        "r3": { +            "links": { +                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"}, +                "r1": {"ipv4": "auto", "ipv6": "auto"}, +                "r2": {"ipv4": "auto", "ipv6": "auto"}, +                "r4": {"ipv4": "auto", "ipv6": "auto"} +            }, +            "bgp": { +                "local_as": "1.300", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r1": {"dest_link": {"r3": {}}}, +                                "r2": {"dest_link": {"r3": {}}}, +                                "r4": {"dest_link": {"r3": {}}} +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r1": {"dest_link": {"r3": {}}}, +                                "r2": {"dest_link": {"r3": {}}}, +                                "r4": {"dest_link": {"r3": {}}} +                            } +                        } +                    } +                } +            } +        }, +        "r4": { +            "links": { +                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"}, +                "r3": {"ipv4": "auto", "ipv6": "auto"} +            }, +            "bgp": { +                "local_as": "1.400", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r3": {"dest_link": {"r4": {}}} +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r3": {"dest_link": {"r4": {}}} +                            } +                        } +                    } +                } +            } +        } +    } +} diff --git a/tests/topotests/bgp_local_asn_dot/bgp_local_asn_dot_ecmp.json b/tests/topotests/bgp_local_asn_dot/bgp_local_asn_dot_ecmp.json new file mode 100644 index 0000000000..afacab4946 --- /dev/null +++ b/tests/topotests/bgp_local_asn_dot/bgp_local_asn_dot_ecmp.json @@ -0,0 +1,317 @@ +{ +    "address_types": [ +        "ipv4", +        "ipv6" +    ], +    "ipv4base": "10.0.0.0", +    "ipv4mask": 24, +    "ipv6base": "fd00::", +    "ipv6mask": 64, +    "link_ip_start": { +        "ipv4": "10.0.0.0", +        "v4mask": 24, +        "ipv6": "fd00::", +        "v6mask": 64 +    }, +    "lo_prefix": { +        "ipv4": "1.0.", +        "v4mask": 32, +        "ipv6": "2001:DB8:F::", +        "v6mask": 128 +    }, +    "routers": { +        "r1": { +            "links": { +                "lo": { +                    "ipv4": "auto", +                    "ipv6": "auto", +                    "type": "loopback" +                }, +                "r2-link1": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                } +            }, +            "bgp": [{ +                "local_as": "1.100", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "redistribute": [ +                                {"redist_type": "static"} +                             ], +                            "neighbor": { +                                "r2": { +                                    "dest_link": { +                                        "r1-link1": {} +                                    } +                                } +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "redistribute": [ +                                {"redist_type": "static"} +                             ], +                            "neighbor": { +                                "r2": { +                                    "dest_link": { +                                        "r1-link1": {} +                                    } +                                } +                            } +                        } +                    } +                } +            } + +            ], +            "static_routes":[ +                { +                   "network":"10.0.0.1/32", +                   "next_hop":"Null0" +                }, +                { +                   "network":"10::1/128", +                   "next_hop":"Null0" +                } +            ] +        }, +        "r2": { +            "links": { +                "lo": { +                    "ipv4": "auto", +                    "ipv6": "auto", +                    "type": "loopback" +                }, +                "r1-link1": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r3-link1": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                } +            }, +            "bgp": [{ +                "local_as": "1.200", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r1": { +                                    "dest_link": { +                                        "r2-link1": {} +                                    } +                                }, +                                "r3": { +                                    "dest_link": { +                                        "r2-link1": {} +                                    } +                                } +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r1": { +                                    "dest_link": { +                                        "r2-link1": {} +                                    } +                                }, +                                "r3": { +                                    "dest_link": { +                                        "r2-link1": {} +                                    } +                                } +                            } +                        } +                    } +                } +            } +        ] +        }, +        "r3": { +            "links": { +                "lo": { +                    "ipv4": "auto", +                    "ipv6": "auto", +                    "type": "loopback" +                }, +                "r2-link1": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r4-link1": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r4-link2": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r4-link3": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r4-link4": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r4-link5": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r4-link6": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r4-link7": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r4-link8": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                } +            }, +            "bgp": [{ +                "local_as": "1.300", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r2": { +                                    "dest_link": { +                                        "r3-link1": {} +                                    } +                                }, +                                "r4": { +                                    "dest_link": { +                                        "r3-link1": {}, +                                        "r3-link2": {}, +                                        "r3-link3": {}, +                                        "r3-link4": {}, +                                        "r3-link5": {}, +                                        "r3-link6": {}, +                                        "r3-link7": {}, +                                        "r3-link8": {} +                                    } +                                } +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r2": { +                                    "dest_link": { +                                        "r3-link1": {} +                                    } +                                }, +                                "r4": { +                                    "dest_link": { +                                        "r3-link1": {}, +                                        "r3-link2": {}, +                                        "r3-link3": {}, +                                        "r3-link4": {}, +                                        "r3-link5": {}, +                                        "r3-link6": {}, +                                        "r3-link7": {}, +                                        "r3-link8": {} +                                    } +                                } +                            } +                        } +                    } +                } +            } +        ] +        }, +        "r4": { +            "links": { +                "lo": { +                    "ipv4": "auto", +                    "ipv6": "auto", +                    "type": "loopback" +                }, +                "r3-link1": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r3-link2": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r3-link3": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r3-link4": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r3-link5": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r3-link6": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r3-link7": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                }, +                "r3-link8": { +                    "ipv4": "auto", +                    "ipv6": "auto" +                } +            }, +            "bgp": [{ +                "local_as": "1.400", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r3": { +                                    "dest_link": { +                                        "r4-link1": {}, +                                        "r4-link2": {}, +                                        "r4-link3": {}, +                                        "r4-link4": {}, +                                        "r4-link5": {}, +                                        "r4-link6": {}, +                                        "r4-link7": {}, +                                        "r4-link8": {} +                                    } +                                } +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r3": { +                                    "dest_link": { +                                        "r4-link1": {}, +                                        "r4-link2": {}, +                                        "r4-link3": {}, +                                        "r4-link4": {}, +                                        "r4-link5": {}, +                                        "r4-link6": {}, +                                        "r4-link7": {}, +                                        "r4-link8": {} +                                    } +                                } +                            } +                        } +                    } +                } +            } +        ] +        } +    } +} diff --git a/tests/topotests/bgp_local_asn_dot/bgp_local_asn_dot_topo1.json b/tests/topotests/bgp_local_asn_dot/bgp_local_asn_dot_topo1.json new file mode 100644 index 0000000000..02aacf791a --- /dev/null +++ b/tests/topotests/bgp_local_asn_dot/bgp_local_asn_dot_topo1.json @@ -0,0 +1,132 @@ +{ +    "address_types": ["ipv4", "ipv6"], +    "ipv4base": "10.0.0.0", +    "ipv4mask": 30, +    "ipv6base": "fd00::", +    "ipv6mask": 64, +    "link_ip_start": {"ipv4": "10.0.0.0", "v4mask": 30, "ipv6": "fd00::", "v6mask": 64}, +    "lo_prefix": {"ipv4": "1.0.", "v4mask": 32, "ipv6": "2001:db8:f::", "v6mask": 128}, +    "routers": { +        "r1": { +            "links": { +                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"}, +                "r2": {"ipv4": "auto", "ipv6": "auto"} +            }, +            "bgp": { +                "local_as": "1.100", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "redistribute": [ +                                {"redist_type": "static"} +                             ], +                            "neighbor": { +                                "r2": {"dest_link": {"r1": {}}} +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "redistribute": [ +                                {"redist_type": "static"} +                             ], +                            "neighbor": { +                                "r2": {"dest_link": {"r1": {}}} +                            } +                        } +                    } +                } +            }, +            "static_routes":[ +                { +                   "network":"10.1.1.0/32", +                   "next_hop":"Null0" +                }, +                { +                   "network":"10:1::1:0/128", +                   "next_hop":"Null0" +                }] +            }, +        "r2": { +            "links": { +                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"}, +                "r1": {"ipv4": "auto", "ipv6": "auto"}, +                "r3": {"ipv4": "auto", "ipv6": "auto"} +            }, +            "bgp": { +                "local_as": "1.200", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r1": {"dest_link": {"r2": {}}}, +                                "r3": {"dest_link": {"r2": {}}} +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r1": {"dest_link": {"r2": {}}}, +                                "r3": {"dest_link": {"r2": {}}} +                            } +                        } +                    } +                } +            } +        }, +        "r3": { +            "links": { +                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"}, +                "r2": {"ipv4": "auto", "ipv6": "auto"}, +                "r4": {"ipv4": "auto", "ipv6": "auto"} +            }, +            "bgp": { +                "local_as": "1.300", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r2": {"dest_link": {"r3": {}}}, +                                "r4": {"dest_link": {"r3": {}}} +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r2": {"dest_link": {"r3": {}}}, +                                "r4": {"dest_link": {"r3": {}}} +                            } +                        } +                    } +                } +            } +        }, +        "r4": { +            "links": { +                "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"}, +                "r3": {"ipv4": "auto", "ipv6": "auto"} +            }, +            "bgp": { +                "local_as": "1.400", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r3": {"dest_link": {"r4": {}}} +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r3": {"dest_link": {"r4": {}}} +                            } +                        } +                    } +                } +            } +        } +    } +} diff --git a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py new file mode 100644 index 0000000000..cb8fa1e9f9 --- /dev/null +++ b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py @@ -0,0 +1,420 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, +# Inc. ("NetDEF") in this file. +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + + +""" +Following tests are covered to test BGP Multi-VRF Dynamic Route Leaking: +1. Verify the BGP Local AS functionality by aggregating routes  in between eBGP Peers. +""" + +import os +import sys +import time +import pytest + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topotest import version_cmp + +from lib.common_config import ( +    start_topology, +    write_test_header, +    write_test_footer, +    reset_config_on_routers, +    verify_rib, +    step, +    check_address_types, +    check_router_status +) + +from lib.topolog import logger +from lib.bgp import ( +    verify_bgp_convergence, +    verify_bgp_rib, +    create_router_bgp, +) +from lib.topojson import build_config_from_json + +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + +# Global variables +BGP_CONVERGENCE = False +ADDR_TYPES = check_address_types() +NETWORK_1_1 = {"ipv4": "10.1.1.0/32", "ipv6": "10:1::1:0/128"} +NETWORK_1_2 = {"ipv4": "10.1.2.0/32", "ipv6": "10:1::2:0/128"} +AGGREGATE_NW = {"ipv4": "10.1.0.0/16", "ipv6": "10:1::/96"} +NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} + + +def setup_module(mod): +    """ +    Sets up the pytest environment + +    * `mod`: module name +    """ + +    testsuite_run_time = time.asctime(time.localtime(time.time())) +    logger.info("Testsuite start time: {}".format(testsuite_run_time)) +    logger.info("=" * 40) + +    logger.info("Running setup_module to create topology") + +    # This function initiates the topology build with Topogen... +    json_file = "{}/bgp_local_asn_dot_agg.json".format(CWD) +    tgen = Topogen(json_file, mod.__name__) +    global topo +    topo = tgen.json_topo +    # ... and here it calls Mininet initialization functions. + +    # Starting topology, create tmp files which are loaded to routers +    #  to start daemons and then start routers +    start_topology(tgen) + +    # Creating configuration from JSON +    build_config_from_json(tgen, topo) + +    global BGP_CONVERGENCE +    global ADDR_TYPES +    ADDR_TYPES = check_address_types() + +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    logger.info("Running setup_module() done") + + +def teardown_module(): +    """Teardown the pytest environment""" + +    logger.info("Running teardown_module to delete topology") + +    tgen = get_topogen() + +    # Stop toplogy and Remove tmp files +    tgen.stop_topology() + +    logger.info( +        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) +    ) +    logger.info("=" * 40) + + +#################################################################################################################### +# +#   Testcases +# +#################################################################################################################### + + +def test_verify_bgp_local_as_agg_in_EBGP_p0(request): +    """ +    Verify the BGP Local AS functionality by aggregating routes  in between eBGP Peers. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE + +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") + +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Base config is done as part of JSON") +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    for addr_type in ADDR_TYPES: +        for dut, asn, neighbor in zip(["r2", "r4"], ["1.200", "1.400"], ["r3", "r3"]): +            input_dict_r2_r4 = { +                dut: { +                    "bgp": { +                        "local_as": asn, +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                dut: {"local_asn": {"remote_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r2_r4) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step("Done in base config: Advertise prefix 10.1.1.0/24 from Router-1(AS-1.100).") +    step( +        "Done in base config: Advertise an ipv6 prefix 10:1::1:0/120 from Router-1(AS-1.100)." +    ) +    step("Verify that Static routes are redistributed in BGP process") +    for addr_type in ADDR_TYPES: +        input_static_verify_r1 = { +            "r1": {"static_routes": [{"network": NETWORK_1_1[addr_type]}]} +        } + +        input_static_verify_r2 = { +            "r2": {"static_routes": [{"network": NETWORK_1_2[addr_type]}]} +        } +        result = verify_rib(tgen, addr_type, "r1", input_static_verify_r1) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) + +        result = verify_rib(tgen, addr_type, "r2", input_static_verify_r2) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure aggregate-address to summarise all the advertised routes.") +    for addr_type in ADDR_TYPES: +        route_aggregate = { +            "r3": { +                "bgp": { +                    "address_family": { +                        addr_type: { +                            "unicast": { +                                "aggregate_address": [ +                                    { +                                        "network": AGGREGATE_NW[addr_type], +                                        "summary": True, +                                        "as_set": True, +                                    } +                                ] +                            } +                        } +                    } +                } +            } +        } + +        result = create_router_bgp(tgen, topo, route_aggregate) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step( +        "Verify that we see a summarised route on advertising router R3 " +        "and receiving router R4 for both AFIs" +    ) + +    for addr_type in ADDR_TYPES: +        input_static_agg_r1 = { +            "r1": {"static_routes": [{"network": AGGREGATE_NW[addr_type]}]} +        } +        input_static_r1 = { +            "r1": {"static_routes": [{"network": [NETWORK_1_1[addr_type]]}]} +        } + +        input_static_r2 = { +            "r2": {"static_routes": [{"network": [NETWORK_1_2[addr_type]]}]} +        } + +        for dut in ["r3", "r4"]: +            result = verify_rib(tgen, addr_type, dut, input_static_agg_r1) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +        for dut, input_routes in zip(["r1", "r2"], [input_static_r1, input_static_r2]): +            result = verify_rib(tgen, addr_type, dut, input_routes) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-110 is got added in the AS list 1.110 {1.100,1.110,1.200} by following " +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "{1.100,1.110,1.200}" +    for addr_type in ADDR_TYPES: +        input_static_agg_r1 = { +            "r1": {"static_routes": [{"network": AGGREGATE_NW[addr_type]}]} +        } +        result = verify_bgp_rib( +            tgen, addr_type, dut, input_static_agg_r1, aspath=aspath +        ) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r3" +    aspath = "{1.100,1.200}" +    for addr_type in ADDR_TYPES: +        input_static_agg_r1 = { +            "r1": {"static_routes": [{"network": AGGREGATE_NW[addr_type]}]} +        } +        result = verify_bgp_rib( +            tgen, addr_type, dut, input_static_agg_r1, aspath=aspath +        ) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r4" +    aspath = "1.110 {1.100,1.200}" +    for addr_type in ADDR_TYPES: +        input_static_agg_r1 = { +            "r1": {"static_routes": [{"network": AGGREGATE_NW[addr_type]}]} +        } +        result = verify_bgp_rib( +            tgen, addr_type, dut, input_static_agg_r1, aspath=aspath +        ) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    write_test_footer(tc_name) + + +if __name__ == "__main__": +    args = ["-s"] + sys.argv[1:] +    sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_ecmp.py b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_ecmp.py new file mode 100644 index 0000000000..6937a61c33 --- /dev/null +++ b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_ecmp.py @@ -0,0 +1,524 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, +# Inc. ("NetDEF") in this file. +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# +# +########################################################################################################################################## +# +#   Testcases +# +########################################################################################################################################### +########################################################################################################################################### +# +# 1.10.1.7. Verify the BGP Local AS functionality with ECMP on 8 links by adding no-prepend and replace-as command in between eBGP Peers. +# +################################################################################################################################################# + +import os +import sys +import time +import pytest +import platform + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topotest import version_cmp + +from lib.common_config import ( +    start_topology, +    write_test_header, +    create_static_routes, +    write_test_footer, +    reset_config_on_routers, +    verify_rib, +    step, +    check_address_types, +    check_router_status, +    create_static_routes, +    verify_fib_routes, +) + +from lib.topolog import logger +from lib.bgp import ( +    verify_bgp_convergence, +    verify_bgp_rib, +    create_router_bgp, +) +from lib.topojson import build_config_from_json + +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + +# Global variables +BGP_CONVERGENCE = False +NETWORK = {"ipv4": "10.1.1.0/32", "ipv6": "10:1::1:0/128"} +NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} + + +def setup_module(mod): +    """ +    Sets up the pytest environment + +    * `mod`: module name +    """ + +    testsuite_run_time = time.asctime(time.localtime(time.time())) +    logger.info("Testsuite start time: {}".format(testsuite_run_time)) +    logger.info("=" * 40) + +    logger.info("Running setup_module to create topology") + +    # This function initiates the topology build with Topogen... +    json_file = "{}/bgp_local_asn_dot_ecmp.json".format(CWD) +    tgen = Topogen(json_file, mod.__name__) +    global topo +    topo = tgen.json_topo +    # ... and here it calls Mininet initialization functions. + +    # Starting topology, create tmp files which are loaded to routers +    #  to start daemons and then start routers +    start_topology(tgen) + +    # Creating configuration from JSON +    build_config_from_json(tgen, topo) + +    global BGP_CONVERGENCE +    global ADDR_TYPES +    ADDR_TYPES = check_address_types() + +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    logger.info("Running setup_module() done") + + +def teardown_module(): +    """Teardown the pytest environment""" + +    logger.info("Running teardown_module to delete topology") + +    tgen = get_topogen() + +    # Stop toplogy and Remove tmp files +    tgen.stop_topology() + +    logger.info( +        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) +    ) +    logger.info("=" * 40) + + +########################################################################################################################################## +# +#   Testcases +# +########################################################################################################################################### + + +def test_verify_bgp_local_as_in_ecmp_EBGP_p0(request): +    """ +    Verify the BGP Local AS functionality with ECMP on 8 links by +    adding no-prepend and replace-as command in between eBGP Peers. +    """ + +    tgen = get_topogen() +    global BGP_CONVERGENCE +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Base config is done as part of JSON") +    dut = "r1" +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_dict_static_route = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") +        input_dict_static_route_redist = { +            "r1": { +                "bgp": [ +                    { +                        "address_family": { +                            addr_type: { +                                "unicast": {"redistribute": [{"redist_type": "static"}]} +                            } +                        } +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_static_route_redist) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("Verify IPv4 and IPv6 static routes received on R1") +        result = verify_rib(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) +        result = verify_bgp_rib(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) +        result = verify_fib_routes(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as at R3 towards R2.") +    for addr_type in ADDR_TYPES: +        input_dict_r3_to_r2 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r2": { +                                            "dest_link": { +                                                "r3-link1": { +                                                    "local_asn": {"local_as": "1.110"} +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r3_to_r2) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as at R3 towards R4.") +    dest_link = {} +    for link_no in range(1, 9): +        link = "r3-link" + str(link_no) +        dest_link[link] = {"local_asn": {"local_as": "1.110"}} +    for addr_type in ADDR_TYPES: +        input_dict_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": {"r4": {"dest_link": dest_link}} +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure remote-as at R2 towards R3.") +    for addr_type in ADDR_TYPES: +        input_dict_r2_to_r3 = { +            "r2": { +                "bgp": [ +                    { +                        "local_as": "1.200", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r3": { +                                            "dest_link": { +                                                "r2-link1": { +                                                    "local_asn": {"remote_as": "1.110"} +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r2_to_r3) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure remote-as at R4 towards R3.") +    dest_link = {} +    for link_no in range(1, 9): +        link = "r4-link" + str(link_no) +        dest_link[link] = {"local_asn": {"remote_as": "1.110"}} +    for addr_type in ADDR_TYPES: +        input_dict_r4_to_r3 = { +            "r4": { +                "bgp": [ +                    { +                        "local_as": "1.400", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": {"r3": {"dest_link": dest_link}} +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r4_to_r3) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step("Verify IPv4 and IPv6 static routes received on R3 & R4") +    for addr_type in ADDR_TYPES: +        static_routes_input = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } +        for dut in ["r3", "r4"]: +            result = verify_fib_routes(tgen, addr_type, dut, static_routes_input) +            assert result is True, "Testcase {} : Failed \n Error: {}".format( +                tc_name, result +            ) + +            result = verify_bgp_rib(tgen, addr_type, dut, static_routes_input) +            assert result is True, "Testcase {} : Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-110 is got added in the AS list 1.110 1.200 1.100 by following " +        " commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R2.") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_r3_to_r2 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r2": { +                                            "dest_link": { +                                                "r3-link1": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_no_prep_r3_to_r2) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R4.") +    dest_link = {} +    for link_no in range(1, 9): +        link = "r3-link" + str(link_no) +        dest_link[link] = {"local_asn": {"local_as": "1.110"}} +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": {"r4": {"dest_link": dest_link}} +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_no_prep_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r3" +    aspath = "1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r2": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R2") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_rep_as_r3_to_r2 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r2": { +                                            "dest_link": { +                                                "r3-link1": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_no_prep_rep_as_r3_to_r2) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4") +    dest_link = {} +    for link_no in range(1, 9): +        link = "r3-link" + str(link_no) +        dest_link[link] = { +            "local_asn": {"local_as": "1.110", "no_prepend": True, "replace_as": True} +        } +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_rep_as_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": {"r4": {"dest_link": dest_link}} +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_no_prep_rep_as_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r4" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    write_test_footer(tc_name) + + +if __name__ == "__main__": +    args = ["-s"] + sys.argv[1:] +    sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py new file mode 100644 index 0000000000..e9234f5172 --- /dev/null +++ b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py @@ -0,0 +1,3655 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, +# Inc. ("NetDEF") in this file. +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +########################################################################################################## +# +#   Functionality Testcases +# +########################################################################################################## +""" +1. Verify the BGP Local AS functionality by adding no-prepend and replace-as command in between eBGP Peers. +2. Verify the BGP Local AS functionality by configuring 4 Byte AS at R3 and 2 Byte AS at R2 & R4 in between eBGP Peers. +3. Verify that BGP Local AS functionality by performing graceful restart in between eBGP Peers. +4. Verify the BGP Local AS functionality by adding another AS & by same AS with AS-Prepend command in between eBGP Peers. +4. Verify the BGP Local AS functionality by adding no-prepend and replace-as command in between iBGP Peers. +5. Verify the BGP Local AS functionality with allowas-in in between iBGP Peers. +6. Verify that BGP Local AS functionality by performing shut/ noshut on the interfaces in between BGP neighbors. +7. Verify that BGP Local AS functionality by restarting BGP,Zebra  and FRR services and +   further restarting clear BGP * and shutdown BGP neighbor. +8. Verify the BGP Local AS functionality with different AS configurations. +9. Verify the BGP Local AS functionality with R3& R4 with different AS configurations. +""" + +import os +import sys +import time +import pytest +from copy import deepcopy + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topotest import version_cmp + +from lib.common_config import ( +    start_topology, +    write_test_header, +    create_static_routes, +    write_test_footer, +    reset_config_on_routers, +    verify_rib, +    step, +    get_frr_ipv6_linklocal, +    check_address_types, +    check_router_status, +    create_static_routes, +    verify_fib_routes, +    create_route_maps, +    kill_router_daemons, +    start_router_daemons, +    shutdown_bringup_interface, +) + +from lib.topolog import logger +from lib.bgp import ( +    verify_bgp_convergence, +    clear_bgp_and_verify, +    verify_bgp_rib, +    modify_as_number, +    create_router_bgp, +    verify_bgp_advertised_routes_from_neighbor, +    verify_graceful_restart, +    verify_r_bit, +) +from lib.topojson import build_config_from_json + +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + +# Global variables +NETWORK = {"ipv4": "10.1.1.0/32", "ipv6": "10:1::1:0/128"} +NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} +NEXT_HOP_IP_GR = {"ipv4": "10.0.0.5", "ipv6": "fd00:0:0:1::2/64"} +NEXT_HOP_IP_1 = {"ipv4": "10.0.0.101", "ipv6": "fd00::1"} +NEXT_HOP_IP_2 = {"ipv4": "10.0.0.102", "ipv6": "fd00::2"} + +BGP_CONVERGENCE = False +PREFERRED_NEXT_HOP = "link_local" +KEEPALIVETIMER = 1 +HOLDDOWNTIMER = 3 + + +def setup_module(mod): +    """ +    Sets up the pytest environment + +    * `mod`: module name +    """ + +    testsuite_run_time = time.asctime(time.localtime(time.time())) +    logger.info("Testsuite start time: {}".format(testsuite_run_time)) +    logger.info("=" * 40) + +    logger.info("Running setup_module to create topology") + +    # This function initiates the topology build with Topogen... +    json_file = "{}/bgp_local_asn_dot_topo1.json".format(CWD) +    tgen = Topogen(json_file, mod.__name__) +    global topo +    topo = tgen.json_topo +    # ... and here it calls Mininet initialization functions. + +    # Starting topology, create tmp files which are loaded to routers +    #  to start daemons and then start routers +    start_topology(tgen) + +    # Creating configuration from JSON +    build_config_from_json(tgen, topo) + +    global BGP_CONVERGENCE +    global ADDR_TYPES +    ADDR_TYPES = check_address_types() + +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "setup_module : Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    logger.info("Running setup_module() done") + + +def teardown_module(): +    """Teardown the pytest environment""" + +    logger.info("Running teardown_module to delete topology") + +    tgen = get_topogen() + +    # Stop toplogy and Remove tmp files +    tgen.stop_topology() + +    logger.info( +        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) +    ) +    logger.info("=" * 40) + + +########################################################################################################## +# +#   Local APIs +# +########################################################################################################## + + +def configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut, peer): +    """ +    This function groups the repetitive function calls into one function. +    """ +    result = create_router_bgp(tgen, topo, input_dict) +    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + +    result = clear_bgp_and_verify(tgen, topo, dut) +    assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + +    return True + + +def next_hop_per_address_family( +    tgen, dut, peer, addr_type, next_hop_dict, preferred_next_hop=PREFERRED_NEXT_HOP +): +    """ +    This function returns link_local or global next_hop per address-family +    """ +    intferface = topo["routers"][peer]["links"]["{}".format(dut)]["interface"] +    if addr_type == "ipv6" and "link_local" in preferred_next_hop: +        next_hop = get_frr_ipv6_linklocal(tgen, peer, intf=intferface) +    else: +        next_hop = next_hop_dict[addr_type] + +    return next_hop + + +########################################################################################################## +# +#   Testcases +# +########################################################################################################## + + +def test_verify_bgp_local_as_in_EBGP_p0(request): +    """ +    Verify the BGP Local AS functionality by adding no-prepend and +    replace-as command in between eBGP Peers. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") + +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Base config is done as part of JSON") +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    for addr_type in ADDR_TYPES: +        for dut, asn, neighbor in zip(["r2", "r4"], ["1.200", "1.400"], ["r3", "r3"]): +            input_dict_r2_r4 = { +                dut: { +                    "bgp": { +                        "local_as": asn, +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                dut: {"local_asn": {"remote_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r2_r4) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    # configure static routes +    step("Done in base config: Advertise prefix 10.1.1.0/32 from Router-1(AS-1.100).") +    step( +        "Done in base config: Advertise an ipv6 prefix 10:1::1:0/128 from Router-1(AS-1.100)." +    ) +    step("Verify that Static routes are redistributed in BGP process") + +    dut = "r1" +    protocol = "bgp" +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_static_r1 = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_static_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") + +        input_static_redist_r1 = { +            "r1": { +                "bgp": { +                    "address_family": { +                        addr_type: { +                            "unicast": {"redistribute": [{"redist_type": "static"}]} +                        } +                    } +                } +            } +        } +        result = create_router_bgp(tgen, topo, input_static_redist_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Verify that Static routes are redistributed in BGP process") +    for addr_type in ADDR_TYPES: +        input_static_verify_r1 = { +            "r1": {"static_routes": [{"network": NETWORK[addr_type]}]} +        } + +        result = verify_rib(tgen, addr_type, "r1", input_static_verify_r1) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) + +        for dut in ["r3", "r4"]: +            result = verify_rib(tgen, addr_type, dut, input_static_r1) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +        for dut, input_routes in zip(["r1"], [input_static_r1]): +            result = verify_rib(tgen, addr_type, dut, input_routes) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step("Verify advertised routes to R4 at R3") +    expected_routes = { +        "ipv4": [ +            {"network": "10.1.1.0/32", "nexthop": ""}, +        ], +        "ipv6": [ +            {"network": "10:1::1:0/128", "nexthop": ""}, +        ], +    } +    result = verify_bgp_advertised_routes_from_neighbor( +        tgen, topo, dut="r3", peer="r4", expected_routes=expected_routes +    ) +    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + +    dut = "r3" +    aspath = "1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r4" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    write_test_footer(tc_name) + + +def test_verify_bgp_local_as_in_EBGP_4B_AS_mid_4B_AS_p0(request): +    """ +    Verify the BGP Local AS functionality by configuring 4 Byte AS +    at R3 and 4 Byte AS at R2 & R4 in between eBGP Peers. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE + +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") + +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Base config is done as part of JSON") +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "183.2926" +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    for addr_type in ADDR_TYPES: +        for dut, asn, neighbor in zip(["r2", "r4"], ["1.200", "1.400"], ["r3", "r3"]): +            input_dict_r2_r4 = { +                dut: { +                    "bgp": { +                        "local_as": asn, +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                dut: { +                                                    "local_asn": { +                                                        "remote_as": "183.2926" +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r2_r4) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    # configure static routes +    step("Done in base config: Advertise prefix 10.1.1.0/32 from Router-1(AS-1.100).") +    step( +        "Done in base config: Advertise an ipv6 prefix 10:1::1:0/128 from Router-1(AS-1.100)." +    ) +    step("Verify that Static routes are redistributed in BGP process") + +    dut = "r1" +    protocol = "bgp" +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_static_r1 = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_static_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") + +        input_static_redist_r1 = { +            "r1": { +                "bgp": { +                    "address_family": { +                        addr_type: { +                            "unicast": {"redistribute": [{"redist_type": "static"}]} +                        } +                    } +                } +            } +        } +        result = create_router_bgp(tgen, topo, input_static_redist_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Verify that Static routes are redistributed in BGP process") +    for addr_type in ADDR_TYPES: +        input_static_verify_r1 = { +            "r1": {"static_routes": [{"network": NETWORK[addr_type]}]} +        } + +        result = verify_rib(tgen, addr_type, "r1", input_static_verify_r1) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) + +        for dut in ["r3", "r4"]: +            result = verify_rib(tgen, addr_type, dut, input_static_r1) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +        for dut, input_routes in zip(["r1"], [input_static_r1]): +            result = verify_rib(tgen, addr_type, dut, input_routes) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-183.2926 is got added in the AS list 183.2926 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "183.2926 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "183.2926", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step("Verify advertised routes to R4 at R3") +    expected_routes = { +        "ipv4": [ +            {"network": "10.1.1.0/32", "nexthop": ""}, +        ], +        "ipv6": [ +            {"network": "10:1::1:0/128", "nexthop": ""}, +        ], +    } +    result = verify_bgp_advertised_routes_from_neighbor( +        tgen, topo, dut="r3", peer="r4", expected_routes=expected_routes +    ) +    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + +    dut = "r3" +    aspath = "1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "183.2926", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r4" +    aspath = "183.2926 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    write_test_footer(tc_name) + + +def test_verify_bgp_local_as_GR_EBGP_p0(request): +    """ +    Verify that BGP Local AS functionality by performing graceful restart in between eBGP Peers. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE + +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Configure basic BGP Peerings between R1,R2,R3 and R4") +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_dict_static_route = { +            "r1": { +                "static_routes": [ +                    { +                        "network": NETWORK[addr_type], +                        "next_hop": NEXT_HOP_IP_GR[addr_type], +                    } +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") +        input_dict_static_route_redist = { +            "r1": { +                "bgp": [ +                    { +                        "address_family": { +                            addr_type: { +                                "unicast": {"redistribute": [{"redist_type": "static"}]} +                            } +                        } +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_static_route_redist) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) +        step("Verify IPv4 and IPv6 static routes received on R1") +        result = verify_rib(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) +        result = verify_bgp_rib(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) +        result = verify_fib_routes(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as at R3 towards R2.") +    for addr_type in ADDR_TYPES: +        input_dict_r3_to_r2 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r2": { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r3_to_r2) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        input_dict_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r4": { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure remote-as at R2 towards R3.") +    for addr_type in ADDR_TYPES: +        input_dict_r2_to_r3 = { +            "r2": { +                "bgp": [ +                    { +                        "local_as": "1.200", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r3": { +                                            "dest_link": { +                                                "r2": { +                                                    "local_asn": {"remote_as": "1.110"} +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r2_to_r3) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure remote-as at R4 towards R3.") +    for addr_type in ADDR_TYPES: +        input_dict_r4_to_r3 = { +            "r4": { +                "bgp": [ +                    { +                        "local_as": "1.400", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r3": { +                                            "dest_link": { +                                                "r4": { +                                                    "local_asn": {"remote_as": "1.110"} +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r4_to_r3) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step("Verify IPv4 and IPv6 static routes received on R3 & R4") +    for addr_type in ADDR_TYPES: +        static_routes_input = { +            "r1": { +                "static_routes": [ +                    { +                        "network": NETWORK[addr_type], +                        "next_hop": NEXT_HOP_IP_GR[addr_type], +                    } +                ] +            } +        } +        for dut in ["r3", "r4"]: +            result = verify_fib_routes(tgen, addr_type, dut, static_routes_input) +            assert result is True, "Testcase {} : Failed \n Error: {}".format( +                tc_name, result +            ) + +            result = verify_bgp_rib(tgen, addr_type, dut, static_routes_input) +            assert result is True, "Testcase {} : Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following " +        " commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    """ +    GR Steps : Helper BGP router R2, mark and unmark IPV4 routes +    as stale as the restarting router R3 come up within the restart time +    """ +    # Create route-map to prefer global next-hop +    input_dict = { +        "r2": { +            "route_maps": { +                "rmap_global": [ +                    {"action": "permit", "set": {"ipv6": {"nexthop": "prefer-global"}}} +                ] +            } +        }, +        "r3": { +            "route_maps": { +                "rmap_global": [ +                    {"action": "permit", "set": {"ipv6": {"nexthop": "prefer-global"}}} +                ] +            } +        }, +    } +    result = create_route_maps(tgen, input_dict) +    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + +    # Configure neighbor for route map +    input_dict_neigh_rm = { +        "r2": { +            "bgp": { +                "address_family": { +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r3": { +                                    "dest_link": { +                                        "r2": { +                                            "route_maps": [ +                                                { +                                                    "name": "rmap_global", +                                                    "direction": "in", +                                                } +                                            ] +                                        } +                                    } +                                } +                            } +                        } +                    } +                } +            } +        }, +        "r3": { +            "bgp": { +                "address_family": { +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r2": { +                                    "dest_link": { +                                        "r3": { +                                            "route_maps": [ +                                                { +                                                    "name": "rmap_global", +                                                    "direction": "in", +                                                } +                                            ] +                                        } +                                    } +                                } +                            } +                        } +                    } +                } +            } +        }, +    } + +    result = create_router_bgp(tgen, topo, input_dict_neigh_rm) +    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + +    # Configure graceful-restart +    input_dict = { +        "r2": { +            "bgp": { +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r3": { +                                    "dest_link": { +                                        "r2": { +                                            "graceful-restart-helper": True, +                                            "local_asn": {"remote_as": "1.110"}, +                                        } +                                    } +                                } +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r3": { +                                    "dest_link": { +                                        "r2": { +                                            "graceful-restart-helper": True, +                                            "local_asn": {"remote_as": "1.110"}, +                                        } +                                    } +                                } +                            } +                        } +                    }, +                } +            } +        }, +        "r3": { +            "bgp": { +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r2": {"dest_link": {"r3": {"graceful-restart": True}}} +                            } +                        } +                    }, +                    "ipv6": { +                        "unicast": { +                            "neighbor": { +                                "r2": {"dest_link": {"r3": {"graceful-restart": True}}} +                            } +                        } +                    }, +                } +            } +        }, +    } + +    configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r3", peer="r2") +    for addr_type in ADDR_TYPES: +        result = verify_graceful_restart( +            tgen, topo, addr_type, input_dict, dut="r3", peer="r2" +        ) +        assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + +        # Verifying BGP RIB routes +        dut = "r2" +        peer = "r3" +        next_hop = next_hop_per_address_family( +            tgen, dut, peer, addr_type, NEXT_HOP_IP_2, preferred_next_hop="global" +        ) +        input_topo = {key: topo["routers"][key] for key in ["r3"]} +        result = verify_bgp_rib(tgen, addr_type, dut, input_topo) +        assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + +        # Verifying RIB routes +        result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, "bgp") +        assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + +    logger.info("[Phase 2] : R3 goes for reload  ") + +    kill_router_daemons(tgen, "r3", ["bgpd"]) + +    logger.info( +        "[Phase 3] : R3 is still down, restart time 120 sec." +        " So time verify the routes are present in BGP RIB" +        " and ZEBRA" +    ) + +    for addr_type in ADDR_TYPES: +        # Verifying BGP RIB routes +        next_hop = next_hop_per_address_family( +            tgen, dut, peer, addr_type, NEXT_HOP_IP_2, preferred_next_hop="global" +        ) +        result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) +        assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + +        # Verifying RIB routes +        protocol = "bgp" +        result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) +        assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + +    logger.info("[Phase 5] : R3 is about to come up now  ") +    start_router_daemons(tgen, "r3", ["bgpd"]) + +    logger.info("[Phase 5] : R3 is UP Now !  ") + +    for addr_type in ADDR_TYPES: +        result = verify_bgp_convergence(tgen, topo) +        assert ( +            result is True +        ), "BGP Convergence after BGPd restart" " :Failed \n Error:{}".format(result) + +        # Verifying GR stats +        result = verify_graceful_restart( +            tgen, topo, addr_type, input_dict, dut="r3", peer="r2" +        ) +        assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + +        result = verify_r_bit(tgen, topo, addr_type, input_dict, dut="r2", peer="r3") +        assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + +        # Verifying BGP RIB routes +        next_hop = next_hop_per_address_family( +            tgen, dut, peer, addr_type, NEXT_HOP_IP_2, preferred_next_hop="global" +        ) +        result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop) +        assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + +        # Verifying RIB routes +        protocol = "bgp" +        result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol) +        assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result) + +    step("Configure local-as with no-prepend at R3 towards R2.") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_r3_to_r2 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r2": { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_no_prep_r3_to_r2) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r4": { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_no_prep_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r3" +    aspath = "1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r2": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R2") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_rep_as_r3_to_r2 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r2": { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_no_prep_rep_as_r3_to_r2) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_rep_as_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r4": { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_no_prep_rep_as_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r4" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    write_test_footer(tc_name) + + +def test_verify_bgp_local_as_in_EBGP_aspath_p0(request): +    """ +    Verify the BGP Local AS functionality by adding another AS & by same AS with AS-Prepend command in between eBGP Peers. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE + +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Configure basic BGP Peerings between R1,R2,R3 and R4") +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    for addr_type in ADDR_TYPES: +        for dut, asn, neighbor in zip(["r2", "r4"], ["1.200", "1.400"], ["r3", "r3"]): +            input_dict_r2_r4 = { +                dut: { +                    "bgp": { +                        "local_as": asn, +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                dut: {"local_asn": {"remote_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r2_r4) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    # configure static routes +    step("Done in base config: Advertise prefix 10.1.1.0/32 from Router-1(AS-1.100).") +    step( +        "Done in base config: Advertise an ipv6 prefix 10:1::1:0/128 from Router-1(AS-1.100)." +    ) +    step("Verify that Static routes are redistributed in BGP process") + +    dut = "r1" +    protocol = "bgp" +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_static_r1 = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_static_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") + +        input_static_redist_r1 = { +            "r1": { +                "bgp": { +                    "address_family": { +                        addr_type: { +                            "unicast": {"redistribute": [{"redist_type": "static"}]} +                        } +                    } +                } +            } +        } +        result = create_router_bgp(tgen, topo, input_static_redist_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Verify that Static routes are redistributed in BGP process") +    for addr_type in ADDR_TYPES: +        input_static_verify_r1 = { +            "r1": {"static_routes": [{"network": NETWORK[addr_type]}]} +        } + +        result = verify_rib(tgen, addr_type, "r1", input_static_verify_r1) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) + +        for dut in ["r3", "r4"]: +            result = verify_rib(tgen, addr_type, dut, input_static_r1) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +        for dut, input_routes in zip(["r1"], [input_static_r1]): +            result = verify_rib(tgen, addr_type, dut, input_routes) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step("Verify advertised routes to R4 at R3") +    expected_routes = { +        "ipv4": [ +            {"network": "10.1.1.0/32", "nexthop": ""}, +        ], +        "ipv6": [ +            {"network": "10:1::1:0/128", "nexthop": ""}, +        ], +    } +    result = verify_bgp_advertised_routes_from_neighbor( +        tgen, topo, dut="r3", peer="r4", expected_routes=expected_routes +    ) +    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + +    dut = "r3" +    aspath = "1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure a route-map on R3 to prepend AS 2 times.") +    for addr_type in ADDR_TYPES: +        input_dict_4 = { +            "r3": { +                "route_maps": { +                    "ASP_{}".format(addr_type): [ +                        { +                            "action": "permit", +                            "set": { +                                "path": {"as_num": "1.1000 1.1000", "as_action": "prepend"} +                            }, +                        } +                    ] +                } +            } +        } +        result = create_route_maps(tgen, input_dict_4) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure route map in out direction on R4") +        # Configure neighbor for route map +        input_dict_7 = { +            "r3": { +                "bgp": { +                    "address_family": { +                        addr_type: { +                            "unicast": { +                                "neighbor": { +                                    "r4": { +                                        "dest_link": { +                                            "r3": { +                                                "route_maps": [ +                                                    { +                                                        "name": "ASP_{}".format( +                                                            addr_type +                                                        ), +                                                        "direction": "out", +                                                    } +                                                ] +                                            } +                                        } +                                    } +                                } +                            } +                        } +                    } +                } +            } +        } + +        result = create_router_bgp(tgen, topo, input_dict_7) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step( +        "Verify that AS-1.300 is got replaced with 1.200 in the AS list 1.110 1.1000 1.1000 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r4" +    aspath = "1.110 1.1000 1.1000 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) +    write_test_footer(tc_name) + + +def test_verify_bgp_local_as_in_iBGP_p0(request): +    """ +    Verify the BGP Local AS functionality by adding no-prepend and replace-as command in between iBGP Peers. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Modify AS Number for R3") +    input_dict_modify_as_number = {"r3": {"bgp": {"local_as": "1.200"}}} +    result = modify_as_number(tgen, topo, input_dict_modify_as_number) + +    step("Base config is done as part of JSON") +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_dict_static_route = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") +        input_dict_static_route_redist = { +            "r1": { +                "bgp": [ +                    { +                        "address_family": { +                            addr_type: { +                                "unicast": {"redistribute": [{"redist_type": "static"}]} +                            } +                        } +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_static_route_redist) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("Verify IPv4 and IPv6 static routes received on R1") +        result = verify_rib(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) +        result = verify_bgp_rib(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) +        result = verify_fib_routes(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        input_dict_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.200", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r4": { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure remote-as at R4 towards R3.") +    for addr_type in ADDR_TYPES: +        input_dict_r4_to_r3 = { +            "r4": { +                "bgp": [ +                    { +                        "local_as": "1.400", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r3": { +                                            "dest_link": { +                                                "r4": { +                                                    "local_asn": {"remote_as": "1.110"} +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r4_to_r3) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure remote-as at R2 towards R3.") +    for addr_type in ADDR_TYPES: +        input_dict_r2_to_r3 = { +            "r2": { +                "bgp": [ +                    { +                        "local_as": "1.200", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r3": { +                                            "dest_link": { +                                                "r2": { +                                                    "next_hop_self": True, +                                                    "local_asn": { +                                                        "remote_as": "1.200", +                                                    }, +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r2_to_r3) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step("Verify IPv4 and IPv6 static routes received on R3 & R4") +    for addr_type in ADDR_TYPES: +        static_routes_input = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } +        for dut in ["r3", "r4"]: +            result = verify_fib_routes(tgen, addr_type, dut, static_routes_input) +            assert result is True, "Testcase {} : Failed \n Error: {}".format( +                tc_name, result +            ) + +            result = verify_bgp_rib(tgen, addr_type, dut, static_routes_input) +            assert result is True, "Testcase {} : Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following " +        " commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    dut = "r4" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.200", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r4": { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_no_prep_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r3" +    aspath = "1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_rep_as_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.200", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r4": { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_no_prep_rep_as_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r4" +    aspath = "1.110 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    write_test_footer(tc_name) + + +def test_verify_bgp_local_as_allow_as_in_iBGP_p0(request): +    """ +    Verify the BGP Local AS functionality with allowas-in in between iBGP Peers. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Modidy AS Number for R4") +    input_dict_modify_as_number = {"r4": {"bgp": {"local_as": "1.100"}}} +    result = modify_as_number(tgen, topo, input_dict_modify_as_number) + +    step("Base config is done as part of JSON") +    dut = "r1" +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_dict_static_route = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") +        input_dict_static_route_redist = { +            "r1": { +                "bgp": [ +                    { +                        "address_family": { +                            addr_type: { +                                "unicast": {"redistribute": [{"redist_type": "static"}]} +                            } +                        } +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_static_route_redist) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("Verify IPv4 and IPv6 static routes received on R1") +        result = verify_rib(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) +        result = verify_bgp_rib(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) +        result = verify_fib_routes(tgen, addr_type, "r1", input_dict_static_route) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure allow-as at R4") +    for addr_type in ADDR_TYPES: +        allow_as_config_r4 = { +            "r4": { +                "bgp": [ +                    { +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r3": { +                                            "dest_link": { +                                                "r4": { +                                                    "allowas-in": { +                                                        "number_occurences": 1 +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        } +                    } +                ] +            } +        } + +        step( +            "Configuring allow-as for {} address-family on router R4 ".format(addr_type) +        ) +        result = create_router_bgp(tgen, topo, allow_as_config_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    # now modify the as in r4 and reconfig bgp in r3 with new remote as. +    topo1 = deepcopy(topo) +    topo1["routers"]["r4"]["bgp"]["local_as"] = "1.100" + +    delete_bgp = {"r3": {"bgp": {"delete": True}}} +    result = create_router_bgp(tgen, topo1, delete_bgp) +    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) +    build_config_from_json(tgen, topo1, save_bkup=False) + +    step("Configure local-as at R3 towards R2.") +    for addr_type in ADDR_TYPES: +        input_dict_r3_to_r2 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r2": { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo1, input_dict_r3_to_r2) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        input_dict_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r4": { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo1, input_dict_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure remote-as at R2 towards R3.") +    for addr_type in ADDR_TYPES: +        input_dict_r2_to_r3 = { +            "r2": { +                "bgp": [ +                    { +                        "local_as": "1.200", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r3": { +                                            "dest_link": { +                                                "r2": { +                                                    "local_asn": {"remote_as": "1.110"} +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo1, input_dict_r2_to_r3) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure remote-as at R4 towards R3.") +    for addr_type in ADDR_TYPES: +        input_dict_r4_to_r3 = { +            "r4": { +                "bgp": [ +                    { +                        "local_as": "1.100", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r3": { +                                            "dest_link": { +                                                "r4": { +                                                    "local_asn": {"remote_as": "1.110"} +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo1, input_dict_r4_to_r3) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo1) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step("Verify IPv4 and IPv6 static routes received on R3 & R4") +    for addr_type in ADDR_TYPES: +        static_routes_input = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } +        for dut in ["r3", "r4"]: +            result = verify_fib_routes(tgen, addr_type, dut, static_routes_input) +            assert result is True, "Testcase {} : Failed \n Error: {}".format( +                tc_name, result +            ) + +            result = verify_bgp_rib(tgen, addr_type, dut, static_routes_input) +            assert result is True, "Testcase {} : Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following " +        " commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R2.") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_r3_to_r2 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r2": { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo1, input_dict_no_prep_r3_to_r2) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r4": { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo1, input_dict_no_prep_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo1) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r3" +    aspath = "1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r2": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R2") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_rep_as_r3_to_r2 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r2": { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo1, input_dict_no_prep_rep_as_r3_to_r2) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4") +    for addr_type in ADDR_TYPES: +        input_dict_no_prep_rep_as_r3_to_r4 = { +            "r3": { +                "bgp": [ +                    { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        "r4": { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                ] +            } +        } +        result = create_router_bgp(tgen, topo1, input_dict_no_prep_rep_as_r3_to_r4) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo1) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r4" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    write_test_footer(tc_name) + + +def test_verify_bgp_local_as_in_EBGP_port_reset_p0(request): +    """ +    Verify that BGP Local AS functionality by performing shut/ noshut on the interfaces in between BGP neighbors. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") + +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Base config is done as part of JSON") +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    for addr_type in ADDR_TYPES: +        for dut, asn, neighbor in zip(["r2", "r4"], ["1.200", "1.400"], ["r3", "r3"]): +            input_dict_r2_r4 = { +                dut: { +                    "bgp": { +                        "local_as": asn, +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                dut: {"local_asn": {"remote_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r2_r4) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    # configure static routes +    step("Done in base config: Advertise prefix 10.1.1.0/32 from Router-1(AS-1.100).") +    step( +        "Done in base config: Advertise an ipv6 prefix 10:1::1:0/128 from Router-1(AS-1.100)." +    ) +    step("Verify that Static routes are redistributed in BGP process") +    dut = "r1" +    protocol = "bgp" +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_static_r1 = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_static_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") +        input_static_redist_r1 = { +            "r1": { +                "bgp": { +                    "address_family": { +                        addr_type: { +                            "unicast": {"redistribute": [{"redist_type": "static"}]} +                        } +                    } +                } +            } +        } +        result = create_router_bgp(tgen, topo, input_static_redist_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Verify that Static routes are redistributed in BGP process") +    for addr_type in ADDR_TYPES: +        input_static_verify_r1 = { +            "r1": {"static_routes": [{"network": NETWORK[addr_type]}]} +        } + +        result = verify_rib(tgen, addr_type, "r1", input_static_verify_r1) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) + +        for dut in ["r3", "r4"]: +            result = verify_rib(tgen, addr_type, dut, input_static_r1) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +        for dut, input_routes in zip(["r1"], [input_static_r1]): +            result = verify_rib(tgen, addr_type, dut, input_routes) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("Api call to modfiy BGP timers at R3") +    for addr_type in ADDR_TYPES: +        input_dict_r3_timers = { +            "r3": { +                "bgp": { +                    "local_as": "1.300", +                    "address_family": { +                        addr_type: { +                            "unicast": { +                                "neighbor": { +                                    "r4": { +                                        "dest_link": { +                                            "r3": { +                                                "keepalivetimer": KEEPALIVETIMER, +                                                "holddowntimer": HOLDDOWNTIMER, +                                            } +                                        } +                                    } +                                } +                            } +                        } +                    }, +                } +            } +        } +        result = create_router_bgp(tgen, topo, input_dict_r3_timers) +        assert result is True, "Testcase {} :Failed \n Error: {}".format( +            tc_name, result +        ) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Verify advertised routes at R3 towards R4") +    expected_routes = { +        "ipv4": [ +            {"network": "10.1.1.0/32", "nexthop": ""}, +        ], +        "ipv6": [ +            {"network": "10:1::1:0/128", "nexthop": ""}, +        ], +    } +    result = verify_bgp_advertised_routes_from_neighbor( +        tgen, topo, dut="r3", peer="r4", expected_routes=expected_routes +    ) +    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + +    for count in range(1, 1): +        step("Iteration {}".format(count)) +        step("Shut down connecting interface between R3<<>>R4 on R3.") + +        intf1 = topo["routers"]["r3"]["links"]["r4"]["interface"] + +        interfaces = [intf1] +        for intf in interfaces: +            shutdown_bringup_interface(tgen, "r3", intf, False) + +        step( +            "On R3, all BGP peering in respective vrf instances go down" +            " when the interface is shut" +        ) + +        result = verify_bgp_convergence(tgen, topo, expected=False) +        assert result is not True, ( +            "Testcase {} :Failed \n " +            "Expected Behaviour: BGP will not be converged \n " +            "Error {}".format(tc_name, result) +        ) + +    step("BGP neighborship is verified after restart of r3") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r3" +    aspath = "1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    dut = "r4" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    write_test_footer(tc_name) + + +def test_verify_bgp_local_as_in_EBGP_negative2_p0(request): +    """ +    Verify the BGP Local AS functionality with different AS configurations. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") + +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Base config is done as part of JSON") +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    for addr_type in ADDR_TYPES: +        for dut, asn, neighbor in zip(["r2", "r4"], ["1.200", "1.400"], ["r3", "r3"]): +            input_dict_r2_r4 = { +                dut: { +                    "bgp": { +                        "local_as": asn, +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                dut: {"local_asn": {"remote_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r2_r4) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    # configure static routes +    step("Done in base config: Advertise prefix 10.1.1.0/32 from Router-1(AS-1.100).") +    step( +        "Done in base config: Advertise an ipv6 prefix 10:1::1:0/128 from Router-1(AS-1.100)." +    ) +    step("Verify that Static routes are redistributed in BGP process") + +    dut = "r1" +    protocol = "bgp" +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_static_r1 = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_static_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") + +        input_static_redist_r1 = { +            "r1": { +                "bgp": { +                    "address_family": { +                        addr_type: { +                            "unicast": {"redistribute": [{"redist_type": "static"}]} +                        } +                    } +                } +            } +        } +        result = create_router_bgp(tgen, topo, input_static_redist_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Verify that Static routes are redistributed in BGP process") +    for addr_type in ADDR_TYPES: +        input_static_verify_r1 = { +            "r1": {"static_routes": [{"network": NETWORK[addr_type]}]} +        } + +        result = verify_rib(tgen, addr_type, "r1", input_static_verify_r1) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) + +        for dut in ["r3", "r4"]: +            result = verify_rib(tgen, addr_type, dut, input_static_r1) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +        for dut, input_routes in zip(["r1"], [input_static_r1]): +            result = verify_rib(tgen, addr_type, dut, input_routes) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step("Verify advertised routes to R4 at R3") +    expected_routes = { +        "ipv4": [ +            {"network": "10.1.1.0/32", "nexthop": ""}, +        ], +        "ipv6": [ +            {"network": "10:1::1:0/128", "nexthop": ""}, +        ], +    } +    result = verify_bgp_advertised_routes_from_neighbor( +        tgen, topo, dut="r3", peer="r4", expected_routes=expected_routes +    ) +    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + +    step( +        "Verify that AS-1.110 is not prepended in the AS list 1.110 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) +    step("Verify that AS-1.300 is replaced with AS-1.110 at R3 router.") +    dut = "r4" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    # configure negative scenarios +    step("Configure local-as at R3 towards R4.") +    input_dict_r3 = { +        "r3": { +            "bgp": { +                "local_as": "1.300", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r4": { +                                    "dest_link": { +                                        "r3": {"local_asn": {"local_as": "1.300"}} +                                    } +                                } +                            } +                        } +                    } +                }, +            } +        } +    } +    if "bgp" in topo["routers"]["r3"].keys(): +        result = create_router_bgp(tgen, topo, input_dict_r3) +        assert result is not True, ( +            "Testcase {} :Failed \n " +            "Expected Behaviour: Cannot have local-as same as BGP AS number \n " +            "Error {}".format(tc_name, result) +        ) + +    step("Configure another local-as at R3 towards R4.") +    input_dict_r3 = { +        "r3": { +            "bgp": { +                "local_as": "1.110", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r4": { +                                    "dest_link": { +                                        "r3": {"local_asn": {"local_as": "1.110"}} +                                    } +                                } +                            } +                        } +                    } +                }, +            } +        } +    } +    if "bgp" in topo["routers"]["r3"].keys(): +        result = create_router_bgp(tgen, topo, input_dict_r3) +        assert result is not True, ( +            "Testcase {} :Failed \n " +            "Expected Behaviour: Cannot have local-as same as BGP AS number \n " +            "Error {}".format(tc_name, result) +        ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    write_test_footer(tc_name) + + +def test_verify_bgp_local_as_in_EBGP_negative3_p0(request): +    """ +    Verify the BGP Local AS functionality with R3& R4 with different AS configurations. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE + +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +        reset_config_on_routers(tgen) + +    step("Configure basic BGP Peerings between R1,R2,R3 and R4") +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    for addr_type in ADDR_TYPES: +        for dut, asn, neighbor in zip(["r2", "r4"], ["1.200", "1.400"], ["r3", "r3"]): +            input_dict_r2_r4 = { +                dut: { +                    "bgp": { +                        "local_as": asn, +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                dut: {"local_asn": {"remote_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r2_r4) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    # configure static routes +    step("Done in base config: Advertise prefix 10.1.1.0/32 from Router-1(AS-1.100).") +    step( +        "Done in base config: Advertise an ipv6 prefix 10:1::1:0/128 from Router-1(AS-1.100)." +    ) +    step("Verify that Static routes are redistributed in BGP process") + +    dut = "r1" +    protocol = "bgp" +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_static_r1 = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_static_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") + +        input_static_redist_r1 = { +            "r1": { +                "bgp": { +                    "address_family": { +                        addr_type: { +                            "unicast": {"redistribute": [{"redist_type": "static"}]} +                        } +                    } +                } +            } +        } +        result = create_router_bgp(tgen, topo, input_static_redist_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Verify that Static routes are redistributed in BGP process") +    for addr_type in ADDR_TYPES: +        input_static_verify_r1 = { +            "r1": {"static_routes": [{"network": NETWORK[addr_type]}]} +        } + +        result = verify_rib(tgen, addr_type, "r1", input_static_verify_r1) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) + +        for dut in ["r3", "r4"]: +            result = verify_rib(tgen, addr_type, dut, input_static_r1) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +        for dut, input_routes in zip(["r1"], [input_static_r1]): +            result = verify_rib(tgen, addr_type, dut, input_routes) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    # Perform Negative scenarios +    step("Configure another local-as at R3 towards R4.") +    input_dict_r3 = { +        "r3": { +            "bgp": { +                "local_as": "1.300", +                "address_family": { +                    "ipv4": { +                        "unicast": { +                            "neighbor": { +                                "r4": { +                                    "dest_link": { +                                        "r3": {"local_asn": {"local_as": "1.300"}} +                                    } +                                } +                            } +                        } +                    } +                }, +            } +        } +    } +    if "bgp" in topo["routers"]["r3"].keys(): +        result = create_router_bgp(tgen, topo, input_dict_r3) +        assert result is not True, ( +            "Testcase {} :Failed \n " +            "Expected Behaviour: Cannot have local-as same as BGP AS number \n " +            "Error {}".format(tc_name, result) +        ) + +    write_test_footer(tc_name) + + +def test_verify_bgp_local_as_in_EBGP_restart_daemons_p0(request): +    """ +    Verify that BGP Local AS functionality by restarting BGP,Zebra  and FRR services and +    further restarting clear BGP * and shutdown BGP neighbor. +    """ +    tgen = get_topogen() +    global BGP_CONVERGENCE +    if BGP_CONVERGENCE != True: +        pytest.skip("skipped because of BGP Convergence failure") +    # test case name +    tc_name = request.node.name +    write_test_header(tc_name) +    if tgen.routers_have_failure(): +        check_router_status(tgen) +    reset_config_on_routers(tgen) + +    step("Base config is done as part of JSON") +    step("Configure local-as at R3 towards R4.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": {"local_asn": {"local_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    for addr_type in ADDR_TYPES: +        for dut, asn, neighbor in zip(["r2", "r4"], ["1.200", "1.400"], ["r3", "r3"]): +            input_dict_r2_r4 = { +                dut: { +                    "bgp": { +                        "local_as": asn, +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                dut: {"local_asn": {"remote_as": "1.110"}} +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r2_r4) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    # configure static routes +    step("Done in base config: Advertise prefix 10.1.1.0/32 from Router-1(AS-1.100).") +    step( +        "Done in base config: Advertise an ipv6 prefix 10:1::1:0/128 from Router-1(AS-1.100)." +    ) +    step("Verify that Static routes are redistributed in BGP process") +    dut = "r1" +    protocol = "bgp" +    for addr_type in ADDR_TYPES: +        # Enable static routes +        input_static_r1 = { +            "r1": { +                "static_routes": [ +                    {"network": NETWORK[addr_type], "next_hop": NEXT_HOP_IP[addr_type]} +                ] +            } +        } + +        logger.info("Configure static routes") +        result = create_static_routes(tgen, input_static_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +        step("configure redistribute static in Router BGP in R1") +        input_static_redist_r1 = { +            "r1": { +                "bgp": { +                    "address_family": { +                        addr_type: { +                            "unicast": {"redistribute": [{"redist_type": "static"}]} +                        } +                    } +                } +            } +        } +        result = create_router_bgp(tgen, topo, input_static_redist_r1) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Verify that Static routes are redistributed in BGP process") +    for addr_type in ADDR_TYPES: +        input_static_verify_r1 = { +            "r1": {"static_routes": [{"network": NETWORK[addr_type]}]} +        } + +        result = verify_rib(tgen, addr_type, "r1", input_static_verify_r1) +        assert result is True, "Testcase {}: Failed \n Error: {}".format( +            tc_name, result +        ) + +        for dut in ["r3", "r4"]: +            result = verify_rib(tgen, addr_type, dut, input_static_r1) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +        for dut, input_routes in zip(["r1"], [input_static_r1]): +            result = verify_rib(tgen, addr_type, dut, input_routes) +            assert result is True, "Testcase {}: Failed \n Error: {}".format( +                tc_name, result +            ) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Kill BGPd daemon on R3.") +    kill_router_daemons(tgen, "r3", ["bgpd"]) + +    step("Bring up BGPd daemon on R3.") +    start_router_daemons(tgen, "r3", ["bgpd"]) + +    step( +        "Verify that AS-1.110 is got added in the AS list 1.110 1.200 1.100 by following" +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Verify advertised routes at R3 towards R4") +    expected_routes = { +        "ipv4": [ +            {"network": "10.1.1.0/32", "nexthop": ""}, +        ], +        "ipv6": [ +            {"network": "10:1::1:0/128", "nexthop": ""}, +        ], +    } +    result = verify_bgp_advertised_routes_from_neighbor( +        tgen, topo, dut="r3", peer="r4", expected_routes=expected_routes +    ) +    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + +    step("Configure local-as with no-prepend at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step( +        "Verify that AS-1.110 is not prepended in the AS list 1.200 1.100 by following " +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Kill BGPd daemon on R3.") +    kill_router_daemons(tgen, "r3", ["bgpd"]) + +    step("Bring up BGPd daemon on R3.") +    start_router_daemons(tgen, "r3", ["bgpd"]) + +    step( +        "Verify that AS-1.110 is not prepended in the AS list 1.200 1.100 by following " +        "commands at R3 router." +    ) +    dut = "r3" +    aspath = "1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step("Configure local-as with no-prepend and replace-as at R3 towards R4 & R2.") +    for addr_type in ADDR_TYPES: +        for neighbor in ["r2", "r4"]: +            input_dict_r3 = { +                "r3": { +                    "bgp": { +                        "local_as": "1.300", +                        "address_family": { +                            addr_type: { +                                "unicast": { +                                    "neighbor": { +                                        neighbor: { +                                            "dest_link": { +                                                "r3": { +                                                    "local_asn": { +                                                        "local_as": "1.110", +                                                        "no_prepend": True, +                                                        "replace_as": True, +                                                    } +                                                } +                                            } +                                        } +                                    } +                                } +                            } +                        }, +                    } +                } +            } +            result = create_router_bgp(tgen, topo, input_dict_r3) +            assert result is True, "Testcase {} :Failed \n Error: {}".format( +                tc_name, result +            ) + +    step("BGP neighborship is verified by following commands in R3 routers") +    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) +    assert BGP_CONVERGENCE is True, "BGP convergence :Failed \n Error: {}".format( +        BGP_CONVERGENCE +    ) + +    step( +        "Verified that AS-1.300 is got replaced with original AS-1.110 at R4 by following commands" +    ) +    dut = "r4" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    step( +        "Verified that AS-1.300 is got replaced with original AS-1.110 at R4 by following commands" +    ) +    dut = "r4" +    aspath = "1.110 1.200 1.100" +    for addr_type in ADDR_TYPES: +        input_static_r1 = {"r1": {"static_routes": [{"network": NETWORK[addr_type]}]}} +        result = verify_bgp_rib(tgen, addr_type, dut, input_static_r1, aspath=aspath) +        assert result is True, "Testcase {} : Failed \n Error: {}".format( +            tc_name, result +        ) + +    write_test_footer(tc_name) + + +if __name__ == "__main__": +    args = ["-s"] + sys.argv[1:] +    sys.exit(pytest.main(args)) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index a17ee812e4..200427fb6e 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1673,10 +1673,14 @@ DEFUNSH(VTYSH_ZEBRA, srv6_locator, srv6_locator_cmd,  #ifdef HAVE_BGPD  DEFUNSH(VTYSH_BGPD, router_bgp, router_bgp_cmd, -	"router bgp [(1-4294967295) [<view|vrf> VIEWVRFNAME]]", +	"router bgp [ASNUM [<view|vrf> VIEWVRFNAME] [as-notation <dot|dot+|plain>]]",  	ROUTER_STR BGP_STR AS_STR  	"BGP view\nBGP VRF\n" -	"View/VRF name\n") +	"View/VRF name\n" +	"Force the AS notation output\n" +	"use 'AA.BB' format for AS 4 byte values\n" +	"use 'AA.BB' format for all AS values\n" +	"use plain format for all AS values\n")  {  	vty->node = BGP_NODE;  	return CMD_SUCCESS; diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang index ad2a142fef..8e288194ec 100644 --- a/yang/frr-bgp-route-map.yang +++ b/yang/frr-bgp-route-map.yang @@ -356,6 +356,102 @@ module frr-bgp-route-map {      }    } +  typedef route-distinguisher { +    type string { +      pattern +        '(0:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' +      +     '6[0-4][0-9]{3}|' +      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0):(429496729[0-5]|' +      +     '42949672[0-8][0-9]|' +      +     '4294967[01][0-9]{2}|429496[0-6][0-9]{3}|' +      +     '42949[0-5][0-9]{4}|' +      +     '4294[0-8][0-9]{5}|429[0-3][0-9]{6}|' +      +     '42[0-8][0-9]{7}|4[01][0-9]{8}|' +      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0))|' +      + '(1:((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|' +      +     '25[0-5])\.){3}([0-9]|[1-9][0-9]|' +      +     '1[0-9]{2}|2[0-4][0-9]|25[0-5])):(6553[0-5]|' +      +     '655[0-2][0-9]|' +      +     '65[0-4][0-9]{2}|6[0-4][0-9]{3}|' +      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|' +      + '(2:(429496729[0-5]|42949672[0-8][0-9]|' +      +     '4294967[01][0-9]{2}|' +      +     '429496[0-6][0-9]{3}|42949[0-5][0-9]{4}|' +      +     '4294[0-8][0-9]{5}|' +      +     '429[0-3][0-9]{6}|42[0-8][0-9]{7}|4[01][0-9]{8}|' +      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0):' +      +     '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' +      +     '6[0-4][0-9]{3}|' +      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|' +      + '(6(:[a-fA-F0-9]{2}){6})|' +      + '(([3-57-9a-fA-F]|[1-9a-fA-F][0-9a-fA-F]{1,3}):' +      +     '[0-9a-fA-F]{1,12})|' +      +  '((6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' +      +     '6[0-4][0-9]{3}|' +      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0):(429496729[0-5]|' +      +     '42949672[0-8][0-9]|' +      +     '4294967[01][0-9]{2}|429496[0-6][0-9]{3}|' +      +     '42949[0-5][0-9]{4}|' +      +     '4294[0-8][0-9]{5}|429[0-3][0-9]{6}|' +      +     '42[0-8][0-9]{7}|4[01][0-9]{8}|' +      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0)|' +      +  '((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|' +      +     '25[0-5])\.){3}([0-9]|[1-9][0-9]|' +      +     '1[0-9]{2}|2[0-4][0-9]|25[0-5])):(6553[0-5]|' +      +     '655[0-2][0-9]|' +      +     '65[0-4][0-9]{2}|6[0-4][0-9]{3}|' +      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|' +      + '((429496729[0-5]|42949672[0-8][0-9]|' +      +     '4294967[01][0-9]{2}|' +      +     '429496[0-6][0-9]{3}|42949[0-5][0-9]{4}|' +      +     '4294[0-8][0-9]{5}|' +      +     '429[0-3][0-9]{6}|42[0-8][0-9]{7}|4[01][0-9]{8}|' +      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0):' +      +     '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' +      +     '6[0-4][0-9]{3}|' +      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|' +      +  '((6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' +      +     '6[0-4][0-9]{3}|' +      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0).' +      +  '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' +      +     '6[0-4][0-9]{3}|' +      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0):' +      +     '(429496729[0-5]|42949672[0-8][0-9]|' +      +     '4294967[01][0-9]{2}|' +      +     '429496[0-6][0-9]{3}|42949[0-5][0-9]{4}|' +      +     '4294[0-8][0-9]{5}|' +      +     '429[0-3][0-9]{6}|42[0-8][0-9]{7}|4[01][0-9]{8}|' +      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0))'; +    } + +    description +      "A Route Distinguisher is an 8-octet value used to +       distinguish routes from different BGP VPNs (RFC 4364). +       A Route Distinguisher will have the same format as a +       Route Target as per RFC 4360 and will consist of +       two or three fields: a 2-octet Type field, an administrator +       field, and, optionally, an assigned number field. +       According to the data formats for types 0, 1, 2, and 6 as +       defined in RFC 4360, RFC 5668, and RFC 7432, the encoding +       pattern is defined as: +       0:2-octet-asn:4-octet-number +       1:4-octet-ipv4addr:2-octet-number +       2:4-octet-asn:2-octet-number +       6:6-octet-mac-address +       Additionally, a generic pattern is defined for future +       route discriminator types: +       2-octet-other-hex-number:6-octet-hex-number +       Some valid examples are 0:100:100, 1:1.1.1.1:100, +       2:1234567890:203, and 6:26:00:08:92:78:00. +       The following route distinguisher with two fields are also +       accepted : 10000:44 1.2.3.4:44."; +    reference +      "RFC 4360: BGP Extended Communities Attribute. +       RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs). +       RFC 5668: 4-Octet AS Specific BGP Extended Community. +       RFC 7432: BGP MPLS-Based Ethernet VPN."; +  } +    typedef extcommunity-lb-type {      type enumeration {        enum "explicit-bandwidth" { @@ -598,7 +694,7 @@ module frr-bgp-route-map {        description          "Match eVPN route-distinguisher";        leaf route-distinguisher { -        type rt-types:route-distinguisher; +        type route-distinguisher;        }      }  | 
