diff options
| author | Donatas Abraitis <donatas.abraitis@gmail.com> | 2021-08-29 21:54:13 +0300 | 
|---|---|---|
| committer | Donatas Abraitis <donatas.abraitis@gmail.com> | 2021-08-30 14:21:49 +0300 | 
| commit | 27aa23a43b9922b8f90c324e2f6483b1cffa6aec (patch) | |
| tree | b9b80497d09f0826a00651614c5985ee212b8d87 /bgpd/bgp_ecommunity.c | |
| parent | 8dbe9214588529872904c433834b3a6b61bc5aa3 (diff) | |
bgpd: Add `neighbor PEER link-bw-encoding-ieee`
This is to avoid breaking changes between existing deployments of
extended community for bandwidth encoding. By default FRR uses uint32
to encode bandwidth, which is not as the draft requires (IEEE floating-point).
This switch enables the required encoding per-peer.
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
Diffstat (limited to 'bgpd/bgp_ecommunity.c')
| -rw-r--r-- | bgpd/bgp_ecommunity.c | 51 | 
1 files changed, 31 insertions, 20 deletions
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 6d3abbd20d..1e95d401aa 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -201,6 +201,7 @@ ecommunity_uniq_sort_internal(struct ecommunity *ecom,  	new = ecommunity_new();  	new->unit_size = ecom_size; +	new->disable_ieee_floating = ecom->disable_ieee_floating;  	for (i = 0; i < ecom->size; i++) {  		eval = (void *)(ecom->val + (i * ecom_size)); @@ -220,8 +221,9 @@ struct ecommunity *ecommunity_uniq_sort(struct ecommunity *ecom)  /* Parse Extended Communites Attribute in BGP packet.  */  static struct ecommunity *ecommunity_parse_internal(uint8_t *pnt, -					unsigned short length, -					unsigned short size_ecom) +						    unsigned short length, +						    unsigned short size_ecom, +						    bool disable_ieee_floating)  {  	struct ecommunity tmp;  	struct ecommunity *new; @@ -234,6 +236,7 @@ static struct ecommunity *ecommunity_parse_internal(uint8_t *pnt,  	   Attribute.  */  	tmp.size = length / size_ecom;  	tmp.val = pnt; +	tmp.disable_ieee_floating = disable_ieee_floating;  	/* Create a new Extended Communities Attribute by uniq and sort each  	   Extended Communities value  */ @@ -242,17 +245,18 @@ static struct ecommunity *ecommunity_parse_internal(uint8_t *pnt,  	return ecommunity_intern(new);  } -struct ecommunity *ecommunity_parse(uint8_t *pnt, -				    unsigned short length) +struct ecommunity *ecommunity_parse(uint8_t *pnt, unsigned short length, +				    bool disable_ieee_floating)  { -	return ecommunity_parse_internal(pnt, length, ECOMMUNITY_SIZE); +	return ecommunity_parse_internal(pnt, length, ECOMMUNITY_SIZE, +					 disable_ieee_floating);  } -struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, -					 unsigned short length) +struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length, +					 bool disable_ieee_floating)  { -	return ecommunity_parse_internal(pnt, length, -					 IPV6_ECOMMUNITY_SIZE); +	return ecommunity_parse_internal(pnt, length, IPV6_ECOMMUNITY_SIZE, +					 disable_ieee_floating);  }  /* Duplicate the Extended Communities Attribute structure.  */ @@ -847,7 +851,8 @@ static uint32_t ieee_float_uint32_to_uint32(uint32_t u)  	return (uint32_t)f.r;  } -static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt) +static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt, +			     bool disable_ieee_floating)  {  	int len = 0;  	as_t as; @@ -862,7 +867,8 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt)  	as |= (*pnt++);  	(void)ptr_get_be32(pnt, &bw_tmp); -	bw = ieee_float_uint32_to_uint32(bw_tmp); +	bw = disable_ieee_floating ? bw_tmp +				   : ieee_float_uint32_to_uint32(bw_tmp);  	if (bw >= ONE_GBPS_BYTES)  		snprintf(bps_buf, sizeof(bps_buf), "%.3f Gbps", @@ -954,8 +960,9 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)  				} else if (sub_type ==  					   ECOMMUNITY_LINK_BANDWIDTH &&  					   type == ECOMMUNITY_ENCODE_AS) { -					ecommunity_lb_str(encbuf, -						sizeof(encbuf), pnt); +					ecommunity_lb_str( +						encbuf, sizeof(encbuf), pnt, +						ecom->disable_ieee_floating);  				} else  					unk_ecom = 1;  			} else { @@ -1161,7 +1168,8 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)  		} else if (type == ECOMMUNITY_ENCODE_AS_NON_TRANS) {  			sub_type = *pnt++;  			if (sub_type == ECOMMUNITY_LINK_BANDWIDTH) -				ecommunity_lb_str(encbuf, sizeof(encbuf), pnt); +				ecommunity_lb_str(encbuf, sizeof(encbuf), pnt, +						  ecom->disable_ieee_floating);  			else  				unk_ecom = 1;  		} else { @@ -1547,7 +1555,10 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)  			pnt = ptr_get_be32(pnt, &bwval);  			(void)pnt; /* consume value */  			if (bw) -				*bw = ieee_float_uint32_to_uint32(bwval); +				*bw = ecom->disable_ieee_floating +					      ? bwval +					      : ieee_float_uint32_to_uint32( +							bwval);  			return eval;  		}  	} @@ -1556,9 +1567,9 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)  } -struct ecommunity *ecommunity_replace_linkbw(as_t as, -					     struct ecommunity *ecom, -					     uint64_t cum_bw) +struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom, +					     uint64_t cum_bw, +					     bool disable_ieee_floating)  {  	struct ecommunity *new;  	struct ecommunity_val lb_eval; @@ -1588,8 +1599,8 @@ struct ecommunity *ecommunity_replace_linkbw(as_t as,  	 */  	if (cum_bw > 0xFFFFFFFF)  		cum_bw = 0xFFFFFFFF; -	encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw, -			  false, &lb_eval); +	encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw, false, +			  &lb_eval, disable_ieee_floating);  	new = ecommunity_dup(ecom);  	ecommunity_add_val(new, &lb_eval, true, true);  | 
