diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 86f41e807f..e6a06ff95d 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1782,7 +1782,7 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS) struct zapi_nexthop_label *znh; znh = &zl.nexthops[i]; - mpls_lsp_install(zvrf, zl.type, zl.local_label, znh->label, + mpls_lsp_install(zvrf, zl.type, zl.local_label, 1, &znh->label, znh->type, &znh->address, znh->ifindex); if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN)) @@ -1883,7 +1883,7 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS) struct zapi_nexthop_label *znh; znh = &zl.nexthops[i]; - mpls_lsp_install(zvrf, zl.type, zl.local_label, znh->label, + mpls_lsp_install(zvrf, zl.type, zl.local_label, 1, &znh->label, znh->type, &znh->address, znh->ifindex); if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN)) { @@ -2282,10 +2282,11 @@ static void zread_vrf_label(ZAPI_HANDLER_ARGS) ifp->ifindex); } - if (nlabel != MPLS_LABEL_NONE) - mpls_lsp_install(def_zvrf, ltype, nlabel, - MPLS_LABEL_IMPLICIT_NULL, NEXTHOP_TYPE_IFINDEX, - NULL, ifp->ifindex); + if (nlabel != MPLS_LABEL_NONE) { + mpls_label_t out_label = MPLS_LABEL_IMPLICIT_NULL; + mpls_lsp_install(def_zvrf, ltype, nlabel, 1, &out_label, + NEXTHOP_TYPE_IFINDEX, NULL, ifp->ifindex); + } zvrf->label[afi] = nlabel; stream_failure: diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 7f993442a6..aecadfadf8 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -1161,7 +1161,8 @@ zebra_nhlfe_t *dplane_ctx_add_nhlfe(struct zebra_dplane_ctx *ctx, enum nexthop_types_t nh_type, union g_addr *gate, ifindex_t ifindex, - mpls_label_t out_label) + uint8_t num_labels, + mpls_label_t out_labels[]) { zebra_nhlfe_t *nhlfe; @@ -1169,7 +1170,7 @@ zebra_nhlfe_t *dplane_ctx_add_nhlfe(struct zebra_dplane_ctx *ctx, nhlfe = zebra_mpls_lsp_add_nhlfe(&(ctx->u.lsp), lsp_type, nh_type, gate, - ifindex, out_label); + ifindex, num_labels, out_labels); return nhlfe; } @@ -1660,7 +1661,8 @@ static int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, nhlfe->nexthop->type, &(nhlfe->nexthop->gate), nhlfe->nexthop->ifindex, - nhlfe->nexthop->nh_label->label[0]); + nhlfe->nexthop->nh_label->num_labels, + nhlfe->nexthop->nh_label->label); if (new_nhlfe == NULL || new_nhlfe->nexthop == NULL) { ret = ENOMEM; diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index fede3bfcca..c0b04e71b0 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -302,7 +302,8 @@ zebra_nhlfe_t *dplane_ctx_add_nhlfe(struct zebra_dplane_ctx *ctx, enum nexthop_types_t nh_type, union g_addr *gate, ifindex_t ifindex, - mpls_label_t out_label); + uint8_t num_labels, + mpls_label_t out_labels[]); const zebra_nhlfe_t *dplane_ctx_get_best_nhlfe( const struct zebra_dplane_ctx *ctx); diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 6942a37989..5146311c6a 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -102,7 +102,8 @@ static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, ifindex_t ifindex); static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex, mpls_label_t out_label); + ifindex_t ifindex, uint8_t num_labels, + mpls_label_t *labels); static int nhlfe_del(zebra_nhlfe_t *snhlfe); static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe, struct mpls_label_stack *nh_label); @@ -218,7 +219,8 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label, /* Add LSP entry to this nexthop */ nhlfe = nhlfe_add(lsp, lsp_type, nexthop->type, &nexthop->gate, nexthop->ifindex, - nexthop->nh_label->label[0]); + nexthop->nh_label->num_labels, + nexthop->nh_label->label); if (!nhlfe) return -1; @@ -1197,7 +1199,8 @@ static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, */ static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex, mpls_label_t out_label) + ifindex_t ifindex, uint8_t num_labels, + mpls_label_t labels[]) { zebra_nhlfe_t *nhlfe; struct nexthop *nexthop; @@ -1216,7 +1219,7 @@ static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type, XFREE(MTYPE_NHLFE, nhlfe); return NULL; } - nexthop_add_labels(nexthop, lsp_type, 1, &out_label); + nexthop_add_labels(nexthop, lsp_type, num_labels, labels); nexthop->vrf_id = VRF_DEFAULT; nexthop->type = gtype; @@ -2083,10 +2086,12 @@ zebra_nhlfe_t *zebra_mpls_lsp_add_nhlfe(zebra_lsp_t *lsp, enum nexthop_types_t gtype, union g_addr *gate, ifindex_t ifindex, - mpls_label_t out_label) + uint8_t num_labels, + mpls_label_t out_labels[]) { /* Just a public pass-through to the internal implementation */ - return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, out_label); + return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, num_labels, + out_labels); } /* @@ -2730,9 +2735,9 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, * the out-label for an existing NHLFE (update case). */ int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, mpls_label_t out_label, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex) + mpls_label_t in_label, uint8_t num_out_labels, + mpls_label_t out_labels[], enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex) { struct hash *lsp_table; zebra_ile_t tmp_ile; @@ -2759,33 +2764,56 @@ int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type, /* Clear deleted flag (in case it was set) */ UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED); - if (nh->nh_label->label[0] == out_label) + if (nh->nh_label->num_labels == num_out_labels + && !memcmp(nh->nh_label->label, out_labels, + sizeof(mpls_label_t) * num_out_labels)) /* No change */ return 0; if (IS_ZEBRA_DEBUG_MPLS) { + char buf2[BUFSIZ]; + char buf3[BUFSIZ]; + nhlfe2str(nhlfe, buf, BUFSIZ); + mpls_label2str(num_out_labels, out_labels, buf2, + sizeof(buf2), 0); + mpls_label2str(nh->nh_label->num_labels, + nh->nh_label->label, buf3, sizeof(buf3), + 0); + zlog_debug( "LSP in-label %u type %d nexthop %s " - "out-label changed to %u (old %u)", - in_label, type, buf, out_label, - nh->nh_label->label[0]); + "out-label(s) changed to %s (old %s)", + in_label, type, buf, buf2, buf3); } - /* Update out label, trigger processing. */ - nh->nh_label->label[0] = out_label; + /* Update out label(s), trigger processing. */ + if (nh->nh_label->num_labels == num_out_labels) + memcpy(nh->nh_label->label, out_labels, + sizeof(mpls_label_t) * num_out_labels); + else { + nexthop_del_labels(nh); + nexthop_add_labels(nh, type, num_out_labels, + out_labels); + } } else { /* Add LSP entry to this nexthop */ - nhlfe = nhlfe_add(lsp, type, gtype, gate, ifindex, out_label); + nhlfe = nhlfe_add(lsp, type, gtype, gate, ifindex, + num_out_labels, out_labels); if (!nhlfe) return -1; if (IS_ZEBRA_DEBUG_MPLS) { + char buf2[BUFSIZ]; + nhlfe2str(nhlfe, buf, BUFSIZ); + mpls_label2str(num_out_labels, out_labels, buf2, + sizeof(buf2), 0); + zlog_debug( "Add LSP in-label %u type %d nexthop %s " - "out-label %u", - in_label, type, buf, out_label); + "out-label(s) %s", + in_label, type, buf, buf2); } lsp->addr_family = NHLFE_FAMILY(nhlfe); @@ -3058,8 +3086,8 @@ int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label, } /* (Re)Install LSP in the main table. */ - if (mpls_lsp_install(zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype, - gate, ifindex)) + if (mpls_lsp_install(zvrf, ZEBRA_LSP_STATIC, in_label, 1, &out_label, + gtype, gate, ifindex)) return -1; return 0; diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 157f43ca98..2489e8e510 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -200,7 +200,8 @@ zebra_nhlfe_t *zebra_mpls_lsp_add_nhlfe(zebra_lsp_t *lsp, enum nexthop_types_t gtype, union g_addr *gate, ifindex_t ifindex, - mpls_label_t out_label); + uint8_t num_labels, + mpls_label_t out_labels[]); /* Free an allocated NHLFE */ void zebra_mpls_nhlfe_del(zebra_nhlfe_t *nhlfe); @@ -282,12 +283,12 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, /* * Install/update a NHLFE for an LSP in the forwarding table. This may be * a new LSP entry or a new NHLFE for an existing in-label or an update of - * the out-label for an existing NHLFE (update case). + * the out-label(s) for an existing NHLFE (update case). */ int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type, - mpls_label_t in_label, mpls_label_t out_label, - enum nexthop_types_t gtype, union g_addr *gate, - ifindex_t ifindex); + mpls_label_t in_label, uint8_t num_out_labels, + mpls_label_t out_labels[], enum nexthop_types_t gtype, + union g_addr *gate, ifindex_t ifindex); /* * Uninstall a particular NHLFE in the forwarding table. If this is