diff --git a/bgpd/bgp_ls_nlri.c b/bgpd/bgp_ls_nlri.c index a20f524d551f..dabf3304be65 100644 --- a/bgpd/bgp_ls_nlri.c +++ b/bgpd/bgp_ls_nlri.c @@ -422,6 +422,15 @@ int bgp_ls_attr_cmp(const struct bgp_ls_attr *attr1, const struct bgp_ls_attr *a return ret; } + if (BGP_LS_TLV_CHECK(attr1->present_tlvs, BGP_LS_ATTR_PREFIX_SID_BIT)) { + if (attr1->prefix_sid.sid != attr2->prefix_sid.sid) + return attr1->prefix_sid.sid - attr2->prefix_sid.sid; + if (attr1->prefix_sid.sid_flag != attr2->prefix_sid.sid_flag) + return attr1->prefix_sid.sid_flag - attr2->prefix_sid.sid_flag; + if (attr1->prefix_sid.algo != attr2->prefix_sid.algo) + return attr1->prefix_sid.algo - attr2->prefix_sid.algo; + } + if (attr1->opaque_len != attr2->opaque_len) return attr1->opaque_len - attr2->opaque_len; if (attr1->opaque_len > 0) { @@ -1243,6 +1252,9 @@ unsigned int bgp_ls_attr_hash_key(const struct bgp_ls_attr *attr) key = jhash(&attr->ospf_fwd_addr6, sizeof(struct in6_addr), key); } + if (BGP_LS_TLV_CHECK(attr->present_tlvs, BGP_LS_ATTR_PREFIX_SID_BIT)) + key = jhash(&attr->prefix_sid, sizeof(attr->prefix_sid), key); + if (attr->opaque_len > 0) key = jhash(attr->opaque_data, attr->opaque_len, key); @@ -2273,9 +2285,55 @@ int bgp_ls_encode_attr(struct stream *s, const struct bgp_ls_attr *attr) } } + /* Prefix SID (TLV 1158) */ + if (BGP_LS_TLV_CHECK(attr->present_tlvs, BGP_LS_ATTR_PREFIX_SID_BIT)) { + int sid_len = bgp_ls_attr_prefix_sid_len(attr->prefix_sid.sid_flag); + + if (sid_len == -1) { + /* Should be impossible here */ + flog_warn(EC_BGP_LS_PACKET, + "BGP-LS: %s wrong combination of V-Flag and L-Flag for Prefix SID", + __func__); + } else { + if (stream_put_tlv_hdr(s, BGP_LS_ATTR_PREFIX_SID, 4 + sid_len) < 0) + return -1; + if (STREAM_WRITEABLE(s) < (size_t)4 + sid_len) + return -1; + stream_putc(s, attr->prefix_sid.sid_flag); + stream_putc(s, attr->prefix_sid.algo); + stream_putw(s, 0); /* Reserved = 0 */ + /* SID Label/Index - three or four bytes */ + if (sid_len == 3) + stream_put3(s, attr->prefix_sid.sid); + else if (sid_len == 4) + stream_putl(s, attr->prefix_sid.sid); + } + } + return stream_get_endp(s) - start_pos; } +/* + * Get Prefix-SID attribute SID length by flags + * + * @return 3 or 4 in normal case, -1 in error case + */ +int bgp_ls_attr_prefix_sid_len(uint8_t flags) +{ + /* + * IS-IS: RFC 8667, 2.1.1; OSPFv2: RFC8665, 5; OSPFv3: RFC8666, 6: + * + * All other combinations of V-Flag and L-Flag [all other = V-Flag!=L-Flag] + * are invalid and any SID Advertisement received with an invalid setting + * for V- and L-Flags MUST be ignored. + */ + if (CHECK_FLAG(flags, BGP_LS_PREFIX_SID_FLAG_VALUE) != + CHECK_FLAG(flags, BGP_LS_PREFIX_SID_FLAG_LOCAL)) + return -1; + + return CHECK_FLAG(flags, BGP_LS_PREFIX_SID_FLAG_VALUE) ? 3 : 4; +} + /* * =========================================================================== * NLRI Decoding Functions @@ -3660,6 +3718,66 @@ static int parse_extended_tag(struct stream *s, uint16_t length, struct bgp_ls_a return 0; } +/* + * Parse Prefix SID (TLV 1158) + * RFC 9085 Section 2.3.1 + */ +static int parse_prefix_sid(struct stream *s, uint16_t length, struct bgp_ls_attr *attr) +{ + int flags; + int sid_len; + + if (length != 7 && length != 8) { + flog_warn(EC_BGP_UPDATE_RCV, + "BGP-LS: Invalid Prefix SID length (%u bytes, expected 7 or 8)", length); + return -1; + } + + /* + * IS-IS in RFC8667 2.1 references RFC8402, in section 3.1: + * Multiple SIDs MAY be allocated to the same prefix so long + * as the tuple is unique. + * + * RFC8665 (OSPFv2), 5; RFC8666 (OSPFv3), 6: + * It MAY appear more than once in the parent TLV + */ + if (BGP_LS_TLV_CHECK(attr->present_tlvs, BGP_LS_ATTR_PREFIX_SID_BIT)) { + flog_warn(EC_BGP_UPDATE_RCV, + "BGP-LS: Only one Prefix SID per prefix is supported, ignoring another one"); + stream_forward_getp(s, length); + return 0; + } + + flags = stream_getc(s); + sid_len = bgp_ls_attr_prefix_sid_len(flags); + + if (sid_len == -1) { + stream_forward_getp(s, length - 1); + flog_warn(EC_BGP_LS_PACKET, + "BGP-LS: %s wrong combination of V-Flag and L-Flag for Prefix SID, ignoring", + __func__); + return 0; + } + + if (sid_len + 4 != length) { + stream_forward_getp(s, length - 1); + flog_warn(EC_BGP_LS_PACKET, + "BGP-LS: %s V-Flag value contradicts length of Prefix SID, ignoring", + __func__); + return 0; + } + + attr->prefix_sid.sid_flag = flags; + attr->prefix_sid.algo = stream_getc(s); + stream_getw(s); /* Reserved, ignore two octets */ + attr->prefix_sid.sid = 0; + for (int i = 0; i < sid_len; i++) + attr->prefix_sid.sid = (attr->prefix_sid.sid << 8) | stream_getc(s); + BGP_LS_TLV_SET(attr->present_tlvs, BGP_LS_ATTR_PREFIX_SID_BIT); + + return 0; +} + /* * Parse BGP-LS Attribute TLVs * RFC 9552 Section 5.3.1 @@ -3830,6 +3948,11 @@ int bgp_ls_parse_attr(struct stream *s, uint16_t total_length, struct bgp_ls_att return -1; break; + case BGP_LS_ATTR_PREFIX_SID: + if (parse_prefix_sid(s, length, attr) < 0) + return -1; + break; + default: if (BGP_DEBUG(update, UPDATE_IN)) zlog_debug("BGP-LS: Skipping unrecognized BGP-LS Attribute TLV %u", @@ -3842,6 +3965,181 @@ int bgp_ls_parse_attr(struct stream *s, uint16_t total_length, struct bgp_ls_att return 0; } +/* + * Convert BGP-LS Attributes to JSON object + * Used for "show bgp" commands to display link-state topology information in json + */ +struct json_object *bgp_ls_attr_to_json(struct bgp_ls_attr *ls_attr) +{ + json_object *json_ls_attr = json_object_new_object(); + char buf[INET6_BUFSIZ]; + + /* Node Name */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_NODE_NAME_BIT)) + json_object_string_add(json_ls_attr, "nodeName", + ls_attr->node_name ? ls_attr->node_name : "(null)"); + + /* Local TE Router-ID (IPv4) */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_IPV4_ROUTER_ID_LOCAL_BIT)) { + snprintfrr(buf, INET6_BUFSIZ, "%pI4", &ls_attr->ipv4_router_id_local); + json_object_string_add(json_ls_attr, "routerIdLocal", buf); + } + + /* Local TE Router-ID (IPv6) */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_IPV6_ROUTER_ID_LOCAL_BIT)) { + snprintfrr(buf, INET6_BUFSIZ, "%pI6", &ls_attr->ipv6_router_id_local); + json_object_string_add(json_ls_attr, "routerIdLocalV6", buf); + } + + /* Link bandwidth */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_MAX_LINK_BW_BIT)) + json_object_double_add(json_ls_attr, "maxLinkBandwidth", ls_attr->max_link_bw); + + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_MAX_RESV_BW_BIT)) + json_object_double_add(json_ls_attr, "maxResvLinkBandwidth", + ls_attr->max_resv_bw); + + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_UNRESV_BW_BIT)) { + json_object *jbw = json_object_new_array(); + + json_object_object_add(json_ls_attr, "unreservedBandwidth", jbw); + for (int i = 0; i < MAX_CLASS_TYPE; i++) { + json_object *jobj = json_object_new_object(); + + snprintfrr(buf, 13, "classType%u", (unsigned int)i); + json_object_double_add(jobj, buf, ls_attr->unreserved_bw[i]); + json_object_array_add(jbw, jobj); + } + } + + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_IGP_METRIC_BIT)) + json_object_int_add(json_ls_attr, "igpMetric", ls_attr->igp_metric); + + /* TE Default Metric */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_TE_METRIC_BIT)) + json_object_int_add(json_ls_attr, "teMetric", ls_attr->te_metric); + + /* Administrative Group */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_ADMIN_GROUP_BIT)) + json_object_int_add(json_ls_attr, "adminGroup", ls_attr->admin_group); + + /* Link Protection Type */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_LINK_PROTECTION_BIT)) + json_object_int_add(json_ls_attr, "linkProtection", ls_attr->link_protection); + + /* MPLS Protocol Mask */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_MPLS_PROTOCOL_BIT)) + json_object_int_add(json_ls_attr, "mplsProtocolMask", + ls_attr->mpls_protocol_mask); + + /* SRLG */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_SRLG_BIT)) { + struct json_object *jsrlg = json_object_new_array(); + + json_object_object_add(json_ls_attr, "srlgs", jsrlg); + for (int i = 0; i < ls_attr->srlg_count; i++) { + json_object *jobj = json_object_new_object(); + + json_object_int_add(jobj, "srlg", ls_attr->srlg_values[i]); + json_object_array_add(jsrlg, jobj); + } + } + + /* Link Name */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_LINK_NAME_BIT)) + json_object_string_add(json_ls_attr, "linkName", ls_attr->link_name); + + /* Performance Metrics - Link Delay */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_DELAY_BIT)) + json_object_int_add(json_ls_attr, "delay", ls_attr->delay); + + /* Min/Max Delay */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_MIN_MAX_DELAY_BIT)) { + json_object_int_add(json_ls_attr, "minDelay", ls_attr->min_delay); + json_object_int_add(json_ls_attr, "maxDelay", ls_attr->max_delay); + } + + /* Delay Variation */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_JITTER_BIT)) + json_object_int_add(json_ls_attr, "jitter", ls_attr->jitter); + + /* Packet Loss */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_PKT_LOSS_BIT)) + json_object_double_add(json_ls_attr, "loss", ls_attr->pkt_loss * LOSS_PRECISION); + + /* Residual Bandwidth */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_RESIDUAL_BW_BIT)) + json_object_double_add(json_ls_attr, "residualBandwidth", ls_attr->residual_bw); + + /* Available Bandwidth */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_AVAILABLE_BW_BIT)) + json_object_double_add(json_ls_attr, "availableBandwidth", ls_attr->available_bw); + + /* Utilized Bandwidth */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_UTILIZED_BW_BIT)) + json_object_double_add(json_ls_attr, "utilizedBandwidth", ls_attr->utilized_bw); + + /* IGP Flags (for prefixes) */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_IGP_FLAGS_BIT)) { + snprintfrr(buf, INET6_BUFSIZ, "0x%x", ls_attr->igp_flags); + json_object_string_add(json_ls_attr, "flags", buf); + } + + /* Route Tags */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_ROUTE_TAG_BIT)) { + struct json_object *jtags = json_object_new_array(); + + json_object_object_add(json_ls_attr, "tags", jtags); + for (int i = 0; i < ls_attr->route_tag_count; i++) { + json_object *jobj = json_object_new_object(); + + json_object_int_add(jobj, "tag", ls_attr->route_tags[i]); + json_object_array_add(jtags, jobj); + } + } + + /* Extended Tags */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_EXTENDED_TAG_BIT)) { + struct json_object *jtags = json_object_new_array(); + + json_object_object_add(json_ls_attr, "extendedTags", jtags); + for (int i = 0; i < ls_attr->extended_tag_count; i++) { + json_object *jobj = json_object_new_object(); + + json_object_int_add(jobj, "tag", ls_attr->extended_tags[i]); + json_object_array_add(jtags, jobj); + } + } + + /* Prefix Metric */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_PREFIX_METRIC_BIT)) + json_object_int_add(json_ls_attr, "prefixMetric", ls_attr->prefix_metric); + + /* OSPF Forwarding Address (IPv4) */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_OSPF_FWD_ADDR_BIT)) { + if (ls_attr->ospf_fwd_addr.s_addr != INADDR_ANY) { + snprintfrr(buf, INET6_BUFSIZ, "%pI4", &ls_attr->ospf_fwd_addr); + json_object_string_add(json_ls_attr, "forwardingAddr", buf); + } else if (!IN6_IS_ADDR_UNSPECIFIED(&ls_attr->ospf_fwd_addr6)) { + snprintfrr(buf, INET6_BUFSIZ, "%pI6", &ls_attr->ospf_fwd_addr6); + json_object_string_add(json_ls_attr, "forwardingAddrV6", buf); + } + } + + /* Prefix SID */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_PREFIX_SID_BIT)) { + json_object *jpref = json_object_new_object(); + + json_object_object_add(json_ls_attr, "prefixSid", jpref); + json_object_int_add(jpref, "sid", ls_attr->prefix_sid.sid); + snprintfrr(buf, INET6_BUFSIZ, "0x%x", ls_attr->prefix_sid.sid_flag); + json_object_string_add(jpref, "flags", buf); + json_object_int_add(jpref, "algo", ls_attr->prefix_sid.algo); + } + + return json_ls_attr; +} + /* * Display BGP-LS Attributes to VTY output * Used for "show bgp" commands to display link-state topology information @@ -3974,7 +4272,8 @@ void bgp_ls_attr_display(struct vty *vty, struct bgp_ls_attr *ls_attr) /* Packet Loss */ if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_PKT_LOSS_BIT)) { CHECK_WRAP(); - col += vty_out(vty, "Packet Loss: %u", ls_attr->pkt_loss); + col += vty_out(vty, "Packet Loss: %g (%%)", + (float)(ls_attr->pkt_loss * LOSS_PRECISION)); } /* Residual Bandwidth */ @@ -4028,13 +4327,21 @@ void bgp_ls_attr_display(struct vty *vty, struct bgp_ls_attr *ls_attr) if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_OSPF_FWD_ADDR_BIT)) { if (ls_attr->ospf_fwd_addr.s_addr != INADDR_ANY) { CHECK_WRAP(); - vty_out(vty, "Forwarding addr: %pI4", &ls_attr->ospf_fwd_addr); + col += vty_out(vty, "Forwarding addr: %pI4", &ls_attr->ospf_fwd_addr); } else if (!IN6_IS_ADDR_UNSPECIFIED(&ls_attr->ospf_fwd_addr6)) { CHECK_WRAP(); - vty_out(vty, "Forwarding addr: %pI6", &ls_attr->ospf_fwd_addr6); + col += vty_out(vty, "Forwarding addr: %pI6", &ls_attr->ospf_fwd_addr6); } } + /* Prefix SID */ + if (BGP_LS_TLV_CHECK(ls_attr->present_tlvs, BGP_LS_ATTR_PREFIX_SID_BIT)) { + CHECK_WRAP(); + col += vty_out(vty, "Prefix-SID: %u Flags 0x%x algo %hhu", ls_attr->prefix_sid.sid, + ls_attr->prefix_sid.sid_flag, ls_attr->prefix_sid.algo); + } + + (void)col; /* Don't complain about last 'col +=' */ #undef CHECK_WRAP #undef COL_WIDTH #undef INIT_INDENT diff --git a/bgpd/bgp_ls_nlri.h b/bgpd/bgp_ls_nlri.h index 4c9cb885c26c..3ffb9b0c6e07 100644 --- a/bgpd/bgp_ls_nlri.h +++ b/bgpd/bgp_ls_nlri.h @@ -317,6 +317,13 @@ enum bgp_ls_attr_tlv { #define BGP_LS_PREFIX_FLAG_PROPAGATE 0x10 /* OSPF Propagate NSSA Bit */ #define BGP_LS_PREFIX_FLAG_NODE 0x08 /* Node Prefix Attached Flag */ +/* + * IGP Prefix SID Flags (TLV 1158) + * RFC 9085 Section 2.3.1 + */ +#define BGP_LS_PREFIX_SID_FLAG_VALUE 0x08 /* Same for IS-IS, OSPFv2, OSPFv3 */ +#define BGP_LS_PREFIX_SID_FLAG_LOCAL 0x04 /* Same for IS-IS, OSPFv2, OSPFv3 */ + /* * =========================================================================== * Descriptor Structures (RFC 9552 Section 5.2) @@ -597,6 +604,13 @@ struct bgp_ls_attr { struct in_addr ospf_fwd_addr; /* IPv4 */ struct in6_addr ospf_fwd_addr6; /* IPv6 */ + /* Prefix-SID (TLV 1158) */ + struct prefix_sid { + uint8_t sid_flag; /* Segment Routing Flags */ + uint8_t algo; /* Algorithm for Segment Routing */ + uint32_t sid; /* Segment Routing ID */ + } prefix_sid; + /* Opaque Node Attribute (TLV 1025/1097/1157) */ uint16_t opaque_len; uint8_t *opaque_data; @@ -733,6 +747,13 @@ extern int bgp_ls_encode_nlri(struct stream *s, const struct bgp_ls_nlri *nlri); /* Encode BGP-LS Attributes (Type 29 TLVs) */ extern int bgp_ls_encode_attr(struct stream *s, const struct bgp_ls_attr *attr); +/* + * Get Prefix-SID attribute SID length by flags + * + * @return 3 or 4 in normal case, -1 in error case + */ +extern int bgp_ls_attr_prefix_sid_len(uint8_t flags); + /* * =========================================================================== * NLRI Decoding Functions @@ -776,6 +797,17 @@ extern int bgp_ls_decode_nlri(struct stream *s, struct bgp_ls_nlri *nlri); */ extern int bgp_ls_parse_attr(struct stream *s, uint16_t total_length, struct bgp_ls_attr *attr); +/* + * Convert BGP-LS Attributes to JSON object + * + * @param ls_attr Pointer to BGP-LS attribute structure to convert + * + * Used for "show bgp" commands to display link-state topology information in json + * + * @return json object + */ +extern struct json_object *bgp_ls_attr_to_json(struct bgp_ls_attr *ls_attr); + /* * Display BGP-LS Attributes to VTY output * diff --git a/bgpd/bgp_ls_ted.c b/bgpd/bgp_ls_ted.c index 495a9a4ca695..a41805e051c1 100644 --- a/bgpd/bgp_ls_ted.c +++ b/bgpd/bgp_ls_ted.c @@ -252,6 +252,19 @@ int bgp_ls_populate_prefix_attr(struct ls_prefix *ls_prefix, struct bgp_ls_attr attr->present_tlvs |= (1ULL << BGP_LS_ATTR_PREFIX_METRIC_BIT); } + /* Prefix-SID (TLV 1158) */ + if (CHECK_FLAG(ls_prefix->flags, LS_PREF_SR)) { + if (bgp_ls_attr_prefix_sid_len(ls_prefix->sr.sid_flag) == -1) { + zlog_warn("BGP-LS: %s TED contains wrong combination of V-Flag and L-Flag for Prefix SID", + __func__); + } else { + attr->prefix_sid.sid = ls_prefix->sr.sid; + attr->prefix_sid.sid_flag = ls_prefix->sr.sid_flag; + attr->prefix_sid.algo = ls_prefix->sr.algo; + attr->present_tlvs |= (1ULL << BGP_LS_ATTR_PREFIX_SID_BIT); + } + } + return 0; } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 269edd8c9515..332b3fc1a654 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -12248,6 +12248,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, json_object *json_string = NULL; json_object *json_int = NULL; json_object *json_adv_to = NULL; + json_object *json_ls_attr = NULL; int first = 0; struct listnode *node, *nnode; struct peer *peer; @@ -13393,8 +13394,11 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, } /* Display BGP-LS attributes if this is link-state SAFI */ - if (safi == SAFI_BGP_LS && !json_paths) { - if (attr && attr->ls_attr) + if (safi == SAFI_BGP_LS && attr && attr->ls_attr) { + if (json_paths) { + json_ls_attr = bgp_ls_attr_to_json(attr->ls_attr); + json_object_object_add(json_path, "linkStateAttrs", json_ls_attr); + } else bgp_ls_attr_display(vty, attr->ls_attr); } diff --git a/tests/topotests/bgp_link_state/r1/frr.conf b/tests/topotests/bgp_link_state/r1/frr.conf index ed9d3275a2a7..222dc96e5b6f 100644 --- a/tests/topotests/bgp_link_state/r1/frr.conf +++ b/tests/topotests/bgp_link_state/r1/frr.conf @@ -48,6 +48,8 @@ router isis 1 mpls-te on mpls-te router-address 1.1.1.1 mpls-te router-address ipv6 fc00:0:1::1 + segment-routing on + segment-routing prefix 1.1.1.1/32 index 1 ! ip forwarding ! diff --git a/tests/topotests/bgp_link_state/r2/frr.conf b/tests/topotests/bgp_link_state/r2/frr.conf index 59a93f408c25..b7b43f10fc2d 100644 --- a/tests/topotests/bgp_link_state/r2/frr.conf +++ b/tests/topotests/bgp_link_state/r2/frr.conf @@ -63,6 +63,8 @@ router isis 1 mpls-te export mpls-te router-address 2.2.2.2 mpls-te router-address ipv6 fc00:0:2::1 + segment-routing on + segment-routing prefix 2.2.2.2/32 index 2 ! ip forwarding ! diff --git a/tests/topotests/bgp_link_state/r3/frr.conf b/tests/topotests/bgp_link_state/r3/frr.conf index cd7582b2a38b..155b3ad05a6e 100644 --- a/tests/topotests/bgp_link_state/r3/frr.conf +++ b/tests/topotests/bgp_link_state/r3/frr.conf @@ -47,6 +47,8 @@ router isis 1 mpls-te on mpls-te router-address 3.3.3.3 mpls-te router-address ipv6 fc00:0:3::1 + segment-routing on + segment-routing prefix 3.3.3.3/32 index 3 ! ip forwarding ! diff --git a/tests/topotests/bgp_link_state/r4/frr.conf b/tests/topotests/bgp_link_state/r4/frr.conf index de41489e865e..b59e35d374d3 100644 --- a/tests/topotests/bgp_link_state/r4/frr.conf +++ b/tests/topotests/bgp_link_state/r4/frr.conf @@ -46,5 +46,7 @@ router isis 1 mpls-te on mpls-te router-address 4.4.4.4 mpls-te router-address ipv6 fc00:0:4::1 + segment-routing on + segment-routing prefix 4.4.4.4/32 index 4 ! end diff --git a/tests/topotests/bgp_link_state/rr/bgp_ls_prefix4.json b/tests/topotests/bgp_link_state/rr/bgp_ls_prefix4.json new file mode 100644 index 000000000000..46339e92fece --- /dev/null +++ b/tests/topotests/bgp_link_state/rr/bgp_ls_prefix4.json @@ -0,0 +1,13 @@ +{ + "paths": [ + { + "linkStateAttrs": { + "prefixSid": { + "sid": 4, + "flags": "0x40", + "algo": 0 + } + } + } + ] +} diff --git a/tests/topotests/bgp_link_state/test_bgp_link_state.py b/tests/topotests/bgp_link_state/test_bgp_link_state.py index 674272d86b3b..541875c3172d 100644 --- a/tests/topotests/bgp_link_state/test_bgp_link_state.py +++ b/tests/topotests/bgp_link_state/test_bgp_link_state.py @@ -419,6 +419,30 @@ def test_bgp_ls_routes_consumer(): assertmsg = '"rr" BGP-LS routes not received correctly' assert result is None, assertmsg +def test_bgp_ls_attributes_consumer(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Checking BGP-LS prefix attributes on consumer") + + router = tgen.gears["rr"] + + # Check BGP-LS attributes are received + reffile = os.path.join(CWD, "rr/bgp_ls_prefix4.json") + expected = json.loads(open(reffile).read()) + + test_func = functools.partial( + topotest.router_json_cmp, + router, + "show bgp link-state link-state [T][L2][I0x0][N[s0000.0000.0004]][P[p4.4.4.4/32]] json", + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = '"rr" BGP-LS prefix attributes not received correctly' + assert result is None, assertmsg + def test_bgp_ls_static_route_add(): """Test adding a static route and verifying BGP-LS update"""