summaryrefslogtreecommitdiff
path: root/zebra/zebra_mpls.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_mpls.c')
-rw-r--r--zebra/zebra_mpls.c230
1 files changed, 169 insertions, 61 deletions
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 5fe0116158..c255c68866 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -862,7 +862,7 @@ static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt)
lsp = (zebra_lsp_t *)backet->data;
if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED))
- (void)kernel_del_lsp(lsp);
+ (void)dplane_lsp_delete(lsp);
}
/*
@@ -887,6 +887,7 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
zebra_nhlfe_t *oldbest, *newbest;
char buf[BUFSIZ], buf2[BUFSIZ];
struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT);
+ enum zebra_dplane_result res;
lsp = (zebra_lsp_t *)data;
if (!lsp) // unexpected
@@ -916,13 +917,20 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
if (newbest) {
UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED);
- switch (kernel_add_lsp(lsp)) {
+
+ switch (dplane_lsp_add(lsp)) {
case ZEBRA_DPLANE_REQUEST_QUEUED:
- flog_err(
- EC_ZEBRA_DP_INVALID_RC,
- "No current DataPlane interfaces can return this, please fix");
+ /* Set 'installed' flag so we will know
+ * that an install is in-flight.
+ */
+ SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+
+ zvrf->lsp_installs_queued++;
break;
case ZEBRA_DPLANE_REQUEST_FAILURE:
+ flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE,
+ "LSP Install Failure: %u",
+ lsp->ile.in_label);
break;
case ZEBRA_DPLANE_REQUEST_SUCCESS:
zvrf->lsp_installs++;
@@ -932,14 +940,22 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
} else {
/* Installed, may need an update and/or delete. */
if (!newbest) {
+ res = dplane_lsp_delete(lsp);
+
+ /* We do some of the lsp cleanup immediately for
+ * deletes.
+ */
+ UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+ clear_nhlfe_installed(lsp);
- switch (kernel_del_lsp(lsp)) {
+ switch (res) {
case ZEBRA_DPLANE_REQUEST_QUEUED:
- flog_err(
- EC_ZEBRA_DP_INVALID_RC,
- "No current DataPlane interfaces can return this, please fix");
+ zvrf->lsp_removals_queued++;
break;
case ZEBRA_DPLANE_REQUEST_FAILURE:
+ flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE,
+ "LSP Deletion Failure: %u",
+ lsp->ile.in_label);
break;
case ZEBRA_DPLANE_REQUEST_SUCCESS:
zvrf->lsp_removals++;
@@ -950,7 +966,10 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
struct nexthop *nexthop;
UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED);
- UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+
+ /* We leave the INSTALLED flag set here
+ * so we know an update in in-flight.
+ */
/*
* Any NHLFE that was installed but is not
@@ -973,13 +992,14 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
}
}
- switch (kernel_upd_lsp(lsp)) {
+ switch (dplane_lsp_update(lsp)) {
case ZEBRA_DPLANE_REQUEST_QUEUED:
- flog_err(
- EC_ZEBRA_DP_INVALID_RC,
- "No current DataPlane interfaces can return this, please fix");
+ zvrf->lsp_installs_queued++;
break;
case ZEBRA_DPLANE_REQUEST_FAILURE:
+ flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE,
+ "LSP Update Failure: %u",
+ lsp->ile.in_label);
break;
case ZEBRA_DPLANE_REQUEST_SUCCESS:
zvrf->lsp_installs++;
@@ -1716,43 +1736,84 @@ static int mpls_processq_init(struct zebra_t *zebra)
/* Public functions */
-void kernel_lsp_pass_fail(zebra_lsp_t *lsp, enum zebra_dplane_status res)
+/*
+ * Process LSP update results from zebra dataplane.
+ */
+void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
{
- struct nexthop *nexthop;
+ struct zebra_vrf *zvrf;
+ zebra_ile_t tmp_ile;
+ struct hash *lsp_table;
+ zebra_lsp_t *lsp;
zebra_nhlfe_t *nhlfe;
+ struct nexthop *nexthop;
+ enum dplane_op_e op;
+ enum zebra_dplane_result status;
+
+ op = dplane_ctx_get_op(ctx);
+ status = dplane_ctx_get_status(ctx);
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("LSP dplane ctx %p, op %s, in-label %u, result %s",
+ ctx, dplane_op2str(op),
+ dplane_ctx_get_in_label(ctx),
+ dplane_res2str(status));
+
+ switch (op) {
+ case DPLANE_OP_LSP_INSTALL:
+ case DPLANE_OP_LSP_UPDATE:
+ /* Look for zebra LSP object */
+ zvrf = vrf_info_lookup(VRF_DEFAULT);
+ if (zvrf == NULL)
+ break;
- if (!lsp)
- return;
+ lsp_table = zvrf->lsp_table;
- switch (res) {
- case ZEBRA_DPLANE_INSTALL_FAILURE:
- UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
- clear_nhlfe_installed(lsp);
- flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE,
- "LSP Install Failure: %u", lsp->ile.in_label);
- break;
- case ZEBRA_DPLANE_INSTALL_SUCCESS:
- SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
- for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
- nexthop = nhlfe->nexthop;
- if (!nexthop)
- continue;
+ tmp_ile.in_label = dplane_ctx_get_in_label(ctx);
+ lsp = hash_lookup(lsp_table, &tmp_ile);
+ if (lsp == NULL) {
+ if (IS_ZEBRA_DEBUG_DPLANE)
+ zlog_debug("LSP ctx %p: in-label %u not found",
+ ctx, dplane_ctx_get_in_label(ctx));
+ break;
+ }
+
+ /* TODO -- Confirm that this result is still 'current' */
+
+ if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
+ /* Update zebra object */
+ SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+ for (nhlfe = lsp->nhlfe_list; nhlfe;
+ nhlfe = nhlfe->next) {
+ nexthop = nhlfe->nexthop;
+ if (!nexthop)
+ continue;
- SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
- SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+ SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
+ SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+ }
+ } else {
+ UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+ clear_nhlfe_installed(lsp);
+ flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE,
+ "LSP Install Failure: in-label %u",
+ lsp->ile.in_label);
}
+
break;
- case ZEBRA_DPLANE_DELETE_SUCCESS:
- UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
- clear_nhlfe_installed(lsp);
- break;
- case ZEBRA_DPLANE_DELETE_FAILURE:
+
+ case DPLANE_OP_LSP_DELETE:
flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE,
- "LSP Deletion Failure: %u", lsp->ile.in_label);
+ "LSP Deletion Failure: in-label %u",
+ dplane_ctx_get_in_label(ctx));
break;
- case ZEBRA_DPLANE_STATUS_NONE:
+
+ default:
break;
- }
+
+ } /* Switch */
+
+ dplane_ctx_fini(&ctx);
}
/*
@@ -1808,22 +1869,50 @@ int zebra_mpls_lsp_uninstall(struct zebra_vrf *zvrf, struct route_node *rn,
}
/*
+ * Add an NHLFE to an LSP, return the newly-added object
+ */
+zebra_nhlfe_t *zebra_mpls_lsp_add_nhlfe(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)
+{
+ /* Just a public pass-through to the internal implementation */
+ return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, out_label);
+}
+
+/*
+ * Free an allocated NHLFE
+ */
+void zebra_mpls_nhlfe_del(zebra_nhlfe_t *nhlfe)
+{
+ /* Just a pass-through to the internal implementation */
+ nhlfe_del(nhlfe);
+}
+
+/*
* Registration from a client for the label binding for a FEC. If a binding
* already exists, it is informed to the client.
* NOTE: If there is a manually configured label binding, that is used.
* Otherwise, if a label index is specified, it means we have to allocate the
* label from a locally configured label block (SRGB), if one exists and index
- * is acceptable.
+ * is acceptable. If no label index then just register the specified label.
+ * NOTE2: Either label or label_index is expected to be set to MPLS_INVALID_*
+ * by the calling function. Register requests with both will be rejected.
*/
int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p,
- uint32_t label_index, struct zserv *client)
+ uint32_t label, uint32_t label_index,
+ struct zserv *client)
{
struct route_table *table;
zebra_fec_t *fec;
char buf[BUFSIZ];
- int new_client;
- int label_change = 0;
+ bool new_client;
+ bool label_change = false;
uint32_t old_label;
+ bool have_label_index = (label_index != MPLS_INVALID_LABEL_INDEX);
+ bool is_configured_fec = false; /* indicate statically configured FEC */
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
if (!table)
@@ -1832,12 +1921,20 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p,
if (IS_ZEBRA_DEBUG_MPLS)
prefix2str(p, buf, BUFSIZ);
+ if (label != MPLS_INVALID_LABEL && have_label_index) {
+ flog_err(
+ EC_ZEBRA_FEC_LABEL_INDEX_LABEL_CONFLICT,
+ "Rejecting FEC register for %s with both label %u and Label Index %u specified, client %s",
+ buf, label, label_index,
+ zebra_route_string(client->proto));
+ return -1;
+ }
+
/* Locate FEC */
fec = fec_find(table, p);
if (!fec) {
- fec = fec_add(table, p, MPLS_INVALID_LABEL, 0, label_index);
+ fec = fec_add(table, p, label, 0, label_index);
if (!fec) {
- prefix2str(p, buf, BUFSIZ);
flog_err(
EC_ZEBRA_FEC_ADD_FAILED,
"Failed to add FEC %s upon register, client %s",
@@ -1846,16 +1943,19 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p,
}
old_label = MPLS_INVALID_LABEL;
- new_client = 1;
+ new_client = true;
} else {
+ /* Check if the FEC has been statically defined in the config */
+ is_configured_fec = fec->flags & FEC_FLAG_CONFIGURED;
/* Client may register same FEC with different label index. */
new_client =
(listnode_lookup(fec->client_list, client) == NULL);
- if (!new_client && fec->label_index == label_index)
+ if (!new_client && fec->label_index == label_index
+ && fec->label == label)
/* Duplicate register */
return 0;
- /* Save current label, update label index */
+ /* Save current label, update the FEC */
old_label = fec->label;
fec->label_index = label_index;
}
@@ -1864,21 +1964,29 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p,
listnode_add(fec->client_list, client);
if (IS_ZEBRA_DEBUG_MPLS)
- zlog_debug("FEC %s Label Index %u %s by client %s", buf,
- label_index, new_client ? "registered" : "updated",
- zebra_route_string(client->proto));
-
- /* If not a configured FEC, derive the local label (from label index)
- * or reset it.
+ zlog_debug("FEC %s label%s %u %s by client %s%s", buf,
+ have_label_index ? " index" : "",
+ have_label_index ? label_index : label,
+ new_client ? "registered" : "updated",
+ zebra_route_string(client->proto),
+ is_configured_fec
+ ? ", but using statically configured label"
+ : "");
+
+ /* If not a statically configured FEC, derive the local label
+ * from label index or use the provided label
*/
- if (!(fec->flags & FEC_FLAG_CONFIGURED)) {
- fec_derive_label_from_index(zvrf, fec);
+ if (!is_configured_fec) {
+ if (have_label_index)
+ fec_derive_label_from_index(zvrf, fec);
+ else
+ fec->label = label;
/* If no label change, exit. */
if (fec->label == old_label)
return 0;
- label_change = 1;
+ label_change = true;
}
/* If new client or label change, update client and install or uninstall
@@ -2106,8 +2214,8 @@ int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p)
if (IS_ZEBRA_DEBUG_MPLS) {
prefix2str(p, buf, BUFSIZ);
- zlog_debug("Delete fec %s label index %u", buf,
- fec->label_index);
+ zlog_debug("Delete fec %s label %u label index %u", buf,
+ fec->label, fec->label_index);
}
old_label = fec->label;