mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-29 18:41:56 +00:00
bgpd: Use IEEE-754 Floating Point for storing extcommunity bandwidth
https://datatracker.ietf.org/doc/html/draft-ietf-idr-link-bandwidth-07 says: The bandwidth of the link is expressed as 4 octets in IEEE floating point format, units being bytes (not bits!) per second. It is carried in the Local Administrator subfield of the Value Field. Before: ``` Extended Community (16), length: 8, Flags [OT]: unknown extd community typecode (0x0004), Flags [none] 0x0000: 0004 fdeb 0001 e848 0x0000: 0004 fdeb 0001 e848 Updated routes: 172.16.16.1/32 ``` 0001 e848 - means 125000 (1Mbps), which is encoded incorrect. After: ``` Extended Community (16), length: 8, Flags [OT]: unknown extd community typecode (0x0004), Flags [none] 0x0000: 0004 fdeb 47f4 2400 0x0000: 0004 fdeb 47f4 2400 Updated routes: 172.16.16.1/32 ``` 47f4 2400 - means the same, but in floating point format. Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
This commit is contained in:
parent
26bf593efb
commit
8bcaad3ded
@ -836,11 +836,22 @@ static int ecommunity_rt_soo_str(char *buf, size_t bufsz, const uint8_t *pnt,
|
|||||||
ECOMMUNITY_SIZE);
|
ECOMMUNITY_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper function to convert IEEE-754 Floating Point to uint32 */
|
||||||
|
static uint32_t ieee_float_uint32_to_uint32(uint32_t u)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
float r;
|
||||||
|
uint32_t d;
|
||||||
|
} f = {.d = 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)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
as_t as;
|
as_t as;
|
||||||
uint32_t bw;
|
uint32_t bw_tmp, bw;
|
||||||
char bps_buf[20] = {0};
|
char bps_buf[20] = {0};
|
||||||
|
|
||||||
#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8)
|
#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8)
|
||||||
@ -849,7 +860,10 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt)
|
|||||||
|
|
||||||
as = (*pnt++ << 8);
|
as = (*pnt++ << 8);
|
||||||
as |= (*pnt++);
|
as |= (*pnt++);
|
||||||
(void)ptr_get_be32(pnt, &bw);
|
(void)ptr_get_be32(pnt, &bw_tmp);
|
||||||
|
|
||||||
|
bw = ieee_float_uint32_to_uint32(bw_tmp);
|
||||||
|
|
||||||
if (bw >= ONE_GBPS_BYTES)
|
if (bw >= ONE_GBPS_BYTES)
|
||||||
snprintf(bps_buf, sizeof(bps_buf), "%.3f Gbps",
|
snprintf(bps_buf, sizeof(bps_buf), "%.3f Gbps",
|
||||||
(float)(bw / ONE_GBPS_BYTES));
|
(float)(bw / ONE_GBPS_BYTES));
|
||||||
@ -1533,7 +1547,7 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
|
|||||||
pnt = ptr_get_be32(pnt, &bwval);
|
pnt = ptr_get_be32(pnt, &bwval);
|
||||||
(void)pnt; /* consume value */
|
(void)pnt; /* consume value */
|
||||||
if (bw)
|
if (bw)
|
||||||
*bw = bwval;
|
*bw = ieee_float_uint32_to_uint32(bwval);
|
||||||
return eval;
|
return eval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,6 +198,17 @@ static inline void encode_route_target_as4(as_t as, uint16_t val,
|
|||||||
eval->val[7] = val & 0xff;
|
eval->val[7] = val & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper function to convert uint32 to IEEE-754 Floating Point */
|
||||||
|
static uint32_t uint32_to_ieee_float_uint32(uint32_t u)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
float r;
|
||||||
|
uint32_t d;
|
||||||
|
} f = {.r = (float)u};
|
||||||
|
|
||||||
|
return f.d;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Encode BGP Link Bandwidth extended community
|
* Encode BGP Link Bandwidth extended community
|
||||||
* bandwidth (bw) is in bytes-per-sec
|
* bandwidth (bw) is in bytes-per-sec
|
||||||
@ -205,6 +216,8 @@ static inline void encode_route_target_as4(as_t as, uint16_t val,
|
|||||||
static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
|
static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
|
||||||
struct ecommunity_val *eval)
|
struct ecommunity_val *eval)
|
||||||
{
|
{
|
||||||
|
uint32_t bandwidth = uint32_to_ieee_float_uint32(bw);
|
||||||
|
|
||||||
memset(eval, 0, sizeof(*eval));
|
memset(eval, 0, sizeof(*eval));
|
||||||
eval->val[0] = ECOMMUNITY_ENCODE_AS;
|
eval->val[0] = ECOMMUNITY_ENCODE_AS;
|
||||||
if (non_trans)
|
if (non_trans)
|
||||||
@ -212,10 +225,10 @@ static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
|
|||||||
eval->val[1] = ECOMMUNITY_LINK_BANDWIDTH;
|
eval->val[1] = ECOMMUNITY_LINK_BANDWIDTH;
|
||||||
eval->val[2] = (as >> 8) & 0xff;
|
eval->val[2] = (as >> 8) & 0xff;
|
||||||
eval->val[3] = as & 0xff;
|
eval->val[3] = as & 0xff;
|
||||||
eval->val[4] = (bw >> 24) & 0xff;
|
eval->val[4] = (bandwidth >> 24) & 0xff;
|
||||||
eval->val[5] = (bw >> 16) & 0xff;
|
eval->val[5] = (bandwidth >> 16) & 0xff;
|
||||||
eval->val[6] = (bw >> 8) & 0xff;
|
eval->val[6] = (bandwidth >> 8) & 0xff;
|
||||||
eval->val[7] = bw & 0xff;
|
eval->val[7] = bandwidth & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void ecommunity_init(void);
|
extern void ecommunity_init(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user