]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
Merge pull request #12223 from yuwata/network-wireguard-preshared-key-file
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
CommitLineData
1f0e3109
SS
1#!/usr/bin/env python3
2# SPDX-License-Identifier: LGPL-2.1+
3# systemd-networkd tests
4
5import os
201bf07f 6import re
1f0e3109
SS
7import shutil
8import signal
9import socket
a9bc5e37
YW
10import subprocess
11import sys
a9bc5e37
YW
12import time
13import unittest
1f0e3109
SS
14from shutil import copytree
15
d486a2d0 16network_unit_file_path='/run/systemd/network'
bad4969b 17networkd_runtime_directory='/run/systemd/netif'
d486a2d0 18networkd_ci_path='/run/networkd-ci'
1f0e3109
SS
19network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
20network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
21
d486a2d0
YW
22dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
23dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
1f0e3109 24
5aa58329
YW
25wait_online_bin='/usr/lib/systemd/systemd-networkd-wait-online'
26
7a0a37b2 27def is_module_available(module_name):
201bf07f
EV
28 lsmod_output = subprocess.check_output('lsmod', universal_newlines=True)
29 module_re = re.compile(r'^{0}\b'.format(re.escape(module_name)), re.MULTILINE)
30 return module_re.search(lsmod_output) or not subprocess.call(["modprobe", module_name])
7a0a37b2
EV
31
32def expectedFailureIfModuleIsNotAvailable(module_name):
33 def f(func):
34 if not is_module_available(module_name):
35 return unittest.expectedFailure(func)
36 return func
37
38 return f
39
7bea7f9b
SS
40def expectedFailureIfERSPANModuleIsNotAvailable():
41 def f(func):
42 rc = subprocess.call(['ip', 'link', 'add', 'dev', 'erspan99', 'type', 'erspan', 'seq', 'key', '30', 'local', '192.168.1.4', 'remote', '192.168.1.1', 'erspan_ver', '1', 'erspan', '123'])
43 if rc == 0:
44 subprocess.call(['ip', 'link', 'del', 'erspan99'])
45 return func
46 else:
47 return unittest.expectedFailure(func)
48
49 return f
50
d586a2c3
YW
51def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
52 def f(func):
53 rc = subprocess.call(['ip', 'rule', 'add', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7'])
54 if rc == 0:
55 subprocess.call(['ip', 'rule', 'del', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7'])
56 return func
57 else:
58 return unittest.expectedFailure(func)
59
60 return f
61
62def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
63 def f(func):
64 rc = subprocess.call(['ip', 'rule', 'add', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7'])
65 if rc == 0:
66 subprocess.call(['ip', 'rule', 'del', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7'])
67 return func
68 else:
69 return unittest.expectedFailure(func)
70
71 return f
72
1f0e3109 73def setUpModule():
1f0e3109
SS
74 os.makedirs(network_unit_file_path, exist_ok=True)
75 os.makedirs(networkd_ci_path, exist_ok=True)
76
77 shutil.rmtree(networkd_ci_path)
6aea9276 78 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
1f0e3109 79
c0bf6733
YW
80 subprocess.check_call('systemctl stop systemd-networkd.socket', shell=True)
81
1f0e3109
SS
82def tearDownModule():
83 shutil.rmtree(networkd_ci_path)
84
c0bf6733
YW
85 subprocess.check_call('systemctl stop systemd-networkd.service', shell=True)
86 subprocess.check_call('systemctl start systemd-networkd.socket', shell=True)
87 subprocess.check_call('systemctl start systemd-networkd.service', shell=True)
88
1f0e3109 89class Utilities():
1f0e3109
SS
90 def read_link_attr(self, link, dev, attribute):
91 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
92 return f.readline().strip()
93
4d7ed14f
SS
94 def read_bridge_port_attr(self, bridge, link, attribute):
95
96 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
97 path_port = 'lower_' + link + '/brport'
98 path = os.path.join(path_bridge, path_port)
99
100 with open(os.path.join(path, attribute)) as f:
101 return f.readline().strip()
102
1f0e3109
SS
103 def link_exits(self, link):
104 return os.path.exists(os.path.join('/sys/class/net', link))
105
106 def link_remove(self, links):
107 for link in links:
108 if os.path.exists(os.path.join('/sys/class/net', link)):
109 subprocess.call(['ip', 'link', 'del', 'dev', link])
9a4720a9 110 time.sleep(1)
1f0e3109 111
cff83db9
YW
112 def l2tp_tunnel_remove(self, tunnel_ids):
113 output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel']).rstrip().decode('utf-8')
114 for tid in tunnel_ids:
115 words='Tunnel ' + tid + ', encap'
116 if words in output:
117 subprocess.call(['ip', 'l2tp', 'del', 'tunnel', 'tid', tid])
118 time.sleep(1)
119
1f0e3109
SS
120 def read_ipv6_sysctl_attr(self, link, attribute):
121 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
122 return f.readline().strip()
123
124 def read_ipv4_sysctl_attr(self, link, attribute):
125 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
126 return f.readline().strip()
127
128 def copy_unit_to_networkd_unit_path(self, *units):
ecdd0392 129 print()
1f0e3109
SS
130 for unit in units:
131 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
013c8dc9
YW
132 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
133 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
1f0e3109
SS
134
135 def remove_unit_from_networkd_path(self, units):
136 for unit in units:
137 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
138 os.remove(os.path.join(network_unit_file_path, unit))
013c8dc9
YW
139 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
140 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
1f0e3109 141
b412fce8
YW
142 def start_dnsmasq(self, additional_options=''):
143 dnsmasq_command = 'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range=2600::10,2600::20 --dhcp-range=192.168.5.10,192.168.5.200 -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
144 subprocess.check_call(dnsmasq_command, shell=True)
1f0e3109
SS
145
146 time.sleep(10)
147
148 def stop_dnsmasq(self, pid_file):
149 if os.path.exists(pid_file):
150 with open(pid_file, 'r') as f:
151 pid = f.read().rstrip(' \t\r\n\0')
152 os.kill(int(pid), signal.SIGTERM)
153
154 os.remove(pid_file)
155
131717cb 156 def search_words_in_dnsmasq_log(self, words, show_all=False):
1f0e3109
SS
157 if os.path.exists(dnsmasq_log_file):
158 with open (dnsmasq_log_file) as in_file:
159 contents = in_file.read()
131717cb
YW
160 if show_all:
161 print(contents)
162 for line in contents.split('\n'):
163 if words in line:
1f0e3109 164 in_file.close()
131717cb 165 print("%s, %s" % (words, line))
1f0e3109
SS
166 return True
167 return False
168
169 def remove_lease_file(self):
170 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
171 os.remove(os.path.join(networkd_ci_path, 'lease'))
172
173 def remove_log_file(self):
174 if os.path.exists(dnsmasq_log_file):
175 os.remove(dnsmasq_log_file)
176
5aa58329 177 def start_networkd(self, sleep_sec=5, remove_state_files=True):
b677774d
YW
178 if (remove_state_files and
179 os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
bad4969b
YW
180 subprocess.check_call('systemctl stop systemd-networkd', shell=True)
181 os.remove(os.path.join(networkd_runtime_directory, 'state'))
182 subprocess.check_call('systemctl start systemd-networkd', shell=True)
183 else:
184 subprocess.check_call('systemctl restart systemd-networkd', shell=True)
5aa58329
YW
185 if sleep_sec > 0:
186 time.sleep(sleep_sec)
187
03db80b2 188 def wait_online(self, links_with_operstate, timeout='20s', bool_any=False):
c7f070bd 189 args = [wait_online_bin, f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
03db80b2
YW
190 if bool_any:
191 args += ['--any']
5aa58329 192 subprocess.check_call(args)
1f0e3109 193
1f0e3109
SS
194class NetworkdNetDevTests(unittest.TestCase, Utilities):
195
09ea6724
YW
196 links =[
197 '6rdtun99',
198 'bond99',
199 'bridge99',
200 'dropin-test',
201 'dummy98',
6a97a864
YW
202 'erspan98',
203 'erspan99',
09ea6724 204 'geneve99',
4b6a6d1e 205 'gretap96',
6a97a864 206 'gretap98',
09ea6724 207 'gretap99',
4b6a6d1e 208 'gretun96',
6a97a864
YW
209 'gretun97',
210 'gretun98',
09ea6724 211 'gretun99',
6a97a864 212 'ip6gretap98',
09ea6724 213 'ip6gretap99',
6a97a864
YW
214 'ip6gretun97',
215 'ip6gretun98',
216 'ip6gretun99',
217 'ip6tnl97',
218 'ip6tnl98',
09ea6724 219 'ip6tnl99',
4b6a6d1e 220 'ipiptun96',
6a97a864
YW
221 'ipiptun97',
222 'ipiptun98',
09ea6724
YW
223 'ipiptun99',
224 'ipvlan99',
225 'isataptun99',
226 'macvlan99',
227 'macvtap99',
4b6a6d1e 228 'sittun96',
6a97a864
YW
229 'sittun97',
230 'sittun98',
09ea6724
YW
231 'sittun99',
232 'tap99',
233 'test1',
234 'tun99',
235 'vcan99',
236 'veth99',
237 'vlan99',
238 'vrf99',
6a97a864
YW
239 'vti6tun97',
240 'vti6tun98',
09ea6724 241 'vti6tun99',
6a97a864
YW
242 'vtitun97',
243 'vtitun98',
09ea6724
YW
244 'vtitun99',
245 'vxlan99',
da44fb8a 246 'wg98',
09ea6724
YW
247 'wg99']
248
249 units = [
250 '10-dropin-test.netdev',
251 '11-dummy.netdev',
03db80b2 252 '11-dummy.network',
09ea6724 253 '12-dummy.netdev',
753e0a24 254 '15-name-conflict-test.netdev',
09ea6724
YW
255 '21-macvlan.netdev',
256 '21-macvtap.netdev',
7f45d738 257 '21-vlan-test1.network',
09ea6724
YW
258 '21-vlan.netdev',
259 '21-vlan.network',
260 '25-6rd-tunnel.netdev',
261 '25-bond.netdev',
fde60a42 262 '25-bond-balanced-tlb.netdev',
09ea6724 263 '25-bridge.netdev',
03db80b2 264 '25-bridge.network',
6a97a864 265 '25-erspan-tunnel-local-any.netdev',
09ea6724 266 '25-erspan-tunnel.netdev',
4b6a6d1e
YW
267 '25-fou-gretap.netdev',
268 '25-fou-gre.netdev',
269 '25-fou-ipip.netdev',
270 '25-fou-ipproto-gre.netdev',
271 '25-fou-ipproto-ipip.netdev',
272 '25-fou-sit.netdev',
09ea6724 273 '25-geneve.netdev',
6a97a864 274 '25-gretap-tunnel-local-any.netdev',
09ea6724 275 '25-gretap-tunnel.netdev',
6a97a864
YW
276 '25-gre-tunnel-local-any.netdev',
277 '25-gre-tunnel-remote-any.netdev',
09ea6724 278 '25-gre-tunnel.netdev',
6a97a864
YW
279 '25-ip6gretap-tunnel-local-any.netdev',
280 '25-ip6gretap-tunnel.netdev',
281 '25-ip6gre-tunnel-local-any.netdev',
282 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 283 '25-ip6gre-tunnel.netdev',
6a97a864
YW
284 '25-ip6tnl-tunnel-remote-any.netdev',
285 '25-ip6tnl-tunnel-local-any.netdev',
09ea6724
YW
286 '25-ip6tnl-tunnel.netdev',
287 '25-ipip-tunnel-independent.netdev',
6a97a864
YW
288 '25-ipip-tunnel-local-any.netdev',
289 '25-ipip-tunnel-remote-any.netdev',
09ea6724
YW
290 '25-ipip-tunnel.netdev',
291 '25-ipvlan.netdev',
292 '25-isatap-tunnel.netdev',
6a97a864
YW
293 '25-sit-tunnel-local-any.netdev',
294 '25-sit-tunnel-remote-any.netdev',
09ea6724
YW
295 '25-sit-tunnel.netdev',
296 '25-tap.netdev',
297 '25-tun.netdev',
298 '25-vcan.netdev',
299 '25-veth.netdev',
300 '25-vrf.netdev',
6a97a864
YW
301 '25-vti6-tunnel-local-any.netdev',
302 '25-vti6-tunnel-remote-any.netdev',
09ea6724 303 '25-vti6-tunnel.netdev',
6a97a864
YW
304 '25-vti-tunnel-local-any.netdev',
305 '25-vti-tunnel-remote-any.netdev',
09ea6724
YW
306 '25-vti-tunnel.netdev',
307 '25-vxlan.netdev',
da44fb8a
YW
308 '25-wireguard-23-peers.netdev',
309 '25-wireguard-23-peers.network',
9e5d79e7 310 '25-wireguard-preshared-key.txt',
39bcff3b 311 '25-wireguard-private-key.txt',
09ea6724 312 '25-wireguard.netdev',
5a0bd90b 313 '25-wireguard.network',
09ea6724 314 '6rd.network',
6730a1f3 315 'erspan.network',
09ea6724
YW
316 'gre.network',
317 'gretap.network',
318 'gretun.network',
319 'ip6gretap.network',
6a97a864 320 'ip6gretun.network',
09ea6724
YW
321 'ip6tnl.network',
322 'ipip.network',
323 'ipvlan.network',
324 'isatap.network',
325 'macvlan.network',
326 'macvtap.network',
327 'sit.network',
328 'vti6.network',
329 'vti.network',
330 'vxlan.network']
1f0e3109
SS
331
332 def setUp(self):
333 self.link_remove(self.links)
334
335 def tearDown(self):
336 self.link_remove(self.links)
337 self.remove_unit_from_networkd_path(self.units)
338
d80734f7 339 def test_dropin(self):
753e0a24 340 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
d80734f7
YW
341 self.start_networkd()
342
343 self.assertTrue(self.link_exits('dropin-test'))
344
753e0a24
YW
345 # This also tests NetDev.Name= conflict and basic networkctl functionalities
346
d80734f7
YW
347 output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
348 print(output)
349 self.assertRegex(output, '00:50:56:c0:00:28')
350
308ae89c
YW
351 output = subprocess.check_output(['networkctl', 'list']).rstrip().decode('utf-8')
352 self.assertRegex(output, '1 lo ')
353 self.assertRegex(output, 'dropin-test')
354
355 output = subprocess.check_output(['networkctl', 'list', 'dropin-test']).rstrip().decode('utf-8')
356 self.assertNotRegex(output, '1 lo ')
357 self.assertRegex(output, 'dropin-test')
358
359 output = subprocess.check_output(['networkctl', 'list', 'dropin-*']).rstrip().decode('utf-8')
360 self.assertNotRegex(output, '1 lo ')
361 self.assertRegex(output, 'dropin-test')
362
96fb7dc3 363 output = subprocess.check_output(['networkctl', 'status', 'dropin-*']).rstrip().decode('utf-8')
fde66c21 364 self.assertNotRegex(output, '1: lo ')
96fb7dc3 365 self.assertRegex(output, 'dropin-test')
232152bc
YW
366
367 ret = subprocess.run(['ethtool', '--driver', 'dropin-test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
368 print(ret.stdout.rstrip().decode('utf-8'))
369 if ret.returncode == 0 and re.search('driver: dummy', ret.stdout.rstrip().decode('utf-8')) != None:
370 self.assertRegex(output, 'Driver: dummy')
371 else:
372 print('ethtool does not support driver field at least for dummy interfaces, skipping test for Driver field of networkctl.')
96fb7dc3 373
03db80b2
YW
374 def test_wait_online_any(self):
375 self.copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
376 self.start_networkd(0)
377
378 self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
379 self.assertTrue(self.link_exits('bridge99'))
380 self.assertTrue(self.link_exits('test1'))
381
382 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
383 print(output)
384 self.assertRegex(output, 'State: (?:off|no-carrier) \(configuring\)')
385
386 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
387 print(output)
388 self.assertRegex(output, 'State: degraded \(configured\)')
389
1f0e3109
SS
390 def test_bridge(self):
391 self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
392 self.start_networkd()
393
394 self.assertTrue(self.link_exits('bridge99'))
395
396 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'hello_time'))
397 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'max_age'))
398 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','forward_delay'))
399 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','ageing_time'))
400 self.assertEqual('9', self.read_link_attr('bridge99', 'bridge','priority'))
401 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_querier'))
402 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_snooping'))
403 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','stp_state'))
404
405 def test_bond(self):
406 self.copy_unit_to_networkd_unit_path('25-bond.netdev')
407 self.start_networkd()
408
409 self.assertTrue(self.link_exits('bond99'))
410
99f68ef0
TJ
411 self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode'))
412 self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
413 self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon'))
414 self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate'))
415 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay'))
416 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay'))
417 self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp'))
418 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links'))
419 self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
420 self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
421 self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
1f0e3109 422
fde60a42
SS
423 def test_bond_balanced_tlb(self):
424 self.copy_unit_to_networkd_unit_path('25-bond-balanced-tlb.netdev')
425 self.start_networkd()
426
427 self.assertTrue(self.link_exits('bond99'))
428
429 self.assertEqual('balance-tlb 5', self.read_link_attr('bond99', 'bonding', 'mode'))
430 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
431
1f0e3109 432 def test_vlan(self):
7f45d738
YW
433 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
434 '21-vlan.network', '21-vlan-test1.network')
1f0e3109
SS
435 self.start_networkd()
436
72b7f1b9 437 self.assertTrue(self.link_exits('test1'))
1f0e3109
SS
438 self.assertTrue(self.link_exits('vlan99'))
439
72b7f1b9
YW
440 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
441 print(output)
442 self.assertTrue(output, ' mtu 2004 ')
443
1f0e3109 444 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
14ecd604 445 print(output)
72b7f1b9 446 self.assertTrue(output, ' mtu 2000 ')
1f0e3109
SS
447 self.assertTrue(output, 'REORDER_HDR')
448 self.assertTrue(output, 'LOOSE_BINDING')
449 self.assertTrue(output, 'GVRP')
450 self.assertTrue(output, 'MVRP')
72b7f1b9 451 self.assertTrue(output, ' id 99 ')
1f0e3109 452
7f45d738
YW
453 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
454 print(output)
455 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
456 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
457
458 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'vlan99']).rstrip().decode('utf-8')
459 print(output)
460 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
461
1f0e3109
SS
462 def test_macvtap(self):
463 self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
1f0e3109
SS
464 self.start_networkd()
465
466 self.assertTrue(self.link_exits('macvtap99'))
467
468 def test_macvlan(self):
469 self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
1f0e3109
SS
470 self.start_networkd()
471
72b7f1b9 472 self.assertTrue(self.link_exits('test1'))
1f0e3109
SS
473 self.assertTrue(self.link_exits('macvlan99'))
474
72b7f1b9
YW
475 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
476 print(output)
477 self.assertTrue(output, ' mtu 2000 ')
478
479 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macvlan99']).rstrip().decode('utf-8')
480 print(output)
481 self.assertTrue(output, ' mtu 2000 ')
482
7a0a37b2 483 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109
SS
484 def test_ipvlan(self):
485 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
1f0e3109
SS
486 self.start_networkd()
487
488 self.assertTrue(self.link_exits('ipvlan99'))
489
490 def test_veth(self):
491 self.copy_unit_to_networkd_unit_path('25-veth.netdev')
1f0e3109
SS
492 self.start_networkd()
493
494 self.assertTrue(self.link_exits('veth99'))
495
496 def test_dummy(self):
497 self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
1f0e3109
SS
498 self.start_networkd()
499
500 self.assertTrue(self.link_exits('test1'))
501
502 def test_tun(self):
503 self.copy_unit_to_networkd_unit_path('25-tun.netdev')
1f0e3109
SS
504 self.start_networkd()
505
506 self.assertTrue(self.link_exits('tun99'))
507
508 def test_tap(self):
509 self.copy_unit_to_networkd_unit_path('25-tap.netdev')
1f0e3109
SS
510 self.start_networkd()
511
512 self.assertTrue(self.link_exits('tap99'))
513
7a0a37b2 514 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109
SS
515 def test_vrf(self):
516 self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
1f0e3109
SS
517 self.start_networkd()
518
519 self.assertTrue(self.link_exits('vrf99'))
520
7a0a37b2 521 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109
SS
522 def test_vcan(self):
523 self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
1f0e3109
SS
524 self.start_networkd()
525
526 self.assertTrue(self.link_exits('vcan99'))
527
7a3bc5a8
EV
528 @expectedFailureIfModuleIsNotAvailable('wireguard')
529 def test_wireguard(self):
5a0bd90b
YW
530 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
531 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
9e5d79e7 532 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
5a0bd90b
YW
533 self.start_networkd(0)
534 self.wait_online(['wg99:carrier', 'wg98:routable'])
535
536 self.assertTrue(self.link_exits('wg99'))
537 self.assertTrue(self.link_exits('wg98'))
7a3bc5a8
EV
538
539 if shutil.which('wg'):
540 subprocess.call('wg')
5a0bd90b 541
16ab043b
YW
542 output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
543 self.assertTrue(output, '51820')
544 output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
545 self.assertTrue(output, '0x4d2')
546 output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
547 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
5a0bd90b 548 self.assertTrue(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
16ab043b
YW
549 output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
550 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20')
551 output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
552 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820')
39bcff3b
YW
553 output = subprocess.check_output(['wg', 'show', 'wg99', 'private-key']).rstrip().decode('utf-8')
554 self.assertTrue(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong=')
9e5d79e7
YW
555 output = subprocess.check_output(['wg', 'show', 'wg99', 'preshared-keys']).rstrip().decode('utf-8')
556 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
557 self.assertTrue(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
7a3bc5a8 558
39bcff3b
YW
559 output = subprocess.check_output(['wg', 'show', 'wg98', 'private-key']).rstrip().decode('utf-8')
560 self.assertTrue(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr+WHtZLZ90FU=')
da44fb8a 561
1f0e3109
SS
562 def test_geneve(self):
563 self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
1f0e3109
SS
564 self.start_networkd()
565
566 self.assertTrue(self.link_exits('geneve99'))
567
568 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
14ecd604 569 print(output)
1f0e3109
SS
570 self.assertTrue(output, '192.168.22.1')
571 self.assertTrue(output, '6082')
572 self.assertTrue(output, 'udpcsum')
573 self.assertTrue(output, 'udp6zerocsumrx')
574
575 def test_ipip_tunnel(self):
6a97a864
YW
576 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network',
577 '25-ipip-tunnel-local-any.netdev', '25-ipip-tunnel-remote-any.netdev')
1f0e3109
SS
578 self.start_networkd()
579
580 self.assertTrue(self.link_exits('dummy98'))
581 self.assertTrue(self.link_exits('ipiptun99'))
6a97a864
YW
582 self.assertTrue(self.link_exits('ipiptun98'))
583 self.assertTrue(self.link_exits('ipiptun97'))
584
585 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun99']).rstrip().decode('utf-8')
586 print(output)
587 self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local 192.168.223.238 dev dummy98')
588 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun98']).rstrip().decode('utf-8')
589 print(output)
590 self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local any dev dummy98')
591 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun97']).rstrip().decode('utf-8')
592 print(output)
593 self.assertRegex(output, 'ipip (?:ipip |)remote any local 192.168.223.238 dev dummy98')
1f0e3109
SS
594
595 def test_gre_tunnel(self):
6a97a864
YW
596 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network',
597 '25-gre-tunnel-local-any.netdev', '25-gre-tunnel-remote-any.netdev')
1f0e3109
SS
598 self.start_networkd()
599
600 self.assertTrue(self.link_exits('dummy98'))
601 self.assertTrue(self.link_exits('gretun99'))
6a97a864
YW
602 self.assertTrue(self.link_exits('gretun98'))
603 self.assertTrue(self.link_exits('gretun97'))
604
605 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun99']).rstrip().decode('utf-8')
606 print(output)
607 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
608 self.assertRegex(output, 'ikey 1.2.3.103')
609 self.assertRegex(output, 'okey 1.2.4.103')
610 self.assertRegex(output, 'iseq')
611 self.assertRegex(output, 'oseq')
6a97a864
YW
612 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun98']).rstrip().decode('utf-8')
613 print(output)
614 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
615 self.assertRegex(output, 'ikey 0.0.0.104')
616 self.assertRegex(output, 'okey 0.0.0.104')
617 self.assertNotRegex(output, 'iseq')
618 self.assertNotRegex(output, 'oseq')
6a97a864
YW
619 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun97']).rstrip().decode('utf-8')
620 print(output)
621 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
38f4bb44
YW
622 self.assertRegex(output, 'ikey 0.0.0.105')
623 self.assertRegex(output, 'okey 0.0.0.105')
624 self.assertNotRegex(output, 'iseq')
625 self.assertNotRegex(output, 'oseq')
6a97a864
YW
626
627 def test_ip6gre_tunnel(self):
628 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretun.network',
629 '25-ip6gre-tunnel-local-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
630 self.start_networkd()
631
632 self.assertTrue(self.link_exits('dummy98'))
633 self.assertTrue(self.link_exits('ip6gretun99'))
634 self.assertTrue(self.link_exits('ip6gretun98'))
635 self.assertTrue(self.link_exits('ip6gretun97'))
636
637 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun99']).rstrip().decode('utf-8')
638 print(output)
639 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
640 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun98']).rstrip().decode('utf-8')
641 print(output)
642 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
643 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun97']).rstrip().decode('utf-8')
644 print(output)
645 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
646
647 def test_gretap_tunnel(self):
6a97a864
YW
648 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network',
649 '25-gretap-tunnel-local-any.netdev')
1f0e3109
SS
650 self.start_networkd()
651
652 self.assertTrue(self.link_exits('dummy98'))
653 self.assertTrue(self.link_exits('gretap99'))
6a97a864
YW
654 self.assertTrue(self.link_exits('gretap98'))
655
656 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap99']).rstrip().decode('utf-8')
657 print(output)
658 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
659 self.assertRegex(output, 'ikey 0.0.0.106')
660 self.assertRegex(output, 'okey 0.0.0.106')
661 self.assertRegex(output, 'iseq')
662 self.assertRegex(output, 'oseq')
6a97a864
YW
663 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap98']).rstrip().decode('utf-8')
664 print(output)
665 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
666 self.assertRegex(output, 'ikey 0.0.0.107')
667 self.assertRegex(output, 'okey 0.0.0.107')
668 self.assertRegex(output, 'iseq')
669 self.assertRegex(output, 'oseq')
1f0e3109
SS
670
671 def test_ip6gretap_tunnel(self):
6a97a864
YW
672 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gretap-tunnel.netdev', 'ip6gretap.network',
673 '25-ip6gretap-tunnel-local-any.netdev')
1f0e3109
SS
674 self.start_networkd()
675
676 self.assertTrue(self.link_exits('dummy98'))
677 self.assertTrue(self.link_exits('ip6gretap99'))
6a97a864
YW
678 self.assertTrue(self.link_exits('ip6gretap98'))
679
680 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap99']).rstrip().decode('utf-8')
681 print(output)
682 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
683 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap98']).rstrip().decode('utf-8')
684 print(output)
685 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1f0e3109
SS
686
687 def test_vti_tunnel(self):
6a97a864
YW
688 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network',
689 '25-vti-tunnel-local-any.netdev', '25-vti-tunnel-remote-any.netdev')
1f0e3109
SS
690 self.start_networkd()
691
692 self.assertTrue(self.link_exits('dummy98'))
693 self.assertTrue(self.link_exits('vtitun99'))
6a97a864
YW
694 self.assertTrue(self.link_exits('vtitun98'))
695 self.assertTrue(self.link_exits('vtitun97'))
696
697 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun99']).rstrip().decode('utf-8')
698 print(output)
699 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
700 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun98']).rstrip().decode('utf-8')
701 print(output)
702 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
703 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun97']).rstrip().decode('utf-8')
704 print(output)
705 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
1f0e3109
SS
706
707 def test_vti6_tunnel(self):
6a97a864
YW
708 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network',
709 '25-vti6-tunnel-local-any.netdev', '25-vti6-tunnel-remote-any.netdev')
1f0e3109
SS
710 self.start_networkd()
711
712 self.assertTrue(self.link_exits('dummy98'))
713 self.assertTrue(self.link_exits('vti6tun99'))
6a97a864
YW
714 self.assertTrue(self.link_exits('vti6tun98'))
715 self.assertTrue(self.link_exits('vti6tun97'))
716
717 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun99']).rstrip().decode('utf-8')
718 print(output)
719 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
720 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun98']).rstrip().decode('utf-8')
721 print(output)
722 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
723 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun97']).rstrip().decode('utf-8')
724 print(output)
725 self.assertRegex(output, 'vti6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
726
727 def test_ip6tnl_tunnel(self):
6a97a864
YW
728 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network',
729 '25-ip6tnl-tunnel-local-any.netdev', '25-ip6tnl-tunnel-remote-any.netdev')
1f0e3109
SS
730 self.start_networkd()
731
732 self.assertTrue(self.link_exits('dummy98'))
733 self.assertTrue(self.link_exits('ip6tnl99'))
6a97a864
YW
734 self.assertTrue(self.link_exits('ip6tnl98'))
735 self.assertTrue(self.link_exits('ip6tnl97'))
736
737 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl99']).rstrip().decode('utf-8')
738 print(output)
739 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
740 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl98']).rstrip().decode('utf-8')
741 print(output)
742 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
743 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl97']).rstrip().decode('utf-8')
744 print(output)
745 self.assertRegex(output, 'ip6tnl ip6ip6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
746
747 def test_sit_tunnel(self):
6a97a864
YW
748 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network',
749 '25-sit-tunnel-local-any.netdev',
750 '25-sit-tunnel-remote-any.netdev')
1f0e3109
SS
751 self.start_networkd()
752
753 self.assertTrue(self.link_exits('dummy98'))
754 self.assertTrue(self.link_exits('sittun99'))
6a97a864
YW
755 self.assertTrue(self.link_exits('sittun98'))
756 self.assertTrue(self.link_exits('sittun97'))
757
758 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99']).rstrip().decode('utf-8')
759 print(output)
760 self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local 10.65.223.238 dev dummy98")
761 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun98']).rstrip().decode('utf-8')
762 print(output)
763 self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local any dev dummy98")
764 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun97']).rstrip().decode('utf-8')
765 print(output)
766 self.assertRegex(output, "sit (?:ip6ip |)remote any local 10.65.223.238 dev dummy98")
1f0e3109 767
d0e728b6
SS
768 def test_isatap_tunnel(self):
769 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
770 self.start_networkd()
771
772 self.assertTrue(self.link_exits('dummy98'))
773 self.assertTrue(self.link_exits('isataptun99'))
e40a58b5 774
d0e728b6 775 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
14ecd604 776 print(output)
d0e728b6
SS
777 self.assertRegex(output, "isatap ")
778
d29dc4f1
DA
779 def test_6rd_tunnel(self):
780 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
781 self.start_networkd()
782
783 self.assertTrue(self.link_exits('dummy98'))
784 self.assertTrue(self.link_exits('sittun99'))
785
6a97a864
YW
786 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99']).rstrip().decode('utf-8')
787 print(output)
788 self.assertRegex(output, '6rd-prefix 2602::/24')
789
7bea7f9b 790 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b 791 def test_erspan_tunnel(self):
6730a1f3
YW
792 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
793 '25-erspan-tunnel.netdev', '25-erspan-tunnel-local-any.netdev')
2266864b
SS
794 self.start_networkd()
795
6730a1f3 796 self.assertTrue(self.link_exits('dummy98'))
6a97a864
YW
797 self.assertTrue(self.link_exits('erspan99'))
798 self.assertTrue(self.link_exits('erspan98'))
2266864b 799
6a97a864
YW
800 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan99']).rstrip().decode('utf-8')
801 print(output)
802 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
38f4bb44
YW
803 self.assertRegex(output, 'ikey 0.0.0.101')
804 self.assertRegex(output, 'okey 0.0.0.101')
805 self.assertRegex(output, 'iseq')
806 self.assertRegex(output, 'oseq')
6a97a864 807 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan98']).rstrip().decode('utf-8')
2266864b 808 print(output)
6a97a864
YW
809 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
810 self.assertRegex(output, '102')
38f4bb44
YW
811 self.assertRegex(output, 'ikey 0.0.0.102')
812 self.assertRegex(output, 'okey 0.0.0.102')
813 self.assertRegex(output, 'iseq')
814 self.assertRegex(output, 'oseq')
2266864b 815
1f0e3109
SS
816 def test_tunnel_independent(self):
817 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
1f0e3109 818 self.start_networkd()
e40a58b5 819
1f0e3109
SS
820 self.assertTrue(self.link_exits('ipiptun99'))
821
4b6a6d1e
YW
822 @expectedFailureIfModuleIsNotAvailable('fou')
823 def test_fou(self):
824 # The following redundant check is necessary for CentOS CI.
825 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
826 self.assertTrue(is_module_available('fou'))
827
828 self.copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
829 '25-fou-ipip.netdev', '25-fou-sit.netdev',
830 '25-fou-gre.netdev', '25-fou-gretap.netdev')
831 self.start_networkd()
832
833 self.assertTrue(self.link_exits('ipiptun96'))
834 self.assertTrue(self.link_exits('sittun96'))
835 self.assertTrue(self.link_exits('gretun96'))
836 self.assertTrue(self.link_exits('gretap96'))
837
838 output = subprocess.check_output(['ip', 'fou', 'show']).rstrip().decode('utf-8')
839 print(output)
840 self.assertRegex(output, 'port 55555 ipproto 4')
841 self.assertRegex(output, 'port 55556 ipproto 47')
842
843 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun96']).rstrip().decode('utf-8')
844 print(output)
845 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
846 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun96']).rstrip().decode('utf-8')
847 print(output)
848 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
849 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun96']).rstrip().decode('utf-8')
850 print(output)
851 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
852 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap96']).rstrip().decode('utf-8')
853 print(output)
854 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
855
856 subprocess.call(['ip', 'fou', 'del', 'port', '55555'])
857 subprocess.call(['ip', 'fou', 'del', 'port', '55556'])
858
1f0e3109 859 def test_vxlan(self):
cff83db9 860 self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network', '11-dummy.netdev')
1f0e3109
SS
861 self.start_networkd()
862
863 self.assertTrue(self.link_exits('vxlan99'))
864
865 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
14ecd604 866 print(output)
1f0e3109
SS
867 self.assertRegex(output, "999")
868 self.assertRegex(output, '5555')
869 self.assertRegex(output, 'l2miss')
870 self.assertRegex(output, 'l3miss')
871 self.assertRegex(output, 'udpcsum')
872 self.assertRegex(output, 'udp6zerocsumtx')
873 self.assertRegex(output, 'udp6zerocsumrx')
874 self.assertRegex(output, 'remcsumtx')
875 self.assertRegex(output, 'remcsumrx')
876 self.assertRegex(output, 'gbp')
877
cff83db9
YW
878class NetworkdL2TPTests(unittest.TestCase, Utilities):
879
880 links =[
881 'l2tp-ses1',
882 'l2tp-ses2',
883 'l2tp-ses3',
884 'l2tp-ses4',
885 'test1']
886
887 units = [
888 '11-dummy.netdev',
889 '25-l2tp-dummy.network',
890 '25-l2tp-ip.netdev',
891 '25-l2tp-udp.netdev']
892
893 l2tp_tunnel_ids = [ '10' ]
894
895 def setUp(self):
896 self.l2tp_tunnel_remove(self.l2tp_tunnel_ids)
897 self.link_remove(self.links)
898
899 def tearDown(self):
900 self.l2tp_tunnel_remove(self.l2tp_tunnel_ids)
901 self.link_remove(self.links)
902 self.remove_unit_from_networkd_path(self.units)
903
904 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
905 def test_l2tp_udp(self):
906 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', '25-l2tp-udp.netdev')
907 self.start_networkd()
908
909 self.assertTrue(self.link_exits('test1'))
910 self.assertTrue(self.link_exits('l2tp-ses1'))
911 self.assertTrue(self.link_exits('l2tp-ses2'))
912
913 output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10']).rstrip().decode('utf-8')
914 print(output)
915 self.assertRegex(output, "Tunnel 10, encap UDP")
916 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
917 self.assertRegex(output, "Peer tunnel 11")
918 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
919 self.assertRegex(output, "UDP checksum: enabled")
920
921 output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '15']).rstrip().decode('utf-8')
922 print(output)
923 self.assertRegex(output, "Session 15 in tunnel 10")
924 self.assertRegex(output, "Peer session 16, tunnel 11")
925 self.assertRegex(output, "interface name: l2tp-ses1")
926
927 output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '17']).rstrip().decode('utf-8')
928 print(output)
929 self.assertRegex(output, "Session 17 in tunnel 10")
930 self.assertRegex(output, "Peer session 18, tunnel 11")
931 self.assertRegex(output, "interface name: l2tp-ses2")
932
933 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
934 def test_l2tp_ip(self):
935 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', '25-l2tp-ip.netdev')
936 self.start_networkd()
937
938 self.assertTrue(self.link_exits('test1'))
939 self.assertTrue(self.link_exits('l2tp-ses3'))
940 self.assertTrue(self.link_exits('l2tp-ses4'))
941
942 output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10']).rstrip().decode('utf-8')
943 print(output)
944 self.assertRegex(output, "Tunnel 10, encap IP")
945 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
946 self.assertRegex(output, "Peer tunnel 12")
947
948 output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '25']).rstrip().decode('utf-8')
949 print(output)
950 self.assertRegex(output, "Session 25 in tunnel 10")
951 self.assertRegex(output, "Peer session 26, tunnel 12")
952 self.assertRegex(output, "interface name: l2tp-ses3")
953
954 output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '27']).rstrip().decode('utf-8')
955 print(output)
956 self.assertRegex(output, "Session 27 in tunnel 10")
957 self.assertRegex(output, "Peer session 28, tunnel 12")
958 self.assertRegex(output, "interface name: l2tp-ses4")
959
1f0e3109 960class NetworkdNetWorkTests(unittest.TestCase, Utilities):
09ea6724
YW
961 links = [
962 'bond199',
963 'dummy98',
cd65d067 964 'dummy99',
09ea6724
YW
965 'test1']
966
967 units = [
968 '11-dummy.netdev',
969 '12-dummy.netdev',
970 '23-active-slave.network',
09ea6724 971 '25-address-link-section.network',
b8102725
YW
972 '25-address-preferred-lifetime-zero-ipv6.network',
973 '25-address-static.network',
cd65d067 974 '25-bind-carrier.network',
09ea6724
YW
975 '25-bond-active-backup-slave.netdev',
976 '25-fibrule-invert.network',
977 '25-fibrule-port-range.network',
978 '25-ipv6-address-label-section.network',
e4a71bf3 979 '25-neighbor-section.network',
05514ae1
YW
980 '25-link-local-addressing-no.network',
981 '25-link-local-addressing-yes.network',
09ea6724 982 '25-link-section-unmanaged.network',
20ca06a6 983 '25-route-ipv6-src.network',
0ef830cf 984 '25-route-static.network',
4da33154 985 '25-sysctl-disable-ipv6.network',
09ea6724
YW
986 '25-sysctl.network',
987 'configure-without-carrier.network',
b677774d 988 'routing-policy-rule-dummy98.network',
b8102725 989 'routing-policy-rule-test1.network']
1f0e3109
SS
990
991 def setUp(self):
992 self.link_remove(self.links)
993
994 def tearDown(self):
995 self.link_remove(self.links)
996 self.remove_unit_from_networkd_path(self.units)
997
b8102725
YW
998 def test_address_static(self):
999 self.copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1000 self.start_networkd(0)
1001
1002 self.wait_online(['dummy98:routable'])
1003
1004 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
1005 print(output)
1006 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1007 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1008 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1009
1010 # invalid sections
1011 self.assertNotRegex(output, '10.10.0.1/16')
1012 self.assertNotRegex(output, '10.10.0.2/16')
1013
1014 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '32']).rstrip().decode('utf-8')
1015 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1016
1017 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '33']).rstrip().decode('utf-8')
1018 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1019
1020 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '34']).rstrip().decode('utf-8')
1021 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1022
1023 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '35']).rstrip().decode('utf-8')
1024 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1025
1026 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
1027 print(output)
1028 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1029 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1030 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1031 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1032 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1033 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1034
1035 def test_address_preferred_lifetime_zero_ipv6(self):
1036 self.copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero-ipv6.network', '12-dummy.netdev')
1f0e3109
SS
1037 self.start_networkd()
1038
1039 self.assertTrue(self.link_exits('dummy98'))
e40a58b5 1040
1f0e3109
SS
1041 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1042 print(output)
b8102725
YW
1043 self.assertRegex(output, 'State: routable \(configuring\)')
1044
1045 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1046 print(output)
1047 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1048 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1f0e3109
SS
1049
1050 def test_configure_without_carrier(self):
1051 self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1052 self.start_networkd()
1053
1054 self.assertTrue(self.link_exits('test1'))
e40a58b5 1055
1f0e3109
SS
1056 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1057 print(output)
1058 self.assertRegex(output, '192.168.0.15')
1059 self.assertRegex(output, '192.168.0.1')
1060 self.assertRegex(output, 'routable')
1061
1f0e3109 1062 def test_routing_policy_rule(self):
b677774d 1063 self.copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
703bc7a2
YW
1064
1065 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
1066
1f0e3109
SS
1067 self.start_networkd()
1068
1069 self.assertTrue(self.link_exits('test1'))
e40a58b5 1070
1f0e3109
SS
1071 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
1072 print(output)
1073 self.assertRegex(output, '111')
1074 self.assertRegex(output, 'from 192.168.100.18')
f7bdd562 1075 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
1f0e3109
SS
1076 self.assertRegex(output, 'iif test1')
1077 self.assertRegex(output, 'oif test1')
1078 self.assertRegex(output, 'lookup 7')
1079
e4eacdb0
YW
1080 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
1081
b677774d
YW
1082 def test_routing_policy_rule_issue_11280(self):
1083 self.copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1084 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1085
1086 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
1087 subprocess.call(['ip', 'rule', 'del', 'table', '8'])
1088
1089 for trial in range(3):
1090 # Remove state files only first time
5aa58329 1091 self.start_networkd(remove_state_files=(trial == 0))
b677774d
YW
1092
1093 self.assertTrue(self.link_exits('test1'))
1094 self.assertTrue(self.link_exits('dummy98'))
1095
1096 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '7']).rstrip().decode('utf-8')
1097 print(output)
1098 self.assertRegex(output, '111: from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
1099
1100 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '8']).rstrip().decode('utf-8')
1101 print(output)
1102 self.assertRegex(output, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1103
1104 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
1105 subprocess.call(['ip', 'rule', 'del', 'table', '8'])
1106
d586a2c3 1107 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0
SS
1108 def test_routing_policy_rule_port_range(self):
1109 self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
703bc7a2
YW
1110
1111 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
1112
926062f0
SS
1113 self.start_networkd()
1114
1115 self.assertTrue(self.link_exits('test1'))
e40a58b5 1116
926062f0
SS
1117 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
1118 print(output)
1119 self.assertRegex(output, '111')
1120 self.assertRegex(output, 'from 192.168.100.18')
1121 self.assertRegex(output, '1123-1150')
1122 self.assertRegex(output, '3224-3290')
1123 self.assertRegex(output, 'tcp')
1124 self.assertRegex(output, 'lookup 7')
1f0e3109 1125
e4eacdb0
YW
1126 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
1127
d586a2c3 1128 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd
SS
1129 def test_routing_policy_rule_invert(self):
1130 self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
703bc7a2
YW
1131
1132 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
1133
efecf9cd
SS
1134 self.start_networkd()
1135
1136 self.assertTrue(self.link_exits('test1'))
e40a58b5 1137
efecf9cd
SS
1138 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
1139 print(output)
efecf9cd
SS
1140 self.assertRegex(output, '111')
1141 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1142 self.assertRegex(output, 'tcp')
1143 self.assertRegex(output, 'lookup 7')
1144
e4eacdb0
YW
1145 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
1146
0ef830cf
YW
1147 def test_route_static(self):
1148 self.copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1149 self.start_networkd(0)
0d34228f 1150
0ef830cf 1151 self.wait_online(['dummy98:routable'])
0d34228f
SS
1152
1153 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
1154 print(output)
0ef830cf
YW
1155 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1156 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1f0e3109 1157
0ef830cf
YW
1158 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
1159 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1f0e3109 1160
0ef830cf 1161 output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
1f0e3109 1162 print(output)
0ef830cf
YW
1163 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1164 self.assertRegex(output, '149.10.124.64 proto static scope link')
1165 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1166 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
1f0e3109 1167
0ef830cf
YW
1168 output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
1169 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1170 self.assertRegex(output, 'default via 149.10.124.64 proto static')
1f0e3109 1171
0ef830cf 1172 output = subprocess.check_output(['ip', 'route', 'show', 'type', 'blackhole']).rstrip().decode('utf-8')
1f0e3109 1173 print(output)
0ef830cf 1174 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
f5050e48 1175
0ef830cf 1176 output = subprocess.check_output(['ip', 'route', 'show', 'type', 'unreachable']).rstrip().decode('utf-8')
f5050e48 1177 print(output)
0ef830cf 1178 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
f5050e48 1179
0ef830cf 1180 output = subprocess.check_output(['ip', 'route', 'show', 'type', 'prohibit']).rstrip().decode('utf-8')
f5050e48 1181 print(output)
0ef830cf 1182 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
f5050e48 1183
0ef830cf
YW
1184 subprocess.call(['ip', 'route', 'del', 'blackhole', '202.54.1.2'])
1185 subprocess.call(['ip', 'route', 'del', 'unreachable', '202.54.1.3'])
1186 subprocess.call(['ip', 'route', 'del', 'prohibit', '202.54.1.4'])
f5050e48 1187
20ca06a6
DA
1188 def test_ip_route_ipv6_src_route(self):
1189 # a dummy device does not make the addresses go through tentative state, so we
1190 # reuse a bond from an earlier test, which does make the addresses go through
1191 # tentative state, and do our test on that
1192 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1193 self.start_networkd()
1194
1195 self.assertTrue(self.link_exits('dummy98'))
1196 self.assertTrue(self.link_exits('bond199'))
1197
1198 output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8')
1199 print(output)
1200 self.assertRegex(output, 'abcd::/16')
1201 self.assertRegex(output, 'src')
1202 self.assertRegex(output, '2001:1234:56:8f63::2')
1203
1f0e3109
SS
1204 def test_ip_link_mac_address(self):
1205 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1206 self.start_networkd()
1207
1208 self.assertTrue(self.link_exits('dummy98'))
1209
1210 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1211 print(output)
1212 self.assertRegex(output, '00:01:02:aa:bb:cc')
1213
1214 def test_ip_link_unmanaged(self):
1215 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
1216 self.start_networkd()
1217
1218 self.assertTrue(self.link_exits('dummy98'))
1219
1220 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1221 print(output)
1222 self.assertRegex(output, 'unmanaged')
1223
1224 def test_ipv6_address_label(self):
1225 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
1226 self.start_networkd()
1227
1228 self.assertTrue(self.link_exits('dummy98'))
1229
1230 output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
1231 print(output)
1232 self.assertRegex(output, '2004:da8:1::/64')
1233
e4a71bf3
WKI
1234 def test_ipv6_neighbor(self):
1235 self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1236 self.start_networkd()
1237
1238 self.assertTrue(self.link_exits('dummy98'))
1239
1240 output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
1241 print(output)
1242 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 1243 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 1244
05514ae1
YW
1245 def test_link_local_addressing(self):
1246 self.copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1247 '25-link-local-addressing-no.network', '12-dummy.netdev')
2dcfcc08
YW
1248 self.start_networkd(0)
1249 self.wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1
YW
1250
1251 self.assertTrue(self.link_exits('test1'))
1252 self.assertTrue(self.link_exits('dummy98'))
1253
05514ae1
YW
1254 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
1255 print(output)
1256 self.assertRegex(output, 'inet .* scope link')
1257 self.assertRegex(output, 'inet6 .* scope link')
1258
1259 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
1260 print(output)
1261 self.assertNotRegex(output, 'inet6* .* scope link')
1262
1263 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1264 print(output)
1265 self.assertRegex(output, 'State: degraded \(configured\)')
1266
1267 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1268 print(output)
1269 self.assertRegex(output, 'State: carrier \(configured\)')
1270
1271 '''
1272 Documentation/networking/ip-sysctl.txt
1273
1274 addr_gen_mode - INTEGER
1275 Defines how link-local and autoconf addresses are generated.
1276
1277 0: generate address based on EUI64 (default)
1278 1: do no generate a link-local address, use EUI64 for addresses generated
1279 from autoconf
1280 2: generate stable privacy addresses, using the secret from
1281 stable_secret (RFC7217)
1282 3: generate stable privacy addresses, using a random secret if unset
1283 '''
1284
1285 test1_addr_gen_mode = ''
1286 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
1287 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
1288 try:
1289 f.readline()
1290 except IOError:
1291 # if stable_secret is unset, then EIO is returned
1292 test1_addr_gen_mode = '0'
1293 else:
1294 test1_addr_gen_mode = '2'
1295 else:
1296 test1_addr_gen_mode = '0'
1297
1298 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
d06f30fc 1299 self.assertEqual(self.read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
05514ae1
YW
1300
1301 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
1302 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1303
1f0e3109
SS
1304 def test_sysctl(self):
1305 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
ba1e0d06
YW
1306 self.start_networkd(0)
1307 self.wait_online(['dummy98:degraded'])
1f0e3109
SS
1308
1309 self.assertTrue(self.link_exits('dummy98'))
1310
1311 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1312 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1313 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1314 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1315 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1316 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1317 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1318
4da33154
YW
1319 def test_sysctl_disable_ipv6(self):
1320 self.copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1321
1322 print('## Disable ipv6')
1323 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=1']), 0)
1324 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=1']), 0)
1325
a15ff207
YW
1326 self.start_networkd(0)
1327 self.wait_online(['dummy98:routable'])
4da33154
YW
1328
1329 self.assertTrue(self.link_exits('dummy98'))
1330
1331 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1332 print(output)
1333 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1334 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1335 print(output)
1336 self.assertEqual(output, '')
1337 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1338 self.assertRegex(output, 'State: routable \(configured\)')
1339
1340 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1341
1342 print('## Enable ipv6')
1343 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=0']), 0)
1344 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=0']), 0)
1345
a15ff207
YW
1346 self.start_networkd(0)
1347 self.wait_online(['dummy98:routable'])
4da33154
YW
1348
1349 self.assertTrue(self.link_exits('dummy98'))
1350
1351 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1352 print(output)
1353 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1354 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1355 print(output)
1356 self.assertRegex(output, 'inet6 .* scope link')
1357 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1358 self.assertRegex(output, 'State: routable \(configured\)')
1359
cd65d067
YW
1360 def test_bind_carrier(self):
1361 self.copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1362 self.start_networkd()
1363
1364 self.assertTrue(self.link_exits('test1'))
1365
cd65d067
YW
1366 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1367 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
b117044c 1368 time.sleep(2)
cd65d067
YW
1369 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1370 print(output)
1371 self.assertRegex(output, 'UP,LOWER_UP')
1372 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1373 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1374 self.assertRegex(output, 'State: routable \(configured\)')
1375
1376 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy99', 'type', 'dummy']), 0)
1377 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy99', 'up']), 0)
b117044c 1378 time.sleep(2)
cd65d067
YW
1379 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1380 print(output)
1381 self.assertRegex(output, 'UP,LOWER_UP')
1382 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1383 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1384 self.assertRegex(output, 'State: routable \(configured\)')
1385
1386 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
b117044c 1387 time.sleep(2)
cd65d067
YW
1388 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1389 print(output)
1390 self.assertRegex(output, 'UP,LOWER_UP')
1391 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1392 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1393 self.assertRegex(output, 'State: routable \(configured\)')
1394
1395 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy99']), 0)
b117044c 1396 time.sleep(2)
cd65d067
YW
1397 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1398 print(output)
1399 self.assertNotRegex(output, 'UP,LOWER_UP')
1400 self.assertRegex(output, 'DOWN')
1401 self.assertNotRegex(output, '192.168.10')
1402 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1403 self.assertRegex(output, 'State: off \(configured\)')
1404
1405 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1406 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
b117044c 1407 time.sleep(2)
cd65d067
YW
1408 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1409 print(output)
1410 self.assertRegex(output, 'UP,LOWER_UP')
1411 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1412 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1413 self.assertRegex(output, 'State: routable \(configured\)')
1414
c3a8853f
YW
1415class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
1416 links = [
c2990ec3 1417 'bond199',
c3a8853f 1418 'bond99',
cc3e488c
YW
1419 'dummy98',
1420 'test1']
c3a8853f
YW
1421
1422 units = [
cc3e488c
YW
1423 '11-dummy.netdev',
1424 '12-dummy.netdev',
c2990ec3
YW
1425 '23-active-slave.network',
1426 '23-bond199.network',
1427 '23-primary-slave.network',
1428 '23-test1-bond199.network',
1429 '25-bond-active-backup-slave.netdev',
c3a8853f 1430 '25-bond.netdev',
c3a8853f 1431 'bond99.network',
cc3e488c 1432 'bond-slave.network']
c3a8853f
YW
1433
1434 def setUp(self):
1435 self.link_remove(self.links)
1436
1437 def tearDown(self):
1438 self.link_remove(self.links)
1439 self.remove_unit_from_networkd_path(self.units)
1440
c2990ec3
YW
1441 def test_bond_active_slave(self):
1442 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1443 self.start_networkd()
1444
1445 self.assertTrue(self.link_exits('dummy98'))
1446 self.assertTrue(self.link_exits('bond199'))
1447
1448 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
1449 print(output)
1450 self.assertRegex(output, 'active_slave dummy98')
1451
1452 def test_bond_primary_slave(self):
1453 self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
1454 self.start_networkd()
1455
1456 self.assertTrue(self.link_exits('test1'))
1457 self.assertTrue(self.link_exits('bond199'))
1458
1459 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
1460 print(output)
1461 self.assertRegex(output, 'primary test1')
1462
cc3e488c
YW
1463 def test_bond_operstate(self):
1464 self.copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
1465 'bond99.network','bond-slave.network')
c3a8853f
YW
1466 self.start_networkd()
1467
1468 self.assertTrue(self.link_exits('bond99'))
cc3e488c
YW
1469 self.assertTrue(self.link_exits('dummy98'))
1470 self.assertTrue(self.link_exits('test1'))
c3a8853f 1471
cc3e488c 1472 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
c3a8853f 1473 print(output)
cc3e488c 1474 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 1475
cc3e488c 1476 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
c3a8853f
YW
1477 print(output)
1478 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1479
1480 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond99']).rstrip().decode('utf-8')
1481 print(output)
1482 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
1483
cc3e488c 1484 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
c3a8853f 1485 print(output)
cc3e488c 1486 self.assertRegex(output, 'State: enslaved \(configured\)')
c3a8853f 1487
cc3e488c 1488 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
c3a8853f
YW
1489 print(output)
1490 self.assertRegex(output, 'State: enslaved \(configured\)')
1491
1492 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1493 print(output)
1494 self.assertRegex(output, 'State: routable \(configured\)')
1495
cc3e488c 1496 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
c3a8853f
YW
1497 time.sleep(2)
1498
cc3e488c 1499 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
c3a8853f
YW
1500 print(output)
1501 self.assertRegex(output, 'State: off \(configured\)')
1502
cc3e488c
YW
1503 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1504 print(output)
1505 self.assertRegex(output, 'State: enslaved \(configured\)')
1506
c3a8853f
YW
1507 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1508 print(output)
c9cc0383 1509 self.assertRegex(output, 'State: degraded-carrier \(configured\)')
c3a8853f 1510
cc3e488c 1511 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
c3a8853f
YW
1512 time.sleep(2)
1513
cc3e488c
YW
1514 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1515 print(output)
1516 self.assertRegex(output, 'State: enslaved \(configured\)')
1517
1518 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
c3a8853f
YW
1519 print(output)
1520 self.assertRegex(output, 'State: enslaved \(configured\)')
1521
1522 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1523 print(output)
1524 self.assertRegex(output, 'State: routable \(configured\)')
1525
cc3e488c
YW
1526 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
1527 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'test1', 'down']), 0)
4ddbf08c 1528 time.sleep(5)
cc3e488c
YW
1529
1530 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1531 print(output)
1532 self.assertRegex(output, 'State: off \(configured\)')
1533
1534 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1535 print(output)
1536 self.assertRegex(output, 'State: off \(configured\)')
1537
1538 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1539 print(output)
4ddbf08c 1540 self.assertRegex(output, 'State: no-carrier \(configured\)')
cc3e488c 1541
14dc0335 1542class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
1543 links = [
1544 'bridge99',
1545 'dummy98',
1546 'test1']
1547
1548 units = [
1549 '11-dummy.netdev',
1550 '12-dummy.netdev',
1551 '26-bridge.netdev',
1552 '26-bridge-slave-interface-1.network',
1553 '26-bridge-slave-interface-2.network',
804b6cd2 1554 'bridge99-ignore-carrier-loss.network',
09ea6724 1555 'bridge99.network']
1f0e3109
SS
1556
1557 def setUp(self):
1558 self.link_remove(self.links)
1559
1560 def tearDown(self):
1561 self.link_remove(self.links)
1562 self.remove_unit_from_networkd_path(self.units)
1563
1564 def test_bridge_property(self):
1565 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1566 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1567 'bridge99.network')
1568 self.start_networkd()
1569
1570 self.assertTrue(self.link_exits('dummy98'))
1571 self.assertTrue(self.link_exits('test1'))
1572 self.assertTrue(self.link_exits('bridge99'))
1573
1574 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
1575 print(output)
1576 self.assertRegex(output, 'master')
1577 self.assertRegex(output, 'bridge')
1578
1579 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1580 print(output)
1581 self.assertRegex(output, 'master')
1582 self.assertRegex(output, 'bridge')
1583
1584 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
1585 print(output)
2be6c5d2 1586 self.assertRegex(output, '192.168.0.15/24')
1f0e3109
SS
1587
1588 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1589 print(output)
4d7ed14f
SS
1590 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
1591 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
1592 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
7f15b714 1593 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
4d7ed14f 1594 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
7f15b714
TJ
1595 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
1596 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
1597 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
4d7ed14f
SS
1598
1599 # CONFIG_BRIDGE_IGMP_SNOOPING=y
1600 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
1601 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1f0e3109 1602
2be6c5d2
YW
1603 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1604 self.assertRegex(output, 'State: enslaved \(configured\)')
1605
1606 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1607 self.assertRegex(output, 'State: enslaved \(configured\)')
1608
1609 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1610 self.assertRegex(output, 'State: routable \(configured\)')
1611
804b6cd2
YW
1612 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1613 time.sleep(1)
1614
2be6c5d2
YW
1615 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
1616 print(output)
1617 self.assertRegex(output, '192.168.0.16/24')
1618
1619 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1620 self.assertRegex(output, 'State: routable \(configured\)')
1621
804b6cd2 1622 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
2be6c5d2
YW
1623 time.sleep(3)
1624
1625 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
c9cc0383 1626 self.assertRegex(output, 'State: degraded-carrier \(configured\)')
2be6c5d2 1627
804b6cd2
YW
1628 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1629 time.sleep(3)
1630
2be6c5d2
YW
1631 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1632 self.assertRegex(output, 'State: no-carrier \(configured\)')
1633
804b6cd2
YW
1634 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1635 print(output)
1636 self.assertRegex(output, 'NO-CARRIER')
1637 self.assertNotRegex(output, '192.168.0.15/24')
1638 self.assertNotRegex(output, '192.168.0.16/24')
1639
1640 def test_bridge_ignore_carrier_loss(self):
1641 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1642 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1643 'bridge99-ignore-carrier-loss.network')
703bc7a2
YW
1644
1645 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1646
804b6cd2
YW
1647 self.start_networkd()
1648
1649 self.assertTrue(self.link_exits('dummy98'))
1650 self.assertTrue(self.link_exits('test1'))
1651 self.assertTrue(self.link_exits('bridge99'))
1652
1653 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1654 time.sleep(1)
1655
1656 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1657 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1658 time.sleep(3)
1659
1660 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1661 print(output)
1662 self.assertRegex(output, 'NO-CARRIER')
1663 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1664 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
1665
6609924c
YW
1666 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1667
1668 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
1669 self.copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
1670 'bridge99-ignore-carrier-loss.network')
703bc7a2
YW
1671
1672 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1673
6609924c
YW
1674 self.start_networkd()
1675
1676 self.assertTrue(self.link_exits('bridge99'))
1677
1678 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1679 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1680 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1681
1682 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1683 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1684 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1685
1686 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1687 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1688 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1689
1690 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1691 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1692
1693 time.sleep(3)
1694
1695 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1696 print(output)
1697 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1698
1699 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1700 self.assertRegex(output, 'State: routable \(configured\)')
1701
1702 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1703 self.assertRegex(output, 'State: enslaved \(configured\)')
1704
1705 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '100']).rstrip().decode('utf-8')
1706 print(output)
1707 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
1708
1709 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1710
1f0e3109
SS
1711class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
1712 links = ['veth99']
1713
09ea6724
YW
1714 units = [
1715 '23-emit-lldp.network',
1716 '24-lldp.network',
1717 '25-veth.netdev']
1f0e3109
SS
1718
1719 def setUp(self):
1720 self.link_remove(self.links)
1721
1722 def tearDown(self):
1723 self.link_remove(self.links)
1724 self.remove_unit_from_networkd_path(self.units)
1725
1726 def test_lldp(self):
1727 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
1728 self.start_networkd()
1729
1730 self.assertTrue(self.link_exits('veth99'))
1731
1732 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
1733 print(output)
1734 self.assertRegex(output, 'veth-peer')
1735 self.assertRegex(output, 'veth99')
1736
1737class NetworkdNetworkRATests(unittest.TestCase, Utilities):
1738 links = ['veth99']
1739
09ea6724
YW
1740 units = [
1741 '25-veth.netdev',
1742 'ipv6-prefix.network',
1743 'ipv6-prefix-veth.network']
1f0e3109
SS
1744
1745 def setUp(self):
1746 self.link_remove(self.links)
1747
1748 def tearDown(self):
1749 self.link_remove(self.links)
1750 self.remove_unit_from_networkd_path(self.units)
1751
1752 def test_ipv6_prefix_delegation(self):
1753 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1754 self.start_networkd()
1755
1756 self.assertTrue(self.link_exits('veth99'))
1757
1758 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1759 print(output)
1760 self.assertRegex(output, '2002:da8:1:0')
1761
1762class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
09ea6724
YW
1763 links = [
1764 'dummy98',
1765 'veth99']
1766
1767 units = [
1768 '12-dummy.netdev',
1769 '24-search-domain.network',
1770 '25-veth.netdev',
1771 'dhcp-client.network',
1772 'dhcp-client-timezone-router.network',
1773 'dhcp-server.network',
1774 'dhcp-server-timezone-router.network']
1f0e3109
SS
1775
1776 def setUp(self):
1777 self.link_remove(self.links)
1778
1779 def tearDown(self):
1780 self.link_remove(self.links)
1781 self.remove_unit_from_networkd_path(self.units)
1782
1783 def test_dhcp_server(self):
1784 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
1785 self.start_networkd()
1786
1787 self.assertTrue(self.link_exits('veth99'))
1788
1f0e3109
SS
1789 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1790 print(output)
1791 self.assertRegex(output, '192.168.5.*')
1792 self.assertRegex(output, 'Gateway: 192.168.5.1')
1793 self.assertRegex(output, 'DNS: 192.168.5.1')
1794 self.assertRegex(output, 'NTP: 192.168.5.1')
1795
1796 def test_domain(self):
f5d191a9 1797 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1f0e3109
SS
1798 self.start_networkd()
1799
1800 self.assertTrue(self.link_exits('dummy98'))
1801
1802 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1803 print(output)
1804 self.assertRegex(output, 'Address: 192.168.42.100')
1805 self.assertRegex(output, 'DNS: 192.168.42.1')
1806 self.assertRegex(output, 'Search Domains: one')
1807
1808 def test_emit_router_timezone(self):
1809 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
1810 self.start_networkd()
1811
1812 self.assertTrue(self.link_exits('veth99'))
1813
1814 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1815 print(output)
1816 self.assertRegex(output, 'Gateway: 192.168.5.*')
1817 self.assertRegex(output, '192.168.5.*')
1818 self.assertRegex(output, 'Europe/Berlin')
1819
1820class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
09ea6724
YW
1821 links = [
1822 'dummy98',
18c613dc
YW
1823 'veth99',
1824 'vrf99']
09ea6724
YW
1825
1826 units = [
1827 '25-veth.netdev',
18c613dc
YW
1828 '25-vrf.netdev',
1829 '25-vrf.network',
09ea6724
YW
1830 'dhcp-client-anonymize.network',
1831 'dhcp-client-critical-connection.network',
af3b1498 1832 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
1833 'dhcp-client-ipv4-dhcp-settings.network',
1834 'dhcp-client-ipv4-only-ipv6-disabled.network',
1835 'dhcp-client-ipv4-only.network',
1836 'dhcp-client-ipv6-only.network',
1837 'dhcp-client-ipv6-rapid-commit.network',
1838 'dhcp-client-listen-port.network',
1839 'dhcp-client-route-metric.network',
1840 'dhcp-client-route-table.network',
18c613dc 1841 'dhcp-client-vrf.network',
3e9d5552 1842 'dhcp-client.network',
09ea6724 1843 'dhcp-server-veth-peer.network',
30d3b54e
YW
1844 'dhcp-v4-server-veth-peer.network',
1845 'static.network']
1f0e3109
SS
1846
1847 def setUp(self):
1848 self.link_remove(self.links)
1849 self.stop_dnsmasq(dnsmasq_pid_file)
1850
1851 def tearDown(self):
1852 self.link_remove(self.links)
1853 self.remove_unit_from_networkd_path(self.units)
1854 self.stop_dnsmasq(dnsmasq_pid_file)
1855 self.remove_lease_file()
1856 self.remove_log_file()
1857
1858 def test_dhcp_client_ipv6_only(self):
f5d191a9 1859 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109
SS
1860 self.start_networkd()
1861
1862 self.assertTrue(self.link_exits('veth99'))
1863
1864 self.start_dnsmasq()
1865
1866 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1867 print(output)
1868 self.assertRegex(output, '2600::')
1869 self.assertNotRegex(output, '192.168.5')
1870
1871 def test_dhcp_client_ipv4_only(self):
f5d191a9 1872 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109
SS
1873 self.start_networkd()
1874
1875 self.assertTrue(self.link_exits('veth99'))
1876
1877 self.start_dnsmasq()
1878
1879 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1880 print(output)
1881 self.assertNotRegex(output, '2600::')
1882 self.assertRegex(output, '192.168.5')
1883
1884 def test_dhcp_client_ipv4_ipv6(self):
1885 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
1886 'dhcp-client-ipv4-only.network')
1887 self.start_networkd()
1888
1889 self.assertTrue(self.link_exits('veth99'))
1890
1891 self.start_dnsmasq()
1892
1893 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1894 print(output)
1895 self.assertRegex(output, '2600::')
1896 self.assertRegex(output, '192.168.5')
1897
1898 def test_dhcp_client_settings(self):
1899 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1900 self.start_networkd()
1901
1902 self.assertTrue(self.link_exits('veth99'))
1903
1904 self.start_dnsmasq()
1905
0ae7a66d 1906 print('## ip address show dev veth99')
1f0e3109
SS
1907 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1908 print(output)
1909 self.assertRegex(output, '12:34:56:78:9a:bc')
1910 self.assertRegex(output, '192.168.5')
1911 self.assertRegex(output, '1492')
1912
0ae7a66d
YW
1913 # issue #8726
1914 print('## ip route show table main dev veth99')
1915 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
1f0e3109 1916 print(output)
0ae7a66d 1917 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 1918
0ae7a66d
YW
1919 print('## ip route show table 211 dev veth99')
1920 output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99']).rstrip().decode('utf-8')
1921 print(output)
1922 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
1923 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
1924 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
1925
1926 print('## dnsmasq log')
131717cb
YW
1927 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
1928 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
1929 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
1930 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1931
1932 def test_dhcp6_client_settings_rapidcommit_true(self):
1933 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1934 self.start_networkd()
1935
1936 self.assertTrue(self.link_exits('veth99'))
1937
1938 self.start_dnsmasq()
1939
1940 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1941 print(output)
1942 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1943 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1944
1945 def test_dhcp6_client_settings_rapidcommit_false(self):
1946 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
1947 self.start_networkd()
1948
1949 self.assertTrue(self.link_exits('veth99'))
1950
1951 self.start_dnsmasq()
1952
1953 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1954 print(output)
1955 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1956 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1957
1958 def test_dhcp_client_settings_anonymize(self):
1959 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
1960 self.start_networkd()
1961
1962 self.assertTrue(self.link_exits('veth99'))
1963
1964 self.start_dnsmasq()
e40a58b5 1965
131717cb
YW
1966 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
1967 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
1968 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1969
1970 def test_dhcp_client_listen_port(self):
1971 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
1f0e3109
SS
1972 self.start_networkd()
1973
1974 self.assertTrue(self.link_exits('veth99'))
1975
b412fce8 1976 self.start_dnsmasq('--dhcp-alternate-port=67,5555')
1f0e3109 1977
b412fce8
YW
1978 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1979 print(output)
1980 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109
SS
1981
1982 def test_dhcp_route_table_id(self):
1983 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
1984 self.start_networkd()
1f0e3109
SS
1985
1986 self.assertTrue(self.link_exits('veth99'))
1987
e40a58b5
YW
1988 self.start_dnsmasq()
1989
1f0e3109
SS
1990 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
1991 print(output)
1f0e3109
SS
1992 self.assertRegex(output, 'veth99 proto dhcp')
1993 self.assertRegex(output, '192.168.5.1')
1994
1995 def test_dhcp_route_metric(self):
1996 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
1997 self.start_networkd()
1f0e3109
SS
1998
1999 self.assertTrue(self.link_exits('veth99'))
2000
e40a58b5
YW
2001 self.start_dnsmasq()
2002
1f0e3109
SS
2003 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
2004 print(output)
1f0e3109
SS
2005 self.assertRegex(output, 'metric 24')
2006
2007 def test_dhcp_route_criticalconnection_true(self):
2008 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
2009 self.start_networkd()
1f0e3109
SS
2010
2011 self.assertTrue(self.link_exits('veth99'))
2012
e40a58b5
YW
2013 self.start_dnsmasq()
2014
1f0e3109
SS
2015 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
2016 print(output)
1f0e3109 2017 self.assertRegex(output, '192.168.5.*')
e40a58b5 2018
1f0e3109
SS
2019 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
2020 self.stop_dnsmasq(dnsmasq_pid_file)
2021
2022 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2023 time.sleep(125)
2024
2025 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
2026 print(output)
2027 self.assertRegex(output, '192.168.5.*')
2028
30d3b54e
YW
2029 def test_dhcp_client_reuse_address_as_static(self):
2030 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2031 self.start_networkd()
2032
2033 self.assertTrue(self.link_exits('veth99'))
2034
2035 self.start_dnsmasq()
2036
2037 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
2038 print(output)
2039 self.assertRegex(output, '192.168.5')
2040 self.assertRegex(output, '2600::')
2041
2042 ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
2043 ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
2044 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
2045 print(static_network)
2046
2047 self.remove_unit_from_networkd_path(['dhcp-client.network'])
2048
2049 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
2050 f.write(static_network)
2051
2052 self.start_networkd()
2053
2054 self.assertTrue(self.link_exits('veth99'))
2055
2056 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
2057 print(output)
2058 self.assertRegex(output, '192.168.5')
2059 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2060
2061 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
2062 print(output)
2063 self.assertRegex(output, '2600::')
2064 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2065
18c613dc
YW
2066 @expectedFailureIfModuleIsNotAvailable('vrf')
2067 def test_dhcp_client_vrf(self):
2068 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2069 '25-vrf.netdev', '25-vrf.network')
2070 self.start_networkd()
2071
2072 self.assertTrue(self.link_exits('veth99'))
2073 self.assertTrue(self.link_exits('vrf99'))
2074
2075 self.start_dnsmasq()
2076
2077 print('## ip -d link show dev vrf99')
2078 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99']).rstrip().decode('utf-8')
2079 print(output)
2080 self.assertRegex(output, 'vrf table 42')
2081
2082 print('## ip address show vrf vrf99')
2083 output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
2084 print(output_ip_vrf)
2085
2086 print('## ip address show dev veth99')
2087 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
2088 print(output)
2089 self.assertEqual(output, output_ip_vrf)
2090 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2091 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2092 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic noprefixroute')
2093 self.assertRegex(output, 'inet6 .* scope link')
2094
2095 print('## ip route show vrf vrf99')
2096 output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
2097 print(output)
2098 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
2099 self.assertRegex(output, 'default dev veth99 proto static scope link')
2100 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
2101 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
2102 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
2103 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
2104
2105 print('## ip route show table main dev veth99')
2106 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
2107 print(output)
2108 self.assertEqual(output, '')
2109
2110 output = subprocess.check_output(['networkctl', 'status', 'vrf99']).rstrip().decode('utf-8')
2111 print(output)
2112 self.assertRegex(output, 'State: carrier \(configured\)')
2113
2114 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
2115 print(output)
2116 self.assertRegex(output, 'State: routable \(configured\)')
2117
af3b1498
YW
2118 def test_dhcp_client_gateway_onlink_implicit(self):
2119 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2120 'dhcp-client-gateway-onlink-implicit.network')
2121 self.start_networkd()
2122
2123 self.assertTrue(self.link_exits('veth99'))
2124
2125 self.start_dnsmasq()
2126
2127 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
2128 print(output)
2129 self.assertRegex(output, '192.168.5')
2130
2131 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '10.0.0.0/8']).rstrip().decode('utf-8')
2132 print(output)
2133 self.assertRegex(output, 'onlink')
2134 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '192.168.100.0/24']).rstrip().decode('utf-8')
2135 print(output)
2136 self.assertRegex(output, 'onlink')
2137
1f0e3109
SS
2138if __name__ == '__main__':
2139 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
2140 verbosity=3))