From 5065db0aa63137daebf96f8f6c0d9a0fe2ddf594 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 29 Nov 2019 11:50:07 -0300 Subject: [PATCH] zebra: support LSPs with multiple outgoing labels For SR-TE we'll need to create Binding-SIDs which are essentially LSPs that can push multiple outgoing labels. This commit sets the groundwork for that. Luckily the netlink code didn't need to be changed since it already supports pushing label stacks. Signed-off-by: Renato Westphal --- zebra/zapi_msg.c | 13 +++++---- zebra/zebra_dplane.c | 8 ++++-- zebra/zebra_dplane.h | 3 +- zebra/zebra_mpls.c | 68 +++++++++++++++++++++++++++++++------------- zebra/zebra_mpls.h | 11 +++---- 5 files changed, 68 insertions(+), 35 deletions(-) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index e809d2ad3d..9e65e67a6e 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