]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
test-network: rename l2tp_tunnel_remove -> remove_l2tp_tunnels
[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
9c1ae484 5import argparse
1f0e3109 6import os
201bf07f 7import re
1f0e3109
SS
8import shutil
9import signal
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
9c1ae484 25networkd_bin='/usr/lib/systemd/systemd-networkd'
5aa58329 26wait_online_bin='/usr/lib/systemd/systemd-networkd-wait-online'
9c1ae484
YW
27networkctl_bin='/usr/bin/networkctl'
28use_valgrind=False
29enable_debug=False
30env = {}
94c03122 31asan_options=None
fa4c6095 32lsan_options=None
94c03122 33ubsan_options=None
5aa58329 34
371810d1
ZJS
35def check_output(*command, **kwargs):
36 # This replaces both check_output and check_call (output can be ignored)
37 command = command[0].split() + list(command[1:])
38 return subprocess.check_output(command, universal_newlines=True, **kwargs).rstrip()
39
40def call(*command, **kwargs):
41 command = command[0].split() + list(command[1:])
42 return subprocess.call(command, universal_newlines=True, **kwargs)
43
44def run(*command, **kwargs):
45 command = command[0].split() + list(command[1:])
46 return subprocess.run(command, universal_newlines=True, **kwargs)
47
7a0a37b2 48def is_module_available(module_name):
371810d1
ZJS
49 lsmod_output = check_output('lsmod')
50 module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE)
51 return module_re.search(lsmod_output) or not call('modprobe', module_name)
7a0a37b2
EV
52
53def expectedFailureIfModuleIsNotAvailable(module_name):
54 def f(func):
55 if not is_module_available(module_name):
56 return unittest.expectedFailure(func)
57 return func
58
59 return f
60
7bea7f9b
SS
61def expectedFailureIfERSPANModuleIsNotAvailable():
62 def f(func):
371810d1 63 rc = 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')
7bea7f9b 64 if rc == 0:
371810d1 65 call('ip link del erspan99')
7bea7f9b
SS
66 return func
67 else:
68 return unittest.expectedFailure(func)
69
70 return f
71
d586a2c3
YW
72def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
73 def f(func):
371810d1 74 rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
d586a2c3 75 if rc == 0:
371810d1 76 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
d586a2c3
YW
77 return func
78 else:
79 return unittest.expectedFailure(func)
80
81 return f
82
83def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
84 def f(func):
371810d1 85 rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7')
d586a2c3 86 if rc == 0:
371810d1 87 call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
d586a2c3
YW
88 return func
89 else:
90 return unittest.expectedFailure(func)
91
92 return f
93
1ca44d7d
YW
94def expectedFailureIfEthtoolDoesNotSupportDriver():
95 def f(func):
96 support = False
371810d1 97 rc = call('ip link add name dummy99 type dummy')
1ca44d7d 98 if rc == 0:
371810d1 99 ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
1ca44d7d
YW
100 if ret.returncode == 0 and 'E: ID_NET_DRIVER=dummy' in ret.stdout.rstrip():
101 support = True
371810d1 102 call('ip link del dummy99')
1ca44d7d
YW
103
104 if support:
105 return func
106 else:
107 return unittest.expectedFailure(func)
108
109 return f
110
1f0e3109 111def setUpModule():
1f0e3109
SS
112 os.makedirs(network_unit_file_path, exist_ok=True)
113 os.makedirs(networkd_ci_path, exist_ok=True)
114
115 shutil.rmtree(networkd_ci_path)
6aea9276 116 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
1f0e3109 117
371810d1
ZJS
118 check_output('systemctl stop systemd-networkd.socket')
119 check_output('systemctl stop systemd-networkd.service')
c0bf6733 120
9c1ae484
YW
121 drop_in = [
122 '[Service]',
123 'Restart=no',
124 'ExecStart=',
125 ]
126 if use_valgrind:
127 drop_in += [
128 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin,
94c03122 129 'PrivateTmp=yes'
9c1ae484
YW
130 ]
131 else:
132 drop_in += ['ExecStart=!!' + networkd_bin]
133 if enable_debug:
134 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
94c03122
YW
135 if asan_options:
136 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
fa4c6095
YW
137 if lsan_options:
138 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
94c03122
YW
139 if ubsan_options:
140 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
78690bb5
YW
141 if asan_options or lsan_options or ubsan_options:
142 drop_in += ['SystemCallFilter=']
fa4c6095 143 if use_valgrind or asan_options or lsan_options or ubsan_options:
94c03122 144 drop_in += ['MemoryDenyWriteExecute=no']
9c1ae484 145
9c1ae484
YW
146 os.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok=True)
147 with open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode='w') as f:
72917fcc 148 f.write('\n'.join(drop_in))
9c1ae484 149
371810d1
ZJS
150 check_output('systemctl daemon-reload')
151 print(check_output('systemctl cat systemd-networkd.service'))
9c1ae484 152
1f0e3109
SS
153def tearDownModule():
154 shutil.rmtree(networkd_ci_path)
d4fda2a5 155
371810d1 156 check_output('systemctl stop systemd-networkd.service')
d4fda2a5 157
9c1ae484 158 shutil.rmtree('/run/systemd/system/systemd-networkd.service.d')
371810d1 159 check_output('systemctl daemon-reload')
1f0e3109 160
371810d1
ZJS
161 check_output('systemctl start systemd-networkd.socket')
162 check_output('systemctl start systemd-networkd.service')
c0bf6733 163
ec38833c
ZJS
164def read_link_attr(link, dev, attribute):
165 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
166 return f.readline().strip()
167
168def read_bridge_port_attr(bridge, link, attribute):
169 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
170 path_port = 'lower_' + link + '/brport'
171 path = os.path.join(path_bridge, path_port)
172
173 with open(os.path.join(path, attribute)) as f:
174 return f.readline().strip()
175
176def link_exists(link):
177 return os.path.exists(os.path.join('/sys/class/net', link))
178
179def remove_links(links):
180 for link in links:
181 if link_exists(link):
182 call('ip link del dev', link)
183 time.sleep(1)
184
185def remove_fou_ports(ports):
186 for port in ports:
5239d7b3 187 call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
188
189def remove_routing_policy_rule_tables(tables):
190 for table in tables:
4ef39b49
YW
191 rc = 0
192 while rc == 0:
193 rc = call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
194
195def remove_routes(routes):
196 for route_type, addr in routes:
5239d7b3 197 call('ip route del', route_type, addr, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c 198
ad78d7b0 199def remove_l2tp_tunnels(tunnel_ids):
ec38833c
ZJS
200 output = check_output('ip l2tp show tunnel')
201 for tid in tunnel_ids:
202 words='Tunnel ' + tid + ', encap'
203 if words in output:
204 call('ip l2tp del tunnel tid', tid)
205 time.sleep(1)
206
207def read_ipv6_sysctl_attr(link, attribute):
208 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
209 return f.readline().strip()
210
211def read_ipv4_sysctl_attr(link, attribute):
212 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
213 return f.readline().strip()
214
215def copy_unit_to_networkd_unit_path(*units):
216 print()
217 for unit in units:
218 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
219 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
220 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
221
222def remove_unit_from_networkd_path(units):
223 for unit in units:
224 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
225 os.remove(os.path.join(network_unit_file_path, unit))
226 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
227 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
228
229def warn_about_firewalld():
230 rc = call('systemctl -q is-active firewalld.service')
231 if rc == 0:
232 print('\nWARNING: firewalld.service is active. The test may fail.')
233
234def start_dnsmasq(additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'):
235 warn_about_firewalld()
236 dnsmasq_command = f'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={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -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
237 check_output(dnsmasq_command)
238
239def stop_dnsmasq(pid_file):
240 if os.path.exists(pid_file):
241 with open(pid_file, 'r') as f:
242 pid = f.read().rstrip(' \t\r\n\0')
243 os.kill(int(pid), signal.SIGTERM)
244
245 os.remove(pid_file)
246
247def search_words_in_dnsmasq_log(words, show_all=False):
248 if os.path.exists(dnsmasq_log_file):
249 with open (dnsmasq_log_file) as in_file:
250 contents = in_file.read()
251 if show_all:
252 print(contents)
253 for line in contents.splitlines():
254 if words in line:
255 in_file.close()
256 print("%s, %s" % (words, line))
257 return True
258 return False
259
260def remove_lease_file():
261 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
262 os.remove(os.path.join(networkd_ci_path, 'lease'))
263
264def remove_log_file():
265 if os.path.exists(dnsmasq_log_file):
266 os.remove(dnsmasq_log_file)
267
268def start_networkd(sleep_sec=5, remove_state_files=True):
269 if (remove_state_files and
270 os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
271 check_output('systemctl stop systemd-networkd')
272 os.remove(os.path.join(networkd_runtime_directory, 'state'))
273 check_output('systemctl start systemd-networkd')
274 else:
275 check_output('systemctl restart systemd-networkd')
276 if sleep_sec > 0:
277 time.sleep(sleep_sec)
278
279def wait_online(links_with_operstate, timeout='20s', bool_any=False):
280 args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
281 if bool_any:
282 args += ['--any']
283 try:
284 check_output(*args, env=env)
285 except subprocess.CalledProcessError:
286 for link in links_with_operstate:
287 output = check_output(*networkctl_cmd, 'status', link.split(':')[0], env=env)
288 print(output)
289 raise
4d7ed14f 290
ec38833c
ZJS
291def get_operstate(link, show_status=True, setup_state='configured'):
292 output = check_output(*networkctl_cmd, 'status', link, env=env)
293 if show_status:
294 print(output)
295 for line in output.splitlines():
296 if 'State:' in line and (not setup_state or setup_state in line):
297 return line.split()[1]
298 return None
1f0e3109 299
ec38833c 300class Utilities():
e39cc445 301 def check_link_exists(self, link):
ec38833c 302 self.assertTrue(link_exists(link))
2be0b6fc
YW
303
304 def check_operstate(self, link, expected, show_status=True, setup_state='configured'):
ec38833c 305 self.assertRegex(get_operstate(link, show_status, setup_state), expected)
2be0b6fc 306
53c32c2b 307 def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
2629df47
YW
308 for i in range(timeout_sec):
309 if i > 0:
310 time.sleep(1)
371810d1 311 output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
2629df47
YW
312 if re.search(address_regex, output):
313 break
314 else:
315 self.assertRegex(output, address_regex)
316
1ca44d7d
YW
317class NetworkctlTests(unittest.TestCase, Utilities):
318
319 links = [
320 'test1',
321 'veth99',
322 ]
323
324 units = [
325 '11-dummy.netdev',
6d5b4efe 326 '11-dummy-mtu.netdev',
1ca44d7d
YW
327 '11-dummy.network',
328 '25-veth.netdev',
329 'netdev-link-local-addressing-yes.network',
330 ]
331
332 def setUp(self):
ec38833c 333 remove_links(self.links)
1ca44d7d
YW
334
335 def tearDown(self):
ec38833c
ZJS
336 remove_links(self.links)
337 remove_unit_from_networkd_path(self.units)
1ca44d7d
YW
338
339 def test_glob(self):
ec38833c
ZJS
340 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
341 start_networkd(0)
1ca44d7d 342
ec38833c 343 wait_online(['test1:degraded'])
1ca44d7d 344
371810d1 345 output = check_output(*networkctl_cmd, 'list', env=env)
1ca44d7d
YW
346 self.assertRegex(output, '1 lo ')
347 self.assertRegex(output, 'test1')
348
371810d1 349 output = check_output(*networkctl_cmd, 'list', 'test1', env=env)
1ca44d7d
YW
350 self.assertNotRegex(output, '1 lo ')
351 self.assertRegex(output, 'test1')
352
371810d1 353 output = check_output(*networkctl_cmd, 'list', 'te*', env=env)
1ca44d7d
YW
354 self.assertNotRegex(output, '1 lo ')
355 self.assertRegex(output, 'test1')
356
371810d1 357 output = check_output(*networkctl_cmd, 'status', 'te*', env=env)
1ca44d7d
YW
358 self.assertNotRegex(output, '1: lo ')
359 self.assertRegex(output, 'test1')
360
371810d1 361 output = check_output(*networkctl_cmd, 'status', 'tes[a-z][0-9]', env=env)
1ca44d7d
YW
362 self.assertNotRegex(output, '1: lo ')
363 self.assertRegex(output, 'test1')
364
6d5b4efe 365 def test_mtu(self):
ec38833c
ZJS
366 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
367 start_networkd(0)
6d5b4efe 368
ec38833c 369 wait_online(['test1:degraded'])
6d5b4efe 370
371810d1 371 output = check_output(*networkctl_cmd, 'status', 'test1', env=env)
6d5b4efe
YW
372 self.assertRegex(output, 'MTU: 1600')
373
1ca44d7d
YW
374 @expectedFailureIfEthtoolDoesNotSupportDriver()
375 def test_udev_driver(self):
ec38833c
ZJS
376 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
377 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
378 start_networkd(0)
1ca44d7d 379
ec38833c 380 wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
1ca44d7d 381
371810d1 382 output = check_output(*networkctl_cmd, 'status', 'test1', env=env)
1ca44d7d
YW
383 self.assertRegex(output, 'Driver: dummy')
384
371810d1 385 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1ca44d7d
YW
386 self.assertRegex(output, 'Driver: veth')
387
371810d1 388 output = check_output(*networkctl_cmd, 'status', 'veth-peer', env=env)
1ca44d7d 389 self.assertRegex(output, 'Driver: veth')
2be0b6fc 390
bee692fd 391 def test_delete_links(self):
ec38833c
ZJS
392 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
393 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
394 start_networkd(0)
bee692fd 395
ec38833c 396 wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
bee692fd 397
371810d1 398 check_output(*networkctl_cmd, 'delete', 'test1', 'veth99')
ec38833c
ZJS
399 self.assertFalse(link_exists('test1'))
400 self.assertFalse(link_exists('veth99'))
401 self.assertFalse(link_exists('veth-peer'))
bee692fd 402
1f0e3109
SS
403class NetworkdNetDevTests(unittest.TestCase, Utilities):
404
09ea6724
YW
405 links =[
406 '6rdtun99',
407 'bond99',
408 'bridge99',
409 'dropin-test',
410 'dummy98',
6a97a864
YW
411 'erspan98',
412 'erspan99',
09ea6724 413 'geneve99',
4b6a6d1e 414 'gretap96',
6a97a864 415 'gretap98',
09ea6724 416 'gretap99',
4b6a6d1e 417 'gretun96',
6a97a864
YW
418 'gretun97',
419 'gretun98',
09ea6724 420 'gretun99',
6a97a864 421 'ip6gretap98',
09ea6724 422 'ip6gretap99',
6a97a864
YW
423 'ip6gretun97',
424 'ip6gretun98',
425 'ip6gretun99',
426 'ip6tnl97',
427 'ip6tnl98',
09ea6724 428 'ip6tnl99',
4b6a6d1e 429 'ipiptun96',
6a97a864
YW
430 'ipiptun97',
431 'ipiptun98',
09ea6724
YW
432 'ipiptun99',
433 'ipvlan99',
956c8fec 434 'ipvtap99',
09ea6724
YW
435 'isataptun99',
436 'macvlan99',
437 'macvtap99',
811f33d0 438 'nlmon99',
4b6a6d1e 439 'sittun96',
6a97a864
YW
440 'sittun97',
441 'sittun98',
09ea6724
YW
442 'sittun99',
443 'tap99',
444 'test1',
445 'tun99',
446 'vcan99',
447 'veth99',
448 'vlan99',
449 'vrf99',
6a97a864
YW
450 'vti6tun97',
451 'vti6tun98',
09ea6724 452 'vti6tun99',
6a97a864
YW
453 'vtitun97',
454 'vtitun98',
09ea6724 455 'vtitun99',
f63b14d3 456 'vxcan99',
09ea6724 457 'vxlan99',
da44fb8a 458 'wg98',
09ea6724
YW
459 'wg99']
460
461 units = [
462 '10-dropin-test.netdev',
463 '11-dummy.netdev',
03db80b2 464 '11-dummy.network',
09ea6724 465 '12-dummy.netdev',
753e0a24 466 '15-name-conflict-test.netdev',
09ea6724
YW
467 '21-macvlan.netdev',
468 '21-macvtap.netdev',
7f45d738 469 '21-vlan-test1.network',
09ea6724
YW
470 '21-vlan.netdev',
471 '21-vlan.network',
472 '25-6rd-tunnel.netdev',
473 '25-bond.netdev',
fde60a42 474 '25-bond-balanced-tlb.netdev',
09ea6724 475 '25-bridge.netdev',
1285edf3 476 '25-bridge-configure-without-carrier.network',
03db80b2 477 '25-bridge.network',
6a97a864 478 '25-erspan-tunnel-local-any.netdev',
09ea6724 479 '25-erspan-tunnel.netdev',
4b6a6d1e
YW
480 '25-fou-gretap.netdev',
481 '25-fou-gre.netdev',
482 '25-fou-ipip.netdev',
483 '25-fou-ipproto-gre.netdev',
484 '25-fou-ipproto-ipip.netdev',
485 '25-fou-sit.netdev',
09ea6724 486 '25-geneve.netdev',
6a97a864 487 '25-gretap-tunnel-local-any.netdev',
09ea6724 488 '25-gretap-tunnel.netdev',
6a97a864
YW
489 '25-gre-tunnel-local-any.netdev',
490 '25-gre-tunnel-remote-any.netdev',
09ea6724 491 '25-gre-tunnel.netdev',
6a97a864
YW
492 '25-ip6gretap-tunnel-local-any.netdev',
493 '25-ip6gretap-tunnel.netdev',
494 '25-ip6gre-tunnel-local-any.netdev',
495 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 496 '25-ip6gre-tunnel.netdev',
6a97a864
YW
497 '25-ip6tnl-tunnel-remote-any.netdev',
498 '25-ip6tnl-tunnel-local-any.netdev',
09ea6724
YW
499 '25-ip6tnl-tunnel.netdev',
500 '25-ipip-tunnel-independent.netdev',
6a97a864
YW
501 '25-ipip-tunnel-local-any.netdev',
502 '25-ipip-tunnel-remote-any.netdev',
09ea6724
YW
503 '25-ipip-tunnel.netdev',
504 '25-ipvlan.netdev',
956c8fec 505 '25-ipvtap.netdev',
09ea6724 506 '25-isatap-tunnel.netdev',
02849d8b
YW
507 '25-macsec.key',
508 '25-macsec.netdev',
509 '25-macsec.network',
811f33d0 510 '25-nlmon.netdev',
6a97a864
YW
511 '25-sit-tunnel-local-any.netdev',
512 '25-sit-tunnel-remote-any.netdev',
09ea6724
YW
513 '25-sit-tunnel.netdev',
514 '25-tap.netdev',
515 '25-tun.netdev',
11309591
YW
516 '25-tunnel-local-any.network',
517 '25-tunnel-remote-any.network',
518 '25-tunnel.network',
09ea6724
YW
519 '25-vcan.netdev',
520 '25-veth.netdev',
521 '25-vrf.netdev',
6a97a864
YW
522 '25-vti6-tunnel-local-any.netdev',
523 '25-vti6-tunnel-remote-any.netdev',
09ea6724 524 '25-vti6-tunnel.netdev',
6a97a864
YW
525 '25-vti-tunnel-local-any.netdev',
526 '25-vti-tunnel-remote-any.netdev',
09ea6724 527 '25-vti-tunnel.netdev',
f63b14d3 528 '25-vxcan.netdev',
09ea6724 529 '25-vxlan.netdev',
da44fb8a
YW
530 '25-wireguard-23-peers.netdev',
531 '25-wireguard-23-peers.network',
9e5d79e7 532 '25-wireguard-preshared-key.txt',
39bcff3b 533 '25-wireguard-private-key.txt',
09ea6724 534 '25-wireguard.netdev',
5a0bd90b 535 '25-wireguard.network',
09ea6724 536 '6rd.network',
6730a1f3 537 'erspan.network',
09ea6724
YW
538 'gre.network',
539 'gretap.network',
540 'gretun.network',
541 'ip6gretap.network',
6a97a864 542 'ip6gretun.network',
09ea6724
YW
543 'ip6tnl.network',
544 'ipip.network',
545 'ipvlan.network',
956c8fec 546 'ipvtap.network',
09ea6724 547 'isatap.network',
02849d8b 548 'macsec.network',
09ea6724
YW
549 'macvlan.network',
550 'macvtap.network',
077f9abc 551 'netdev-link-local-addressing-yes.network',
09ea6724
YW
552 'sit.network',
553 'vti6.network',
554 'vti.network',
1c862fe0 555 'vxlan-test1.network',
09ea6724 556 'vxlan.network']
1f0e3109 557
def9fc0d
YW
558 fou_ports = [
559 '55555',
560 '55556']
561
1f0e3109 562 def setUp(self):
ec38833c
ZJS
563 remove_fou_ports(self.fou_ports)
564 remove_links(self.links)
1f0e3109
SS
565
566 def tearDown(self):
ec38833c
ZJS
567 remove_fou_ports(self.fou_ports)
568 remove_links(self.links)
569 remove_unit_from_networkd_path(self.units)
1f0e3109 570
1ca44d7d 571 def test_dropin_and_name_conflict(self):
ec38833c
ZJS
572 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
573 start_networkd(0)
d80734f7 574
ec38833c 575 wait_online(['dropin-test:off'])
d80734f7 576
371810d1 577 output = check_output('ip link show dropin-test')
d80734f7
YW
578 print(output)
579 self.assertRegex(output, '00:50:56:c0:00:28')
580
03db80b2 581 def test_wait_online_any(self):
ec38833c
ZJS
582 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
583 start_networkd(0)
03db80b2 584
ec38833c 585 wait_online(['bridge99', 'test1:degraded'], bool_any=True)
03db80b2 586
791c1140
YW
587 self.check_operstate('bridge99', '(?:off|no-carrier)', setup_state='configuring')
588 self.check_operstate('test1', 'degraded')
03db80b2 589
1f0e3109 590 def test_bridge(self):
1285edf3 591 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
ec38833c 592 start_networkd(0)
1f0e3109 593
1285edf3 594 wait_online(['bridge99:no-carrier'])
1f0e3109 595
3d165124 596 tick = os.sysconf('SC_CLK_TCK')
ec38833c
ZJS
597 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick))
598 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick))
599 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge','forward_delay')) / tick))
600 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge','ageing_time')) / tick))
601 self.assertEqual(9, int(read_link_attr('bridge99', 'bridge','priority')))
602 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge','multicast_querier')))
603 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge','multicast_snooping')))
604 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge','stp_state')))
1f0e3109
SS
605
606 def test_bond(self):
ec38833c
ZJS
607 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
608 start_networkd(0)
609
610 wait_online(['bond99:off', 'bond98:off'])
611
612 self.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
613 self.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
614 self.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
615 self.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
616 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
617 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
618 self.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
619 self.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
620 self.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
621 self.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
622 self.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
623
624 self.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
625 self.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
fde60a42 626
1f0e3109 627 def test_vlan(self):
ec38833c
ZJS
628 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
629 '21-vlan.network', '21-vlan-test1.network')
630 start_networkd(0)
1f0e3109 631
ec38833c 632 wait_online(['test1:degraded', 'vlan99:routable'])
1f0e3109 633
371810d1 634 output = check_output('ip -d link show test1')
72b7f1b9 635 print(output)
7d7be1b9 636 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 637
371810d1 638 output = check_output('ip -d link show vlan99')
14ecd604 639 print(output)
06895a1d
YW
640 self.assertRegex(output, ' mtu 2000 ')
641 self.assertRegex(output, 'REORDER_HDR')
642 self.assertRegex(output, 'LOOSE_BINDING')
643 self.assertRegex(output, 'GVRP')
644 self.assertRegex(output, 'MVRP')
645 self.assertRegex(output, ' id 99 ')
1f0e3109 646
371810d1 647 output = check_output('ip -4 address show dev test1')
7f45d738
YW
648 print(output)
649 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
650 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
651
371810d1 652 output = check_output('ip -4 address show dev vlan99')
7f45d738
YW
653 print(output)
654 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
655
1f0e3109 656 def test_macvtap(self):
460feb61
YW
657 for mode in ['private', 'vepa', 'bridge', 'passthru']:
658 with self.subTest(mode=mode):
659 if mode != 'private':
660 self.tearDown()
ec38833c
ZJS
661 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
662 '11-dummy.netdev', 'macvtap.network')
460feb61
YW
663 with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f:
664 f.write('[MACVTAP]\nMode=' + mode)
ec38833c 665 start_networkd(0)
1f0e3109 666
ec38833c 667 wait_online(['macvtap99:degraded', 'test1:degraded'])
460feb61 668
371810d1 669 output = check_output('ip -d link show macvtap99')
460feb61
YW
670 print(output)
671 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
1f0e3109
SS
672
673 def test_macvlan(self):
dff9792b
YW
674 for mode in ['private', 'vepa', 'bridge', 'passthru']:
675 with self.subTest(mode=mode):
676 if mode != 'private':
677 self.tearDown()
ec38833c
ZJS
678 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
679 '11-dummy.netdev', 'macvlan.network')
dff9792b
YW
680 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
681 f.write('[MACVLAN]\nMode=' + mode)
ec38833c 682 start_networkd(0)
dff9792b 683
ec38833c 684 wait_online(['macvlan99:degraded', 'test1:degraded'])
dff9792b 685
371810d1 686 output = check_output('ip -d link show test1')
dff9792b
YW
687 print(output)
688 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 689
371810d1 690 output = check_output('ip -d link show macvlan99')
dff9792b
YW
691 print(output)
692 self.assertRegex(output, ' mtu 2000 ')
693 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
72b7f1b9 694
7a0a37b2 695 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109 696 def test_ipvlan(self):
bc6dff6e
YW
697 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
698 with self.subTest(mode=mode, flag=flag):
699 if mode != 'L2':
700 self.tearDown()
ec38833c
ZJS
701 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
702 '11-dummy.netdev', 'ipvlan.network')
bc6dff6e
YW
703 with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f:
704 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
1f0e3109 705
ec38833c
ZJS
706 start_networkd(0)
707 wait_online(['ipvlan99:degraded', 'test1:degraded'])
bc6dff6e 708
371810d1 709 output = check_output('ip -d link show ipvlan99')
bc6dff6e
YW
710 print(output)
711 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
1f0e3109 712
956c8fec
YW
713 @expectedFailureIfModuleIsNotAvailable('ipvtap')
714 def test_ipvtap(self):
40921f08
YW
715 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
716 with self.subTest(mode=mode, flag=flag):
717 if mode != 'L2':
718 self.tearDown()
ec38833c
ZJS
719 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
720 '11-dummy.netdev', 'ipvtap.network')
40921f08
YW
721 with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f:
722 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
723
ec38833c
ZJS
724 start_networkd(0)
725 wait_online(['ipvtap99:degraded', 'test1:degraded'])
956c8fec 726
371810d1 727 output = check_output('ip -d link show ipvtap99')
40921f08
YW
728 print(output)
729 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
956c8fec 730
1f0e3109 731 def test_veth(self):
ec38833c
ZJS
732 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
733 start_networkd(0)
1f0e3109 734
ec38833c 735 wait_online(['veth99:degraded', 'veth-peer:degraded'])
671dacdf 736
371810d1 737 output = check_output('ip -d link show veth99')
671dacdf
YW
738 print(output)
739 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
371810d1 740 output = check_output('ip -d link show veth-peer')
671dacdf
YW
741 print(output)
742 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
1f0e3109 743
1f0e3109 744 def test_tun(self):
ec38833c
ZJS
745 copy_unit_to_networkd_unit_path('25-tun.netdev')
746 start_networkd(0)
1f0e3109 747
ec38833c 748 wait_online(['tun99:off'])
1f0e3109 749
371810d1 750 output = check_output('ip -d link show tun99')
2746d307
YW
751 print(output)
752 # Old ip command does not support IFF_ flags
753 self.assertRegex(output, 'tun (?:type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
754
1f0e3109 755 def test_tap(self):
ec38833c
ZJS
756 copy_unit_to_networkd_unit_path('25-tap.netdev')
757 start_networkd(0)
1f0e3109 758
ec38833c 759 wait_online(['tap99:off'])
1f0e3109 760
371810d1 761 output = check_output('ip -d link show tap99')
2746d307
YW
762 print(output)
763 # Old ip command does not support IFF_ flags
764 self.assertRegex(output, 'tun (?:type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
765
7a0a37b2 766 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109 767 def test_vrf(self):
ec38833c
ZJS
768 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
769 start_networkd(0)
1f0e3109 770
ec38833c 771 wait_online(['vrf99:carrier'])
1f0e3109 772
7a0a37b2 773 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109 774 def test_vcan(self):
ec38833c
ZJS
775 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
776 start_networkd(0)
1f0e3109 777
ec38833c 778 wait_online(['vcan99:carrier'])
1f0e3109 779
f63b14d3
YW
780 @expectedFailureIfModuleIsNotAvailable('vxcan')
781 def test_vxcan(self):
ec38833c
ZJS
782 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
783 start_networkd(0)
f63b14d3 784
ec38833c 785 wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
f63b14d3 786
7a3bc5a8
EV
787 @expectedFailureIfModuleIsNotAvailable('wireguard')
788 def test_wireguard(self):
ec38833c
ZJS
789 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
790 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
791 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
792 start_networkd(0)
793 wait_online(['wg99:carrier', 'wg98:routable'])
5a0bd90b 794
7a3bc5a8 795 if shutil.which('wg'):
371810d1 796 call('wg')
5a0bd90b 797
371810d1 798 output = check_output('wg show wg99 listen-port')
06895a1d 799 self.assertRegex(output, '51820')
371810d1 800 output = check_output('wg show wg99 fwmark')
06895a1d 801 self.assertRegex(output, '0x4d2')
371810d1 802 output = check_output('wg show wg99 allowed-ips')
88aaf89e
ZJS
803 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
804 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
371810d1 805 output = check_output('wg show wg99 persistent-keepalive')
88aaf89e 806 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
371810d1 807 output = check_output('wg show wg99 endpoints')
88aaf89e 808 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
371810d1 809 output = check_output('wg show wg99 private-key')
88aaf89e 810 self.assertRegex(output, r'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
371810d1 811 output = check_output('wg show wg99 preshared-keys')
88aaf89e
ZJS
812 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
813 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
7a3bc5a8 814
371810d1 815 output = check_output('wg show wg98 private-key')
88aaf89e 816 self.assertRegex(output, r'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
da44fb8a 817
1f0e3109 818 def test_geneve(self):
ec38833c
ZJS
819 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
820 start_networkd(0)
1f0e3109 821
ec38833c 822 wait_online(['geneve99:degraded'])
1f0e3109 823
371810d1 824 output = check_output('ip -d link show geneve99')
14ecd604 825 print(output)
06895a1d
YW
826 self.assertRegex(output, '192.168.22.1')
827 self.assertRegex(output, '6082')
828 self.assertRegex(output, 'udpcsum')
829 self.assertRegex(output, 'udp6zerocsumrx')
1f0e3109
SS
830
831 def test_ipip_tunnel(self):
ec38833c
ZJS
832 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
833 '25-ipip-tunnel.netdev', '25-tunnel.network',
834 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
835 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
836 start_networkd(0)
837 wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'dummy98:degraded'])
6a97a864 838
371810d1 839 output = check_output('ip -d link show ipiptun99')
6a97a864
YW
840 print(output)
841 self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local 192.168.223.238 dev dummy98')
371810d1 842 output = check_output('ip -d link show ipiptun98')
6a97a864
YW
843 print(output)
844 self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local any dev dummy98')
371810d1 845 output = check_output('ip -d link show ipiptun97')
6a97a864
YW
846 print(output)
847 self.assertRegex(output, 'ipip (?:ipip |)remote any local 192.168.223.238 dev dummy98')
1f0e3109
SS
848
849 def test_gre_tunnel(self):
ec38833c
ZJS
850 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
851 '25-gre-tunnel.netdev', '25-tunnel.network',
852 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
853 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
854 start_networkd(0)
855 wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'dummy98:degraded'])
6a97a864 856
371810d1 857 output = check_output('ip -d link show gretun99')
6a97a864
YW
858 print(output)
859 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
860 self.assertRegex(output, 'ikey 1.2.3.103')
861 self.assertRegex(output, 'okey 1.2.4.103')
862 self.assertRegex(output, 'iseq')
863 self.assertRegex(output, 'oseq')
371810d1 864 output = check_output('ip -d link show gretun98')
6a97a864
YW
865 print(output)
866 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
867 self.assertRegex(output, 'ikey 0.0.0.104')
868 self.assertRegex(output, 'okey 0.0.0.104')
869 self.assertNotRegex(output, 'iseq')
870 self.assertNotRegex(output, 'oseq')
371810d1 871 output = check_output('ip -d link show gretun97')
6a97a864
YW
872 print(output)
873 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
38f4bb44
YW
874 self.assertRegex(output, 'ikey 0.0.0.105')
875 self.assertRegex(output, 'okey 0.0.0.105')
876 self.assertNotRegex(output, 'iseq')
877 self.assertNotRegex(output, 'oseq')
6a97a864
YW
878
879 def test_ip6gre_tunnel(self):
ec38833c
ZJS
880 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
881 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
882 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
883 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
01943d43 884 start_networkd(5)
6a97a864 885
17bcf0a0
YW
886 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
887
e39cc445
YW
888 self.check_link_exists('dummy98')
889 self.check_link_exists('ip6gretun99')
890 self.check_link_exists('ip6gretun98')
891 self.check_link_exists('ip6gretun97')
6a97a864 892
371810d1 893 output = check_output('ip -d link show ip6gretun99')
6a97a864
YW
894 print(output)
895 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 896 output = check_output('ip -d link show ip6gretun98')
6a97a864
YW
897 print(output)
898 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
371810d1 899 output = check_output('ip -d link show ip6gretun97')
6a97a864
YW
900 print(output)
901 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109 902
11309591 903 def test_gretap_tunnel(self):
ec38833c
ZJS
904 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
905 '25-gretap-tunnel.netdev', '25-tunnel.network',
906 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
907 start_networkd(0)
908 wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
6a97a864 909
371810d1 910 output = check_output('ip -d link show gretap99')
6a97a864
YW
911 print(output)
912 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
913 self.assertRegex(output, 'ikey 0.0.0.106')
914 self.assertRegex(output, 'okey 0.0.0.106')
915 self.assertRegex(output, 'iseq')
916 self.assertRegex(output, 'oseq')
371810d1 917 output = check_output('ip -d link show gretap98')
6a97a864
YW
918 print(output)
919 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
920 self.assertRegex(output, 'ikey 0.0.0.107')
921 self.assertRegex(output, 'okey 0.0.0.107')
922 self.assertRegex(output, 'iseq')
923 self.assertRegex(output, 'oseq')
1f0e3109
SS
924
925 def test_ip6gretap_tunnel(self):
ec38833c
ZJS
926 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
927 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
928 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
929 start_networkd(0)
930 wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
6a97a864 931
371810d1 932 output = check_output('ip -d link show ip6gretap99')
6a97a864
YW
933 print(output)
934 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 935 output = check_output('ip -d link show ip6gretap98')
6a97a864
YW
936 print(output)
937 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1f0e3109
SS
938
939 def test_vti_tunnel(self):
ec38833c
ZJS
940 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
941 '25-vti-tunnel.netdev', '25-tunnel.network',
942 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
943 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
944 start_networkd(0)
945 wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'dummy98:degraded'])
6a97a864 946
371810d1 947 output = check_output('ip -d link show vtitun99')
6a97a864
YW
948 print(output)
949 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
371810d1 950 output = check_output('ip -d link show vtitun98')
6a97a864
YW
951 print(output)
952 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
371810d1 953 output = check_output('ip -d link show vtitun97')
6a97a864
YW
954 print(output)
955 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
1f0e3109
SS
956
957 def test_vti6_tunnel(self):
ec38833c
ZJS
958 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
959 '25-vti6-tunnel.netdev', '25-tunnel.network',
960 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
961 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
962 start_networkd(0)
963 wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
6a97a864 964
371810d1 965 output = check_output('ip -d link show vti6tun99')
6a97a864
YW
966 print(output)
967 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 968 output = check_output('ip -d link show vti6tun98')
6a97a864
YW
969 print(output)
970 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
371810d1 971 output = check_output('ip -d link show vti6tun97')
6a97a864
YW
972 print(output)
973 self.assertRegex(output, 'vti6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
974
975 def test_ip6tnl_tunnel(self):
ec38833c
ZJS
976 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
977 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
978 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
979 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
980 start_networkd(0)
981 wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
6a97a864 982
371810d1 983 output = check_output('ip -d link show ip6tnl99')
6a97a864
YW
984 print(output)
985 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 986 output = check_output('ip -d link show ip6tnl98')
6a97a864
YW
987 print(output)
988 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
371810d1 989 output = check_output('ip -d link show ip6tnl97')
6a97a864
YW
990 print(output)
991 self.assertRegex(output, 'ip6tnl ip6ip6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
992
993 def test_sit_tunnel(self):
ec38833c
ZJS
994 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
995 '25-sit-tunnel.netdev', '25-tunnel.network',
996 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
997 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
998 start_networkd(0)
999 wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'dummy98:degraded'])
6a97a864 1000
371810d1 1001 output = check_output('ip -d link show sittun99')
6a97a864
YW
1002 print(output)
1003 self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local 10.65.223.238 dev dummy98")
371810d1 1004 output = check_output('ip -d link show sittun98')
6a97a864
YW
1005 print(output)
1006 self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local any dev dummy98")
371810d1 1007 output = check_output('ip -d link show sittun97')
6a97a864
YW
1008 print(output)
1009 self.assertRegex(output, "sit (?:ip6ip |)remote any local 10.65.223.238 dev dummy98")
1f0e3109 1010
d0e728b6 1011 def test_isatap_tunnel(self):
ec38833c
ZJS
1012 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1013 '25-isatap-tunnel.netdev', '25-tunnel.network')
1014 start_networkd(0)
1015 wait_online(['isataptun99:routable', 'dummy98:degraded'])
d0e728b6 1016
371810d1 1017 output = check_output('ip -d link show isataptun99')
14ecd604 1018 print(output)
d0e728b6
SS
1019 self.assertRegex(output, "isatap ")
1020
d29dc4f1 1021 def test_6rd_tunnel(self):
ec38833c
ZJS
1022 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1023 '25-6rd-tunnel.netdev', '25-tunnel.network')
1024 start_networkd(0)
1025 wait_online(['sittun99:routable', 'dummy98:degraded'])
d29dc4f1 1026
371810d1 1027 output = check_output('ip -d link show sittun99')
6a97a864
YW
1028 print(output)
1029 self.assertRegex(output, '6rd-prefix 2602::/24')
1030
7bea7f9b 1031 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b 1032 def test_erspan_tunnel(self):
ec38833c
ZJS
1033 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1034 '25-erspan-tunnel.netdev', '25-tunnel.network',
1035 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1036 start_networkd(0)
1037 wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
2266864b 1038
371810d1 1039 output = check_output('ip -d link show erspan99')
6a97a864
YW
1040 print(output)
1041 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
38f4bb44
YW
1042 self.assertRegex(output, 'ikey 0.0.0.101')
1043 self.assertRegex(output, 'okey 0.0.0.101')
1044 self.assertRegex(output, 'iseq')
1045 self.assertRegex(output, 'oseq')
371810d1 1046 output = check_output('ip -d link show erspan98')
2266864b 1047 print(output)
6a97a864
YW
1048 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
1049 self.assertRegex(output, '102')
38f4bb44
YW
1050 self.assertRegex(output, 'ikey 0.0.0.102')
1051 self.assertRegex(output, 'okey 0.0.0.102')
1052 self.assertRegex(output, 'iseq')
1053 self.assertRegex(output, 'oseq')
2266864b 1054
1f0e3109 1055 def test_tunnel_independent(self):
ec38833c
ZJS
1056 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
1057 start_networkd(0)
e40a58b5 1058
ec38833c 1059 wait_online(['ipiptun99:carrier'])
1f0e3109 1060
4b6a6d1e
YW
1061 @expectedFailureIfModuleIsNotAvailable('fou')
1062 def test_fou(self):
1063 # The following redundant check is necessary for CentOS CI.
1064 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1065 self.assertTrue(is_module_available('fou'))
1066
ec38833c
ZJS
1067 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1068 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1069 '25-fou-gre.netdev', '25-fou-gretap.netdev')
1070 start_networkd(0)
4b6a6d1e 1071
ec38833c 1072 wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'])
4b6a6d1e 1073
371810d1 1074 output = check_output('ip fou show')
4b6a6d1e
YW
1075 print(output)
1076 self.assertRegex(output, 'port 55555 ipproto 4')
1077 self.assertRegex(output, 'port 55556 ipproto 47')
1078
371810d1 1079 output = check_output('ip -d link show ipiptun96')
4b6a6d1e
YW
1080 print(output)
1081 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1082 output = check_output('ip -d link show sittun96')
4b6a6d1e
YW
1083 print(output)
1084 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1085 output = check_output('ip -d link show gretun96')
4b6a6d1e
YW
1086 print(output)
1087 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
371810d1 1088 output = check_output('ip -d link show gretap96')
4b6a6d1e
YW
1089 print(output)
1090 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1091
1f0e3109 1092 def test_vxlan(self):
ec38833c
ZJS
1093 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1094 '11-dummy.netdev', 'vxlan-test1.network')
1095 start_networkd(0)
1f0e3109 1096
ec38833c 1097 wait_online(['test1:degraded', 'vxlan99:degraded'])
1f0e3109 1098
371810d1 1099 output = check_output('ip -d link show vxlan99')
14ecd604 1100 print(output)
1c862fe0 1101 self.assertRegex(output, '999')
1f0e3109
SS
1102 self.assertRegex(output, '5555')
1103 self.assertRegex(output, 'l2miss')
1104 self.assertRegex(output, 'l3miss')
1105 self.assertRegex(output, 'udpcsum')
1106 self.assertRegex(output, 'udp6zerocsumtx')
1107 self.assertRegex(output, 'udp6zerocsumrx')
1108 self.assertRegex(output, 'remcsumtx')
1109 self.assertRegex(output, 'remcsumrx')
1110 self.assertRegex(output, 'gbp')
1111
371810d1 1112 output = check_output('bridge fdb show dev vxlan99')
1c862fe0
YW
1113 print(output)
1114 self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1115 self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1116 self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1117
02849d8b 1118 def test_macsec(self):
ec38833c
ZJS
1119 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1120 'macsec.network', '12-dummy.netdev')
1121 start_networkd(0)
02849d8b 1122
ec38833c 1123 wait_online(['dummy98:degraded', 'macsec99:routable'])
02849d8b 1124
371810d1 1125 output = check_output('ip -d link show macsec99')
02849d8b
YW
1126 print(output)
1127 self.assertRegex(output, 'macsec99@dummy98')
1128 self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
1129 self.assertRegex(output, 'encrypt on')
1130
371810d1 1131 output = check_output('ip macsec show macsec99')
02849d8b
YW
1132 print(output)
1133 self.assertRegex(output, 'encrypt on')
1134 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
1135 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1136 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1137 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on')
1138 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1139 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1140 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1141 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1142 self.assertNotRegex(output, 'key 02030405067080900000000000000000')
1143 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
1144 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1145
811f33d0 1146 def test_nlmon(self):
ec38833c 1147 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
df7f9afa 1148 start_networkd(0)
811f33d0 1149
ec38833c 1150 wait_online(['nlmon99:carrier'])
02849d8b 1151
cff83db9
YW
1152class NetworkdL2TPTests(unittest.TestCase, Utilities):
1153
1154 links =[
1155 'l2tp-ses1',
1156 'l2tp-ses2',
1157 'l2tp-ses3',
1158 'l2tp-ses4',
1159 'test1']
1160
1161 units = [
1162 '11-dummy.netdev',
1163 '25-l2tp-dummy.network',
1164 '25-l2tp-ip.netdev',
1165 '25-l2tp-udp.netdev']
1166
1167 l2tp_tunnel_ids = [ '10' ]
1168
1169 def setUp(self):
ad78d7b0 1170 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c 1171 remove_links(self.links)
cff83db9
YW
1172
1173 def tearDown(self):
ad78d7b0 1174 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c
ZJS
1175 remove_links(self.links)
1176 remove_unit_from_networkd_path(self.units)
cff83db9
YW
1177
1178 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1179 def test_l2tp_udp(self):
ec38833c
ZJS
1180 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', '25-l2tp-udp.netdev')
1181 start_networkd(0)
cff83db9 1182
ec38833c 1183 wait_online(['test1:routable', 'l2tp-ses1:off', 'l2tp-ses2:off'])
cff83db9 1184
371810d1 1185 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1186 print(output)
1187 self.assertRegex(output, "Tunnel 10, encap UDP")
1188 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1189 self.assertRegex(output, "Peer tunnel 11")
1190 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
1191 self.assertRegex(output, "UDP checksum: enabled")
1192
371810d1 1193 output = check_output('ip l2tp show session tid 10 session_id 15')
cff83db9
YW
1194 print(output)
1195 self.assertRegex(output, "Session 15 in tunnel 10")
1196 self.assertRegex(output, "Peer session 16, tunnel 11")
1197 self.assertRegex(output, "interface name: l2tp-ses1")
1198
371810d1 1199 output = check_output('ip l2tp show session tid 10 session_id 17')
cff83db9
YW
1200 print(output)
1201 self.assertRegex(output, "Session 17 in tunnel 10")
1202 self.assertRegex(output, "Peer session 18, tunnel 11")
1203 self.assertRegex(output, "interface name: l2tp-ses2")
1204
1205 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1206 def test_l2tp_ip(self):
ec38833c
ZJS
1207 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', '25-l2tp-ip.netdev')
1208 start_networkd(0)
cff83db9 1209
ec38833c 1210 wait_online(['test1:routable', 'l2tp-ses3:off', 'l2tp-ses4:off'])
cff83db9 1211
371810d1 1212 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1213 print(output)
1214 self.assertRegex(output, "Tunnel 10, encap IP")
1215 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1216 self.assertRegex(output, "Peer tunnel 12")
1217
371810d1 1218 output = check_output('ip l2tp show session tid 10 session_id 25')
cff83db9
YW
1219 print(output)
1220 self.assertRegex(output, "Session 25 in tunnel 10")
1221 self.assertRegex(output, "Peer session 26, tunnel 12")
1222 self.assertRegex(output, "interface name: l2tp-ses3")
1223
371810d1 1224 output = check_output('ip l2tp show session tid 10 session_id 27')
cff83db9
YW
1225 print(output)
1226 self.assertRegex(output, "Session 27 in tunnel 10")
1227 self.assertRegex(output, "Peer session 28, tunnel 12")
1228 self.assertRegex(output, "interface name: l2tp-ses4")
1229
be68c2c9 1230class NetworkdNetworkTests(unittest.TestCase, Utilities):
09ea6724
YW
1231 links = [
1232 'bond199',
1233 'dummy98',
cd65d067 1234 'dummy99',
09ea6724
YW
1235 'test1']
1236
1237 units = [
1238 '11-dummy.netdev',
1239 '12-dummy.netdev',
1240 '23-active-slave.network',
1e498853 1241 '24-keep-configuration-static.network',
fdcd1ec5 1242 '24-search-domain.network',
09ea6724 1243 '25-address-link-section.network',
b8102725
YW
1244 '25-address-preferred-lifetime-zero-ipv6.network',
1245 '25-address-static.network',
cd65d067 1246 '25-bind-carrier.network',
09ea6724
YW
1247 '25-bond-active-backup-slave.netdev',
1248 '25-fibrule-invert.network',
1249 '25-fibrule-port-range.network',
1250 '25-ipv6-address-label-section.network',
e4a71bf3 1251 '25-neighbor-section.network',
05514ae1
YW
1252 '25-link-local-addressing-no.network',
1253 '25-link-local-addressing-yes.network',
09ea6724 1254 '25-link-section-unmanaged.network',
20ca06a6 1255 '25-route-ipv6-src.network',
0ef830cf 1256 '25-route-static.network',
4da33154 1257 '25-sysctl-disable-ipv6.network',
09ea6724
YW
1258 '25-sysctl.network',
1259 'configure-without-carrier.network',
b677774d 1260 'routing-policy-rule-dummy98.network',
b8102725 1261 'routing-policy-rule-test1.network']
1f0e3109 1262
95c74b0a 1263 routing_policy_rule_tables = ['7', '8']
5f68a6a4 1264 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
95c74b0a 1265
1f0e3109 1266 def setUp(self):
ec38833c
ZJS
1267 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1268 remove_routes(self.routes)
1269 remove_links(self.links)
1f0e3109
SS
1270
1271 def tearDown(self):
ec38833c
ZJS
1272 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1273 remove_routes(self.routes)
1274 remove_links(self.links)
1275 remove_unit_from_networkd_path(self.units)
1f0e3109 1276
b8102725 1277 def test_address_static(self):
ec38833c
ZJS
1278 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1279 start_networkd(0)
b8102725 1280
ec38833c 1281 wait_online(['dummy98:routable'])
b8102725 1282
371810d1 1283 output = check_output('ip -4 address show dev dummy98')
b8102725
YW
1284 print(output)
1285 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1286 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1287 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1288
1289 # invalid sections
1290 self.assertNotRegex(output, '10.10.0.1/16')
1291 self.assertNotRegex(output, '10.10.0.2/16')
1292
371810d1 1293 output = check_output('ip -4 address show dev dummy98 label 32')
b8102725
YW
1294 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1295
371810d1 1296 output = check_output('ip -4 address show dev dummy98 label 33')
b8102725
YW
1297 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1298
371810d1 1299 output = check_output('ip -4 address show dev dummy98 label 34')
b8102725
YW
1300 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1301
371810d1 1302 output = check_output('ip -4 address show dev dummy98 label 35')
b8102725
YW
1303 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1304
371810d1 1305 output = check_output('ip -6 address show dev dummy98')
b8102725
YW
1306 print(output)
1307 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1308 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1309 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1310 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1311 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1312 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1313
1314 def test_address_preferred_lifetime_zero_ipv6(self):
ec38833c 1315 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero-ipv6.network', '12-dummy.netdev')
01943d43 1316 start_networkd(5)
1f0e3109 1317
e39cc445 1318 self.check_link_exists('dummy98')
791c1140 1319 self.check_operstate('dummy98', 'routable', setup_state='configuring')
b8102725 1320
371810d1 1321 output = check_output('ip address show dummy98')
b8102725
YW
1322 print(output)
1323 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1324 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1f0e3109
SS
1325
1326 def test_configure_without_carrier(self):
ec38833c 1327 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
df7f9afa
YW
1328 start_networkd(0)
1329 wait_online(['test1:routable'])
e40a58b5 1330
371810d1 1331 output = check_output(*networkctl_cmd, 'status', 'test1')
1f0e3109
SS
1332 print(output)
1333 self.assertRegex(output, '192.168.0.15')
1334 self.assertRegex(output, '192.168.0.1')
1335 self.assertRegex(output, 'routable')
1336
1f0e3109 1337 def test_routing_policy_rule(self):
ec38833c 1338 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
df7f9afa
YW
1339 start_networkd(0)
1340 wait_online(['test1:degraded'])
e40a58b5 1341
371810d1 1342 output = check_output('ip rule')
1f0e3109
SS
1343 print(output)
1344 self.assertRegex(output, '111')
1345 self.assertRegex(output, 'from 192.168.100.18')
f7bdd562 1346 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
1f0e3109
SS
1347 self.assertRegex(output, 'iif test1')
1348 self.assertRegex(output, 'oif test1')
1349 self.assertRegex(output, 'lookup 7')
1350
b677774d 1351 def test_routing_policy_rule_issue_11280(self):
ec38833c
ZJS
1352 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1353 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
b677774d 1354
b677774d
YW
1355 for trial in range(3):
1356 # Remove state files only first time
df7f9afa
YW
1357 start_networkd(0, remove_state_files=(trial == 0))
1358 wait_online(['test1:degraded', 'dummy98:degraded'])
1359 time.sleep(1)
b677774d 1360
371810d1 1361 output = check_output('ip rule list table 7')
b677774d
YW
1362 print(output)
1363 self.assertRegex(output, '111: from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
1364
371810d1 1365 output = check_output('ip rule list table 8')
b677774d
YW
1366 print(output)
1367 self.assertRegex(output, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1368
d586a2c3 1369 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0 1370 def test_routing_policy_rule_port_range(self):
ec38833c 1371 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
df7f9afa
YW
1372 start_networkd(0)
1373 wait_online(['test1:degraded'])
e40a58b5 1374
371810d1 1375 output = check_output('ip rule')
926062f0
SS
1376 print(output)
1377 self.assertRegex(output, '111')
1378 self.assertRegex(output, 'from 192.168.100.18')
1379 self.assertRegex(output, '1123-1150')
1380 self.assertRegex(output, '3224-3290')
1381 self.assertRegex(output, 'tcp')
1382 self.assertRegex(output, 'lookup 7')
1f0e3109 1383
d586a2c3 1384 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd 1385 def test_routing_policy_rule_invert(self):
ec38833c 1386 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
df7f9afa
YW
1387 start_networkd(0)
1388 wait_online(['test1:degraded'])
e40a58b5 1389
371810d1 1390 output = check_output('ip rule')
efecf9cd 1391 print(output)
efecf9cd
SS
1392 self.assertRegex(output, '111')
1393 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1394 self.assertRegex(output, 'tcp')
1395 self.assertRegex(output, 'lookup 7')
1396
0ef830cf 1397 def test_route_static(self):
ec38833c
ZJS
1398 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1399 start_networkd(0)
ec38833c 1400 wait_online(['dummy98:routable'])
0d34228f 1401
371810d1 1402 output = check_output('ip -6 route show dev dummy98')
0d34228f 1403 print(output)
0ef830cf
YW
1404 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1405 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1f0e3109 1406
371810d1 1407 output = check_output('ip -6 route show dev dummy98 default')
0ef830cf 1408 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1f0e3109 1409
371810d1 1410 output = check_output('ip -4 route show dev dummy98')
1f0e3109 1411 print(output)
0ef830cf
YW
1412 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1413 self.assertRegex(output, '149.10.124.64 proto static scope link')
2b00dff8 1414 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
0ef830cf
YW
1415 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1416 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
1f0e3109 1417
371810d1 1418 output = check_output('ip -4 route show dev dummy98 default')
0ef830cf
YW
1419 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1420 self.assertRegex(output, 'default via 149.10.124.64 proto static')
6543b7fd 1421 self.assertRegex(output, 'default proto static')
1f0e3109 1422
371810d1 1423 output = check_output('ip route show type blackhole')
1f0e3109 1424 print(output)
0ef830cf 1425 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
f5050e48 1426
371810d1 1427 output = check_output('ip route show type unreachable')
f5050e48 1428 print(output)
0ef830cf 1429 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
f5050e48 1430
371810d1 1431 output = check_output('ip route show type prohibit')
f5050e48 1432 print(output)
0ef830cf 1433 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
f5050e48 1434
20ca06a6
DA
1435 def test_ip_route_ipv6_src_route(self):
1436 # a dummy device does not make the addresses go through tentative state, so we
1437 # reuse a bond from an earlier test, which does make the addresses go through
1438 # tentative state, and do our test on that
ec38833c 1439 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
df7f9afa
YW
1440 start_networkd(0)
1441 wait_online(['dummy98:enslaved', 'bond199:routable'])
20ca06a6 1442
371810d1 1443 output = check_output('ip -6 route list dev bond199')
20ca06a6
DA
1444 print(output)
1445 self.assertRegex(output, 'abcd::/16')
1446 self.assertRegex(output, 'src')
1447 self.assertRegex(output, '2001:1234:56:8f63::2')
1448
1f0e3109 1449 def test_ip_link_mac_address(self):
ec38833c 1450 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
df7f9afa
YW
1451 start_networkd(0)
1452 wait_online(['dummy98:degraded'])
1f0e3109 1453
371810d1 1454 output = check_output('ip link show dummy98')
1f0e3109
SS
1455 print(output)
1456 self.assertRegex(output, '00:01:02:aa:bb:cc')
1457
1458 def test_ip_link_unmanaged(self):
ec38833c 1459 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
df7f9afa 1460 start_networkd(5)
1f0e3109 1461
e39cc445 1462 self.check_link_exists('dummy98')
1f0e3109 1463
df7f9afa 1464 self.check_operstate('dummy98', 'off', setup_state='unmanaged')
1f0e3109
SS
1465
1466 def test_ipv6_address_label(self):
ec38833c 1467 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
df7f9afa
YW
1468 start_networkd(0)
1469 wait_online(['dummy98:degraded'])
1f0e3109 1470
371810d1 1471 output = check_output('ip addrlabel list')
1f0e3109
SS
1472 print(output)
1473 self.assertRegex(output, '2004:da8:1::/64')
1474
e4a71bf3 1475 def test_ipv6_neighbor(self):
ec38833c 1476 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
df7f9afa
YW
1477 start_networkd(0)
1478 wait_online(['dummy98:degraded'], timeout='40s')
e4a71bf3 1479
df7f9afa 1480 output = check_output('ip neigh list dev dummy98')
e4a71bf3
WKI
1481 print(output)
1482 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 1483 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 1484
05514ae1 1485 def test_link_local_addressing(self):
ec38833c
ZJS
1486 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1487 '25-link-local-addressing-no.network', '12-dummy.netdev')
1488 start_networkd(0)
1489 wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1 1490
371810d1 1491 output = check_output('ip address show dev test1')
05514ae1
YW
1492 print(output)
1493 self.assertRegex(output, 'inet .* scope link')
1494 self.assertRegex(output, 'inet6 .* scope link')
1495
371810d1 1496 output = check_output('ip address show dev dummy98')
05514ae1
YW
1497 print(output)
1498 self.assertNotRegex(output, 'inet6* .* scope link')
1499
05514ae1
YW
1500 '''
1501 Documentation/networking/ip-sysctl.txt
1502
1503 addr_gen_mode - INTEGER
1504 Defines how link-local and autoconf addresses are generated.
1505
1506 0: generate address based on EUI64 (default)
1507 1: do no generate a link-local address, use EUI64 for addresses generated
1508 from autoconf
1509 2: generate stable privacy addresses, using the secret from
1510 stable_secret (RFC7217)
1511 3: generate stable privacy addresses, using a random secret if unset
1512 '''
1513
1514 test1_addr_gen_mode = ''
1515 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
1516 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
1517 try:
1518 f.readline()
1519 except IOError:
1520 # if stable_secret is unset, then EIO is returned
1521 test1_addr_gen_mode = '0'
1522 else:
1523 test1_addr_gen_mode = '2'
1524 else:
1525 test1_addr_gen_mode = '0'
1526
1527 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
ec38833c 1528 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
05514ae1
YW
1529
1530 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
ec38833c 1531 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
05514ae1 1532
1f0e3109 1533 def test_sysctl(self):
ec38833c
ZJS
1534 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1535 start_networkd(0)
1536 wait_online(['dummy98:degraded'])
1537
1538 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1539 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1540 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1541 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1542 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1543 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1544 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1f0e3109 1545
4da33154 1546 def test_sysctl_disable_ipv6(self):
ec38833c 1547 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
4da33154
YW
1548
1549 print('## Disable ipv6')
cefd6b3d
ZJS
1550 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
1551 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
4da33154 1552
ec38833c
ZJS
1553 start_networkd(0)
1554 wait_online(['dummy98:routable'])
4da33154 1555
371810d1 1556 output = check_output('ip -4 address show dummy98')
4da33154
YW
1557 print(output)
1558 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 1559 output = check_output('ip -6 address show dummy98')
4da33154
YW
1560 print(output)
1561 self.assertEqual(output, '')
4933b97d
YW
1562 output = check_output('ip -4 route show dev dummy98')
1563 print(output)
1564 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1565 output = check_output('ip -6 route show dev dummy98')
1566 print(output)
1567 self.assertEqual(output, '')
4da33154 1568
cefd6b3d 1569 check_output('ip link del dummy98')
4da33154
YW
1570
1571 print('## Enable ipv6')
cefd6b3d
ZJS
1572 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
1573 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
4da33154 1574
ec38833c
ZJS
1575 start_networkd(0)
1576 wait_online(['dummy98:routable'])
4da33154 1577
371810d1 1578 output = check_output('ip -4 address show dummy98')
4da33154
YW
1579 print(output)
1580 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 1581 output = check_output('ip -6 address show dummy98')
4da33154 1582 print(output)
4933b97d 1583 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
4da33154 1584 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
1585 output = check_output('ip -4 route show dev dummy98')
1586 print(output)
1587 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1588 output = check_output('ip -6 route show dev dummy98')
1589 print(output)
1590 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
4da33154 1591
cd65d067 1592 def test_bind_carrier(self):
ec38833c 1593 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
df7f9afa
YW
1594 start_networkd(0)
1595 wait_online(['test1:routable'])
cd65d067 1596
cefd6b3d
ZJS
1597 check_output('ip link add dummy98 type dummy')
1598 check_output('ip link set dummy98 up')
b117044c 1599 time.sleep(2)
371810d1 1600 output = check_output('ip address show test1')
cd65d067
YW
1601 print(output)
1602 self.assertRegex(output, 'UP,LOWER_UP')
1603 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
791c1140 1604 self.check_operstate('test1', 'routable')
cd65d067 1605
cefd6b3d
ZJS
1606 check_output('ip link add dummy99 type dummy')
1607 check_output('ip link set dummy99 up')
b117044c 1608 time.sleep(2)
371810d1 1609 output = check_output('ip address show test1')
cd65d067
YW
1610 print(output)
1611 self.assertRegex(output, 'UP,LOWER_UP')
1612 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
791c1140 1613 self.check_operstate('test1', 'routable')
cd65d067 1614
cefd6b3d 1615 check_output('ip link del dummy98')
b117044c 1616 time.sleep(2)
371810d1 1617 output = check_output('ip address show test1')
cd65d067
YW
1618 print(output)
1619 self.assertRegex(output, 'UP,LOWER_UP')
1620 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
791c1140 1621 self.check_operstate('test1', 'routable')
cd65d067 1622
cefd6b3d 1623 check_output('ip link del dummy99')
b117044c 1624 time.sleep(2)
371810d1 1625 output = check_output('ip address show test1')
cd65d067
YW
1626 print(output)
1627 self.assertNotRegex(output, 'UP,LOWER_UP')
1628 self.assertRegex(output, 'DOWN')
1629 self.assertNotRegex(output, '192.168.10')
791c1140 1630 self.check_operstate('test1', 'off')
cd65d067 1631
cefd6b3d
ZJS
1632 check_output('ip link add dummy98 type dummy')
1633 check_output('ip link set dummy98 up')
b117044c 1634 time.sleep(2)
371810d1 1635 output = check_output('ip address show test1')
cd65d067
YW
1636 print(output)
1637 self.assertRegex(output, 'UP,LOWER_UP')
1638 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
791c1140 1639 self.check_operstate('test1', 'routable')
cd65d067 1640
fdcd1ec5 1641 def test_domain(self):
ec38833c
ZJS
1642 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1643 start_networkd(0)
1644 wait_online(['dummy98:routable'])
fdcd1ec5 1645
371810d1 1646 output = check_output(*networkctl_cmd, 'status', 'dummy98', env=env)
fdcd1ec5
YW
1647 print(output)
1648 self.assertRegex(output, 'Address: 192.168.42.100')
1649 self.assertRegex(output, 'DNS: 192.168.42.1')
1650 self.assertRegex(output, 'Search Domains: one')
1651
1e498853
YW
1652 def test_keep_configuration_static(self):
1653 check_output('systemctl stop systemd-networkd')
1654
1655 check_output('ip link add name dummy98 type dummy')
1656 check_output('ip address add 10.1.2.3/16 dev dummy98')
1657 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
1658 output = check_output('ip address show dummy98')
1659 print(output)
1660 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
1661 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
1662 output = check_output('ip route show dev dummy98')
1663 print(output)
1664
1665 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
1666 start_networkd(0)
1667 wait_online(['dummy98:routable'])
1668
1669 output = check_output('ip address show dummy98')
1670 print(output)
1671 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
1672 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
1673
be68c2c9 1674class NetworkdBondTests(unittest.TestCase, Utilities):
c3a8853f 1675 links = [
c2990ec3 1676 'bond199',
c3a8853f 1677 'bond99',
cc3e488c
YW
1678 'dummy98',
1679 'test1']
c3a8853f
YW
1680
1681 units = [
cc3e488c
YW
1682 '11-dummy.netdev',
1683 '12-dummy.netdev',
c2990ec3
YW
1684 '23-active-slave.network',
1685 '23-bond199.network',
1686 '23-primary-slave.network',
1687 '23-test1-bond199.network',
1688 '25-bond-active-backup-slave.netdev',
c3a8853f 1689 '25-bond.netdev',
c3a8853f 1690 'bond99.network',
cc3e488c 1691 'bond-slave.network']
c3a8853f
YW
1692
1693 def setUp(self):
ec38833c 1694 remove_links(self.links)
c3a8853f
YW
1695
1696 def tearDown(self):
ec38833c
ZJS
1697 remove_links(self.links)
1698 remove_unit_from_networkd_path(self.units)
c3a8853f 1699
c2990ec3 1700 def test_bond_active_slave(self):
ec38833c
ZJS
1701 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1702 start_networkd()
c2990ec3 1703
e39cc445
YW
1704 self.check_link_exists('dummy98')
1705 self.check_link_exists('bond199')
c2990ec3 1706
371810d1 1707 output = check_output('ip -d link show bond199')
c2990ec3
YW
1708 print(output)
1709 self.assertRegex(output, 'active_slave dummy98')
1710
1711 def test_bond_primary_slave(self):
ec38833c
ZJS
1712 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
1713 start_networkd()
c2990ec3 1714
e39cc445
YW
1715 self.check_link_exists('test1')
1716 self.check_link_exists('bond199')
c2990ec3 1717
371810d1 1718 output = check_output('ip -d link show bond199')
c2990ec3
YW
1719 print(output)
1720 self.assertRegex(output, 'primary test1')
1721
cc3e488c 1722 def test_bond_operstate(self):
ec38833c
ZJS
1723 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
1724 'bond99.network','bond-slave.network')
1725 start_networkd()
c3a8853f 1726
e39cc445
YW
1727 self.check_link_exists('bond99')
1728 self.check_link_exists('dummy98')
1729 self.check_link_exists('test1')
c3a8853f 1730
371810d1 1731 output = check_output('ip -d link show dummy98')
c3a8853f 1732 print(output)
cc3e488c 1733 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 1734
371810d1 1735 output = check_output('ip -d link show test1')
c3a8853f
YW
1736 print(output)
1737 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1738
371810d1 1739 output = check_output('ip -d link show bond99')
c3a8853f
YW
1740 print(output)
1741 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
1742
791c1140
YW
1743 self.check_operstate('dummy98', 'enslaved')
1744 self.check_operstate('test1', 'enslaved')
1745 self.check_operstate('bond99', 'routable')
c3a8853f 1746
cefd6b3d 1747 check_output('ip link set dummy98 down')
c3a8853f
YW
1748 time.sleep(2)
1749
791c1140
YW
1750 self.check_operstate('dummy98', 'off')
1751 self.check_operstate('test1', 'enslaved')
1752 self.check_operstate('bond99', 'degraded-carrier')
c3a8853f 1753
cefd6b3d 1754 check_output('ip link set dummy98 up')
c3a8853f
YW
1755 time.sleep(2)
1756
791c1140
YW
1757 self.check_operstate('dummy98', 'enslaved')
1758 self.check_operstate('test1', 'enslaved')
1759 self.check_operstate('bond99', 'routable')
c3a8853f 1760
cefd6b3d
ZJS
1761 check_output('ip link set dummy98 down')
1762 check_output('ip link set test1 down')
2700d2c7 1763 time.sleep(2)
cc3e488c 1764
791c1140
YW
1765 self.check_operstate('dummy98', 'off')
1766 self.check_operstate('test1', 'off')
2700d2c7 1767
2700d2c7
YW
1768 for trial in range(30):
1769 if trial > 0:
1770 time.sleep(1)
371810d1 1771 output = check_output('ip address show bond99')
2700d2c7 1772 print(output)
ec38833c 1773 if get_operstate('bond99') == 'no-carrier':
2700d2c7
YW
1774 break
1775 else:
1776 # Huh? Kernel does not recognize that all slave interfaces are down?
1777 # Let's confirm that networkd's operstate is consistent with ip's result.
1778 self.assertNotRegex(output, 'NO-CARRIER')
cc3e488c 1779
be68c2c9 1780class NetworkdBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
1781 links = [
1782 'bridge99',
1783 'dummy98',
1784 'test1']
1785
1786 units = [
1787 '11-dummy.netdev',
1788 '12-dummy.netdev',
1789 '26-bridge.netdev',
1790 '26-bridge-slave-interface-1.network',
1791 '26-bridge-slave-interface-2.network',
804b6cd2 1792 'bridge99-ignore-carrier-loss.network',
09ea6724 1793 'bridge99.network']
1f0e3109
SS
1794
1795 def setUp(self):
ec38833c 1796 remove_links(self.links)
1f0e3109
SS
1797
1798 def tearDown(self):
ec38833c
ZJS
1799 remove_links(self.links)
1800 remove_unit_from_networkd_path(self.units)
1f0e3109
SS
1801
1802 def test_bridge_property(self):
ec38833c
ZJS
1803 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1804 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1805 'bridge99.network')
1806 start_networkd()
1f0e3109 1807
e39cc445
YW
1808 self.check_link_exists('dummy98')
1809 self.check_link_exists('test1')
1810 self.check_link_exists('bridge99')
1f0e3109 1811
371810d1 1812 output = check_output('ip -d link show test1')
1f0e3109
SS
1813 print(output)
1814 self.assertRegex(output, 'master')
1815 self.assertRegex(output, 'bridge')
1816
371810d1 1817 output = check_output('ip -d link show dummy98')
1f0e3109
SS
1818 print(output)
1819 self.assertRegex(output, 'master')
1820 self.assertRegex(output, 'bridge')
1821
371810d1 1822 output = check_output('ip addr show bridge99')
1f0e3109 1823 print(output)
2be6c5d2 1824 self.assertRegex(output, '192.168.0.15/24')
1f0e3109 1825
371810d1 1826 output = check_output('bridge -d link show dummy98')
1f0e3109 1827 print(output)
ec38833c
ZJS
1828 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
1829 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
1830 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
1831 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
1832 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
7f15b714 1833 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
ec38833c
ZJS
1834 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
1835 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
4d7ed14f
SS
1836
1837 # CONFIG_BRIDGE_IGMP_SNOOPING=y
1838 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
ec38833c 1839 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1f0e3109 1840
791c1140
YW
1841 self.check_operstate('test1', 'enslaved')
1842 self.check_operstate('dummy98', 'enslaved')
1843 self.check_operstate('bridge99', 'routable')
2be6c5d2 1844
371810d1 1845 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
1846 time.sleep(1)
1847
371810d1 1848 output = check_output('ip addr show bridge99')
2be6c5d2
YW
1849 print(output)
1850 self.assertRegex(output, '192.168.0.16/24')
1851
791c1140 1852 self.check_operstate('bridge99', 'routable')
2be6c5d2 1853
371810d1 1854 self.assertEqual(call('ip link del test1'), 0)
2be6c5d2
YW
1855 time.sleep(3)
1856
791c1140 1857 self.check_operstate('bridge99', 'degraded-carrier')
2be6c5d2 1858
cefd6b3d 1859 check_output('ip link del dummy98')
804b6cd2
YW
1860 time.sleep(3)
1861
791c1140 1862 self.check_operstate('bridge99', 'no-carrier')
2be6c5d2 1863
371810d1 1864 output = check_output('ip address show bridge99')
804b6cd2
YW
1865 print(output)
1866 self.assertRegex(output, 'NO-CARRIER')
1867 self.assertNotRegex(output, '192.168.0.15/24')
1868 self.assertNotRegex(output, '192.168.0.16/24')
1869
1870 def test_bridge_ignore_carrier_loss(self):
ec38833c
ZJS
1871 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1872 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1873 'bridge99-ignore-carrier-loss.network')
371810d1 1874 call('ip rule del table 100')
703bc7a2 1875
ec38833c 1876 start_networkd()
804b6cd2 1877
e39cc445
YW
1878 self.check_link_exists('dummy98')
1879 self.check_link_exists('test1')
1880 self.check_link_exists('bridge99')
804b6cd2 1881
371810d1 1882 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
1883 time.sleep(1)
1884
371810d1
ZJS
1885 check_output('ip link del test1')
1886 check_output('ip link del dummy98')
804b6cd2
YW
1887 time.sleep(3)
1888
371810d1 1889 output = check_output('ip address show bridge99')
804b6cd2
YW
1890 print(output)
1891 self.assertRegex(output, 'NO-CARRIER')
1892 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1893 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
1894
371810d1 1895 call('ip rule del table 100')
6609924c
YW
1896
1897 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
ec38833c
ZJS
1898 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
1899 'bridge99-ignore-carrier-loss.network')
703bc7a2 1900
371810d1 1901 call('ip rule del table 100')
703bc7a2 1902
ec38833c 1903 start_networkd()
6609924c 1904
e39cc445 1905 self.check_link_exists('bridge99')
6609924c 1906
cefd6b3d
ZJS
1907 check_output('ip link add dummy98 type dummy')
1908 check_output('ip link set dummy98 up')
1909 check_output('ip link del dummy98')
6609924c 1910
cefd6b3d
ZJS
1911 check_output('ip link add dummy98 type dummy')
1912 check_output('ip link set dummy98 up')
1913 check_output('ip link del dummy98')
6609924c 1914
cefd6b3d
ZJS
1915 check_output('ip link add dummy98 type dummy')
1916 check_output('ip link set dummy98 up')
1917 check_output('ip link del dummy98')
6609924c 1918
cefd6b3d
ZJS
1919 check_output('ip link add dummy98 type dummy')
1920 check_output('ip link set dummy98 up')
6609924c 1921
be0e1ef9
YW
1922 for trial in range(30):
1923 if trial > 0:
1924 time.sleep(1)
ec38833c 1925 if get_operstate('bridge99') == 'routable' and get_operstate('dummy98') == 'enslaved':
be0e1ef9
YW
1926 break
1927 else:
1928 self.assertTrue(False)
6609924c 1929
371810d1 1930 output = check_output('ip address show bridge99')
6609924c
YW
1931 print(output)
1932 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1933
371810d1 1934 output = check_output('ip rule list table 100')
6609924c
YW
1935 print(output)
1936 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
1937
371810d1 1938 call('ip rule del table 100')
6609924c 1939
be68c2c9 1940class NetworkdLLDPTests(unittest.TestCase, Utilities):
1f0e3109
SS
1941 links = ['veth99']
1942
09ea6724
YW
1943 units = [
1944 '23-emit-lldp.network',
1945 '24-lldp.network',
1946 '25-veth.netdev']
1f0e3109
SS
1947
1948 def setUp(self):
ec38833c 1949 remove_links(self.links)
1f0e3109
SS
1950
1951 def tearDown(self):
ec38833c
ZJS
1952 remove_links(self.links)
1953 remove_unit_from_networkd_path(self.units)
1f0e3109
SS
1954
1955 def test_lldp(self):
ec38833c
ZJS
1956 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
1957 start_networkd(0)
1958 wait_online(['veth99:degraded', 'veth-peer:degraded'])
1f0e3109 1959
371810d1 1960 output = check_output(*networkctl_cmd, 'lldp', env=env)
1f0e3109
SS
1961 print(output)
1962 self.assertRegex(output, 'veth-peer')
1963 self.assertRegex(output, 'veth99')
1964
be68c2c9 1965class NetworkdRATests(unittest.TestCase, Utilities):
1f0e3109
SS
1966 links = ['veth99']
1967
09ea6724
YW
1968 units = [
1969 '25-veth.netdev',
1970 'ipv6-prefix.network',
1971 'ipv6-prefix-veth.network']
1f0e3109
SS
1972
1973 def setUp(self):
ec38833c 1974 remove_links(self.links)
1f0e3109
SS
1975
1976 def tearDown(self):
ec38833c
ZJS
1977 remove_links(self.links)
1978 remove_unit_from_networkd_path(self.units)
1f0e3109
SS
1979
1980 def test_ipv6_prefix_delegation(self):
ec38833c
ZJS
1981 warn_about_firewalld()
1982 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1983 start_networkd(0)
1984 wait_online(['veth99:routable', 'veth-peer:degraded'])
1f0e3109 1985
371810d1 1986 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
1987 print(output)
1988 self.assertRegex(output, '2002:da8:1:0')
1989
be68c2c9 1990class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
fdcd1ec5 1991 links = ['veth99']
09ea6724
YW
1992
1993 units = [
09ea6724
YW
1994 '25-veth.netdev',
1995 'dhcp-client.network',
1996 'dhcp-client-timezone-router.network',
1997 'dhcp-server.network',
1998 'dhcp-server-timezone-router.network']
1f0e3109
SS
1999
2000 def setUp(self):
ec38833c 2001 remove_links(self.links)
1f0e3109
SS
2002
2003 def tearDown(self):
ec38833c
ZJS
2004 remove_links(self.links)
2005 remove_unit_from_networkd_path(self.units)
1f0e3109
SS
2006
2007 def test_dhcp_server(self):
ec38833c
ZJS
2008 warn_about_firewalld()
2009 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2010 start_networkd(0)
2011 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2012
371810d1 2013 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
2014 print(output)
2015 self.assertRegex(output, '192.168.5.*')
2016 self.assertRegex(output, 'Gateway: 192.168.5.1')
2017 self.assertRegex(output, 'DNS: 192.168.5.1')
2018 self.assertRegex(output, 'NTP: 192.168.5.1')
2019
1f0e3109 2020 def test_emit_router_timezone(self):
ec38833c
ZJS
2021 warn_about_firewalld()
2022 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2023 start_networkd(0)
2024 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2025
371810d1 2026 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
2027 print(output)
2028 self.assertRegex(output, 'Gateway: 192.168.5.*')
2029 self.assertRegex(output, '192.168.5.*')
2030 self.assertRegex(output, 'Europe/Berlin')
2031
be68c2c9 2032class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
09ea6724 2033 links = [
18c613dc
YW
2034 'veth99',
2035 'vrf99']
09ea6724
YW
2036
2037 units = [
2038 '25-veth.netdev',
18c613dc
YW
2039 '25-vrf.netdev',
2040 '25-vrf.network',
09ea6724 2041 'dhcp-client-anonymize.network',
af3b1498 2042 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
2043 'dhcp-client-ipv4-dhcp-settings.network',
2044 'dhcp-client-ipv4-only-ipv6-disabled.network',
2045 'dhcp-client-ipv4-only.network',
2046 'dhcp-client-ipv6-only.network',
2047 'dhcp-client-ipv6-rapid-commit.network',
1e498853
YW
2048 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2049 'dhcp-client-keep-configuration-dhcp.network',
09ea6724
YW
2050 'dhcp-client-listen-port.network',
2051 'dhcp-client-route-metric.network',
2052 'dhcp-client-route-table.network',
18c613dc 2053 'dhcp-client-vrf.network',
117a55c7
YW
2054 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2055 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
3e9d5552 2056 'dhcp-client.network',
09ea6724 2057 'dhcp-server-veth-peer.network',
30d3b54e
YW
2058 'dhcp-v4-server-veth-peer.network',
2059 'static.network']
1f0e3109
SS
2060
2061 def setUp(self):
ec38833c
ZJS
2062 stop_dnsmasq(dnsmasq_pid_file)
2063 remove_links(self.links)
1f0e3109
SS
2064
2065 def tearDown(self):
ec38833c
ZJS
2066 stop_dnsmasq(dnsmasq_pid_file)
2067 remove_lease_file()
2068 remove_log_file()
2069 remove_links(self.links)
2070 remove_unit_from_networkd_path(self.units)
1f0e3109
SS
2071
2072 def test_dhcp_client_ipv6_only(self):
ec38833c 2073 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109 2074
ec38833c
ZJS
2075 start_networkd(0)
2076 wait_online(['veth-peer:carrier'])
2077 start_dnsmasq()
2078 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2079
371810d1 2080 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
2081 print(output)
2082 self.assertRegex(output, '2600::')
2083 self.assertNotRegex(output, '192.168.5')
2084
3a956d38 2085 # Confirm that ipv6 token is not set in the kernel
371810d1 2086 output = check_output('ip token show dev veth99')
3a956d38
YW
2087 print(output)
2088 self.assertRegex(output, 'token :: dev veth99')
2089
1f0e3109 2090 def test_dhcp_client_ipv4_only(self):
ec38833c 2091 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109 2092
ec38833c
ZJS
2093 start_networkd(0)
2094 wait_online(['veth-peer:carrier'])
2095 start_dnsmasq()
2096 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2097
371810d1 2098 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
2099 print(output)
2100 self.assertNotRegex(output, '2600::')
2101 self.assertRegex(output, '192.168.5')
2102
2103 def test_dhcp_client_ipv4_ipv6(self):
ec38833c
ZJS
2104 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2105 'dhcp-client-ipv4-only.network')
2106 start_networkd(0)
2107 wait_online(['veth-peer:carrier'])
2108 start_dnsmasq()
2109 wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
2110
2111 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79
YW
2112 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2113 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 2114
371810d1 2115 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
2116 print(output)
2117 self.assertRegex(output, '2600::')
2118 self.assertRegex(output, '192.168.5')
2119
2120 def test_dhcp_client_settings(self):
ec38833c 2121 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 2122
ec38833c
ZJS
2123 start_networkd(0)
2124 wait_online(['veth-peer:carrier'])
2125 start_dnsmasq()
2126 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2127
0ae7a66d 2128 print('## ip address show dev veth99')
371810d1 2129 output = check_output('ip address show dev veth99')
1f0e3109
SS
2130 print(output)
2131 self.assertRegex(output, '12:34:56:78:9a:bc')
2132 self.assertRegex(output, '192.168.5')
2133 self.assertRegex(output, '1492')
2134
0ae7a66d
YW
2135 # issue #8726
2136 print('## ip route show table main dev veth99')
371810d1 2137 output = check_output('ip route show table main dev veth99')
1f0e3109 2138 print(output)
0ae7a66d 2139 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 2140
0ae7a66d 2141 print('## ip route show table 211 dev veth99')
371810d1 2142 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
2143 print(output)
2144 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
2145 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2146 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
2147
2148 print('## dnsmasq log')
ec38833c
ZJS
2149 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2150 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2151 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
2152 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
2153
2154 def test_dhcp6_client_settings_rapidcommit_true(self):
ec38833c
ZJS
2155 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2156 start_networkd(0)
2157 wait_online(['veth-peer:carrier'])
2158 start_dnsmasq()
2159 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2160
371810d1 2161 output = check_output('ip address show dev veth99')
1f0e3109
SS
2162 print(output)
2163 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 2164 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
2165
2166 def test_dhcp6_client_settings_rapidcommit_false(self):
ec38833c
ZJS
2167 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2168 start_networkd(0)
2169 wait_online(['veth-peer:carrier'])
2170 start_dnsmasq()
2171 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2172
371810d1 2173 output = check_output('ip address show dev veth99')
1f0e3109
SS
2174 print(output)
2175 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 2176 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
2177
2178 def test_dhcp_client_settings_anonymize(self):
ec38833c
ZJS
2179 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2180 start_networkd(0)
2181 wait_online(['veth-peer:carrier'])
2182 start_dnsmasq()
2183 wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2184
ec38833c
ZJS
2185 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2186 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
2187 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
2188
2189 def test_dhcp_client_listen_port(self):
ec38833c
ZJS
2190 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2191 start_networkd(0)
2192 wait_online(['veth-peer:carrier'])
2193 start_dnsmasq('--dhcp-alternate-port=67,5555')
2194 wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
2195
2196 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79
YW
2197 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2198 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 2199
371810d1 2200 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
2201 print(output)
2202 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109
SS
2203
2204 def test_dhcp_route_table_id(self):
ec38833c
ZJS
2205 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2206 start_networkd(0)
2207 wait_online(['veth-peer:carrier'])
2208 start_dnsmasq()
2209 wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2210
371810d1 2211 output = check_output('ip route show table 12')
1f0e3109 2212 print(output)
1f0e3109
SS
2213 self.assertRegex(output, 'veth99 proto dhcp')
2214 self.assertRegex(output, '192.168.5.1')
2215
2216 def test_dhcp_route_metric(self):
ec38833c
ZJS
2217 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2218 start_networkd(0)
2219 wait_online(['veth-peer:carrier'])
2220 start_dnsmasq()
2221 wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2222
371810d1 2223 output = check_output('ip route show dev veth99')
1f0e3109 2224 print(output)
1f0e3109
SS
2225 self.assertRegex(output, 'metric 24')
2226
1e498853
YW
2227 def test_dhcp_keep_configuration_dhcp(self):
2228 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
ec38833c
ZJS
2229 start_networkd(0)
2230 wait_online(['veth-peer:carrier'])
1e498853 2231 start_dnsmasq(lease_time='2m')
ec38833c 2232 wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2233
1e498853
YW
2234 output = check_output('ip address show dev veth99 scope global')
2235 print(output)
2236 self.assertRegex(output, r'192.168.5.*')
2237
371810d1 2238 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109 2239 print(output)
1e498853 2240 self.assertRegex(output, r'192.168.5.*')
e40a58b5 2241
5238e957 2242 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
ec38833c 2243 stop_dnsmasq(dnsmasq_pid_file)
1f0e3109
SS
2244
2245 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 2246 print('Wait for the dynamic address to be expired')
1f0e3109
SS
2247 time.sleep(125)
2248
1e498853
YW
2249 print('The lease address should be kept after lease expired')
2250 output = check_output('ip address show dev veth99 scope global')
2251 print(output)
2252 self.assertRegex(output, r'192.168.5.*')
2253
371810d1 2254 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109 2255 print(output)
1e498853
YW
2256 self.assertRegex(output, r'192.168.5.*')
2257
2258 check_output('systemctl stop systemd-networkd')
2259
2260 print('The lease address should be kept after networkd stopped')
2261 output = check_output('ip address show dev veth99 scope global')
2262 print(output)
2263 self.assertRegex(output, r'192.168.5.*')
2264
2265 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2266 print(output)
2267 self.assertRegex(output, r'192.168.5.*')
2268
2269 check_output('systemctl start systemd-networkd')
2270 wait_online(['veth-peer:routable'])
2271
2272 print('Still the lease address should be kept after networkd restarted')
2273 output = check_output('ip address show dev veth99 scope global')
2274 print(output)
2275 self.assertRegex(output, r'192.168.5.*')
2276
2277 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2278 print(output)
2279 self.assertRegex(output, r'192.168.5.*')
2280
2281 def test_dhcp_keep_configuration_dhcp_on_stop(self):
2282 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2283 start_networkd(0)
2284 wait_online(['veth-peer:carrier'])
2285 start_dnsmasq(lease_time='2m')
2286 wait_online(['veth99:routable', 'veth-peer:routable'])
2287
2288 output = check_output('ip address show dev veth99 scope global')
2289 print(output)
2290 self.assertRegex(output, r'192.168.5.*')
2291
2292 stop_dnsmasq(dnsmasq_pid_file)
2293 check_output('systemctl stop systemd-networkd')
2294
2295 output = check_output('ip address show dev veth99 scope global')
2296 print(output)
2297 self.assertRegex(output, r'192.168.5.*')
2298
2299 start_networkd(0)
2300 wait_online(['veth-peer:routable'])
2301
2302 output = check_output('ip address show dev veth99 scope global')
2303 print(output)
2304 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 2305
30d3b54e 2306 def test_dhcp_client_reuse_address_as_static(self):
ec38833c
ZJS
2307 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2308 start_networkd(0)
2309 wait_online(['veth-peer:carrier'])
2310 start_dnsmasq()
2311 wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
2312
2313 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79
YW
2314 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2315 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 2316
371810d1 2317 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
2318 print(output)
2319 self.assertRegex(output, '192.168.5')
2320 self.assertRegex(output, '2600::')
2321
2629df47
YW
2322 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
2323 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
2324 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
2325 print(static_network)
2326
ec38833c 2327 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
2328
2329 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
2330 f.write(static_network)
2331
2629df47
YW
2332 # When networkd started, the links are already configured, so let's wait for 5 seconds
2333 # the links to be re-configured.
ec38833c
ZJS
2334 start_networkd(5)
2335 wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 2336
371810d1 2337 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
2338 print(output)
2339 self.assertRegex(output, '192.168.5')
2340 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2341
371810d1 2342 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
2343 print(output)
2344 self.assertRegex(output, '2600::')
2345 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2346
18c613dc
YW
2347 @expectedFailureIfModuleIsNotAvailable('vrf')
2348 def test_dhcp_client_vrf(self):
ec38833c
ZJS
2349 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2350 '25-vrf.netdev', '25-vrf.network')
2351 start_networkd(0)
2352 wait_online(['veth-peer:carrier'])
2353 start_dnsmasq()
2354 wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
2355
2356 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79
YW
2357 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2358 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
2359
2360 print('## ip -d link show dev vrf99')
371810d1 2361 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
2362 print(output)
2363 self.assertRegex(output, 'vrf table 42')
2364
2365 print('## ip address show vrf vrf99')
371810d1 2366 output = check_output('ip address show vrf vrf99')
d90f4f7d
YW
2367 print(output)
2368 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2369 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2370 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
2371 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
2372
2373 print('## ip address show dev veth99')
371810d1 2374 output = check_output('ip address show dev veth99')
18c613dc 2375 print(output)
18c613dc
YW
2376 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2377 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
d90f4f7d 2378 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
2379 self.assertRegex(output, 'inet6 .* scope link')
2380
2381 print('## ip route show vrf vrf99')
371810d1 2382 output = check_output('ip route show vrf vrf99')
18c613dc
YW
2383 print(output)
2384 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
2385 self.assertRegex(output, 'default dev veth99 proto static scope link')
2386 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
2387 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
2388 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
2389 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
2390
2391 print('## ip route show table main dev veth99')
371810d1 2392 output = check_output('ip route show table main dev veth99')
18c613dc
YW
2393 print(output)
2394 self.assertEqual(output, '')
2395
af3b1498 2396 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
2397 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2398 'dhcp-client-gateway-onlink-implicit.network')
2399 start_networkd(0)
2400 wait_online(['veth-peer:carrier'])
2401 start_dnsmasq()
2402 wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 2403
371810d1 2404 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
af3b1498
YW
2405 print(output)
2406 self.assertRegex(output, '192.168.5')
2407
371810d1 2408 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
2409 print(output)
2410 self.assertRegex(output, 'onlink')
371810d1 2411 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
2412 print(output)
2413 self.assertRegex(output, 'onlink')
2414
117a55c7 2415 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
ec38833c
ZJS
2416 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2417 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
2418 start_networkd(0)
2419 wait_online(['veth-peer:carrier'])
2420 start_dnsmasq(lease_time='2m')
2421 wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 2422
371810d1 2423 output = check_output('ip address show dev veth99')
63c598ed
YW
2424 print(output)
2425
371810d1 2426 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 2427 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 2428 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 2429 self.assertRegex(output, 'inet6 .* scope link')
371810d1 2430 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 2431 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 2432 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
2433 self.assertNotRegex(output, 'inet .* scope link')
2434
2435 print('Wait for the dynamic address to be expired')
2436 time.sleep(130)
2437
371810d1 2438 output = check_output('ip address show dev veth99')
63c598ed
YW
2439 print(output)
2440
371810d1 2441 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 2442 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 2443 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 2444 self.assertRegex(output, 'inet6 .* scope link')
371810d1 2445 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 2446 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 2447 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
2448 self.assertNotRegex(output, 'inet .* scope link')
2449
ec38833c 2450 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 2451
117a55c7 2452 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
ec38833c
ZJS
2453 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2454 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
2455 start_networkd(0)
2456 wait_online(['veth99:degraded', 'veth-peer:routable'])
117a55c7 2457
371810d1 2458 output = check_output('ip address show dev veth99')
117a55c7
YW
2459 print(output)
2460
371810d1 2461 output = check_output('ip -6 address show dev veth99 scope global dynamic')
117a55c7 2462 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 2463 output = check_output('ip -6 address show dev veth99 scope link')
117a55c7 2464 self.assertRegex(output, 'inet6 .* scope link')
371810d1 2465 output = check_output('ip -4 address show dev veth99 scope global dynamic')
117a55c7 2466 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 2467 output = check_output('ip -4 address show dev veth99 scope link')
117a55c7
YW
2468 self.assertRegex(output, 'inet .* scope link')
2469
b6efd661 2470 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
2471 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2472 'dhcp-client-ipv4-only-ipv6-disabled.network')
2473 start_networkd(0)
2474 wait_online(['veth-peer:carrier'])
2475 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
2476 wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
2477
2478 # test for issue #12490
2479
371810d1 2480 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
2481 print(output)
2482 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2483 address1=None
2484 for line in output.splitlines():
2485 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
2486 address1 = line.split()[1].split('/')[0]
2487 break
2488
371810d1 2489 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
2490 print(output)
2491 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
2492 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
2493
ec38833c
ZJS
2494 stop_dnsmasq(dnsmasq_pid_file)
2495 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
2496
2497 print('Wait for the dynamic address to be expired')
2498 time.sleep(130)
2499
371810d1 2500 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
2501 print(output)
2502 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2503 address2=None
2504 for line in output.splitlines():
2505 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
2506 address2 = line.split()[1].split('/')[0]
2507 break
2508
2509 self.assertNotEqual(address1, address2)
2510
371810d1 2511 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
2512 print(output)
2513 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
2514 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
2515 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
2516 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
2517
1f0e3109 2518if __name__ == '__main__':
9c1ae484
YW
2519 parser = argparse.ArgumentParser()
2520 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
2521 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
2522 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
2523 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
2524 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
2525 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 2526 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 2527 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 2528 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
9c1ae484
YW
2529 ns, args = parser.parse_known_args(namespace=unittest)
2530
2531 if ns.build_dir:
2532 if ns.networkd_bin or ns.wait_online_bin or ns.networkctl_bin:
2533 print('WARNING: --networkd, --wait-online, or --networkctl options are ignored when --build-dir is specified.')
2534 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
2535 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
2536 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
2537 else:
2538 if ns.networkd_bin:
2539 networkd_bin = ns.networkd_bin
2540 if ns.wait_online_bin:
2541 wait_online_bin = ns.wait_online_bin
2542 if ns.networkctl_bin:
2543 networkctl_bin = ns.networkctl_bin
2544
2545 use_valgrind = ns.use_valgrind
2546 enable_debug = ns.enable_debug
94c03122 2547 asan_options = ns.asan_options
fa4c6095 2548 lsan_options = ns.lsan_options
94c03122 2549 ubsan_options = ns.ubsan_options
9c1ae484
YW
2550
2551 if use_valgrind:
2552 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
2553 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
2554 else:
2555 networkctl_cmd = [networkctl_bin]
2556 wait_online_cmd = [wait_online_bin]
2557
2558 if enable_debug:
2559 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
2560 if asan_options:
2561 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
2562 if lsan_options:
2563 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
2564 if ubsan_options:
2565 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
2566
2567 sys.argv[1:] = args
1f0e3109
SS
2568 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
2569 verbosity=3))