Skip to content

Commit

Permalink
Merge pull request #2052 from jestabro/revise-interface-dict
Browse files Browse the repository at this point in the history
vyos.configdict: T5308: Remove workarounds for incorrect defaults in get_interface_dict
  • Loading branch information
c-po committed Jun 24, 2023
2 parents efc19e7 + 0a32e44 commit ce37b95
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 83 deletions.
99 changes: 17 additions & 82 deletions python/vyos/configdict.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ def get_pppoe_interfaces(conf, vrf=None):

return pppoe_interfaces

def get_interface_dict(config, base, ifname=''):
def get_interface_dict(config, base, ifname='', recursive_defaults=True):
"""
Common utility function to retrieve and mangle the interfaces configuration
from the CLI input nodes. All interfaces have a common base where value
Expand All @@ -405,55 +405,36 @@ def get_interface_dict(config, base, ifname=''):
raise ConfigError('Interface (VYOS_TAGNODE_VALUE) not specified')
ifname = os.environ['VYOS_TAGNODE_VALUE']

# retrieve interface default values
default_values = defaults(base)

# We take care about VLAN (vif, vif-s, vif-c) default values later on when
# parsing vlans in default dict and merge the "proper" values in correctly,
# see T2665.
for vif in ['vif', 'vif_s']:
if vif in default_values: del default_values[vif]

dict = config.get_config_dict(base + [ifname], key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True)

# Check if interface has been removed. We must use exists() as
# get_config_dict() will always return {} - even when an empty interface
# node like the following exists.
# +macsec macsec1 {
# +}
if not config.exists(base + [ifname]):
dict = config.get_config_dict(base + [ifname], key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True)
dict.update({'deleted' : {}})

# Add interface instance name into dictionary
dict.update({'ifname': ifname})

# Check if QoS policy applied on this interface - See ifconfig.interface.set_mirror_redirect()
if config.exists(['qos', 'interface', ifname]):
dict.update({'traffic_policy': {}})

# XXX: T2665: When there is no DHCPv6-PD configuration given, we can safely
# remove the default values from the dict.
if 'dhcpv6_options' not in dict:
if 'dhcpv6_options' in default_values:
del default_values['dhcpv6_options']

# We have gathered the dict representation of the CLI, but there are
# default options which we need to update into the dictionary retrived.
# But we should only add them when interface is not deleted - as this might
# confuse parsers
if 'deleted' not in dict:
dict = dict_merge(default_values, dict)
else:
# Get config_dict with default values
dict = config.get_config_dict(base + [ifname], key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True,
with_defaults=True,
with_recursive_defaults=recursive_defaults)

# 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)
# Add interface instance name into dictionary
dict.update({'ifname': ifname})

# Check if QoS policy applied on this interface - See ifconfig.interface.set_mirror_redirect()
if config.exists(['qos', 'interface', ifname]):
dict.update({'traffic_policy': {}})

address = leaf_node_changed(config, base + [ifname, 'address'])
if address: dict.update({'address_old' : address})
Expand Down Expand Up @@ -497,32 +478,17 @@ def get_interface_dict(config, base, ifname=''):
else:
dict['ipv6']['address'].update({'eui64_old': eui64})

# Implant default dictionary in vif/vif-s VLAN interfaces. Values are
# identical for all types of VLAN interfaces as they all include the same
# XML definitions which hold the defaults.
for vif, vif_config in dict.get('vif', {}).items():
# Add subinterface name to dictionary
dict['vif'][vif].update({'ifname' : f'{ifname}.{vif}'})

if config.exists(['qos', 'interface', f'{ifname}.{vif}']):
dict['vif'][vif].update({'traffic_policy': {}})

default_vif_values = defaults(base + ['vif'])
# XXX: T2665: When there is no DHCPv6-PD configuration given, we can safely
# remove the default values from the dict.
if not 'dhcpv6_options' in vif_config:
del default_vif_values['dhcpv6_options']

# Only add defaults if interface is not about to be deleted - this is
# to keep a cleaner config dict.
if 'deleted' not in dict:
address = leaf_node_changed(config, base + [ifname, 'vif', vif, 'address'])
if address: dict['vif'][vif].update({'address_old' : address})

dict['vif'][vif] = dict_merge(default_vif_values, dict['vif'][vif])
# 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']:
Expand All @@ -544,26 +510,10 @@ def get_interface_dict(config, base, ifname=''):
if config.exists(['qos', 'interface', f'{ifname}.{vif_s}']):
dict['vif_s'][vif_s].update({'traffic_policy': {}})

default_vif_s_values = defaults(base + ['vif-s'])
# XXX: T2665: we only wan't the vif-s defaults - do not care about vif-c
if 'vif_c' in default_vif_s_values: del default_vif_s_values['vif_c']

# XXX: T2665: When there is no DHCPv6-PD configuration given, we can safely
# remove the default values from the dict.
if not 'dhcpv6_options' in vif_s_config:
del default_vif_s_values['dhcpv6_options']

# Only add defaults if interface is not about to be deleted - this is
# to keep a cleaner config dict.
if 'deleted' not in dict:
address = leaf_node_changed(config, base + [ifname, 'vif-s', vif_s, 'address'])
if address: dict['vif_s'][vif_s].update({'address_old' : address})

dict['vif_s'][vif_s] = dict_merge(default_vif_s_values,
dict['vif_s'][vif_s])
# 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 \
Expand All @@ -586,26 +536,11 @@ def get_interface_dict(config, base, ifname=''):
if config.exists(['qos', 'interface', f'{ifname}.{vif_s}.{vif_c}']):
dict['vif_s'][vif_s]['vif_c'][vif_c].update({'traffic_policy': {}})

default_vif_c_values = defaults(base + ['vif-s', 'vif-c'])

# XXX: T2665: When there is no DHCPv6-PD configuration given, we can safely
# remove the default values from the dict.
if not 'dhcpv6_options' in vif_c_config:
del default_vif_c_values['dhcpv6_options']

# Only add defaults if interface is not about to be deleted - this is
# to keep a cleaner config dict.
if 'deleted' not in dict:
address = leaf_node_changed(config, base + [ifname, 'vif-s', vif_s, 'vif-c', vif_c, 'address'])
if address: dict['vif_s'][vif_s]['vif_c'][vif_c].update(
{'address_old' : address})

dict['vif_s'][vif_s]['vif_c'][vif_c] = dict_merge(
default_vif_c_values, dict['vif_s'][vif_s]['vif_c'][vif_c])
# XXX: T2665: blend in proper DHCPv6-PD default values
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' \
Expand Down
2 changes: 1 addition & 1 deletion python/vyos/configverify.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ def verify_dhcpv6(config):

# It is not allowed to have duplicate SLA-IDs as those identify an
# assigned IPv6 subnet from a delegated prefix
for pd in dict_search('dhcpv6_options.pd', config):
for pd in (dict_search('dhcpv6_options.pd', config) or []):
sla_ids = []
interfaces = dict_search(f'dhcpv6_options.pd.{pd}.interface', config)

Expand Down

0 comments on commit ce37b95

Please sign in to comment.