Commit 71f86931d8 for frr
commit 71f86931d8eefa8d42655cda063fd41a9803bb2d
Author: Carmine Scarpitta <cscarpit@cisco.com>
Date: Fri Oct 30 21:11:23 2026 +0100
bgpd: Request BGP-LS sync when producer registers
When BGP activates the link-state address family before an IGP
registers as a link-state producer, no producer is available to answer
the initial TED sync request. When the producer registers later, BGP
does not request another sync, so existing TED data is missed and
the BGP link-state database remains incomplete.
Fix by subscribing to link-state producer registration notifications
and requesting a TED sync when a producer registers. This lets BGP
receive existing TED data regardless of startup order.
Fixes #23713
Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
diff --git a/bgpd/bgp_ls.c b/bgpd/bgp_ls.c
index 77378f1466..b8770223f2 100644
--- a/bgpd/bgp_ls.c
+++ b/bgpd/bgp_ls.c
@@ -9,6 +9,7 @@
#include "lib/json.h"
#include "stream.h"
+#include "zclient.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_ls.h"
@@ -29,6 +30,21 @@ static int bgp_ls_refresh_bgp_link_endx_attrs(struct bgp *bgp, struct peer *peer
static struct bgp_ls_nlri *bgp_ls_lookup_bgp_prefix_nlri(struct bgp *bgp, const struct prefix *p,
enum bgp_ls_bgp_route_type route_type);
+/* Request a TED sync from the currently registered link-state producers. */
+void bgp_ls_request_sync(struct bgp *bgp)
+{
+ enum zclient_send_status ret;
+
+ if (!bgp_ls_is_registered(bgp))
+ return;
+
+ ret = ls_request_sync(bgp_zclient);
+ if (ret == ZCLIENT_SEND_FAILURE)
+ zlog_warn("BGP-LS: Failed to request Link State database sync");
+ else
+ zlog_info("BGP-LS: Requested initial Link State database sync");
+}
+
void bgp_ls_handle_srv6_localsid_update(struct bgp *bgp, const struct prefix *p, afi_t afi,
uint8_t type, unsigned short instance,
uint32_t seg6local_action,
@@ -945,12 +961,14 @@ bool bgp_ls_register(struct bgp *bgp)
return false;
}
- if (ls_request_sync(bgp_zclient) == -1)
- zlog_warn("BGP-LS: Failed to request initial Link State database sync");
- else
- zlog_info("BGP-LS: Requested initial Link State database sync");
-
bgp->ls_info->registered_ls_db = true;
+ if (zclient_opaque_request_notify(bgp_zclient, LINK_STATE_SYNC) == ZCLIENT_SEND_FAILURE) {
+ zlog_err("BGP-LS: Failed to register for Link State producer notifications");
+ bgp->ls_info->registered_ls_db = false;
+ if (ls_unregister(bgp_zclient, false) == ZCLIENT_SEND_FAILURE)
+ zlog_err("BGP-LS: Failed to unregister from Link State database");
+ return false;
+ }
zlog_info("BGP-LS: Registered with Link State database for BGP instance %s",
bgp->name_pretty);
@@ -971,6 +989,9 @@ bool bgp_ls_unregister(struct bgp *bgp)
if (!bgp_ls_is_registered(bgp))
return true;
+ if (zclient_opaque_drop_notify(bgp_zclient, LINK_STATE_SYNC) == ZCLIENT_SEND_FAILURE)
+ zlog_err("BGP-LS: Failed to unregister Link State producer notifications");
+
/*
* Clear the local registration flag *before* the zebra call.
*
diff --git a/bgpd/bgp_ls.h b/bgpd/bgp_ls.h
index 081d0a6542..becab02227 100644
--- a/bgpd/bgp_ls.h
+++ b/bgpd/bgp_ls.h
@@ -84,6 +84,7 @@ extern int bgp_nlri_parse_ls(struct peer *peer, struct attr *attr, struct bgp_nl
/* BGP-LS registration with link-state database */
extern bool bgp_ls_register(struct bgp *bgp);
extern bool bgp_ls_unregister(struct bgp *bgp);
+extern void bgp_ls_request_sync(struct bgp *bgp);
extern bool bgp_ls_is_registered(struct bgp *bgp);
/* BGP-LS NLRI lookup helpers */
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 669fecba6d..8811b4bfb4 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -4551,6 +4551,30 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
return 0;
}
+/* Handle producer registration notifications for BGP-LS link-state sync */
+static int bgp_zebra_opaque_notif_handler(ZAPI_CALLBACK_ARGS)
+{
+ struct zapi_opaque_notif_info info;
+ struct bgp *bgp = bgp_get_default();
+
+ if (zclient_opaque_notif_decode(zclient->ibuf, &info) != 0) {
+ zlog_err("%s: Failed to decode opaque notification", __func__);
+ return -1;
+ }
+
+ if (info.msg_type != LINK_STATE_SYNC || !info.reg)
+ return 0;
+
+ if (!bgp_ls_is_registered(bgp))
+ return 0;
+
+ if (BGP_DEBUG(zebra, ZEBRA) || BGP_DEBUG(linkstate, LINKSTATE))
+ zlog_debug("BGP-LS: Link State producer registered, requesting initial sync");
+
+ bgp_ls_request_sync(bgp);
+ return 0;
+}
+
/* Handle ZEBRA_OPAQUE_MESSAGE for BGP-LS link-state updates */
static int bgp_zebra_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
{
@@ -4610,6 +4634,7 @@ static zclient_handler *const bgp_handlers[] = {
[ZEBRA_SRV6_LOCATOR_DELETE] = bgp_zebra_process_srv6_locator_delete,
[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] = bgp_zebra_process_srv6_locator_chunk,
[ZEBRA_SRV6_SID_NOTIFY] = bgp_zebra_srv6_sid_notify,
+ [ZEBRA_OPAQUE_NOTIFY] = bgp_zebra_opaque_notif_handler,
[ZEBRA_OPAQUE_MESSAGE] = bgp_zebra_opaque_msg_handler,
};