Commit 103a33a19d for frr

commit 103a33a19df49df12a35875abc4e612eebec3455
Author: Philippe Guibert <philippe.guibert@6wind.com>
Date:   Thu Oct 22 15:47:05 2026 +0200

    bgpd: fix srv6 locator after a zebra restart

    When zebra restarts while bgpd keeps running, the locator used by a BGP
    instance may have changed in the configuration of the restarted zebra,
    or may no longer exist. BGP keeps the locator it received from the
    previous zebra: 'show bgp segment-routing srv6' still displays its
    prefix, while zebra is stopped and after it is started again. Once zebra
    is stopped on r1, and still 30 seconds later:

    > r1# show bgp segment-routing srv6
    > locator_name: default
    >   prefix: 2001:db8:1:1::/64
    >   block-length: 40
    >   node-length: 24
    >   func-length: 16
    >   arg-length: 0
    > [..]

    BGP is not notified when the connection to zebra is lost. The restarted
    zebra does not send a locator delete for a locator it never knew. And
    bgp_zebra_instance_register(), called when the connection to zebra is
    established, only requests the locator when the instance has none:
    bgp_srv6_locator_lookup() returns the locator of the previous zebra, so
    the locator is never requested again.

    Fix this by forgetting the locator of every BGP instance when the
    connection to zebra is lost, with the zebra_disconnected callback of
    zclient. When the connection is established again,
    bgp_zebra_instance_register() requests the locator again, and the
    instance gets it only if the restarted zebra has it. The SIDs allocated
    from this locator are lost by zebra too; they are handled separately
    for the VPN and the unicast SIDs.

    With this fix, once zebra is stopped on r1:

    > r1# show bgp segment-routing srv6
    > locator_name: default
    > locator_chunks:
    > [..]

    Once zebra is started again on r1, the locator is received again:

    > r1# show bgp segment-routing srv6
    > locator_name: default
    >   prefix: 2001:db8:1:1::/64
    >   block-length: 40
    >   node-length: 24
    >   func-length: 16
    >   arg-length: 0
    > [..]

    Fixes: 16640b615dfa ("bgpd: Request SRv6 locator after zebra connection")
    Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>

diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index ba792e8a25..00c3e98cba 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -3393,6 +3393,19 @@ static void bgp_zebra_connected(struct zclient *zclient)
 	 */
 }

+/* BGP has lost its connection with Zebra. */
+static void bgp_zebra_disconnected(struct zclient *zclient)
+{
+	struct bgp *bgp;
+	struct listnode *node;
+
+	for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
+		/* the locators may have changed when zebra is started again */
+		srv6_locator_free(bgp->srv6_locator);
+		bgp->srv6_locator = NULL;
+	}
+}
+
 void bgp_zebra_process_remote_routes_for_l2vni(struct event *e)
 {
 	/*
@@ -4688,6 +4701,7 @@ void bgp_zebra_init(struct event_loop *master, unsigned short instance)
 	zclient_init(bgp_zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
 	bgp_zclient->zebra_buffer_write_ready = bgp_zebra_buffer_write_ready;
 	bgp_zclient->zebra_connected = bgp_zebra_connected;
+	bgp_zclient->zebra_disconnected = bgp_zebra_disconnected;
 	bgp_zclient->zebra_capabilities = bgp_zebra_capabilities;
 	bgp_zclient->nexthop_update = bgp_nexthop_update;
 	bgp_zclient->instance = instance;