diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/package-build/frr/patches/frr/0010-bgp-Support-multiple-labels-in-BGP-LU.patch | 662 |
1 files changed, 662 insertions, 0 deletions
diff --git a/scripts/package-build/frr/patches/frr/0010-bgp-Support-multiple-labels-in-BGP-LU.patch b/scripts/package-build/frr/patches/frr/0010-bgp-Support-multiple-labels-in-BGP-LU.patch new file mode 100644 index 00000000..ba37123f --- /dev/null +++ b/scripts/package-build/frr/patches/frr/0010-bgp-Support-multiple-labels-in-BGP-LU.patch @@ -0,0 +1,662 @@ +From 2fc836b3a2f7778d311e385966e3b2f00eebba1b Mon Sep 17 00:00:00 2001 +From: Kyrylo Yatsenko <hedrok@gmail.com> +Date: Fri, 31 Oct 2025 21:20:20 +0200 +Subject: [PATCH] bgpd: Support multiple labels in BGP-LU + +Updated behaviour for SAFI_LABELED_UNICAST to support multiple labels: + +* Change BGP_MAX_LABELS 2 -> 10 (maximum possible number of labels for + BGP-LU), previously for SAFI_LABELED_UNICAST only one label was + supported +* Save all labels when receiving an update event in + `bgp_nlri_get_labels`, send them all to zebra in + `bgp_zebra_announce_parse_nexthop` + +One of uses of multiple labels is SR-TE with BGP-LU. + +Resolves #19506 + +cherry-picked-from: 17a082ee3a5d1295c27323773c523c945af12c3d + +Signed-off-by: Kyrylo Yatsenko <hedrok@gmail.com> +--- + bgpd/bgp_attr.c | 13 +++- + bgpd/bgp_debug.c | 6 +- + bgpd/bgp_label.c | 142 ++++++++++++++++++++++++++++++--------- + bgpd/bgp_label.h | 30 +++++++-- + bgpd/bgp_mplsvpn.c | 25 ------- + bgpd/bgp_mplsvpn.h | 2 - + bgpd/bgp_route.c | 56 +++++++++------ + bgpd/bgp_updgrp_packet.c | 14 ++-- + bgpd/bgp_zebra.c | 47 +++++++++---- + 9 files changed, 223 insertions(+), 112 deletions(-) + +diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c +index 1a2fa8318e..53e54b9c12 100644 +--- a/bgpd/bgp_attr.c ++++ b/bgpd/bgp_attr.c +@@ -4280,6 +4280,8 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi, + uint8_t num_labels, bool addpath_capable, + uint32_t addpath_tx_id, struct attr *attr) + { ++ mpls_label_t restore_label; ++ + switch (safi) { + case SAFI_UNSPEC: + case SAFI_MAX: +@@ -4304,9 +4306,16 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi, + assert(!"Add encoding bits here for other AFI's"); + break; + case SAFI_LABELED_UNICAST: ++ if (num_labels > 1) { ++ zlog_warn("%s: stream_put_labeled_prefix currently supports only one label, ignoring rest (num_labels=%d)", ++ __func__, num_labels); ++ restore_label = label[0]; ++ label_set_bos(&label[0]); ++ } + /* Prefix write with label. */ +- stream_put_labeled_prefix(s, p, label, addpath_capable, +- addpath_tx_id); ++ stream_put_labeled_prefix(s, p, label, addpath_capable, addpath_tx_id); ++ if (num_labels > 1) ++ label[0] = restore_label; + break; + case SAFI_FLOWSPEC: + stream_putc(s, p->u.prefix_flowspec.prefixlen); +diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c +index 97c3e5740f..06b9543114 100644 +--- a/bgpd/bgp_debug.c ++++ b/bgpd/bgp_debug.c +@@ -2767,11 +2767,7 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi, + snprintf(tag_buf, sizeof(tag_buf), " label %s", + tag_buf2); + } else { +- uint32_t label_value; +- +- label_value = decode_label(label); +- snprintf(tag_buf, sizeof(tag_buf), " label %u", +- label_value); ++ mpls_labels2str(label, num_labels, " label ", tag_buf, sizeof(tag_buf)); + } + } + +diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c +index 8ed9584b0a..fc2ab78371 100644 +--- a/bgpd/bgp_label.c ++++ b/bgpd/bgp_label.c +@@ -198,19 +198,20 @@ int bgp_parse_fec_update(void) + return 1; + } + +-mpls_label_t bgp_adv_label(struct bgp_dest *dest, struct bgp_path_info *pi, +- struct peer *to, afi_t afi, safi_t safi) ++void bgp_adv_label(struct bgp_dest *dest, struct bgp_path_info *pi, struct peer *to, afi_t afi, ++ safi_t safi, mpls_label_t *labels, uint8_t *num_labels) + { + struct peer *from; +- mpls_label_t remote_label; + int reflect; ++ uint8_t i; ++ bool use_local_label = true; + +- if (!dest || !pi || !to) +- return MPLS_INVALID_LABEL; ++ labels[0] = MPLS_INVALID_LABEL; ++ if (!dest || !pi || !to) { ++ *num_labels = 0; ++ return; ++ } + +- remote_label = BGP_PATH_INFO_NUM_LABELS(pi) +- ? pi->extra->labels->label[0] +- : MPLS_INVALID_LABEL; + from = pi->peer; + reflect = + ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP)); +@@ -218,12 +219,19 @@ mpls_label_t bgp_adv_label(struct bgp_dest *dest, struct bgp_path_info *pi, + if (reflect + && !CHECK_FLAG(to->af_flags[afi][safi], + PEER_FLAG_FORCE_NEXTHOP_SELF)) +- return remote_label; ++ use_local_label = false; + + if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) +- return remote_label; ++ use_local_label = false; + +- return dest->local_label; ++ if (use_local_label) { ++ *num_labels = 1; ++ labels[0] = dest->local_label; ++ } else { ++ *num_labels = BGP_PATH_INFO_NUM_LABELS(pi); ++ for (i = 0; i < *num_labels; i++) ++ labels[i] = pi->extra->labels->label[i]; ++ } + } + + static void bgp_send_fec_register_label_msg(struct bgp_dest *dest, bool reg, +@@ -414,35 +422,50 @@ void bgp_reg_dereg_for_label(struct bgp_dest *dest, struct bgp_path_info *pi, + dest, reg, with_label_index ? pi->attr->label_index : 0); + } + +-static int bgp_nlri_get_labels(struct peer *peer, uint8_t *pnt, uint8_t plen, +- mpls_label_t *label) ++/* Labels must have BGP_MAX_LABELS elements */ ++static int bgp_nlri_get_labels(struct peer *peer, uint8_t *pnt, uint8_t plen, mpls_label_t *labels, ++ uint8_t *num_labels) + { + uint8_t *data = pnt; + uint8_t *lim = pnt + plen; + uint8_t llen = 0; + uint8_t label_depth = 0; ++ mpls_label_t *label_pnt; ++ mpls_label_t label; + + if (plen < BGP_LABEL_BYTES) + return 0; + +- for (; data < lim; data += BGP_LABEL_BYTES) { +- memcpy(label, data, BGP_LABEL_BYTES); ++ label_pnt = &labels[0]; ++ for (; (data + BGP_LABEL_BYTES) <= lim; data += BGP_LABEL_BYTES, label_pnt++) { ++ /* ++ * Support only BGP_MAX_LABELS, read rest to local variable and ++ * discard, shouldn't be possible - see comment to BGP_MAX_LABELS ++ */ ++ if (label_depth >= BGP_MAX_LABELS) ++ label_pnt = &label; ++ ++ memcpy(label_pnt, data, BGP_LABEL_BYTES); + llen += BGP_LABEL_BYTES; + +- bgp_set_valid_label(label); ++ bgp_set_valid_label(label_pnt); ++ + label_depth += 1; + +- if (bgp_is_withdraw_label(label) || label_bos(label)) ++ if (bgp_is_withdraw_label(label_pnt) || label_bos(label_pnt)) + break; + } + +- /* If we RX multiple labels we will end up keeping only the last +- * one. We do not yet support a label stack greater than 1. */ +- if (label_depth > 1) +- zlog_info("%pBP rcvd UPDATE with label stack %d deep", peer, +- label_depth); ++ *num_labels = label_depth; + +- if (!(bgp_is_withdraw_label(label) || label_bos(label))) ++ if (label_depth > BGP_MAX_LABELS) { ++ *num_labels = BGP_MAX_LABELS; ++ label_set_bos(&labels[*num_labels - 1]); ++ zlog_info("%pBP rcvd UPDATE with label stack %d deep, using only first %d labels", ++ peer, label_depth, BGP_MAX_LABELS); ++ } ++ ++ if (!(bgp_is_withdraw_label(label_pnt) || label_bos(label_pnt))) + flog_warn( + EC_BGP_INVALID_LABEL_STACK, + "%pBP rcvd UPDATE with invalid label stack - no bottom of stack", +@@ -463,7 +486,8 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, + safi_t safi; + bool addpath_capable; + uint32_t addpath_id; +- mpls_label_t label = MPLS_INVALID_LABEL; ++ mpls_label_t labels[MPLS_MAX_LABELS] = { MPLS_INVALID_LABEL }; ++ uint8_t num_labels = 0; + uint8_t llen; + + pnt = packet->nlri; +@@ -507,7 +531,7 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, + } + + /* Fill in the labels */ +- llen = bgp_nlri_get_labels(peer, pnt, psize, &label); ++ llen = bgp_nlri_get_labels(peer, pnt, psize, labels, &num_labels); + if (llen == 0) { + flog_err( + EC_BGP_UPDATE_RCV, +@@ -574,13 +598,11 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, + } + + if (attr) { +- bgp_update(peer, &p, addpath_id, attr, packet->afi, +- safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, +- NULL, &label, 1, 0, NULL); ++ bgp_update(peer, &p, addpath_id, attr, packet->afi, safi, ZEBRA_ROUTE_BGP, ++ BGP_ROUTE_NORMAL, NULL, labels, num_labels, 0, NULL); + } else { +- bgp_withdraw(peer, &p, addpath_id, packet->afi, +- SAFI_UNICAST, ZEBRA_ROUTE_BGP, +- BGP_ROUTE_NORMAL, NULL, &label, 1); ++ bgp_withdraw(peer, &p, addpath_id, packet->afi, SAFI_UNICAST, ++ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, labels, num_labels); + } + } + +@@ -596,6 +618,37 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, + return BGP_NLRI_PARSE_OK; + } + ++uint32_t decode_label(mpls_label_t *label_pnt) ++{ ++ uint32_t l; ++ uint8_t *pnt = (uint8_t *)label_pnt; ++ ++ l = ((uint32_t)*pnt++ << 12); ++ l |= (uint32_t)*pnt++ << 4; ++ l |= (uint32_t)((*pnt & 0xf0) >> 4); ++ return l; ++} ++ ++void encode_label_bos(mpls_label_t label, mpls_label_t *label_pnt, bool bos) ++{ ++ uint8_t *pnt = (uint8_t *)label_pnt; ++ ++ if (pnt == NULL) ++ return; ++ if (label == BGP_PREVENT_VRF_2_VRF_LEAK) { ++ *label_pnt = label; ++ return; ++ } ++ *pnt++ = (label >> 12) & 0xff; ++ *pnt++ = (label >> 4) & 0xff; ++ *pnt++ = ((label << 4) + (bos ? 1 : 0)) & 0xff; ++} ++ ++void encode_label(mpls_label_t label, mpls_label_t *label_pnt) ++{ ++ encode_label_bos(label, label_pnt, true); ++} ++ + bool bgp_labels_same(const mpls_label_t *tbl_a, const uint8_t num_labels_a, + const mpls_label_t *tbl_b, const uint8_t num_labels_b) + { +@@ -612,3 +665,30 @@ bool bgp_labels_same(const mpls_label_t *tbl_a, const uint8_t num_labels_a, + } + return true; + } ++ ++char *mpls_labels2str(mpls_label_t *labels, uint8_t num_labels, const char *prefix, char *buf, ++ int size) ++{ ++ uint32_t label_value; ++ uint32_t len = 0; ++ uint8_t i; ++ ++ buf[0] = '\0'; ++ if (!num_labels) ++ return buf; ++ ++ if (prefix) { ++ strlcat(buf + len, prefix, size - len); ++ len = strlen(buf); ++ } ++ ++ label_value = decode_label(&labels[0]); ++ len += snprintf(buf + len, size - len, "%u", label_value); ++ ++ for (i = 1; i < num_labels; i++) { ++ label_value = decode_label(&labels[i]); ++ len += snprintf(buf + len, size - len, "/%u", label_value); ++ } ++ ++ return buf; ++} +diff --git a/bgpd/bgp_label.h b/bgpd/bgp_label.h +index 2ffd5b699d..ab972c4830 100644 +--- a/bgpd/bgp_label.h ++++ b/bgpd/bgp_label.h +@@ -16,9 +16,15 @@ struct bgp_path_info; + struct peer; + + /* Maximum number of labels we can process or send with a prefix. We +- * really do only 1 for MPLS (BGP-LU) but we can do 2 for EVPN-VxLAN. ++ * support 10 for MPLS (BGP-LU) and need only 2 for EVPN-VxLAN. ++ * ++ * According to RFC 3107/RFC 8277 label stack is distributed in NLRI, length is given in ++ * one byte in bits! (prefix length + whole number of label stack bits), so even if ++ * prefix is 0 length, (each label takes 3 bytes) floor(256/24) = 10 ++ * ++ * It is impossible to pass more than 10 labels by BGP-LU + */ +-#define BGP_MAX_LABELS 2 ++#define BGP_MAX_LABELS 10 + + /* MPLS label(s) - VNI(s) for EVPN-VxLAN */ + struct bgp_labels { +@@ -40,16 +46,21 @@ extern int bgp_reg_for_label_callback(mpls_label_t new_label, void *labelid, + extern void bgp_reg_dereg_for_label(struct bgp_dest *dest, + struct bgp_path_info *pi, bool reg); + extern int bgp_parse_fec_update(void); +-extern mpls_label_t bgp_adv_label(struct bgp_dest *dest, +- struct bgp_path_info *pi, struct peer *to, +- afi_t afi, safi_t safi); ++extern void bgp_adv_label(struct bgp_dest *dest, struct bgp_path_info *pi, struct peer *to, ++ afi_t afi, safi_t safi, mpls_label_t *labels, uint8_t *num_labels); + + extern int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet); ++extern uint32_t decode_label(mpls_label_t *label); ++extern void encode_label_bos(mpls_label_t label_in, mpls_label_t *label_out, bool bos); ++extern void encode_label(mpls_label_t label_in, mpls_label_t *label_out); + extern bool bgp_labels_same(const mpls_label_t *tbl_a, + const uint8_t num_labels_a, + const mpls_label_t *tbl_b, + const uint8_t num_labels_b); ++/* Write labels to str of format "prefixLABEL1/LABEL2/.../LABELN", prefix may be NULL */ ++extern char *mpls_labels2str(mpls_label_t *labels, uint8_t num_labels, const char *prefix, ++ char *buf, int size); + + static inline int bgp_labeled_safi(safi_t safi) + { +@@ -114,4 +125,13 @@ static inline uint8_t label_bos(mpls_label_t *label) + return (t[2] & 0x01); + }; + ++/* Set BOS to 1 */ ++static inline void label_set_bos(mpls_label_t *label) ++{ ++ uint8_t *t = (uint8_t *)label; ++ ++ if (t) ++ t[2] |= 0x01; ++} ++ + #endif /* _BGP_LABEL_H */ +diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c +index a35b4037bb..057ecb318e 100644 +--- a/bgpd/bgp_mplsvpn.c ++++ b/bgpd/bgp_mplsvpn.c +@@ -64,31 +64,6 @@ extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, + return ret; + } + +-uint32_t decode_label(mpls_label_t *label_pnt) +-{ +- uint32_t l; +- uint8_t *pnt = (uint8_t *)label_pnt; +- +- l = ((uint32_t)*pnt++ << 12); +- l |= (uint32_t)*pnt++ << 4; +- l |= (uint32_t)((*pnt & 0xf0) >> 4); +- return l; +-} +- +-void encode_label(mpls_label_t label, mpls_label_t *label_pnt) +-{ +- uint8_t *pnt = (uint8_t *)label_pnt; +- if (pnt == NULL) +- return; +- if (label == BGP_PREVENT_VRF_2_VRF_LEAK) { +- *label_pnt = label; +- return; +- } +- *pnt++ = (label >> 12) & 0xff; +- *pnt++ = (label >> 4) & 0xff; +- *pnt++ = ((label << 4) + 1) & 0xff; /* S=1 */ +-} +- + int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet) + { +diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h +index 3b036d2167..ab84cc2118 100644 +--- a/bgpd/bgp_mplsvpn.h ++++ b/bgpd/bgp_mplsvpn.h +@@ -34,8 +34,6 @@ + extern void bgp_mplsvpn_init(void); + extern void bgp_mplsvpn_path_nh_label_unlink(struct bgp_path_info *pi); + extern int bgp_nlri_parse_vpn(struct peer *, struct attr *, struct bgp_nlri *); +-extern uint32_t decode_label(mpls_label_t *); +-extern void encode_label(mpls_label_t, mpls_label_t *); + + extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc, + int *index, afi_t *afi); +diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c +index 85cad88979..867b4a7cea 100644 +--- a/bgpd/bgp_route.c ++++ b/bgpd/bgp_route.c +@@ -2145,8 +2145,9 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, + int samepeer_safe = 0; /* for synthetic mplsvpns routes */ + bool nh_reset = false; + uint64_t cum_bw; +- mpls_label_t label; + bool global_and_ll = false; ++ uint8_t num_labels; ++ mpls_label_t labels[BGP_MAX_LABELS] = { MPLS_INVALID_LABEL }; + + if (DISABLE_BGP_ANNOUNCE) + return false; +@@ -2231,13 +2232,11 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, + + /* If it's labeled safi, make sure the route has a valid label. */ + if (safi == SAFI_LABELED_UNICAST) { +- label = bgp_adv_label(dest, pi, peer, afi, safi); +- if (!bgp_is_valid_label(&label)) { ++ bgp_adv_label(dest, pi, peer, afi, safi, labels, &num_labels); ++ if (!bgp_is_valid_label(&labels[0])) { + if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) +- zlog_debug("u%" PRIu64 ":s%" PRIu64 +- " %pFX is filtered - no label (%p)", +- subgrp->update_group->id, subgrp->id, +- p, &label); ++ zlog_debug("u%" PRIu64 ":s%" PRIu64 " %pFX is filtered - no label", ++ subgrp->update_group->id, subgrp->id, p); + return false; + } + } else if (safi == SAFI_MPLS_VPN && +@@ -2254,8 +2253,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, + * then get appropriate mpls local label + * and check its validity + */ +- label = bgp_mplsvpn_nh_label_bind_get_label(pi); +- if (!bgp_is_valid_label(&label)) { ++ labels[0] = bgp_mplsvpn_nh_label_bind_get_label(pi); ++ if (!bgp_is_valid_label(&labels[0])) { + if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) + zlog_debug("u%" PRIu64 ":s%" PRIu64 + " %pFX is filtered - no valid label", +@@ -10493,6 +10492,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, + json_object *json_paths) + { + char buf[INET6_ADDRSTRLEN]; ++ char labels_buf[9 * BGP_MAX_LABELS]; /* 8 per label + / or \0 for each */ + char vni_buf[30] = {}; + struct attr *attr = path->attr; + time_t tbuf; +@@ -10500,6 +10500,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, + json_object *json_bestpath = NULL; + json_object *json_cluster_list = NULL; + json_object *json_cluster_list_list = NULL; ++ json_object *json_labels = NULL; + json_object *json_ext_community = NULL; + json_object *json_ext_ipv6_community = NULL; + json_object *json_last_update = NULL; +@@ -10510,6 +10511,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, + json_object *json_path = NULL; + json_object *json_peer = NULL; + json_object *json_string = NULL; ++ json_object *json_int = NULL; + json_object *json_adv_to = NULL; + int first = 0; + struct listnode *node, *nnode; +@@ -10520,12 +10522,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, + bool nexthop_self = + CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false; + int i; +- char *nexthop_hostname = +- bgp_nexthop_hostname(path->peer, path->nexthop); +- uint32_t ttl = 0; +- uint32_t bos = 0; +- uint32_t exp = 0; +- mpls_label_t label = MPLS_INVALID_LABEL; ++ char *nexthop_hostname = bgp_nexthop_hostname(path->peer, path->nexthop); + struct bgp_path_info *bpi_ultimate = + bgp_get_imported_bpi_ultimate(path); + struct bgp_route_evpn *bre = bgp_attr_get_evpn_overlay(attr); +@@ -11338,13 +11335,28 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, + /* Remote Label */ + if (bgp_path_info_has_valid_label(path) && + (safi != SAFI_EVPN && !is_route_parent_evpn(path))) { +- mpls_lse_decode(path->extra->labels->label[0], &label, &ttl, +- &exp, &bos); +- +- if (json_paths) +- json_object_int_add(json_path, "remoteLabel", label); +- else +- vty_out(vty, " Remote label: %d\n", label); ++ if (json_paths) { ++#if CONFDATE > 20261107 ++ CPP_NOTICE("Remove 'remoteLabel' field"); ++#endif ++ /* For backward compatibility write top label to remoteLabel */ ++ json_object_int_add(json_path, "remoteLabel", ++ decode_label(&path->extra->labels->label[0])); ++ ++ /* Write full stack to remoteLabels */ ++ json_labels = json_object_new_array(); ++ for (int label_index = 0; label_index < path->extra->labels->num_labels; ++ label_index++) { ++ json_int = json_object_new_int( ++ decode_label(&path->extra->labels->label[label_index])); ++ json_object_array_add(json_labels, json_int); ++ } ++ json_object_object_add(json_path, "remoteLabels", json_labels); ++ } else { ++ mpls_labels2str(path->extra->labels->label, path->extra->labels->num_labels, ++ NULL, labels_buf, sizeof(labels_buf)); ++ vty_out(vty, " Remote labels: %s\n", labels_buf); ++ } + } + + /* Remote SID */ +diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c +index 3ce136ef87..4e0702aeb4 100644 +--- a/bgpd/bgp_updgrp_packet.c ++++ b/bgpd/bgp_updgrp_packet.c +@@ -664,7 +664,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) + int addpath_overhead = 0; + uint32_t addpath_tx_id = 0; + struct prefix_rd *prd = NULL; +- mpls_label_t label = MPLS_INVALID_LABEL, *label_pnt = NULL; ++ mpls_label_t *label_pnt = NULL; ++ mpls_label_t labels[BGP_MAX_LABELS] = { MPLS_INVALID_LABEL }; + uint8_t num_labels = 0; + + if (!subgrp) +@@ -785,10 +786,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) + dest->pdest); + + if (safi == SAFI_LABELED_UNICAST) { +- label = bgp_adv_label(dest, path, peer, afi, +- safi); +- label_pnt = &label; +- num_labels = 1; ++ bgp_adv_label(dest, path, peer, afi, safi, labels, &num_labels); ++ label_pnt = &labels[0]; + } else if (safi == SAFI_MPLS_VPN && path && + CHECK_FLAG(path->flags, + BGP_PATH_MPLSVPN_NH_LABEL_BIND) && +@@ -808,9 +807,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) + * called here, 'get_label()' returns a valid + * label. + */ +- label = bgp_mplsvpn_nh_label_bind_get_label( +- path); +- label_pnt = &label; ++ labels[0] = bgp_mplsvpn_nh_label_bind_get_label(path); ++ label_pnt = &labels[0]; + num_labels = 1; + } else { + num_labels = BGP_PATH_INFO_NUM_LABELS(path); +diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c +index 51af57ac68..ecfc278f2c 100644 +--- a/bgpd/bgp_zebra.c ++++ b/bgpd/bgp_zebra.c +@@ -1328,11 +1328,10 @@ static void bgp_zebra_announce_parse_nexthop( + + if (bgp_debug_zebra(&api->prefix)) { + if (BGP_PATH_INFO_NUM_LABELS(mpinfo)) { +- zlog_debug("%s: p=%pFX, bgp_is_valid_label: %d", ++ zlog_debug("%s: p=%pFX, bgp_is_valid_label: %d, num_labels: %d", + __func__, p, +- bgp_is_valid_label( +- &mpinfo->extra->labels +- ->label[0])); ++ bgp_is_valid_label(&mpinfo->extra->labels->label[0]), ++ BGP_PATH_INFO_NUM_LABELS(mpinfo)); + } else { + zlog_debug("%s: p=%pFX, no label", __func__, p); + } +@@ -1411,15 +1410,28 @@ static void bgp_zebra_announce_parse_nexthop( + nh_label = *bgp_evpn_path_info_labels_get_l3vni( + labels, num_labels); + nh_label_type = ZEBRA_LSP_EVPN; ++ ++ api_nh->label_num = 1; ++ api_nh->labels[0] = nh_label; + } else { +- mpls_lse_decode(labels[0], &nh_label, &ttl, +- &exp, &bos); ++ uint8_t i; ++ int max_elements = sizeof(api_nh->labels) / ++ sizeof(api_nh->labels[0]); ++ ++ api_nh->label_num = num_labels; ++ if (api_nh->label_num > max_elements) { ++ zlog_warn("%s: too many labels provided for zebra (%d), copying first %d", ++ __func__, num_labels, max_elements); ++ api_nh->label_num = max_elements; ++ } ++ for (i = 0; i < api_nh->label_num; i++) { ++ mpls_lse_decode(labels[i], &api_nh->labels[i], &ttl, &exp, ++ &bos); ++ } + } + + SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL); +- api_nh->label_num = 1; + api_nh->label_type = nh_label_type; +- api_nh->labels[0] = nh_label; + } + + if (is_evpn && !(bre && bre->type == OVERLAY_INDEX_GATEWAY_IP)) +@@ -1475,7 +1487,8 @@ static void bgp_debug_zebra_nh(struct zapi_route *api) + char nh_buf[INET6_ADDRSTRLEN]; + char eth_buf[ETHER_ADDR_STRLEN + 7] = { '\0' }; + char buf1[ETHER_ADDR_STRLEN]; +- char label_buf[20]; ++ /* strlen("label ") + 8 chars per label + '/' or '\0' for each label */ ++ char label_buf[6 + 9 * BGP_MAX_LABELS]; + char sid_buf[20]; + char segs_buf[256]; + struct zapi_nexthop *api_nh; +@@ -1513,9 +1526,19 @@ static void bgp_debug_zebra_nh(struct zapi_route *api) + eth_buf[0] = '\0'; + segs_buf[0] = '\0'; + if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL) && +- !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) +- snprintf(label_buf, sizeof(label_buf), "label %u", +- api_nh->labels[0]); ++ !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) { ++ int label_len; ++ int j; ++ ++ label_len = snprintf(label_buf, sizeof(label_buf), "label %u", ++ api_nh->labels[0]); ++ ++ for (j = 1; j < api_nh->label_num; j++) { ++ label_len += snprintf(label_buf + label_len, ++ sizeof(label_buf) - label_len, "/%u", ++ api_nh->labels[j]); ++ } ++ } + if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6) && + !CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN)) { + inet_ntop(AF_INET6, &api_nh->seg6_segs[0], sid_buf, +-- +2.50.1 + |
