summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2020-03-04 19:51:37 +0100
committerChristian Poessinger <christian@poessinger.com>2020-03-04 21:45:23 +0100
commit5bf9dfd17096af6e7cf06e8e20eb16e8e55b9177 (patch)
tree6e02e47c2813d30c9bab5ce25b3a0d45061bb268
parentbb705d1a90cad14f07b5e61c44365868283feee9 (diff)
downloadvyos-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.i8
-rw-r--r--python/vyos/ifconfig.py28
-rwxr-xr-xsrc/conf_mode/vrf.py81
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')