diff options
author | Christian Poessinger <christian@poessinger.com> | 2020-03-04 19:51:37 +0100 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2020-03-04 21:45:23 +0100 |
commit | 5bf9dfd17096af6e7cf06e8e20eb16e8e55b9177 (patch) | |
tree | 6e02e47c2813d30c9bab5ce25b3a0d45061bb268 | |
parent | bb705d1a90cad14f07b5e61c44365868283feee9 (diff) | |
download | vyos-1x-5bf9dfd17096af6e7cf06e8e20eb16e8e55b9177.tar.gz vyos-1x-5bf9dfd17096af6e7cf06e8e20eb16e8e55b9177.zip |
vrf: T31: support add/remove of interfaces from vrf
-rw-r--r-- | interface-definitions/include/interface-vrf.xml.i | 8 | ||||
-rw-r--r-- | python/vyos/ifconfig.py | 28 | ||||
-rwxr-xr-x | src/conf_mode/vrf.py | 81 |
3 files changed, 83 insertions, 34 deletions
diff --git a/interface-definitions/include/interface-vrf.xml.i b/interface-definitions/include/interface-vrf.xml.i index 7e880e6ee..355e7f0f3 100644 --- a/interface-definitions/include/interface-vrf.xml.i +++ b/interface-definitions/include/interface-vrf.xml.i @@ -1,12 +1,12 @@ <leafNode name="vrf"> <properties> <help>VRF instance name</help> + <valueHelp> + <format>text</format> + <description>VRF instance name</description> + </valueHelp> <completionHelp> <path>vrf name</path> </completionHelp> - <constraint> - <validator name="interface-name"/> - </constraint> - <constraintErrorMessage>VRF name not allowed or to long</constraintErrorMessage> </properties> </leafNode> diff --git a/python/vyos/ifconfig.py b/python/vyos/ifconfig.py index beeafa420..430b3c4e4 100644 --- a/python/vyos/ifconfig.py +++ b/python/vyos/ifconfig.py @@ -202,6 +202,12 @@ class Interface(Control): 'validate': assert_mac, 'shellcmd': 'ip link set dev {ifname} address {value}', }, + 'add_vrf': { + 'shellcmd': 'ip link set dev {ifname} master {value}', + }, + 'del_vrf': { + 'shellcmd': 'ip link set dev {ifname} nomaster {value}', + }, } _sysfs_get = { @@ -345,7 +351,7 @@ class Interface(Control): self.del_addr(addr) # --------------------------------------------------------------------- - # A code refactoring is required as this type check is present as + # A code refactoring is required as this type check is present as # Interface implement behaviour for one of it's sub-class. # It is required as the current pattern for vlan is: @@ -405,6 +411,26 @@ class Interface(Control): """ self.set_interface('mac', mac) + def add_vrf(self, vrf): + """ + Add interface to given VRF instance. + + Example: + >>> from vyos.ifconfig import Interface + >>> Interface('eth0').add_vrf('foo') + """ + self.set_interface('add_vrf', vrf) + + def del_vrf(self, vrf): + """ + Remove interface from given VRF instance. + + Example: + >>> from vyos.ifconfig import Interface + >>> Interface('eth0').del_vrf('foo') + """ + self.set_interface('del_vrf', vrf) + def set_arp_cache_tmo(self, tmo): """ Set ARP cache timeout value in seconds. Internal Kernel representation diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index c2bbc72b3..ad2b72a5b 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -24,6 +24,7 @@ from vyos.configdict import list_diff from vyos import ConfigError default_config_data = { + 'deleted': False, 'vrf_add': [], 'vrf_existing': [], 'vrf_remove': [] @@ -63,49 +64,71 @@ def get_config(): if not conf.exists(cfg_base): # get all currently effetive VRFs and mark them for deletion vrf_config['vrf_remove'] = conf.list_effective_nodes(cfg_base + ['name']) - return vrf_config - - # Determine vrf interfaces (currently effective) - to determine which - # vrf interface is no longer present and needs to be removed - eff_vrf = conf.list_effective_nodes(cfg_base + ['name']) - act_vrf = conf.list_nodes(cfg_base + ['name']) - vrf_config['vrf_remove'] = list_diff(eff_vrf, act_vrf) - - # read in individual VRF definition and build up - # configuration - for name in conf.list_nodes(cfg_base + ['name']): + else: + # Determine vrf interfaces (currently effective) - to determine which + # vrf interface is no longer present and needs to be removed + eff_vrf = conf.list_effective_nodes(cfg_base + ['name']) + act_vrf = conf.list_nodes(cfg_base + ['name']) + vrf_config['vrf_remove'] = list_diff(eff_vrf, act_vrf) + + # read in individual VRF definition and build up + # configuration + for name in conf.list_nodes(cfg_base + ['name']): + vrf_inst = { + 'description' : '\0', + 'members': [], + 'name' : name, + 'table' : '', + 'table_mod': False + } + conf.set_level(cfg_base + ['name', name]) + + if conf.exists(['table']): + # VRF table can't be changed on demand, thus we need to read in the + # current and the effective routing table number + act_table = conf.return_value(['table']) + eff_table = conf.return_effective_value(['table']) + vrf_inst['table'] = act_table + if eff_table and eff_table != act_table: + vrf_inst['table_mod'] = True + + if conf.exists(['description']): + vrf_inst['description'] = conf.return_value(['description']) + + # find member interfaces of this particulat VRF + vrf_inst['members'] = interfaces_with_vrf(name) + + # append individual VRF configuration to global configuration list + vrf_config['vrf_add'].append(vrf_inst) + + # check VRFs which need to be removed as they are not allowed to have + # interfaces attached + tmp = [] + for name in vrf_config['vrf_remove']: vrf_inst = { - 'description' : '\0', 'members': [], 'name' : name, - 'table' : '', - 'table_mod': False } - conf.set_level(cfg_base + ['name', name]) - - if conf.exists(['table']): - # VRF table can't be changed on demand, thus we need to read in the - # current and the effective routing table number - act_table = conf.return_value(['table']) - eff_table = conf.return_effective_value(['table']) - vrf_inst['table'] = act_table - if eff_table and eff_table != act_table: - vrf_inst['table_mod'] = True - - if conf.exists(['description']): - vrf_inst['description'] = conf.return_value(['description']) # find member interfaces of this particulat VRF vrf_inst['members'] = interfaces_with_vrf(name) - # append individual VRF configuration to global configuration list - vrf_config['vrf_add'].append(vrf_inst) + # append individual VRF configuration to temporary configuration list + tmp.append(vrf_inst) + # replace values in vrf_remove with list of dictionaries + # as we need it in verify() - we can't delete a VRF with members attached + vrf_config['vrf_remove'] = tmp return vrf_config def verify(vrf_config): # ensure VRF is not assigned to any interface + for vrf in vrf_config['vrf_remove']: + if len(vrf['members']) > 0: + raise ConfigError('VRF "{}" can not be deleted as it has active members'.format(vrf['name'])) + + # routing table id can't be changed - OS restriction for vrf in vrf_config['vrf_add']: if vrf['table_mod']: raise ConfigError('VRF routing table id modification is not possible') |