Commit f14fef7665 for frr
commit f14fef7665f3f4cb4ada98564f7010add4b5d3a8
Author: Donald Sharp <sharpd@nvidia.com>
Date: Tue Nov 10 18:09:39 2026 -0500
zebra: Make all label operations work through the metaQ
Currently the a replace operation, or a add operation
gets put on the metaQ for handling. Then if a delete
comes in, the delete operation happens immediately
leaving the operation on the metaQ. When the metaQ
wakes up the add/replace operation is handled which
adds the label back incorrectly.
Modify the code to place all label operations on the
Q and to handle everything done in the order on the
label MetaQ.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 5c3a40828e..aa4aaa63b0 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -2602,7 +2602,7 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
if (zapi_labels_validate(&zl) < 0)
return;
- mpls_zapi_labels_process(true, zvrf, &zl);
+ mpls_zapi_labels_process(true /*add*/, false /*replace*/, zvrf, &zl);
}
/*
@@ -2632,15 +2632,7 @@ static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
if (!mpls_enabled)
return;
- if (zl.nexthop_num > 0) {
- mpls_zapi_labels_process(false /*delete*/, zvrf, &zl);
- } else {
- mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
-
- if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
- mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix,
- zl.route.type, zl.route.instance);
- }
+ mpls_zapi_labels_process(false /*add*/, false /*replace*/, zvrf, &zl);
}
/*
@@ -2676,16 +2668,7 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
if (zapi_labels_validate(&zl) < 0)
return;
- /* This removes everything, then re-adds from the client's
- * zapi message. Since the LSP will be processed later, on this
- * this same pthread, all of the changes will 'appear' at once.
- */
- mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
- if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
- mpls_ftn_uninstall(zvrf, zl.type, &zl.route.prefix,
- zl.route.type, zl.route.instance);
-
- mpls_zapi_labels_process(true, zvrf, &zl);
+ mpls_zapi_labels_process(true /*add*/, true /*replace*/, zvrf, &zl);
}
static void zread_sr_policy_set(ZAPI_HANDLER_ARGS)
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 9478d31e9d..72b5efe0bd 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -2906,13 +2906,32 @@ static bool ftn_update_znh(bool add_p, enum lsp_types_t type,
return success;
}
+/*
+ * Uninstall every NHLFE of this label and, when requested, the FTN binding.
+ */
+static void mpls_zapi_labels_uninstall_all(struct zebra_vrf *zvrf, const struct zapi_labels *zl)
+{
+ struct prefix p;
+
+ mpls_lsp_uninstall_all_vrf(zvrf, zl->type, zl->local_label);
+
+ if (!CHECK_FLAG(zl->message, ZAPI_LABELS_FTN))
+ return;
+
+ p = zl->route.prefix;
+ zebra_mpls_ftn_uninstall(zvrf, zl->type, &p, zl->route.type, zl->route.instance);
+}
+
/*
* Install/uninstall LSP and (optionally) FEC-To-NHLFE (FTN) bindings,
* using zapi message info.
* There are several changes that need to be made, in several zebra
* data structures, so we want to do all the work required at once.
+ *
+ * A delete with no nexthops removes the whole LSP. A replace removes the
+ * current LSP and then applies the message as an add.
*/
-void zebra_mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
+void zebra_mpls_zapi_labels_process(bool add_p, bool replace_p, struct zebra_vrf *zvrf,
const struct zapi_labels *zl)
{
int i, counter, ret = 0;
@@ -2929,6 +2948,14 @@ void zebra_mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
struct zebra_ile tmp_ile;
struct zebra_lsp *lsp = NULL;
+ if (!add_p && zl->nexthop_num == 0) {
+ mpls_zapi_labels_uninstall_all(zvrf, zl);
+ return;
+ }
+
+ if (replace_p)
+ mpls_zapi_labels_uninstall_all(zvrf, zl);
+
/* Prep LSP for add case */
if (add_p) {
/* Lookup table. */
diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h
index 5d7553aa15..85b8517f74 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -250,11 +250,15 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf,
*
* mpls_zapi_labels_process -> Installs for future processing
* in the meta-q
- * zebra_mpls_labels_process -> called by the meta-q
+ * zebra_mpls_zapi_labels_process -> called by the meta-q
+ *
+ * replace_p is meaningful only when add_p is true. The queued replace
+ * uninstalls the current LSP and then applies the message, in that order,
+ * when the meta-q item runs.
*/
-void mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
+void mpls_zapi_labels_process(bool add_p, bool replace_p, struct zebra_vrf *zvrf,
const struct zapi_labels *zl);
-void zebra_mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
+void zebra_mpls_zapi_labels_process(bool add_p, bool replace_p, struct zebra_vrf *zvrf,
const struct zapi_labels *zl);
/*
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 736bec1a92..453c507bbe 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -239,6 +239,7 @@ struct wq_label_wrapper {
uint8_t route_instance;
bool add_p;
+ bool replace_p;
struct zapi_labels zl;
int afi;
@@ -2573,7 +2574,7 @@ static void process_subq_early_label(struct listnode *lnode)
w->route_instance);
break;
case WQ_LABEL_LABELS_PROCESS:
- zebra_mpls_zapi_labels_process(w->add_p, zvrf, &w->zl);
+ zebra_mpls_zapi_labels_process(w->add_p, w->replace_p, zvrf, &w->zl);
break;
}
@@ -3554,7 +3555,7 @@ void mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
mq_add_handler(w, early_label_meta_queue_add);
}
-void mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
+void mpls_zapi_labels_process(bool add_p, bool replace_p, struct zebra_vrf *zvrf,
const struct zapi_labels *zl)
{
struct wq_label_wrapper *w;
@@ -3563,6 +3564,7 @@ void mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
w->type = WQ_LABEL_LABELS_PROCESS;
w->vrf_id = zvrf->vrf->vrf_id;
w->add_p = add_p;
+ w->replace_p = replace_p;
w->zl = *zl;
if (IS_ZEBRA_DEBUG_RIB_DETAILED)