summaryrefslogtreecommitdiff
path: root/tests/generator/test_tunnels.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/generator/test_tunnels.py')
-rw-r--r--tests/generator/test_tunnels.py280
1 files changed, 277 insertions, 3 deletions
diff --git a/tests/generator/test_tunnels.py b/tests/generator/test_tunnels.py
index e772e9c..bdf9719 100644
--- a/tests/generator/test_tunnels.py
+++ b/tests/generator/test_tunnels.py
@@ -1,8 +1,11 @@
#
# Tests for tunnel devices config generated via netplan
#
-# Copyright (C) 2018 Canonical, Ltd.
+# Copyright (C) 2018-2022 Canonical, Ltd.
+# Copyright (C) 2022 Datto, Inc.
# Author: Mathieu Trudel-Lapierre <mathieu.trudel.lapierre@canonical.com>
+# Author: Anthony Timmins <atimmins@datto.com>
+# Author: Lukas Märdian <slyon@ubuntu.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -16,7 +19,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from .base import TestBase, ND_WITHIPGW, ND_EMPTY, NM_WG, ND_WG
+import os
+import re
+
+from .base import TestBase, ND_WITHIPGW, ND_EMPTY, NM_WG, ND_WG, ND_VXLAN
def prepare_config_for_mode(renderer, mode, key=None, ttl=None):
@@ -328,6 +334,76 @@ must be X.X.X.X/NN or X:X:X:X:X:X:X:X/NN", out)
out = self.generate(config, expect_fail=True)
self.assertIn("Error in network definition: wg0: 'to' is required to define the allowed IPs.", out)
+ def test_vxlan_port_range_fail(self):
+ out = self.generate('''network:
+ tunnels:
+ vx0:
+ mode: vxlan
+ port-range: [1,2,3]''', expect_fail=True)
+ self.assertIn("Expected exactly two values for port-range", out)
+
+ def test_vxlan_port_min_wrong_type(self):
+ out = self.generate('''network:
+ tunnels:
+ vx0:
+ mode: vxlan
+ port-range: [a,10]''', expect_fail=True)
+ self.assertIn("invalid unsigned int value 'a'", out)
+
+ def test_vxlan_port_max_wrong_type(self):
+ out = self.generate('''network:
+ tunnels:
+ vx0:
+ mode: vxlan
+ port-range: [10,b]''', expect_fail=True)
+ self.assertIn("invalid unsigned int value 'b'", out)
+
+ def test_vxlan_flags_fail(self):
+ out = self.generate('''network:
+ tunnels:
+ vx0:
+ mode: vxlan
+ notifications: [INVALID]''', expect_fail=True)
+ self.assertIn("invalid value for notifications: 'INVALID'", out)
+
+ def test_vxlan_missing_vni(self):
+ out = self.generate('''network:
+ version: 2
+ tunnels:
+ vxlan1005:
+ mode: vxlan''', expect_fail=True)
+ self.assertIn('missing \'id\' property (VXLAN VNI)', out)
+
+ def test_vxlan_oob_vni(self):
+ out = self.generate('''network:
+ version: 2
+ tunnels:
+ vxlan1005:
+ mode: vxlan
+ id: 17000000''', expect_fail=True)
+ self.assertIn('VXLAN \'id\' (VNI) must be in range [1..16777215]', out)
+
+ def test_vxlan_oob_flow_label(self):
+ out = self.generate('''network:
+ version: 2
+ tunnels:
+ vxlan1005:
+ mode: vxlan
+ id: 1005
+ flow-label: 1111111''', expect_fail=True)
+ self.assertIn('VXLAN \'flow-label\' must be in range [0..1048575]', out)
+
+ def test_vxlan_local_remote_ip_family_mismatch(self):
+ out = self.generate('''network:
+ version: 2
+ tunnels:
+ vxlan1005:
+ mode: vxlan
+ id: 1005
+ local: 10.10.10.1
+ remote: fe80::3''', expect_fail=True)
+ self.assertIn('\'local\' and \'remote\' must be of same IP family type', out)
+
class _CommonTests():
@@ -508,6 +584,124 @@ persistent-keepalive=23
endpoint=[2001:fe:ad:de:ad:be:ef:11]:5
allowed-ips=0.0.0.0/0;2001:fe:ad:de:ad:be:ef:1/24;''')})
+ def test_vxlan(self):
+ out = self.generate('''network:
+ renderer: %(r)s
+ version: 2
+ tunnels:
+ vxlan1005:
+ link: br0
+ mode: vxlan
+ local: 10.10.10.1
+ remote: 224.0.0.5
+ id: 1005
+ port: 4789
+ ageing: 42
+ mac-learning: true
+ limit: 37
+ arp-proxy: true
+ short-circuit: true
+ type-of-service: 292
+ ttl: 128
+ flow-label: 0
+ do-not-fragment: true
+ notifications: [l2-miss, l3-miss]
+ checksums: [udp, zero-udp6-tx, zero-udp6-rx, remote-tx, remote-rx]
+ extensions: [group-policy, generic-protocol]
+ port-range: [42, 442]
+ neigh-suppress: false
+ bridges:
+ br0:
+ interfaces: [vxlan1005]''' % {'r': self.backend})
+
+ if self.backend == 'networkd':
+ self.assert_networkd({'vxlan1005.netdev': ND_VXLAN % ('vxlan1005', 1005) +
+ '''Group=224.0.0.5
+Local=10.10.10.1
+TOS=292
+TTL=128
+MacLearning=true
+FDBAgeingSec=42
+MaximumFDBEntries=37
+ReduceARPProxy=true
+L2MissNotification=true
+L3MissNotification=true
+RouteShortCircuit=true
+UDPChecksum=true
+UDP6ZeroChecksumTx=true
+UDP6ZeroChecksumRx=true
+RemoteChecksumTx=true
+RemoteChecksumRx=true
+GroupPolicyExtension=true
+GenericProtocolExtension=true
+DestinationPort=4789
+PortRange=42-442
+FlowLabel=0
+IPDoNotFragment=true\n''',
+ 'vxlan1005.network': '''[Match]
+Name=vxlan1005
+
+[Network]
+LinkLocalAddressing=no
+ConfigureWithoutCarrier=yes
+Bridge=br0
+
+[Bridge]
+NeighborSuppression=false\n''',
+ 'br0.network': '''[Match]
+Name=br0
+
+[Network]
+LinkLocalAddressing=ipv6
+ConfigureWithoutCarrier=yes
+VXLAN=vxlan1005\n''',
+ 'br0.netdev': '''[NetDev]
+Name=br0
+Kind=bridge\n'''})
+ elif self.backend == 'NetworkManager':
+ self.assertIn('checksums/extensions/flow-lable/do-not-fragment are '
+ 'not supported by NetworkManager', out)
+ self.assert_nm({'vxlan1005': '''[connection]
+id=netplan-vxlan1005
+type=vxlan
+interface-name=vxlan1005
+slave-type=bridge
+master=br0
+
+[vxlan]
+ageing=42
+destination-port=4789
+id=1005
+learning=true
+limit=37
+local=10.10.10.1
+remote=224.0.0.5
+proxy=true
+l2-miss=true
+l3-miss=true
+source-port-min=42
+source-port-max=442
+tos=292
+ttl=128
+rsc=true
+parent=br0
+
+[ipv4]
+method=disabled
+
+[ipv6]
+method=ignore\n''',
+ 'br0': '''[connection]
+id=netplan-br0
+type=bridge
+interface-name=br0
+
+[ipv4]
+method=link-local
+
+[ipv6]
+method=ignore\n'''})
+
# Execute the _CommonParserErrors only for one backend, to spare some test cycles
class TestNetworkd(TestBase, _CommonTests, _CommonParserErrors):
@@ -799,7 +993,7 @@ ConfigureWithoutCarrier=yes
def test_ip6gre(self):
"""[networkd] Validate generation of IP6GRE tunnels"""
- config = prepare_config_for_mode('networkd', 'ip6gre')
+ config = prepare_config_for_mode('networkd', 'ip6gre', '33490175')
self.generate(config)
self.assert_networkd({'tun0.netdev': '''[NetDev]
Name=tun0
@@ -809,6 +1003,8 @@ Kind=ip6gre
Independent=true
Local=fe80::dead:beef
Remote=2001:fe:ad:de:ad:be:ef:1
+InputKey=33490175
+OutputKey=33490175
''',
'tun0.network': '''[Match]
Name=tun0
@@ -866,6 +1062,34 @@ Gateway=20.20.20.21
ConfigureWithoutCarrier=yes
'''})
+ def test_vxlan_port_range_swap(self):
+ out = self.generate('''network:
+ version: 2
+ tunnels:
+ vx0:
+ mode: vxlan
+ id: 1005
+ remote: 10.0.0.5
+ port-range: [100, 10]''')
+ self.assertIn("swapped invalid port-range order [MIN, MAX]", out)
+
+ self.assert_networkd({'vx0.netdev': ND_VXLAN % ('vx0', 1005) +
+ 'Remote=10.0.0.5\nPortRange=10-100\nIndependent=true\n',
+ 'vx0.network': ND_EMPTY % ('vx0', 'ipv6')})
+
+ def test_vxlan_ip6_multicast(self):
+ self.generate('''network:
+ version: 2
+ tunnels:
+ vx0:
+ mode: vxlan
+ id: 1005
+ remote: "ff42::dead:beef"''')
+
+ self.assert_networkd({'vx0.netdev': ND_VXLAN % ('vx0', 1005) +
+ 'Group=ff42::dead:beef\nIndependent=true\n',
+ 'vx0.network': ND_EMPTY % ('vx0', 'ipv6')})
+
class TestNetworkManager(TestBase, _CommonTests):
backend = 'NetworkManager'
@@ -1189,6 +1413,56 @@ gateway=20.20.20.21
method=ignore
'''})
+ def test_vxlan_uuid(self):
+ self.generate('''network:
+ renderer: NetworkManager
+ tunnels:
+ vx0:
+ mode: vxlan
+ id: 42
+ link: id0
+ ethernets:
+ id0:
+ match: {name: 'someIface'}''')
+
+ self.assert_networkd({})
+
+ # get assigned UUID from id0 connection
+ with open(os.path.join(self.workdir.name, 'run/NetworkManager/system-connections/netplan-id0.nmconnection')) as f:
+ m = re.search('uuid=([0-9a-fA-F-]{36})\n', f.read())
+ self.assertTrue(m)
+ uuid = m.group(1)
+ self.assertNotEquals(uuid, "00000000-0000-0000-0000-000000000000")
+
+ self.assert_nm({'vx0': '''[connection]
+id=netplan-vx0
+type=vxlan
+interface-name=vx0
+
+[vxlan]
+id=42
+parent=%s
+
+[ipv4]
+method=disabled
+
+[ipv6]
+method=ignore\n''' % uuid,
+ 'id0': '''[connection]
+id=netplan-id0
+type=ethernet
+uuid=%s
+interface-name=someIface
+
+[ethernet]
+wake-on-lan=0
+
+[ipv4]
+method=link-local
+
+[ipv6]
+method=ignore\n''' % uuid})
+
class TestConfigErrors(TestBase):