diff options
| author | Christian Breunig <christian@breunig.cc> | 2026-07-06 05:56:00 +0000 |
|---|---|---|
| committer | Christian Breunig <christian@breunig.cc> | 2026-07-06 22:23:17 +0200 |
| commit | 021f9c1b2be91e246e560a67396e54133e9eb626 (patch) | |
| tree | ea6a5c045035b1ef670a46e1c4564b52035ab3e0 /python | |
| parent | b90c21db2edefb02e22ea9233cf76ed6435f91f6 (diff) | |
| download | vyos-1x-021f9c1b2be91e246e560a67396e54133e9eb626.tar.gz vyos-1x-021f9c1b2be91e246e560a67396e54133e9eb626.zip | |
frrender: T9054: keep PPPoE/DHCP default route when "protocols static" is deleted
Deleting "protocols static" set config_dict['static'] to a dict object shared
by reference across every deleted protocol. Merging the PPPoE/DHCP default-route
data into it left the "deleted" marker in place, so the entire staticd section -
including the just-merged default route - was skipped during FRR rendering,
dropping the default route from the RIB/FIB.
Copy the shared deleted-protocol marker before mutating it, and clear the marker
once DHCP/PPPoE content has been merged in so the section is still rendered.
Diffstat (limited to 'python')
| -rw-r--r-- | python/vyos/frrender.py | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/python/vyos/frrender.py b/python/vyos/frrender.py index 7c9a72c50..a905c9a00 100644 --- a/python/vyos/frrender.py +++ b/python/vyos/frrender.py @@ -467,7 +467,9 @@ def get_frrender_dict(conf: Config, argv=None) -> dict: no_tag_node_value_mangle=True) dict.update({'static' : static}) elif conf.exists_effective(static_cli_path): - dict.update({'static' : deleted_protocol}) + # Use a copy - static.dhcp/static.pppoe below may be merged in, + # and deleted_protocol is shared by reference with other protocols + dict.update({'static' : deleted_protocol.copy()}) # We need to check the CLI if the NHRP node is present and thus load in all the default # values present on the CLI - that's why we have if conf.exists() @@ -488,6 +490,12 @@ def get_frrender_dict(conf: Config, argv=None) -> dict: tmp = get_pppoe_interfaces(conf) if tmp: dict_set_nested('static.pppoe', tmp, dict) + # T6991/T9054: "protocols static" may have been deleted while a DHCP or + # PPPoE interface still contributes a default route - in that case the + # static section must still be rendered, so drop the deletion marker + if 'static' in dict and ('dhcp' in dict['static'] or 'pppoe' in dict['static']): + dict['static'].pop('deleted', None) + # keep a re-usable list of dependent VRFs dependent_vrfs_default = {} if 'bgp' in dict: @@ -615,7 +623,9 @@ def get_frrender_dict(conf: Config, argv=None) -> dict: no_tag_node_value_mangle=True) dict_set_nested(f'{protocol_dict_path}.static', static, vrf) elif conf.exists_effective(static_vrf_path): - dict_set_nested(f'{protocol_dict_path}.static', deleted_protocol, vrf) + # Use a copy - static.dhcp/static.pppoe below may be merged in, + # and deleted_protocol is shared by reference with other protocols + dict_set_nested(f'{protocol_dict_path}.static', deleted_protocol.copy(), vrf) # T3680 - get a list of all interfaces currently configured to use DHCP tmp = get_dhcp_interfaces(conf, vrf_name) @@ -624,6 +634,14 @@ def get_frrender_dict(conf: Config, argv=None) -> dict: tmp = get_pppoe_interfaces(conf, vrf_name) if tmp: dict_set_nested(f'name.{vrf_name}.protocols.static.pppoe', tmp, vrf) + # T6991/T9054: "protocols static" may have been deleted while a + # DHCP or PPPoE interface still contributes a default route - in + # that case the static section must still be rendered, so drop + # the deletion marker + static_dict = dict_search(f'{protocol_dict_path}.static', vrf) + if static_dict and ('dhcp' in static_dict or 'pppoe' in static_dict): + static_dict.pop('deleted', None) + vrf_vni_path = ['vrf', 'name', vrf_name, 'vni'] if conf.exists(vrf_vni_path): vrf_config.update({'vni': conf.return_value(vrf_vni_path)}) |
