Commit 0e25c2d17c for frr

commit 0e25c2d17c8d03b98e6ba3b274d5800b04e3e6a2
Author: Philippe Guibert <philippe.guibert@6wind.com>
Date:   Tue Nov 3 10:07:20 2026 +0100

    bgpd: reset the wide function flag of the VPN SIDs freed

    When a VPN SID allocated with a wide function is released with 'no sid
    vpn export' or 'no sid vpn per-vrf export', the wide function flag of
    the address-family (BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE) or of the VRF
    (BGP_VRF_TOVPN_SID_FUNC_WIDE) is reset with the SID. It is not reset
    when the SID is freed because the locator is deleted by zebra, because
    zebra notifies that the SID is released, or because the locator is
    removed from the BGP SRv6 configuration.

    No wrong behavior has been observed: the flag is only read when the
    VPN SID and its locator are set, and the withdrawal of the local SID by
    vpn_leak_postchange_all() resets it after a locator deletion or a SID
    release notification. But the state of the address-family or of the
    VRF is not consistent while the flag is kept without SID.

    Fix this by resetting the flag when the SID is freed in
    bgp_zebra_process_srv6_locator_delete_per_bgp(), in the release
    notification of bgp_zebra_srv6_sid_notify(), and in
    bgp_srv6_sids_unset().

    Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>

diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 5b18b5a523..2b127f0980 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -414,6 +414,8 @@ static void bgp_srv6_sids_unset(struct bgp *bgp)
 								 .tovpn_sid_locator->name);
 			/* refresh vpnv4 tovpn_sid */
 			XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+			UNSET_FLAG(bgp_vrf->vpn_policy[AFI_IP].flags,
+				   BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE);
 		}

 		if (bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid) {
@@ -423,6 +425,8 @@ static void bgp_srv6_sids_unset(struct bgp *bgp)
 								 .tovpn_sid_locator->name);
 			/* refresh vpnv6 tovpn_sid */
 			XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+			UNSET_FLAG(bgp_vrf->vpn_policy[AFI_IP6].flags,
+				   BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE);
 		}

 		if (bgp_vrf->tovpn_sid) {
@@ -431,6 +435,7 @@ static void bgp_srv6_sids_unset(struct bgp *bgp)
 			bgp_zebra_release_srv6_sid(&ctx, bgp_vrf->tovpn_sid_locator->name);
 			/* refresh per-vrf tovpn_sid */
 			XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
+			UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_FUNC_WIDE);
 		}

 		/* refresh vpnv4 tovpn_sid_locator */
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 304720792e..b5b33c6c97 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -4195,6 +4195,8 @@ static int bgp_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS)
 			/* Unregister the SID */
 			sid_unregister(bgp, bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
 			XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+			UNSET_FLAG(bgp_vrf->vpn_policy[AFI_IP6].flags,
+				   BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE);
 			sid_unregister(bgp_vrf, bgp_vrf->srv6_unicast[AFI_IP6].sid);
 			XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->srv6_unicast[AFI_IP6].sid);
 		} else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT4) {
@@ -4210,6 +4212,8 @@ static int bgp_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS)
 			/* Unregister the SID */
 			sid_unregister(bgp, bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
 			XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+			UNSET_FLAG(bgp_vrf->vpn_policy[AFI_IP].flags,
+				   BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE);
 			sid_unregister(bgp_vrf, bgp_vrf->srv6_unicast[AFI_IP].sid);
 			XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->srv6_unicast[AFI_IP].sid);

@@ -4225,6 +4229,7 @@ static int bgp_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS)
 				/* Unregister the SID */
 				sid_unregister(bgp, bgp_vrf->tovpn_sid);
 				XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
+				UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_FUNC_WIDE);
 			}

 			if (is_srv6_unicast_dt46_enabled(bgp_vrf, AFI_IP) ||
@@ -4428,6 +4433,8 @@ static void bgp_zebra_process_srv6_locator_delete_per_bgp(struct srv6_locator *l
 					 (struct prefix *)&tmp_prefix)) {
 				XFREE(MTYPE_BGP_SRV6_SID,
 				      bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+				UNSET_FLAG(bgp_vrf->vpn_policy[AFI_IP].flags,
+					   BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE);
 				/* refresh vpnv4 tovpn_sid_locator */
 				srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator);
 				bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator = NULL;
@@ -4444,6 +4451,8 @@ static void bgp_zebra_process_srv6_locator_delete_per_bgp(struct srv6_locator *l
 					 (struct prefix *)&tmp_prefix)) {
 				XFREE(MTYPE_BGP_SRV6_SID,
 				      bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+				UNSET_FLAG(bgp_vrf->vpn_policy[AFI_IP6].flags,
+					   BGP_VPN_POLICY_TOVPN_SID_FUNC_WIDE);
 				/* refresh vpnv6 tovpn_sid_locator */
 				srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator);
 				bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator = NULL;
@@ -4459,6 +4468,7 @@ static void bgp_zebra_process_srv6_locator_delete_per_bgp(struct srv6_locator *l
 			if (prefix_match((struct prefix *)&loc->prefix,
 					 (struct prefix *)&tmp_prefix)) {
 				XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
+				UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_FUNC_WIDE);
 				/* refresh per-vrf tovpn_sid_locator */
 				srv6_locator_free(bgp_vrf->tovpn_sid_locator);
 				bgp_vrf->tovpn_sid_locator = NULL;