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