diff options
| author | Donatas Abraitis <donatas@opensourcerouting.org> | 2023-06-27 13:03:22 +0300 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-27 13:03:22 +0300 | 
| commit | 4199f032e594984e08dddf079e4b4e8755f20c85 (patch) | |
| tree | 8f53f63df9f911814e1c9e72967b90461125d11b /bgpd/bgp_ecommunity.c | |
| parent | f018e3cdcfe3671be8bbcc59a834ef4b64fb16a8 (diff) | |
| parent | fc4478721150af6177a5101bdee8359acfa300d8 (diff) | |
Merge pull request #13722 from fdumontet6WIND/color_extcomm
bgpd,lib,yang: add colored extended communities support
Diffstat (limited to 'bgpd/bgp_ecommunity.c')
| -rw-r--r-- | bgpd/bgp_ecommunity.c | 120 | 
1 files changed, 105 insertions, 15 deletions
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 29b2250747..e473468dbf 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -355,6 +355,22 @@ bool ecommunity_cmp(const void *arg1, const void *arg2)  			  ecom1->unit_size) == 0);  } +static void ecommunity_color_str(char *buf, size_t bufsz, uint8_t *ptr) +{ +	/* +	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +	 *  | 0x03         | Sub-Type(0x0b) |    Flags                      | +	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +	 *  |                          Color Value                          | +	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +	 */ +	uint32_t colorid; + +	memcpy(&colorid, ptr + 3, 4); +	colorid = ntohl(colorid); +	snprintf(buf, bufsz, "Color:%d", colorid); +} +  /* Initialize Extended Comminities related hash. */  void ecommunity_init(void)  { @@ -373,6 +389,7 @@ enum ecommunity_token {  	ecommunity_token_rt,  	ecommunity_token_nt,  	ecommunity_token_soo, +	ecommunity_token_color,  	ecommunity_token_val,  	ecommunity_token_rt6,  	ecommunity_token_val6, @@ -510,6 +527,9 @@ static int ecommunity_encode_internal(uint8_t type, uint8_t sub_type,  		memcpy(&eval6->val[2], ip6, sizeof(struct in6_addr));  		eval6->val[18] = (val >> 8) & 0xff;  		eval6->val[19] = val & 0xff; +	} else if (type == ECOMMUNITY_ENCODE_OPAQUE && +		   sub_type == ECOMMUNITY_COLOR) { +		encode_color(val, eval);  	} else {  		encode_route_target_as4(as, val, eval, trans);  	} @@ -537,16 +557,22 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,  	int dot = 0;  	int digit = 0;  	int separator = 0; +	int i;  	const char *p = str;  	char *endptr;  	struct in_addr ip;  	struct in6_addr ip6;  	as_t as = 0;  	uint32_t val = 0; -	uint8_t ecomm_type; +	uint32_t val_color = 0; +	uint8_t ecomm_type = 0; +	uint8_t sub_type = 0;  	char buf[INET_ADDRSTRLEN + 1];  	struct ecommunity_val *eval = (struct ecommunity_val *)eval_ptr;  	uint64_t tmp_as = 0; +	static const char str_color[5] = "color"; +	const char *ptr_color; +	bool val_color_set = false;  	/* Skip white space. */  	while (isspace((unsigned char)*p)) { @@ -558,7 +584,7 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,  	if (*p == '\0')  		return NULL; -	/* "rt", "nt", and "soo" keyword parse. */ +	/* "rt", "nt", "soo", and "color" keyword parse. */  	if (!isdigit((unsigned char)*p)) {  		/* "rt" match check.  */  		if (tolower((unsigned char)*p) == 'r') { @@ -612,10 +638,33 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,  				return p;  			}  			goto error; +		} else if (tolower((unsigned char)*p) == 'c') { +			/* "color" match check. +			 * 'c', 'co', 'col', 'colo' are also accepted +			 */ +			for (i = 0; i < 5; i++) { +				ptr_color = &str_color[0]; +				if (tolower((unsigned char)*p) == *ptr_color) { +					p++; +					ptr_color++; +				} else if (i > 0) { +					if (isspace((unsigned char)*p) || +					    *p == '\0') { +						*token = ecommunity_token_color; +						return p; +					} +					goto error; +				} +				if (isspace((unsigned char)*p) || *p == '\0') { +					*token = ecommunity_token_color; +					return p; +				} +				goto error; +			} +			goto error;  		}  		goto error;  	} -  	/* What a mess, there are several possibilities:  	 *  	 * a) A.B.C.D:MN @@ -716,17 +765,24 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,  		} else {  			digit = 1; -			/* We're past the IP/ASN part */ +			/* We're past the IP/ASN part, +			 * or we have a color +			 */  			if (separator) {  				val *= 10;  				val += (*p - '0'); +				val_color_set = false; +			} else { +				val_color *= 10; +				val_color += (*p - '0'); +				val_color_set = true;  			}  		}  		p++;  	}  	/* Low digit part must be there. */ -	if (!digit || !separator) +	if (!digit && (!separator || !val_color_set))  		goto error;  	/* Encode result into extended community.  */ @@ -734,9 +790,15 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,  		ecomm_type = ECOMMUNITY_ENCODE_IP;  	else if (as > BGP_AS_MAX)  		ecomm_type = ECOMMUNITY_ENCODE_AS4; -	else +	else if (as > 0)  		ecomm_type = ECOMMUNITY_ENCODE_AS; -	if (ecommunity_encode(ecomm_type, type, 1, as, ip, val, eval)) +	else if (val_color) { +		ecomm_type = ECOMMUNITY_ENCODE_OPAQUE; +		sub_type = ECOMMUNITY_COLOR; +		val = val_color; +	} + +	if (ecommunity_encode(ecomm_type, sub_type, 1, as, ip, val, eval))  		goto error;  	*token = ecommunity_token_val;  	return p; @@ -763,6 +825,7 @@ static struct ecommunity *ecommunity_str2com_internal(const char *str, int type,  		case ecommunity_token_nt:  		case ecommunity_token_rt6:  		case ecommunity_token_soo: +		case ecommunity_token_color:  			if (!keyword_included || keyword) {  				if (ecom)  					ecommunity_free(&ecom); @@ -771,15 +834,14 @@ static struct ecommunity *ecommunity_str2com_internal(const char *str, int type,  			keyword = 1;  			if (token == ecommunity_token_rt || -			    token == ecommunity_token_rt6) { +			    token == ecommunity_token_rt6)  				type = ECOMMUNITY_ROUTE_TARGET; -			} -			if (token == ecommunity_token_soo) { +			if (token == ecommunity_token_soo)  				type = ECOMMUNITY_SITE_ORIGIN; -			} -			if (token == ecommunity_token_nt) { +			if (token == ecommunity_token_nt)  				type = ECOMMUNITY_NODE_TARGET; -			} +			if (token == ecommunity_token_color) +				type = ECOMMUNITY_COLOR;  			break;  		case ecommunity_token_val:  			if (keyword_included) { @@ -998,10 +1060,12 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt,  	"rt 100:1 100:2soo 100:3"     extcommunity-list -	"rt 100:1 rt 100:2 soo 100:3show [ip] bgp" and extcommunity-list regular expression matching +	"rt 100:1 rt 100:2 soo 100:3 +	show [ip] bgp" +   and extcommunity-list regular expression matching  	"RT:100:1 RT:100:2 SoO:100:3" -   For each formath please use below definition for format: +   For each format please use below definition for format:     ECOMMUNITY_FORMAT_ROUTE_MAP     ECOMMUNITY_FORMAT_COMMUNITY_LIST @@ -1086,6 +1150,9 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)  			} else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW) {  				strlcpy(encbuf, "Default Gateway",  					sizeof(encbuf)); +			} else if (*pnt == ECOMMUNITY_COLOR) { +				ecommunity_color_str(encbuf, sizeof(encbuf), +						     pnt);  			} else {  				unk_ecom = 1;  			} @@ -1353,6 +1420,29 @@ bool ecommunity_match(const struct ecommunity *ecom1,  		return false;  } +/* return last occurence of color */ +/* it will be the greatest color value */ +extern uint32_t ecommunity_select_color(const struct ecommunity *ecom) +{ + +	uint32_t aux_color = 0; +	uint8_t *p; +	uint32_t c = 0; + +	/* If the value already exists in the structure return 0.  */ + +	for (p = ecom->val; c < ecom->size; p += ecom->unit_size, c++) { +		if (p == NULL) +			break; + +		if (p[0] == ECOMMUNITY_ENCODE_OPAQUE && +		    p[1] == ECOMMUNITY_COLOR) +			ptr_get_be32((const uint8_t *)&p[4], &aux_color); +	} +	return aux_color; +} + +  /* return first occurence of type */  extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *ecom,  						uint8_t type, uint8_t subtype)  | 
