diff options
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/zebra_dplane.c | 7 | ||||
-rw-r--r-- | zebra/zebra_dplane.h | 1 | ||||
-rw-r--r-- | zebra/zebra_mpls.c | 124 | ||||
-rw-r--r-- | zebra/zebra_mpls.h | 3 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 4 |
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); |