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