diff options
-rw-r--r-- | interface-definitions/interfaces-geneve.xml.in | 25 | ||||
-rw-r--r-- | python/vyos/ifconfig/geneve.py | 26 | ||||
-rw-r--r-- | python/vyos/ifconfig/vxlan.py | 3 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_interfaces_geneve.py | 46 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_interfaces_vxlan.py | 31 | ||||
-rwxr-xr-x | src/op_mode/show_interfaces.py | 5 |
6 files changed, 124 insertions, 12 deletions
diff --git a/interface-definitions/interfaces-geneve.xml.in b/interface-definitions/interfaces-geneve.xml.in index 5894f580c..25308c8ef 100644 --- a/interface-definitions/interfaces-geneve.xml.in +++ b/interface-definitions/interfaces-geneve.xml.in @@ -23,6 +23,31 @@ #include <include/interface-ipv6-options.xml.i> #include <include/interface-mac.xml.i> #include <include/interface-mtu-1450-16000.xml.i> + <node name="parameters"> + <properties> + <help>GENEVE tunnel parameters</help> + </properties> + <children> + <node name="ip"> + <properties> + <help>IPv4 specific tunnel parameters</help> + </properties> + <children> + #include <include/interface-parameters-dont-fragment.xml.i> + #include <include/interface-parameters-tos.xml.i> + #include <include/interface-parameters-ttl.xml.i> + </children> + </node> + <node name="ipv6"> + <properties> + <help>IPv6 specific tunnel parameters</help> + </properties> + <children> + #include <include/interface-parameters-flowlabel.xml.i> + </children> + </node> + </children> + </node> #include <include/tunnel-remote.xml.i> #include <include/vni.xml.i> </children> diff --git a/python/vyos/ifconfig/geneve.py b/python/vyos/ifconfig/geneve.py index 6747d2bd6..7cb3968df 100644 --- a/python/vyos/ifconfig/geneve.py +++ b/python/vyos/ifconfig/geneve.py @@ -13,7 +13,8 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see <http://www.gnu.org/licenses/>. -from vyos.ifconfig.interface import Interface +from vyos.ifconfig import Interface +from vyos.util import dict_search @Interface.register class GeneveIf(Interface): @@ -37,8 +38,27 @@ class GeneveIf(Interface): } def _create(self): - cmd = 'ip link add name {ifname} type geneve id {vni} remote {remote}'.format(**self.config) - self._cmd(cmd) + # This table represents a mapping from VyOS internal config dict to + # arguments used by iproute2. For more information please refer to: + # - https://man7.org/linux/man-pages/man8/ip-link.8.html + mapping = { + 'parameters.ip.dont_fragment': 'df set', + 'parameters.ip.tos' : 'tos', + 'parameters.ip.ttl' : 'ttl', + 'parameters.ipv6.flowlabel' : 'flowlabel', + } + + cmd = 'ip link add name {ifname} type {type} id {vni} remote {remote}' + for vyos_key, iproute2_key in mapping.items(): + # dict_search will return an empty dict "{}" for valueless nodes like + # "parameters.nolearning" - thus we need to test the nodes existence + # by using isinstance() + tmp = dict_search(vyos_key, self.config) + if isinstance(tmp, dict): + cmd += f' {iproute2_key}' + elif tmp != None: + cmd += f' {iproute2_key} {tmp}' + self._cmd(cmd.format(**self.config)) # interface is always A/D down. It needs to be enabled explicitly self.set_admin_state('down') diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py index 6556aff5a..d73fb47b8 100644 --- a/python/vyos/ifconfig/vxlan.py +++ b/python/vyos/ifconfig/vxlan.py @@ -14,7 +14,7 @@ # License along with this library. If not, see <http://www.gnu.org/licenses/>. from vyos import ConfigError -from vyos.ifconfig.interface import Interface +from vyos.ifconfig import Interface from vyos.util import dict_search @Interface.register @@ -77,4 +77,5 @@ class VXLANIf(Interface): cmd += f' {iproute2_key} {tmp}' self._cmd(cmd.format(**self.config)) + # interface is always A/D down. It needs to be enabled explicitly self.set_admin_state('down') diff --git a/smoketest/scripts/cli/test_interfaces_geneve.py b/smoketest/scripts/cli/test_interfaces_geneve.py index b708b5437..e31867900 100755 --- a/smoketest/scripts/cli/test_interfaces_geneve.py +++ b/smoketest/scripts/cli/test_interfaces_geneve.py @@ -17,6 +17,9 @@ import unittest from vyos.configsession import ConfigSession +from vyos.ifconfig import Interface +from vyos.util import get_json_iface_options + from base_interfaces_test import BasicInterfaceTest class GeneveInterfaceTest(BasicInterfaceTest.BaseTest): @@ -28,8 +31,51 @@ class GeneveInterfaceTest(BasicInterfaceTest.BaseTest): cls._options = { 'gnv0': ['vni 10', 'remote 127.0.1.1'], 'gnv1': ['vni 20', 'remote 127.0.1.2'], + 'gnv1': ['vni 30', 'remote 2001:db8::1', 'parameters ipv6 flowlabel 0x1000'], } cls._interfaces = list(cls._options) + def test_geneve_parameters(self): + tos = '40' + ttl = 20 + for intf in self._interfaces: + for option in self._options.get(intf, []): + self.session.set(self._base_path + [intf] + option.split()) + + self.session.set(self._base_path + [intf, 'parameters', 'ip', 'dont-fragment']) + self.session.set(self._base_path + [intf, 'parameters', 'ip', 'tos', tos]) + self.session.set(self._base_path + [intf, 'parameters', 'ip', 'ttl', str(ttl)]) + ttl += 10 + + self.session.commit() + + ttl = 20 + for interface in self._interfaces: + options = get_json_iface_options(interface) + import pprint + pprint.pprint(options) + + vni = options['linkinfo']['info_data']['id'] + self.assertIn(f'vni {vni}', self._options[interface]) + + if any('remote' in s for s in self._options[interface]): + key = 'remote' + if 'remote6' in options['linkinfo']['info_data']: + key = 'remote6' + + remote = options['linkinfo']['info_data'][key] + self.assertIn(f'remote {remote}', self._options[interface]) + + if any('flowlabel' in s for s in self._options[interface]): + label = options['linkinfo']['info_data']['label'] + self.assertIn(f'parameters ipv6 flowlabel {label}', self._options[interface]) + + self.assertEqual('geneve', options['linkinfo']['info_kind']) + self.assertEqual('set', options['linkinfo']['info_data']['df']) + self.assertEqual(f'0x{tos}', options['linkinfo']['info_data']['tos']) + self.assertEqual(ttl, options['linkinfo']['info_data']['ttl']) + self.assertEqual(Interface(interface).get_admin_state(), 'up') + ttl += 10 + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_vxlan.py b/smoketest/scripts/cli/test_interfaces_vxlan.py index c52dc410b..b66315c5e 100755 --- a/smoketest/scripts/cli/test_interfaces_vxlan.py +++ b/smoketest/scripts/cli/test_interfaces_vxlan.py @@ -32,16 +32,14 @@ class VXLANInterfaceTest(BasicInterfaceTest.BaseTest): cls._options = { 'vxlan10': ['vni 10', 'remote 127.0.0.2'], 'vxlan20': ['vni 20', 'group 239.1.1.1', 'source-interface eth0'], - 'vxlan30': ['vni 30', 'remote 2001:db8:2000::1', 'source-address 2001:db8:1000::1'], + 'vxlan30': ['vni 30', 'remote 2001:db8:2000::1', 'source-address 2001:db8:1000::1', 'parameters ipv6 flowlabel 0x1000'], } cls._interfaces = list(cls._options) def test_vxlan_parameters(self): - addr = '192.0.2.0/31' tos = '40' ttl = 20 for intf in self._interfaces: - self.session.set(self._base_path + [intf, 'address', addr]) for option in self._options.get(intf, []): self.session.set(self._base_path + [intf] + option.split()) @@ -55,6 +53,31 @@ class VXLANInterfaceTest(BasicInterfaceTest.BaseTest): ttl = 20 for interface in self._interfaces: options = get_json_iface_options(interface) + + vni = options['linkinfo']['info_data']['id'] + self.assertIn(f'vni {vni}', self._options[interface]) + + if any('link' in s for s in self._options[interface]): + link = options['linkinfo']['info_data']['link'] + self.assertIn(f'source-interface {link}', self._options[interface]) + + if any('local6' in s for s in self._options[interface]): + remote = options['linkinfo']['info_data']['local6'] + self.assertIn(f'source-address {local6}', self._options[interface]) + + if any('remote6' in s for s in self._options[interface]): + remote = options['linkinfo']['info_data']['remote6'] + self.assertIn(f'remote {remote}', self._options[interface]) + + if any('group' in s for s in self._options[interface]): + group = options['linkinfo']['info_data']['group'] + self.assertIn(f'group {group}', self._options[interface]) + + if any('flowlabel' in s for s in self._options[interface]): + label = options['linkinfo']['info_data']['label'] + self.assertIn(f'parameters ipv6 flowlabel {label}', self._options[interface]) + + self.assertEqual('vxlan', options['linkinfo']['info_kind']) self.assertEqual('set', options['linkinfo']['info_data']['df']) self.assertEqual(f'0x{tos}', options['linkinfo']['info_data']['tos']) self.assertEqual(ttl, options['linkinfo']['info_data']['ttl']) @@ -62,4 +85,4 @@ class VXLANInterfaceTest(BasicInterfaceTest.BaseTest): ttl += 10 if __name__ == '__main__': - unittest.main(verbosity=2, failfast=True) + unittest.main(verbosity=2) diff --git a/src/op_mode/show_interfaces.py b/src/op_mode/show_interfaces.py index 256c86d2a..5375a8406 100755 --- a/src/op_mode/show_interfaces.py +++ b/src/op_mode/show_interfaces.py @@ -71,10 +71,7 @@ def filtered_interfaces(ifnames, iftypes, vif, vrrp): if ifnames and ifname not in ifnames: continue - # return the class which can handle this interface name - klass = Section.klass(ifname) - # connect to the interface - interface = klass(ifname, create=False, debug=False) + interface = Interface(ifname) if iftypes and interface.definition['section'] not in iftypes: continue |