summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/zebra_dplane.c7
-rw-r--r--zebra/zebra_dplane.h1
-rw-r--r--zebra/zebra_mpls.c124
-rw-r--r--zebra/zebra_mpls.h3
-rw-r--r--zebra/zebra_rib.c4
5 files changed, 138 insertions, 1 deletions
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index df6188661..2509d9081 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -421,6 +421,7 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
case DPLANE_OP_LSP_INSTALL:
case DPLANE_OP_LSP_UPDATE:
case DPLANE_OP_LSP_DELETE:
+ case DPLANE_OP_LSP_NOTIFY:
{
zebra_nhlfe_t *nhlfe, *next;
@@ -596,6 +597,9 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_LSP_DELETE:
ret = "LSP_DELETE";
break;
+ case DPLANE_OP_LSP_NOTIFY:
+ ret = "LSP_NOTIFY";
+ break;
case DPLANE_OP_PW_INSTALL:
ret = "PW_INSTALL";
@@ -2377,10 +2381,11 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
res = kernel_dplane_address_update(ctx);
break;
- /* Ignore 'notifications' */
+ /* Ignore 'notifications' - no-op */
case DPLANE_OP_SYS_ROUTE_ADD:
case DPLANE_OP_SYS_ROUTE_DELETE:
case DPLANE_OP_ROUTE_NOTIFY:
+ case DPLANE_OP_LSP_NOTIFY:
res = ZEBRA_DPLANE_REQUEST_SUCCESS;
break;
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 506dcb499..a4c93cefd 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -111,6 +111,7 @@ enum dplane_op_e {
DPLANE_OP_LSP_INSTALL,
DPLANE_OP_LSP_UPDATE,
DPLANE_OP_LSP_DELETE,
+ DPLANE_OP_LSP_NOTIFY,
/* Pseudowire update */
DPLANE_OP_PW_INSTALL,
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 5356a7f49..18b480bdf 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -1810,6 +1810,130 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
}
/*
+ * Process async dplane notifications.
+ */
+void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
+{
+ struct zebra_vrf *zvrf;
+ zebra_ile_t tmp_ile;
+ struct hash *lsp_table;
+ zebra_lsp_t *lsp;
+ zebra_nhlfe_t *nhlfe;
+ const zebra_nhlfe_t *ctx_nhlfe;
+ struct nexthop *nexthop;
+ const struct nexthop *ctx_nexthop;
+ int start_count = 0, end_count = 0; /* Installed counts */
+ bool is_debug = (IS_ZEBRA_DEBUG_DPLANE | IS_ZEBRA_DEBUG_MPLS);
+
+ if (is_debug)
+ zlog_debug("LSP dplane notif, in-label %u",
+ dplane_ctx_get_in_label(ctx));
+
+ /* Look for zebra LSP object */
+ zvrf = vrf_info_lookup(VRF_DEFAULT);
+ if (zvrf == NULL)
+ goto done;
+
+ lsp_table = zvrf->lsp_table;
+
+ tmp_ile.in_label = dplane_ctx_get_in_label(ctx);
+ lsp = hash_lookup(lsp_table, &tmp_ile);
+ if (lsp == NULL) {
+ if (is_debug)
+ zlog_debug("dplane LSP notif: in-label %u not found",
+ dplane_ctx_get_in_label(ctx));
+ goto done;
+ }
+
+ /*
+ * The dataplane/forwarding plane is notifying zebra about the state
+ * of the nexthops associated with this LSP. We bring the zebra
+ * nexthop state into sync with the forwarding-plane state.
+ */
+ for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) {
+ char buf[NEXTHOP_STRLEN];
+
+ nexthop = nhlfe->nexthop;
+ if (!nexthop)
+ continue;
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
+ start_count++;
+
+ ctx_nexthop = NULL;
+ for (ctx_nhlfe = dplane_ctx_get_nhlfe(ctx);
+ ctx_nhlfe; ctx_nhlfe = ctx_nhlfe->next) {
+
+ ctx_nexthop = ctx_nhlfe->nexthop;
+ if (!ctx_nexthop)
+ continue;
+
+ if ((ctx_nexthop->type == nexthop->type) &&
+ nexthop_same(ctx_nexthop, nexthop)) {
+ /* Matched */
+ break;
+ }
+ }
+
+ if (is_debug)
+ nexthop2str(nexthop, buf, sizeof(buf));
+
+ if (ctx_nhlfe && ctx_nexthop) {
+ if (is_debug) {
+ const char *tstr = "";
+
+ if (!CHECK_FLAG(ctx_nhlfe->flags,
+ NHLFE_FLAG_INSTALLED))
+ tstr = "not ";
+
+ zlog_debug("LSP dplane notif: matched nh %s (%sinstalled)",
+ buf, tstr);
+ }
+
+ /* Bring zebra nhlfe install state into sync */
+ if (CHECK_FLAG(ctx_nhlfe->flags,
+ NHLFE_FLAG_INSTALLED)) {
+ SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
+
+ /* Update counter */
+ end_count++;
+ } else
+ UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
+
+ if (CHECK_FLAG(ctx_nhlfe->nexthop->flags,
+ NEXTHOP_FLAG_FIB))
+ SET_FLAG(nhlfe->nexthop->flags,
+ NEXTHOP_FLAG_FIB);
+ else
+ UNSET_FLAG(nhlfe->nexthop->flags,
+ NEXTHOP_FLAG_FIB);
+ } else {
+ /* Not mentioned in lfib set -> uninstalled */
+ UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
+ UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+
+ if (is_debug)
+ zlog_debug("LSP dplane notif: no match, nh %s",
+ buf);
+ }
+ }
+
+ if (is_debug)
+ zlog_debug("LSP dplane notif: lfib start_count %d, end_count %d",
+ start_count, end_count);
+
+ if (end_count > 0)
+ SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+ else {
+ UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
+ clear_nhlfe_installed(lsp);
+ }
+
+done:
+ dplane_ctx_fini(&ctx);
+}
+
+/*
* Install dynamic LSP entry.
*/
int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h
index 3a131e1aa..d983221cb 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -352,6 +352,9 @@ struct zebra_dplane_ctx;
void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx);
+/* Process async dplane notifications. */
+void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx);
+
/*
* Schedule all MPLS label forwarding entries for processing.
* Called upon changes that may affect one or more of them such as
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index adf9f9900..d1311dfdd 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -3738,6 +3738,10 @@ static int rib_process_dplane_results(struct thread *thread)
zebra_mpls_lsp_dplane_result(ctx);
break;
+ case DPLANE_OP_LSP_NOTIFY:
+ zebra_mpls_process_dplane_notify(ctx);
+ break;
+
case DPLANE_OP_PW_INSTALL:
case DPLANE_OP_PW_UNINSTALL:
handle_pw_result(ctx);