diff options
| author | Christian Breunig <christian@breunig.cc> | 2026-09-04 22:26:37 +0200 |
|---|---|---|
| committer | Christian Breunig <christian@breunig.cc> | 2026-09-04 22:26:37 +0200 |
| commit | 3f1e103d6774159fb7835c3562a1c1ab834cfd7a (patch) | |
| tree | e6e79bebccba0921477705d8a9f21675c889f218 /python | |
| parent | 9a7d5b27cd908473b7cd9e16fc0d1bbe7e983d2e (diff) | |
| download | vyos-1x-3f1e103d6774159fb7835c3562a1c1ab834cfd7a.tar.gz vyos-1x-3f1e103d6774159fb7835c3562a1c1ab834cfd7a.zip | |
static: T9278: honor dhcp-interface routes in dedicated routing tables
get_dhcp_route_interfaces() only walked "protocols static route <prefix>
dhcp-interface", so routes configured below "protocols static table <id> route
<prefix> dhcp-interface" never made it into the interface list. Both nodes share
the same include/static/static-route.xml.i definition and both are rendered from
the DHCP lease via the get_dhcp_router() filter in staticd.frr.j2, so they depend
on the current lease in exactly the same way.
As a result the affected interfaces were missing from the DHCP gateway cache used
for FRR change detection. A lease event on an interface referenced only by a
table based route would compare equal to the cached state and the re-render
requested by the dhclient hook was skipped, leaving the stale gateway in the
rendered configuration.
Iterate the route sections of every table in addition to the top level ones.
Only IPv4 routes are considered, as "dhcp-interface" does not exist for route6.
Named VRFs have no table node, but the collection is shared and stays correct
there as well.
Diffstat (limited to 'python')
| -rw-r--r-- | python/vyos/frrender.py | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/python/vyos/frrender.py b/python/vyos/frrender.py index b3f2718ac..1ea49abe4 100644 --- a/python/vyos/frrender.py +++ b/python/vyos/frrender.py @@ -695,18 +695,29 @@ def get_dhcp_route_interfaces(config_dict) -> set: DHCP lease. Two CLI constructs end up reading the DHCP lease file via the "get_dhcp_router" Jinja filter and thus depend on the current lease: - - "protocols static route <prefix> dhcp-interface <ifname>" + - "protocols static route <prefix> dhcp-interface <ifname>", either directly + or below "protocols static table <id>" - the default route implied by "interfaces <type> <ifname> address dhcp" Both variants exist in the default VRF as well as inside any named VRF. """ interfaces = set() + def _add_from_routes(route_conf): + if not isinstance(route_conf, dict): + return + for prefix_options in route_conf.values(): + interfaces.update(prefix_options.get('dhcp_interface', [])) + def _add_from_static(static_conf): if not isinstance(static_conf, dict): return - for prefix_options in static_conf.get('route', {}).values(): - interfaces.update(prefix_options.get('dhcp_interface', [])) + _add_from_routes(static_conf.get('route')) + # Routes in a dedicated routing table use the same "dhcp-interface" + # node, thus they depend on the DHCP lease in the very same way + for table_config in static_conf.get('table', {}).values(): + if isinstance(table_config, dict): + _add_from_routes(table_config.get('route')) for ifname, if_config in static_conf.get('dhcp', {}).items(): # An interface explicitly opting out of the default route does not # contribute a route, thus a lease change is irrelevant for it |
