diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 67659ea198..3c980eb1da 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -36,27 +36,6 @@ static inline int is_evpn_enabled(void) return bgp ? EVPN_ENABLED(bgp) : 0; } -static inline void vni2label(vni_t vni, mpls_label_t *label) -{ - uint8_t *tag = (uint8_t *)label; - - tag[0] = (vni >> 16) & 0xFF; - tag[1] = (vni >> 8) & 0xFF; - tag[2] = vni & 0xFF; -} - -static inline vni_t label2vni(mpls_label_t *label) -{ - uint8_t *tag = (uint8_t *)label; - vni_t vni; - - vni = ((uint32_t)*tag++ << 16); - vni |= (uint32_t)*tag++ << 8; - vni |= (uint32_t)(*tag & 0xFF); - - return vni; -} - static inline int advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi) { diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 22625ed247..215108a280 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -2285,7 +2285,8 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix, label2str( nexthop->label_stack->label[i], - buf_label, sizeof(buf_label)); + 0, buf_label, + sizeof(buf_label)); if (i != 0) strlcat(buf_labels, "/", sizeof(buf_labels)); @@ -2293,7 +2294,7 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix, sizeof(buf_labels)); } } else if (nexthop->sr.present) - label2str(nexthop->sr.label, buf_labels, + label2str(nexthop->sr.label, 0, buf_labels, sizeof(buf_labels)); else strlcpy(buf_labels, "-", sizeof(buf_labels)); diff --git a/lib/mpls.c b/lib/mpls.c index ac5792a686..1b21dd29ff 100644 --- a/lib/mpls.c +++ b/lib/mpls.c @@ -80,7 +80,7 @@ int mpls_str2label(const char *label_str, uint8_t *num_labels, * Label to string conversion, labels in string separated by '/'. */ char *mpls_label2str(uint8_t num_labels, const mpls_label_t *labels, char *buf, - int len, int pretty) + int len, enum lsp_types_t type, int pretty) { char label_buf[BUFSIZ]; int i; @@ -90,9 +90,14 @@ char *mpls_label2str(uint8_t num_labels, const mpls_label_t *labels, char *buf, if (i != 0) strlcat(buf, "/", len); if (pretty) - label2str(labels[i], label_buf, sizeof(label_buf)); + label2str(labels[i], type, label_buf, + sizeof(label_buf)); else - snprintf(label_buf, sizeof(label_buf), "%u", labels[i]); + snprintf(label_buf, sizeof(label_buf), "%u", + ((type == ZEBRA_LSP_EVPN) + ? label2vni(&labels[i]) + : labels[i])); + strlcat(buf, label_buf, len); } diff --git a/lib/mpls.h b/lib/mpls.h index 74bd7aae3e..f89d3246ff 100644 --- a/lib/mpls.h +++ b/lib/mpls.h @@ -23,6 +23,7 @@ #define _QUAGGA_MPLS_H #include +#include #include #ifdef __cplusplus @@ -129,10 +130,32 @@ enum lsp_types_t { ZEBRA_LSP_ISIS_SR = 5,/* IS-IS Segment Routing LSP. */ ZEBRA_LSP_SHARP = 6, /* Identifier for test protocol */ ZEBRA_LSP_SRTE = 7, /* SR-TE LSP */ + ZEBRA_LSP_EVPN = 8, /* EVPN VNI Label */ }; /* Functions for basic label operations. */ +static inline void vni2label(vni_t vni, mpls_label_t *label) +{ + uint8_t *tag = (uint8_t *)label; + + tag[0] = (vni >> 16) & 0xFF; + tag[1] = (vni >> 8) & 0xFF; + tag[2] = vni & 0xFF; +} + +static inline vni_t label2vni(const mpls_label_t *label) +{ + uint8_t *tag = (uint8_t *)label; + vni_t vni; + + vni = ((uint32_t)*tag++ << 16); + vni |= (uint32_t)*tag++ << 8; + vni |= (uint32_t)(*tag & 0xFF); + + return vni; +} + /* Encode a label stack entry from fields; convert to network byte-order as * the Netlink interface expects MPLS labels to be in this format. */ @@ -168,8 +191,14 @@ static inline void mpls_lse_decode(mpls_lse_t lse, mpls_label_t *label, #define MPLS_INVALID_LABEL_INDEX 0xFFFFFFFF /* Printable string for labels (with consideration for reserved values). */ -static inline char *label2str(mpls_label_t label, char *buf, size_t len) +static inline char *label2str(mpls_label_t label, enum lsp_types_t type, + char *buf, size_t len) { + if (type == ZEBRA_LSP_EVPN) { + snprintf(buf, len, "%u", label2vni(&label)); + return (buf); + } + switch (label) { case MPLS_LABEL_IPV4_EXPLICIT_NULL: strlcpy(buf, "IPv4 Explicit Null", len); @@ -217,7 +246,7 @@ int mpls_str2label(const char *label_str, uint8_t *num_labels, * Label to string conversion, labels in string separated by '/'. */ char *mpls_label2str(uint8_t num_labels, const mpls_label_t *labels, char *buf, - int len, int pretty); + int len, enum lsp_types_t type, int pretty); #ifdef __cplusplus } diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 44bddacd58..7e27798062 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -1070,9 +1070,8 @@ void nexthop_group_write_nexthop(struct vty *vty, const struct nexthop *nh) if (nh->nh_label && nh->nh_label->num_labels > 0) { char buf[200]; - mpls_label2str(nh->nh_label->num_labels, - nh->nh_label->label, - buf, sizeof(buf), 0); + mpls_label2str(nh->nh_label->num_labels, nh->nh_label->label, + buf, sizeof(buf), nh->nh_label_type, 0); vty_out(vty, " label %s", buf); } @@ -1129,7 +1128,7 @@ void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh) char buf[200]; mpls_label2str(nh->nh_label->num_labels, nh->nh_label->label, - buf, sizeof(buf), 0); + buf, sizeof(buf), nh->nh_label_type, 0); json_object_string_add(j, "label", buf); } diff --git a/ospfd/ospf_ti_lfa.c b/ospfd/ospf_ti_lfa.c index 28d24bcbe6..76f61f783e 100644 --- a/ospfd/ospf_ti_lfa.c +++ b/ospfd/ospf_ti_lfa.c @@ -723,7 +723,7 @@ static void ospf_ti_lfa_generate_q_spaces(struct ospf_area *area, if (q_space->label_stack) { mpls_label2str(q_space->label_stack->num_labels, q_space->label_stack->label, label_buf, - MPLS_LABEL_STRLEN, true); + MPLS_LABEL_STRLEN, 0, true); zlog_info( "%s: Generated label stack %s for root %pI4 and destination %pI4 for %s", __func__, label_buf, &p_space->root->id, @@ -1050,7 +1050,7 @@ void ospf_ti_lfa_insert_backup_paths(struct ospf_area *area, path->srni.backup_label_stack ->num_labels, path->srni.backup_label_stack->label, - label_buf, MPLS_LABEL_STRLEN, true); + label_buf, MPLS_LABEL_STRLEN, 0, true); if (IS_DEBUG_OSPF_TI_LFA) zlog_debug( "%s: inserted backup path %s for prefix %pFX, router id %pI4 and nexthop %pI4.", diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index fdea766a1b..3288373dbe 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1779,13 +1779,18 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, nexthop->srte_color = api_nh->srte_color; } - /* MPLS labels for BGP-LU or Segment Routing */ + /* Labels for MPLS BGP-LU or Segment Routing or EVPN */ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL) && api_nh->type != NEXTHOP_TYPE_IFINDEX && api_nh->type != NEXTHOP_TYPE_BLACKHOLE && api_nh->label_num > 0) { - label_type = lsp_type_from_re_type(client->proto); + if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) + label_type = ZEBRA_LSP_EVPN; + else + label_type = + lsp_type_from_re_type(client->proto); + nexthop_add_labels(nexthop, label_type, api_nh->label_num, &api_nh->labels[0]); @@ -1823,7 +1828,7 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, mpls_label2str(nexthop->nh_label->num_labels, nexthop->nh_label->label, labelbuf, sizeof(labelbuf), - false); + nexthop->nh_label_type, false); } zlog_debug("%s: nh=%s, vrf_id=%d %s", diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 13963d9cc3..aec4961126 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -492,7 +492,7 @@ static void fec_print(struct zebra_fec *fec, struct vty *vty) rn = fec->rn; vty_out(vty, "%pRN\n", rn); - vty_out(vty, " Label: %s", label2str(fec->label, buf, BUFSIZ)); + vty_out(vty, " Label: %s", label2str(fec->label, 0, buf, BUFSIZ)); if (fec->label_index != MPLS_INVALID_LABEL_INDEX) vty_out(vty, ", Label Index: %u", fec->label_index); vty_out(vty, "\n"); @@ -1597,8 +1597,8 @@ static void nhlfe_print(struct zebra_nhlfe *nhlfe, struct vty *vty, vty_out(vty, " type: %s remote label: %s distance: %d\n", nhlfe_type2str(nhlfe->type), mpls_label2str(nexthop->nh_label->num_labels, - nexthop->nh_label->label, - buf, sizeof(buf), 0), + nexthop->nh_label->label, buf, sizeof(buf), + nexthop->nh_label_type, 0), nhlfe->distance); if (indent) @@ -2719,7 +2719,7 @@ int zebra_mpls_write_fec_config(struct vty *vty, struct zebra_vrf *zvrf) write = 1; vty_out(vty, "mpls label bind %pFX %s\n", &rn->p, - label2str(fec->label, lstr, BUFSIZ)); + label2str(fec->label, 0, lstr, BUFSIZ)); } } @@ -3164,10 +3164,10 @@ lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t type, nhlfe2str(nhlfe, buf, sizeof(buf)); mpls_label2str(num_out_labels, out_labels, buf2, - sizeof(buf2), 0); + sizeof(buf2), 0, 0); mpls_label2str(nh->nh_label->num_labels, nh->nh_label->label, buf3, sizeof(buf3), - 0); + nh->nh_label_type, 0); zlog_debug("LSP in-label %u type %d %snexthop %s out-label(s) changed to %s (old %s)", lsp->ile.in_label, type, backup_str, buf, @@ -3195,7 +3195,7 @@ lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t type, nhlfe2str(nhlfe, buf, sizeof(buf)); mpls_label2str(num_out_labels, out_labels, buf2, - sizeof(buf2), 0); + sizeof(buf2), 0, 0); zlog_debug("Add LSP in-label %u type %d %snexthop %s out-label(s) %s", lsp->ile.in_label, type, backup_str, buf, @@ -3778,10 +3778,10 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, json = json_object_new_object(); for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) - json_object_object_add( - json, label2str(lsp->ile.in_label, buf, - sizeof(buf)), - lsp_json(lsp)); + json_object_object_add(json, + label2str(lsp->ile.in_label, 0, + buf, sizeof(buf)), + lsp_json(lsp)); vty_json(vty, json); } else { @@ -3833,7 +3833,8 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, out_label_str = mpls_label2str( nexthop->nh_label->num_labels, &nexthop->nh_label->label[0], - buf, sizeof(buf), 1); + buf, sizeof(buf), + nexthop->nh_label_type, 1); else out_label_str = "-"; diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index cf247861f8..1e63a59576 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -446,6 +446,7 @@ static inline uint8_t lsp_distance(enum lsp_types_t type) return (route_distance(ZEBRA_ROUTE_BGP)); case ZEBRA_LSP_NONE: case ZEBRA_LSP_SHARP: + case ZEBRA_LSP_EVPN: case ZEBRA_LSP_OSPF_SR: case ZEBRA_LSP_ISIS_SR: case ZEBRA_LSP_SRTE: @@ -498,6 +499,7 @@ static inline int re_type_from_lsp_type(enum lsp_types_t lsp_type) case ZEBRA_LSP_LDP: return ZEBRA_ROUTE_LDP; case ZEBRA_LSP_BGP: + case ZEBRA_LSP_EVPN: return ZEBRA_ROUTE_BGP; case ZEBRA_LSP_OSPF_SR: return ZEBRA_ROUTE_OSPF; @@ -538,6 +540,8 @@ static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type) return "SHARP"; case ZEBRA_LSP_SRTE: return "SR-TE"; + case ZEBRA_LSP_EVPN: + return "EVPN"; case ZEBRA_LSP_NONE: return "Unknown"; } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index ba8073defe..3aec97dfee 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -4025,7 +4025,8 @@ static void _route_entry_dump_nh(const struct route_entry *re, if (nexthop->nh_label && nexthop->nh_label->num_labels > 0) { mpls_label2str(nexthop->nh_label->num_labels, nexthop->nh_label->label, label_str, - sizeof(label_str), 0 /*pretty*/); + sizeof(label_str), nexthop->nh_label_type, + 0 /*pretty*/); strlcat(label_str, ", ", sizeof(label_str)); } diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 342a8d0f96..3bbb1f2325 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -1413,8 +1413,14 @@ void show_nexthop_json_helper(json_object *json_nexthop, label_index < nexthop->nh_label->num_labels; label_index++) json_object_array_add( json_labels, - json_object_new_int( - nexthop->nh_label->label[label_index])); + json_object_new_int(( + (nexthop->nh_label_type == + ZEBRA_LSP_EVPN) + ? label2vni( + &nexthop->nh_label->label + [label_index]) + : nexthop->nh_label->label + [label_index]))); json_object_object_add(json_nexthop, "labels", json_labels); } @@ -1534,7 +1540,7 @@ void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re, vty_out(vty, ", label %s", mpls_label2str(nexthop->nh_label->num_labels, nexthop->nh_label->label, buf, - sizeof(buf), 1)); + sizeof(buf), nexthop->nh_label_type, 1)); } if (nexthop->nh_srv6) { diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 34d8ea95b3..540a88437a 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -418,7 +418,8 @@ static void show_nexthop_detail_helper(struct vty *vty, vty_out(vty, ", label %s", mpls_label2str(nexthop->nh_label->num_labels, nexthop->nh_label->label, buf, - sizeof(buf), 1 /*pretty*/)); + sizeof(buf), nexthop->nh_label_type, + 1 /*pretty*/)); } if (nexthop->weight)