XFREE(MTYPE_ECOMMUNITY_STR, *s);
}
-/* Allocate ecommunities. */
+/* Free ecommunities. */
void ecommunity_free(struct ecommunity **ecom)
{
if (!(*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));
return new;
}
-/* This function takes pointer to Extended Communites strucutre then
+/* This function takes pointer to Extended Communites structure then
* create a new Extended Communities structure by uniq and sort each
* Extended Communities value.
*/
/* 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;
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 */
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. */
ECOMMUNITY_SIZE);
}
-static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt)
+/* 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,
+ bool disable_ieee_floating)
{
int len = 0;
as_t as;
- uint32_t bw;
+ uint32_t bw_tmp, bw;
char bps_buf[20] = {0};
#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8)
as = (*pnt++ << 8);
as |= (*pnt++);
- (void)ptr_get_be32(pnt, &bw);
+ (void)ptr_get_be32(pnt, &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",
(float)(bw / ONE_GBPS_BYTES));
strlcat(str_buf, " ", str_size);
/* Retrieve value field */
- pnt = ecom->val + (i * 8);
+ pnt = ecom->val + (i * ecom->unit_size);
/* High-order octet is the type */
type = *pnt++;
} 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 {
} 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 {
return str_buf;
}
+bool ecommunity_include(struct ecommunity *e1, struct ecommunity *e2)
+{
+ uint32_t i, j;
+
+ if (!e1 || !e2)
+ return false;
+ for (i = 0; i < e1->size; ++i) {
+ for (j = 0; j < e2->size; ++j) {
+ if (!memcmp(e1->val + (i * e1->unit_size),
+ e2->val + (j * e2->unit_size),
+ e1->unit_size))
+ return true;
+ }
+ }
+ return false;
+}
+
bool ecommunity_match(const struct ecommunity *ecom1,
const struct ecommunity *ecom2)
{
pnt = ptr_get_be32(pnt, &bwval);
(void)pnt; /* consume value */
if (bw)
- *bw = bwval;
+ *bw = ecom->disable_ieee_floating
+ ? bwval
+ : ieee_float_uint32_to_uint32(
+ bwval);
return eval;
}
}
}
-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;
*/
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);