diff options
| author | Christian Poessinger <christian@poessinger.com> | 2022-02-20 10:40:38 +0100 | 
|---|---|---|
| committer | Christian Poessinger <christian@poessinger.com> | 2022-02-20 18:49:55 +0100 | 
| commit | b693f929b63c0c847d9a3c6ee9160845ef501be1 (patch) | |
| tree | 7791c4f4c546739669ffff268490393e7ac548d5 | |
| parent | 3a1a7c40a13ee9f5561823a79876d88d3f5bf053 (diff) | |
| download | vyos-1x-b693f929b63c0c847d9a3c6ee9160845ef501be1.tar.gz vyos-1x-b693f929b63c0c847d9a3c6ee9160845ef501be1.zip | |
static: T4203: obey interface dhcp default route distance
Commit 05aa22dc ("protocols: static: T3680: do not delete DHCP received routes")
added a bug whenever a static route is modified - the DHCP interface will
always end up with metric 210 - if there was a default route over a DHCP
interface.
| -rw-r--r-- | data/templates/frr/staticd.frr.tmpl | 4 | ||||
| -rw-r--r-- | interface-definitions/include/interface/dhcp-options.xml.i | 3 | ||||
| -rw-r--r-- | python/vyos/configdict.py | 54 | 
3 files changed, 48 insertions, 13 deletions
| diff --git a/data/templates/frr/staticd.frr.tmpl b/data/templates/frr/staticd.frr.tmpl index bfe959c1d..5d833228a 100644 --- a/data/templates/frr/staticd.frr.tmpl +++ b/data/templates/frr/staticd.frr.tmpl @@ -17,10 +17,10 @@ vrf {{ vrf }}  {% endif %}  {# IPv4 default routes from DHCP interfaces #}  {% if dhcp is defined and dhcp is not none %} -{%   for interface in dhcp %} +{%   for interface, interface_config in dhcp.items() %}  {%     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 +{{ ip_prefix }} route 0.0.0.0/0 {{ next_hop }} {{ interface }} tag 210 {{ interface_config.distance }}  {%     endif %}  {%   endfor %}  {% endif %} diff --git a/interface-definitions/include/interface/dhcp-options.xml.i b/interface-definitions/include/interface/dhcp-options.xml.i index b65b0802a..f62b06640 100644 --- a/interface-definitions/include/interface/dhcp-options.xml.i +++ b/interface-definitions/include/interface/dhcp-options.xml.i @@ -30,12 +30,13 @@          <help>Distance for the default route from DHCP server</help>          <valueHelp>            <format>u32:1-255</format> -          <description>Distance for the default route from DHCP server (default 210)</description> +          <description>Distance for the default route from DHCP server (default: 210)</description>          </valueHelp>          <constraint>            <validator name="numeric" argument="--range 1-255"/>          </constraint>        </properties> +      <defaultValue>210</defaultValue>      </leafNode>      <leafNode name="reject">        <properties> diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index efeb6dc1f..f2ec93520 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -319,34 +319,42 @@ def is_source_interface(conf, interface, intftype=None):  def get_dhcp_interfaces(conf, vrf=None):      """ Common helper functions to retrieve all interfaces from current CLI      sessions that have DHCP configured. """ -    dhcp_interfaces = [] +    dhcp_interfaces = {}      dict = conf.get_config_dict(['interfaces'], get_first_key=True)      if not dict:          return dhcp_interfaces      def check_dhcp(config, ifname): -        out = [] +        tmp = {}          if 'address' in config and 'dhcp' in config['address']: +            options = {} +            if 'dhcp_options' in config and 'default_route_distance' in config['dhcp_options']: +                options.update({'distance' : config['dhcp_options']['default_route_distance']})              if 'vrf' in config: -                if vrf is config['vrf']: out.append(ifname) -            else: out.append(ifname) -        return out +                if vrf is config['vrf']: tmp.update({ifname : options}) +            else: tmp.update({ifname : options}) +        return tmp      for section, interface in dict.items(): -        for ifname, ifconfig in interface.items(): +        for ifname in interface: +            # we already have a dict representation of the config from get_config_dict(), +            # but with the extended information from get_interface_dict() we also +            # get the DHCP client default-route-distance default option if not specified. +            ifconfig = get_interface_dict(conf, ['interfaces', section], ifname) +              tmp = check_dhcp(ifconfig, ifname) -            dhcp_interfaces.extend(tmp) +            dhcp_interfaces.update(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) +                dhcp_interfaces.update(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) +                dhcp_interfaces.update(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) +                    dhcp_interfaces.update(tmp)      return dhcp_interfaces @@ -405,6 +413,12 @@ def get_interface_dict(config, base, ifname=''):      if 'deleted' not in dict:          dict = dict_merge(default_values, dict) +        # If interface does not request an IPv4 DHCP address there is no need +        # to keep the dhcp-options key +        if 'address' not in dict or 'dhcp' not in dict['address']: +            if 'dhcp_options' in dict: +                del dict['dhcp_options'] +      # XXX: T2665: blend in proper DHCPv6-PD default values      dict = T2665_set_dhcpv6pd_defaults(dict) @@ -475,6 +489,12 @@ def get_interface_dict(config, base, ifname=''):              # XXX: T2665: blend in proper DHCPv6-PD default values              dict['vif'][vif] = T2665_set_dhcpv6pd_defaults(dict['vif'][vif]) +            # If interface does not request an IPv4 DHCP address there is no need +            # to keep the dhcp-options key +            if 'address' not in dict['vif'][vif] or 'dhcp' not in dict['vif'][vif]['address']: +                if 'dhcp_options' in dict['vif'][vif]: +                    del dict['vif'][vif]['dhcp_options'] +          # Check if we are a member of a bridge device          bridge = is_member(config, f'{ifname}.{vif}', 'bridge')          if bridge: dict['vif'][vif].update({'is_bridge_member' : bridge}) @@ -509,6 +529,13 @@ def get_interface_dict(config, base, ifname=''):              # XXX: T2665: blend in proper DHCPv6-PD default values              dict['vif_s'][vif_s] = T2665_set_dhcpv6pd_defaults(dict['vif_s'][vif_s]) +            # If interface does not request an IPv4 DHCP address there is no need +            # to keep the dhcp-options key +            if 'address' not in dict['vif_s'][vif_s] or 'dhcp' not in \ +                dict['vif_s'][vif_s]['address']: +                if 'dhcp_options' in dict['vif_s'][vif_s]: +                    del dict['vif_s'][vif_s]['dhcp_options'] +          # Check if we are a member of a bridge device          bridge = is_member(config, f'{ifname}.{vif_s}', 'bridge')          if bridge: dict['vif_s'][vif_s].update({'is_bridge_member' : bridge}) @@ -543,6 +570,13 @@ def get_interface_dict(config, base, ifname=''):                  dict['vif_s'][vif_s]['vif_c'][vif_c] = T2665_set_dhcpv6pd_defaults(                      dict['vif_s'][vif_s]['vif_c'][vif_c]) +                # If interface does not request an IPv4 DHCP address there is no need +                # to keep the dhcp-options key +                if 'address' not in dict['vif_s'][vif_s]['vif_c'][vif_c] or 'dhcp' \ +                    not in dict['vif_s'][vif_s]['vif_c'][vif_c]['address']: +                    if 'dhcp_options' in dict['vif_s'][vif_s]['vif_c'][vif_c]: +                        del dict['vif_s'][vif_s]['vif_c'][vif_c]['dhcp_options'] +              # Check if we are a member of a bridge device              bridge = is_member(config, f'{ifname}.{vif_s}.{vif_c}', 'bridge')              if bridge: dict['vif_s'][vif_s]['vif_c'][vif_c].update( | 
