Description
VyOS incorrectly allows a route-map definition to be deleted even when it is still referenced by BGP VRF/VPN import/export.
Reproduction
Configure a route-map and import a connected route from VRF red into the default BGP instance:
configure set policy route-map KEEP rule 10 action permit set vrf name red table 1001 set interfaces dummy dum0 address 203.0.113.1/32 set interfaces dummy dum0 vrf red set vrf name red protocols bgp system-as 65100 set vrf name red protocols bgp parameters router-id 203.0.113.1 set vrf name red protocols bgp address-family ipv4-unicast redistribute connected set protocols bgp system-as 65100 set protocols bgp parameters router-id 203.0.113.2 set protocols bgp address-family ipv4-unicast import vrf red set protocols bgp address-family ipv4-unicast route-map vrf import KEEP commit
Delete only the route-map definition, leaving its BGP reference unchanged:
delete policy route-map KEEP commit
Expected result: The commit should be rejected by the existing policy-in-use validation:
Cannot delete route-map "KEEP", still in use!
Actual result: The commit succeeds. FRR no longer contains the route-map KEEP permit 10 definition, but retains:
router bgp 65100 address-family ipv4 unicast import vrf route-map KEEP import vrf red
Cause
The issue originates in routing_policy_find() in src/conf_mode/policy.py:
if k == key:
if isinstance(v, dict):
for a, b in v.items():
if a in ['import', 'export']:
yield b
else:
yield v
elif isinstance(v, dict):
for result in routing_policy_find(key, v):
yield resultOnce route_map is matched, only its immediate import and export children are checked. The helper does not descend into intermediate vrf or vpn dictionaries, so references such as the following are missed:
{'route_map': {'vrf': {'import': 'KEEP'}}}Proposed fix
Recursively inspect nested dictionaries under the matched policy key. Wrap b as {key: b} so the recursive call retains the policy-key context and reuses the existing import/export handling.
if k == key:
if isinstance(v, dict):
for a, b in v.items():
if a in ['import', 'export']:
yield b
+ elif isinstance(b, dict):
+ # BGP AF policies also nest directions under vpn/vrf.
+ yield from routing_policy_find(key, {key: b})
else:
yield v