args->total);
}
- attr->ecommunity =
- ecommunity_parse(stream_pnt(peer->curr), length);
+ attr->ecommunity = ecommunity_parse(
+ stream_pnt(peer->curr), length,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
/* XXX: fix ecommunity_parse to use stream API */
stream_forward_getp(peer->curr, length);
args->total);
}
- ipv6_ecomm = ecommunity_parse_ipv6(stream_pnt(peer->curr), length);
+ ipv6_ecomm = ecommunity_parse_ipv6(
+ stream_pnt(peer->curr), length,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
/* XXX: fix ecommunity_parse to use stream API */
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));
/* 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. */
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;
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",
} 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 {
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;
}
}
}
-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);
/* Human readable format string. */
char *str;
+
+ /* Disable IEEE floating-point encoding for extended community */
+ bool disable_ieee_floating;
};
struct ecommunity_as {
* bandwidth (bw) is in bytes-per-sec
*/
static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
- struct ecommunity_val *eval)
+ struct ecommunity_val *eval,
+ bool disable_ieee_floating)
{
- uint32_t bandwidth = uint32_to_ieee_float_uint32(bw);
+ uint32_t bandwidth =
+ disable_ieee_floating ? bw : uint32_to_ieee_float_uint32(bw);
memset(eval, 0, sizeof(*eval));
eval->val[0] = ECOMMUNITY_ENCODE_AS;
extern void ecommunity_init(void);
extern void ecommunity_finish(void);
extern void ecommunity_free(struct ecommunity **);
-extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short);
+extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short,
+ bool disable_ieee_floating);
extern struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt,
- unsigned short length);
+ unsigned short length,
+ bool disable_ieee_floating);
extern struct ecommunity *ecommunity_dup(struct ecommunity *);
extern struct ecommunity *ecommunity_merge(struct ecommunity *,
struct ecommunity *);
extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom,
uint32_t *bw);
extern struct ecommunity *ecommunity_replace_linkbw(as_t as,
- struct ecommunity *ecom, uint64_t cum_bw);
+ struct ecommunity *ecom,
+ uint64_t cum_bw,
+ bool disable_ieee_floating);
static inline void ecommunity_strip_rts(struct ecommunity *ecom)
{
prev_mpath = cur_mpath;
mpath_count++;
if (ecommunity_linkbw_present(
- cur_mpath->attr->ecommunity, &bwval))
+ cur_mpath->attr->ecommunity,
+ &bwval))
cum_bw += bwval;
else
all_paths_lb = false;
mpath_changed = 1;
mpath_count++;
if (ecommunity_linkbw_present(
- new_mpath->attr->ecommunity, &bwval))
+ new_mpath->attr->ecommunity,
+ &bwval))
cum_bw += bwval;
else
all_paths_lb = false;
if (new_best) {
bgp_path_info_mpath_count_set(new_best, mpath_count - 1);
- if (mpath_count <= 1 ||
- !ecommunity_linkbw_present(
- new_best->attr->ecommunity, &bwval))
+ if (mpath_count <= 1
+ || !ecommunity_linkbw_present(new_best->attr->ecommunity,
+ &bwval))
all_paths_lb = false;
else
cum_bw += bwval;
(cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
!CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
attr->ecommunity = ecommunity_replace_linkbw(
- bgp->as, attr->ecommunity, cum_bw);
+ bgp->as, attr->ecommunity, cum_bw,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
return true;
}
bw_bytes *= mpath_count;
}
- encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval);
+ encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
/* add to route or merge with existing */
old_ecom = path->attr->ecommunity;
PEER_FLAG_DISABLE_CONNECTED_CHECK);
}
+/* link-bw-encoding-ieee */
+DEFUN(neighbor_link_bw_encoding_ieee, neighbor_link_bw_encoding_ieee_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> disable-link-bw-encoding-ieee",
+ NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Enable IEEE floating-point encoding for extended community bandwidth\n")
+{
+ int idx_peer = 1;
+
+ return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE);
+}
+
+DEFUN(no_neighbor_link_bw_encoding_ieee, no_neighbor_link_bw_encoding_ieee_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> disable-link-bw-encoding-ieee",
+ NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+ "Enable IEEE floating-point encoding for extended community bandwidth\n")
+{
+ int idx_peer = 2;
+
+ return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE);
+}
+
/* enforce-first-as */
DEFUN (neighbor_enforce_first_as,
if (peergroup_flag_check(peer, PEER_FLAG_DISABLE_CONNECTED_CHECK))
vty_out(vty, " neighbor %s disable-connected-check\n", addr);
+ /* link-bw-encoding-ieee */
+ if (peergroup_flag_check(peer, PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE))
+ vty_out(vty, " neighbor %s disable-link-bw-encoding-ieee\n",
+ addr);
+
/* enforce-first-as */
if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
vty_out(vty, " neighbor %s enforce-first-as\n", addr);
install_element(BGP_NODE, &neighbor_disable_connected_check_cmd);
install_element(BGP_NODE, &no_neighbor_disable_connected_check_cmd);
+ /* "neighbor link-bw-encoding-ieee" commands. */
+ install_element(BGP_NODE, &neighbor_link_bw_encoding_ieee_cmd);
+ install_element(BGP_NODE, &no_neighbor_link_bw_encoding_ieee_cmd);
+
/* "neighbor enforce-first-as" commands. */
install_element(BGP_NODE, &neighbor_enforce_first_as_cmd);
install_element(BGP_NODE, &no_neighbor_enforce_first_as_cmd);
{PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_none},
{PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_none},
{PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
+ {PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none},
{0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = {
#define PEER_FLAG_RTT_SHUTDOWN (1U << 26) /* shutdown rtt */
#define PEER_FLAG_TIMER_DELAYOPEN (1U << 27) /* delayopen timer */
#define PEER_FLAG_TCP_MSS (1U << 28) /* tcp-mss */
+/* Disable IEEE floating-point link bandwidth encoding in
+ * extended communities.
+ */
+#define PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE (1U << 29)
/*
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
printf("%s: %s\n", t->name, t->desc);
- ecom = ecommunity_parse((uint8_t *)t->data, t->len);
+ ecom = ecommunity_parse((uint8_t *)t->data, t->len, 0);
printf("ecom: %s\nvalidating...:\n", ecommunity_str(ecom));