From 05aa22dcb4ce54e3fb9909eddaa2aca3a6ac206e Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 7 Nov 2021 19:54:09 +0100 Subject: protocols: static: T3680: do not delete DHCP received routes An ISC DHCP hook script is used to install the received default route into FRR by simple calls to vtysh. By moving to frr-reload.py the DHCP default route was deleted as it was not found in the running config. This commit checks all interfaces if DHCP is enabled and if so - will dynamically add the route to the generated FRR configuration. --- data/templates/frr/staticd.frr.tmpl | 9 +++++++++ python/vyos/configdict.py | 35 +++++++++++++++++++++++++++++++++++ src/conf_mode/protocols_static.py | 5 +++++ 3 files changed, 49 insertions(+) diff --git a/data/templates/frr/staticd.frr.tmpl b/data/templates/frr/staticd.frr.tmpl index db59a44c2..bfe959c1d 100644 --- a/data/templates/frr/staticd.frr.tmpl +++ b/data/templates/frr/staticd.frr.tmpl @@ -15,6 +15,15 @@ vrf {{ vrf }} {{ static_routes(ip_prefix, prefix, prefix_config) }} {%- endfor -%} {% endif %} +{# IPv4 default routes from DHCP interfaces #} +{% if dhcp is defined and dhcp is not none %} +{% for interface in dhcp %} +{% set next_hop = interface | get_dhcp_router %} +{% if next_hop is defined and next_hop is not none %} +{{ ip_prefix }} route 0.0.0.0/0 {{ next_hop }} {{ interface }} tag 210 210 +{% endif %} +{% endfor %} +{% endif %} {# IPv6 routing #} {% if route6 is defined and route6 is not none %} {% for prefix, prefix_config in route6.items() %} diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index e8a87bc38..998c10bb5 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -316,6 +316,41 @@ def is_source_interface(conf, interface, intftype=None): old_level = conf.set_level(old_level) return ret_val +def get_dhcp_interfaces(conf, vrf=None): + """ Common helper functions to retrieve all interfaces from current CLI + sessions that have DHCP configured. """ + dhcp_interfaces = [] + dict = conf.get_config_dict(['interfaces'], get_first_key=True) + if not dict: + return dhcp_interfaces + +def check_dhcp(config, ifname): + out = [] + if 'address' in config and 'dhcp' in config['address']: + if 'vrf' in config and vrf is config['vrf']: + out.append(ifname) + else: + out.append(ifname) + return out + + for section, interface in dict.items(): + for ifname, ifconfig in interface.items(): + tmp = check_dhcp(ifconfig, ifname) + dhcp_interfaces.extend(tmp) + # check per VLAN interfaces + for vif, vif_config in ifconfig.get('vif', {}).items(): + tmp = check_dhcp(vif_config, f'{ifname}.{vif}') + dhcp_interfaces.extend(tmp) + # check QinQ VLAN interfaces + for vif_s, vif_s_config in ifconfig.get('vif-s', {}).items(): + tmp = check_dhcp(vif_s_config, f'{ifname}.{vif_s}') + dhcp_interfaces.extend(tmp) + for vif_c, vif_c_config in vif_s_config.get('vif-c', {}).items(): + tmp = check_dhcp(vif_c_config, f'{ifname}.{vif_s}.{vif_c}') + dhcp_interfaces.extend(tmp) + + return dhcp_interfaces + def get_interface_dict(config, base, ifname=''): """ Common utility function to retrieve and mangle the interfaces configuration diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py index 597fcc443..f010141e9 100755 --- a/src/conf_mode/protocols_static.py +++ b/src/conf_mode/protocols_static.py @@ -21,6 +21,7 @@ from sys import argv from vyos.config import Config from vyos.configdict import dict_merge +from vyos.configdict import get_dhcp_interfaces from vyos.configverify import verify_common_route_maps from vyos.configverify import verify_vrf from vyos.template import render_to_string @@ -56,6 +57,10 @@ def get_config(config=None): # Merge policy dict into "regular" config dict static = dict_merge(tmp, static) + # T3680 - get a list of all interfaces currently configured to use DHCP + tmp = get_dhcp_interfaces(conf, vrf) + if tmp: static['dhcp'] = tmp + return static def verify(static): -- cgit v1.2.3