summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Stapp <mjs@voltanet.io>2020-06-02 13:22:10 -0400
committerMark Stapp <mjs@voltanet.io>2020-07-07 13:14:01 -0400
commit68110c42f5ad671321ed19f4fc23dd512c1a2a97 (patch)
treec1bcf3286ff6e58dd904ecc8f27866ea8a76699e
parent65f264cf42551e217d43bf9f49ca2cf1f608e013 (diff)
zebra: support backup nhlfes in lsp async notifications
Include backup nhlfes and nexthops in LSP async notification processing from the dataplane. Signed-off-by: Mark Stapp <mjs@voltanet.io>
-rw-r--r--zebra/zebra_mpls.c187
1 files changed, 131 insertions, 56 deletions
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 68dfe20371..7903b97c49 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -167,6 +167,15 @@ static void clear_nhlfe_installed(zebra_lsp_t *lsp)
UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
+
+ frr_each_safe(nhlfe_list, &lsp->backup_nhlfe_list, nhlfe) {
+ nexthop = nhlfe->nexthop;
+ if (!nexthop)
+ continue;
+
+ UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
+ UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+ }
}
/*
@@ -1970,53 +1979,23 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
}
/*
- * Process async dplane notifications.
+ * Process LSP installation info from two sets of nhlfes: a set from
+ * a dplane notification, and a set from the zebra LSP object. Update
+ * counters of installed nexthops, and return whether the LSP has changed.
*/
-void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
+static bool compare_notif_nhlfes(const struct nhlfe_list_head *ctx_head,
+ struct nhlfe_list_head *nhlfe_head,
+ int *start_counter, int *end_counter)
{
- struct zebra_vrf *zvrf;
- zebra_ile_t tmp_ile;
- struct hash *lsp_table;
- zebra_lsp_t *lsp;
zebra_nhlfe_t *nhlfe;
- const struct nhlfe_list_head *head;
const zebra_nhlfe_t *ctx_nhlfe;
struct nexthop *nexthop;
const struct nexthop *ctx_nexthop;
- int start_count = 0, end_count = 0; /* Installed counts */
+ int start_count = 0, end_count = 0;
bool changed_p = false;
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. First, we take a
- * pre-scan pass to determine whether the LSP has transitioned
- * from installed -> uninstalled. In that case, we need to have
- * the existing state of the LSP objects available before making
- * any changes.
- */
- head = dplane_ctx_get_nhlfe_list(ctx);
- frr_each_safe(nhlfe_list, &lsp->nhlfe_list, nhlfe) {
+ frr_each_safe(nhlfe_list, nhlfe_head, nhlfe) {
char buf[NEXTHOP_STRLEN];
nexthop = nhlfe->nexthop;
@@ -2026,8 +2005,9 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
start_count++;
+ ctx_nhlfe = NULL;
ctx_nexthop = NULL;
- frr_each(nhlfe_list_const, head, ctx_nhlfe) {
+ frr_each(nhlfe_list_const, ctx_head, ctx_nhlfe) {
ctx_nexthop = ctx_nhlfe->nexthop;
if (!ctx_nexthop)
continue;
@@ -2085,24 +2065,30 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
}
}
- if (is_debug)
- zlog_debug("LSP dplane notif: lfib start_count %d, end_count %d%s",
- start_count, end_count,
- changed_p ? ", changed" : "");
+ if (start_counter)
+ *start_counter += start_count;
+ if (end_counter)
+ *end_counter += end_count;
- /*
- * Has the LSP become uninstalled?
- */
- if (start_count > 0 && end_count == 0) {
- /* Inform other lfibs */
- dplane_lsp_notif_update(lsp, DPLANE_OP_LSP_DELETE, ctx);
- }
+ return changed_p;
+}
- /*
- * Now we take a second pass and bring the zebra
- * nexthop state into sync with the forwarding-plane state.
- */
- frr_each_safe(nhlfe_list, &lsp->nhlfe_list, nhlfe) {
+/*
+ * Update an lsp nhlfe list from a dplane context, typically an async
+ * notification context. Update the LSP list to match the installed
+ * status from the context's list.
+ */
+static int update_nhlfes_from_ctx(struct nhlfe_list_head *nhlfe_head,
+ const struct nhlfe_list_head *ctx_head)
+{
+ int ret = 0;
+ zebra_nhlfe_t *nhlfe;
+ const zebra_nhlfe_t *ctx_nhlfe;
+ struct nexthop *nexthop;
+ const struct nexthop *ctx_nexthop;
+ bool is_debug = (IS_ZEBRA_DEBUG_DPLANE | IS_ZEBRA_DEBUG_MPLS);
+
+ frr_each_safe(nhlfe_list, nhlfe_head, nhlfe) {
char buf[NEXTHOP_STRLEN];
nexthop = nhlfe->nexthop;
@@ -2110,7 +2096,7 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
continue;
ctx_nexthop = NULL;
- frr_each(nhlfe_list_const, head, ctx_nhlfe) {
+ frr_each(nhlfe_list_const, nhlfe_head, ctx_nhlfe) {
ctx_nexthop = ctx_nhlfe->nexthop;
if (!ctx_nexthop)
continue;
@@ -2160,6 +2146,92 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
}
}
+ return ret;
+}
+
+/*
+ * 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;
+ const struct nhlfe_list_head *ctx_list;
+ int start_count = 0, end_count = 0; /* Installed counts */
+ bool changed_p = false;
+ 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. First, we take a
+ * pre-scan pass to determine whether the LSP has transitioned
+ * from installed -> uninstalled. In that case, we need to have
+ * the existing state of the LSP objects available before making
+ * any changes.
+ */
+ ctx_list = dplane_ctx_get_nhlfe_list(ctx);
+
+ changed_p = compare_notif_nhlfes(ctx_list, &lsp->nhlfe_list,
+ &start_count, &end_count);
+
+ if (is_debug)
+ zlog_debug("LSP dplane notif: lfib start_count %d, end_count %d%s",
+ start_count, end_count,
+ changed_p ? ", changed" : "");
+
+ ctx_list = dplane_ctx_get_backup_nhlfe_list(ctx);
+
+ if (compare_notif_nhlfes(ctx_list, &lsp->backup_nhlfe_list,
+ &start_count, &end_count))
+ /* Avoid accidentally setting back to 'false' */
+ changed_p = true;
+
+ if (is_debug)
+ zlog_debug("LSP dplane notif: lfib backups, start_count %d, end_count %d%s",
+ start_count, end_count,
+ changed_p ? ", changed" : "");
+
+ /*
+ * Has the LSP become uninstalled? We need the existing state of the
+ * nexthops/nhlfes at this point so we know what to delete.
+ */
+ if (start_count > 0 && end_count == 0) {
+ /* Inform other lfibs */
+ dplane_lsp_notif_update(lsp, DPLANE_OP_LSP_DELETE, ctx);
+ }
+
+ /*
+ * Now we take a second pass and bring the zebra
+ * nexthop state into sync with the forwarding-plane state.
+ */
+ ctx_list = dplane_ctx_get_nhlfe_list(ctx);
+ update_nhlfes_from_ctx(&lsp->nhlfe_list, ctx_list);
+
+ ctx_list = dplane_ctx_get_backup_nhlfe_list(ctx);
+ update_nhlfes_from_ctx(&lsp->backup_nhlfe_list, ctx_list);
+
if (end_count > 0) {
SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
@@ -2846,6 +2918,9 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
+ /* This will create (or ref) a new nhe, so we will discard the local
+ * temporary nhe
+ */
mpls_zebra_nhe_update(re, afi, new_nhe);
zebra_nhg_free(new_nhe);