]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
network: TC - introduce BFIFO
[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
7471bcb0
DS
25systemd_lib_paths=['/usr/lib/systemd', '/lib/systemd']
26which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
27
28networkd_bin=shutil.which('systemd-networkd', path=which_paths)
29resolved_bin=shutil.which('systemd-resolved', path=which_paths)
641aa412 30udevd_bin=shutil.which('systemd-udevd', path=which_paths)
7471bcb0
DS
31wait_online_bin=shutil.which('systemd-networkd-wait-online', path=which_paths)
32networkctl_bin=shutil.which('networkctl', path=which_paths)
33resolvectl_bin=shutil.which('resolvectl', path=which_paths)
34timedatectl_bin=shutil.which('timedatectl', path=which_paths)
35
9c1ae484 36use_valgrind=False
aaae5713 37enable_debug=True
9c1ae484 38env = {}
94c03122 39asan_options=None
fa4c6095 40lsan_options=None
94c03122 41ubsan_options=None
5aa58329 42
2225e7fd
YW
43running_units = []
44
371810d1
ZJS
45def check_output(*command, **kwargs):
46 # This replaces both check_output and check_call (output can be ignored)
47 command = command[0].split() + list(command[1:])
48 return subprocess.check_output(command, universal_newlines=True, **kwargs).rstrip()
49
50def call(*command, **kwargs):
51 command = command[0].split() + list(command[1:])
52 return subprocess.call(command, universal_newlines=True, **kwargs)
53
54def run(*command, **kwargs):
55 command = command[0].split() + list(command[1:])
56 return subprocess.run(command, universal_newlines=True, **kwargs)
57
7a0a37b2 58def is_module_available(module_name):
371810d1
ZJS
59 lsmod_output = check_output('lsmod')
60 module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE)
856423f1 61 return module_re.search(lsmod_output) or not call('modprobe', module_name, stderr=subprocess.DEVNULL)
7a0a37b2
EV
62
63def expectedFailureIfModuleIsNotAvailable(module_name):
64 def f(func):
65 if not is_module_available(module_name):
66 return unittest.expectedFailure(func)
67 return func
68
69 return f
70
7bea7f9b
SS
71def expectedFailureIfERSPANModuleIsNotAvailable():
72 def f(func):
856423f1 73 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', stderr=subprocess.DEVNULL)
7bea7f9b 74 if rc == 0:
371810d1 75 call('ip link del erspan99')
7bea7f9b
SS
76 return func
77 else:
78 return unittest.expectedFailure(func)
79
80 return f
81
d586a2c3
YW
82def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
83 def f(func):
856423f1 84 rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr=subprocess.DEVNULL)
d586a2c3 85 if rc == 0:
371810d1 86 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
d586a2c3
YW
87 return func
88 else:
89 return unittest.expectedFailure(func)
90
91 return f
92
93def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
94 def f(func):
856423f1 95 rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr=subprocess.DEVNULL)
d586a2c3 96 if rc == 0:
371810d1 97 call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
d586a2c3
YW
98 return func
99 else:
100 return unittest.expectedFailure(func)
101
102 return f
103
6be8e78e
YW
104def expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable():
105 def f(func):
106 support = False
107 rc = call('ip rule add from 192.168.100.19 table 7 uidrange 200-300', stderr=subprocess.DEVNULL)
108 if rc == 0:
109 ret = run('ip rule list from 192.168.100.19 table 7', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
110 if ret.returncode == 0 and 'uidrange 200-300' in ret.stdout.rstrip():
111 support = True
112 call('ip rule del from 192.168.100.19 table 7 uidrange 200-300')
113
114 if support:
115 return func
116 else:
117 return unittest.expectedFailure(func)
118
119 return f
120
e28fd95f
YW
121def expectedFailureIfLinkFileFieldIsNotSet():
122 def f(func):
123 support = False
856423f1 124 rc = call('ip link add name dummy99 type dummy', stderr=subprocess.DEVNULL)
e28fd95f
YW
125 if rc == 0:
126 ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
127 if ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout.rstrip():
128 support = True
129 call('ip link del dummy99')
130
131 if support:
132 return func
133 else:
134 return unittest.expectedFailure(func)
135
136 return f
137
086bcf5d
YW
138def expectedFailureIfNexthopIsNotAvailable():
139 def f(func):
856423f1 140 rc = call('ip nexthop list', stderr=subprocess.DEVNULL)
086bcf5d
YW
141 if rc == 0:
142 return func
143 else:
144 return unittest.expectedFailure(func)
145
146 return f
147
6934ace0
YW
148def expectedFailureIfAlternativeNameIsNotAvailable():
149 def f(func):
150 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
151 rc = call('ip link prop add dev dummy98 altname hogehogehogehogehoge', stderr=subprocess.DEVNULL)
834ea1a4 152 call('ip link del dummy98', stderr=subprocess.DEVNULL)
6934ace0
YW
153 if rc == 0:
154 return func
155 else:
156 return unittest.expectedFailure(func)
157
158 return f
159
f6c6af38
YW
160def expectedFailureIfCAKEIsNotAvailable():
161 def f(func):
162 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
163 rc = call('tc qdisc add dev dummy98 parent root cake', stderr=subprocess.DEVNULL)
164 call('ip link del dummy98', stderr=subprocess.DEVNULL)
165 if rc == 0:
166 return func
167 else:
168 return unittest.expectedFailure(func)
169
170 return f
171
be94e591
YW
172def expectedFailureIfPIEIsNotAvailable():
173 def f(func):
174 call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
175 rc = call('tc qdisc add dev dummy98 parent root pie', stderr=subprocess.DEVNULL)
176 call('ip link del dummy98', stderr=subprocess.DEVNULL)
177 if rc == 0:
178 return func
179 else:
180 return unittest.expectedFailure(func)
181
182 return f
183
1f0e3109 184def setUpModule():
2225e7fd
YW
185 global running_units
186
1f0e3109
SS
187 os.makedirs(network_unit_file_path, exist_ok=True)
188 os.makedirs(networkd_ci_path, exist_ok=True)
189
190 shutil.rmtree(networkd_ci_path)
6aea9276 191 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
1f0e3109 192
f7ada4b8
YW
193 for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service',
194 'systemd-udevd-kernel.socket', 'systemd-udevd-control.socket', 'systemd-udevd.service',
195 'firewalld.service']:
2225e7fd
YW
196 if call(f'systemctl is-active --quiet {u}') == 0:
197 check_output(f'systemctl stop {u}')
198 running_units.append(u)
c0bf6733 199
9c1ae484 200 drop_in = [
3e821525
DS
201 '[Unit]',
202 'StartLimitIntervalSec=0',
9c1ae484
YW
203 '[Service]',
204 'Restart=no',
205 'ExecStart=',
206 ]
207 if use_valgrind:
208 drop_in += [
209 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin,
94c03122 210 'PrivateTmp=yes'
9c1ae484
YW
211 ]
212 else:
213 drop_in += ['ExecStart=!!' + networkd_bin]
214 if enable_debug:
215 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
94c03122
YW
216 if asan_options:
217 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
fa4c6095
YW
218 if lsan_options:
219 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
94c03122
YW
220 if ubsan_options:
221 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
78690bb5
YW
222 if asan_options or lsan_options or ubsan_options:
223 drop_in += ['SystemCallFilter=']
fa4c6095 224 if use_valgrind or asan_options or lsan_options or ubsan_options:
94c03122 225 drop_in += ['MemoryDenyWriteExecute=no']
9c1ae484 226
9c1ae484
YW
227 os.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok=True)
228 with open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode='w') as f:
72917fcc 229 f.write('\n'.join(drop_in))
9c1ae484 230
b6d587d1
YW
231 drop_in = [
232 '[Service]',
233 'Restart=no',
234 'ExecStart=',
235 ]
236 if use_valgrind:
237 drop_in += ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin]
238 else:
239 drop_in += ['ExecStart=!!' + resolved_bin]
240 if enable_debug:
241 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
242 if asan_options:
243 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
244 if lsan_options:
245 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
246 if ubsan_options:
247 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
248 if asan_options or lsan_options or ubsan_options:
249 drop_in += ['SystemCallFilter=']
250 if use_valgrind or asan_options or lsan_options or ubsan_options:
251 drop_in += ['MemoryDenyWriteExecute=no']
252
253 os.makedirs('/run/systemd/system/systemd-resolved.service.d', exist_ok=True)
254 with open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode='w') as f:
255 f.write('\n'.join(drop_in))
256
641aa412
YW
257 drop_in = [
258 '[Service]',
259 'ExecStart=',
260 'ExecStart=!!' + udevd_bin,
261 ]
262
263 os.makedirs('/run/systemd/system/systemd-udevd.service.d', exist_ok=True)
264 with open('/run/systemd/system/systemd-udevd.service.d/00-override.conf', mode='w') as f:
265 f.write('\n'.join(drop_in))
266
371810d1
ZJS
267 check_output('systemctl daemon-reload')
268 print(check_output('systemctl cat systemd-networkd.service'))
b6d587d1 269 print(check_output('systemctl cat systemd-resolved.service'))
641aa412 270 print(check_output('systemctl cat systemd-udevd.service'))
b6d587d1 271 check_output('systemctl restart systemd-resolved')
641aa412 272 check_output('systemctl restart systemd-udevd')
9c1ae484 273
1f0e3109 274def tearDownModule():
2225e7fd
YW
275 global running_units
276
1f0e3109 277 shutil.rmtree(networkd_ci_path)
d4fda2a5 278
f7ada4b8 279 for u in ['systemd-networkd.service', 'systemd-resolved.service']:
2225e7fd 280 check_output(f'systemctl stop {u}')
d4fda2a5 281
9c1ae484 282 shutil.rmtree('/run/systemd/system/systemd-networkd.service.d')
b6d587d1 283 shutil.rmtree('/run/systemd/system/systemd-resolved.service.d')
641aa412 284 shutil.rmtree('/run/systemd/system/systemd-udevd.service.d')
371810d1 285 check_output('systemctl daemon-reload')
f7ada4b8 286 check_output('systemctl restart systemd-udevd.service')
1f0e3109 287
2225e7fd
YW
288 for u in running_units:
289 check_output(f'systemctl start {u}')
c0bf6733 290
befd4b8b
DS
291def read_link_attr(*args):
292 with open(os.path.join('/sys/class/net/', *args)) as f:
ec38833c
ZJS
293 return f.readline().strip()
294
295def read_bridge_port_attr(bridge, link, attribute):
296 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
297 path_port = 'lower_' + link + '/brport'
298 path = os.path.join(path_bridge, path_port)
299
300 with open(os.path.join(path, attribute)) as f:
301 return f.readline().strip()
302
303def link_exists(link):
304 return os.path.exists(os.path.join('/sys/class/net', link))
305
306def remove_links(links):
307 for link in links:
308 if link_exists(link):
309 call('ip link del dev', link)
310 time.sleep(1)
311
312def remove_fou_ports(ports):
313 for port in ports:
5239d7b3 314 call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
315
316def remove_routing_policy_rule_tables(tables):
317 for table in tables:
4ef39b49
YW
318 rc = 0
319 while rc == 0:
320 rc = call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
321
322def remove_routes(routes):
323 for route_type, addr in routes:
5239d7b3 324 call('ip route del', route_type, addr, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c 325
ad78d7b0 326def remove_l2tp_tunnels(tunnel_ids):
ec38833c
ZJS
327 output = check_output('ip l2tp show tunnel')
328 for tid in tunnel_ids:
329 words='Tunnel ' + tid + ', encap'
330 if words in output:
331 call('ip l2tp del tunnel tid', tid)
332 time.sleep(1)
333
334def read_ipv6_sysctl_attr(link, attribute):
335 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
336 return f.readline().strip()
337
338def read_ipv4_sysctl_attr(link, attribute):
339 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
340 return f.readline().strip()
341
9dfc1a93
DS
342def copy_unit_to_networkd_unit_path(*units, dropins=True):
343 """Copy networkd unit files into the testbed.
344
345 Any networkd unit file type can be specified, as well as drop-in files.
346
347 By default, all drop-ins for a specified unit file are copied in;
348 to avoid that specify dropins=False.
349
350 When a drop-in file is specified, its unit file is also copied in automatically.
351 """
ec38833c
ZJS
352 print()
353 for unit in units:
9dfc1a93 354 if dropins and os.path.exists(os.path.join(networkd_ci_path, unit + '.d')):
ec38833c 355 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
9dfc1a93
DS
356 if unit.endswith('.conf'):
357 dropin = unit
358 dropindir = os.path.join(network_unit_file_path, os.path.dirname(dropin))
359 os.makedirs(dropindir, exist_ok=True)
360 shutil.copy(os.path.join(networkd_ci_path, dropin), dropindir)
361 unit = os.path.dirname(dropin).rstrip('.d')
362 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
ec38833c
ZJS
363
364def remove_unit_from_networkd_path(units):
9dfc1a93
DS
365 """Remove previously copied unit files from the testbed.
366
367 Drop-ins will be removed automatically.
368 """
ec38833c
ZJS
369 for unit in units:
370 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
371 os.remove(os.path.join(network_unit_file_path, unit))
372 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
373 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
374
ec38833c 375def start_dnsmasq(additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'):
ec38833c
ZJS
376 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
377 check_output(dnsmasq_command)
378
379def stop_dnsmasq(pid_file):
380 if os.path.exists(pid_file):
381 with open(pid_file, 'r') as f:
382 pid = f.read().rstrip(' \t\r\n\0')
383 os.kill(int(pid), signal.SIGTERM)
384
385 os.remove(pid_file)
386
387def search_words_in_dnsmasq_log(words, show_all=False):
388 if os.path.exists(dnsmasq_log_file):
389 with open (dnsmasq_log_file) as in_file:
390 contents = in_file.read()
391 if show_all:
392 print(contents)
393 for line in contents.splitlines():
394 if words in line:
395 in_file.close()
396 print("%s, %s" % (words, line))
397 return True
398 return False
399
400def remove_lease_file():
401 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
402 os.remove(os.path.join(networkd_ci_path, 'lease'))
403
404def remove_log_file():
405 if os.path.exists(dnsmasq_log_file):
406 os.remove(dnsmasq_log_file)
407
aaae5713
YW
408def remove_networkd_state_files():
409 if os.path.exists(os.path.join(networkd_runtime_directory, 'state')):
ec38833c 410 os.remove(os.path.join(networkd_runtime_directory, 'state'))
aaae5713
YW
411
412def stop_networkd(show_logs=True, remove_state_files=True):
413 if show_logs:
414 invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value')
415 check_output('systemctl stop systemd-networkd')
416 if show_logs:
417 print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id))
418 if remove_state_files:
419 remove_networkd_state_files()
420
421def start_networkd(sleep_sec=0):
422 check_output('systemctl start systemd-networkd')
ec38833c
ZJS
423 if sleep_sec > 0:
424 time.sleep(sleep_sec)
425
aaae5713
YW
426def restart_networkd(sleep_sec=0, show_logs=True, remove_state_files=True):
427 stop_networkd(show_logs, remove_state_files)
428 start_networkd(sleep_sec)
429
1f0e3109 430
ec38833c 431class Utilities():
e39cc445 432 def check_link_exists(self, link):
ec38833c 433 self.assertTrue(link_exists(link))
2be0b6fc 434
a4632dc7
DS
435 def wait_operstate(self, link, operstate='degraded', setup_state='configured', setup_timeout=5, fail_assert=True):
436 """Wait for the link to reach the specified operstate and/or setup state.
437
438 Specify None or '' for either operstate or setup_state to ignore that state.
439 This will recheck until the state conditions are met or the timeout expires.
440
441 If the link successfully matches the requested state, this returns True.
442 If this times out waiting for the link to match, the behavior depends on the
443 'fail_assert' parameter; if True, this causes a test assertion failure,
444 otherwise this returns False. The default is to cause assertion failure.
445
446 Note that this function matches on *exactly* the given operstate and setup_state.
447 To wait for a link to reach *or exceed* a given operstate, use wait_online().
448 """
449 if not operstate:
450 operstate = r'\S+'
451 if not setup_state:
452 setup_state = r'\S+'
453
454 for secs in range(setup_timeout + 1):
455 output = check_output(*networkctl_cmd, '-n', '0', 'status', link, env=env)
456 print(output)
457 if re.search(rf'(?m)^\s*State:\s+{operstate}\s+\({setup_state}\)\s*$', output):
458 return True
459 # don't bother sleeping if time is up
460 if secs < setup_timeout:
461 time.sleep(1)
462 if fail_assert:
463 self.fail(f'Timed out waiting for {link} to reach state {operstate}/{setup_state}')
464 return False
2be0b6fc 465
fd372b1a 466 def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, setup_state='configured', setup_timeout=5):
0c020321
DS
467 """Wait for the link(s) to reach the specified operstate and/or setup state.
468
469 This is similar to wait_operstate() but can be used for multiple links,
470 and it also calls systemd-networkd-wait-online to wait for the given operstate.
471 The operstate should be specified in the link name, like 'eth0:degraded'.
472 If just a link name is provided, wait-online's default operstate to wait for is degraded.
473
474 The 'timeout' parameter controls the systemd-networkd-wait-online timeout, and the
475 'setup_timeout' controls the per-link timeout waiting for the setup_state.
476
477 Set 'bool_any' to True to wait for any (instead of all) of the given links.
478 If this is set, no setup_state checks are done.
479
480 Note that this function waits for the link(s) to reach *or exceed* the given operstate.
481 However, the setup_state, if specified, must be matched *exactly*.
482
483 This returns if the link(s) reached the requested operstate/setup_state; otherwise it
484 raises CalledProcessError or fails test assertion.
485 """
e2aea43f
YW
486 args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
487 if bool_any:
488 args += ['--any']
489 try:
490 check_output(*args, env=env)
491 except subprocess.CalledProcessError:
492 for link in links_with_operstate:
fc79e6ff 493 output = check_output(*networkctl_cmd, '-n', '0', 'status', link.split(':')[0], env=env)
e2aea43f
YW
494 print(output)
495 raise
fd372b1a 496 if not bool_any and setup_state:
0c020321
DS
497 for link in links_with_operstate:
498 self.wait_operstate(link.split(':')[0], None, setup_state, setup_timeout)
e2aea43f 499
53c32c2b 500 def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
2629df47
YW
501 for i in range(timeout_sec):
502 if i > 0:
503 time.sleep(1)
371810d1 504 output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
2629df47
YW
505 if re.search(address_regex, output):
506 break
507 else:
508 self.assertRegex(output, address_regex)
509
1ca44d7d
YW
510class NetworkctlTests(unittest.TestCase, Utilities):
511
512 links = [
dcd9f07c 513 'dummy98',
1ca44d7d
YW
514 'test1',
515 'veth99',
516 ]
517
518 units = [
519 '11-dummy.netdev',
6d5b4efe 520 '11-dummy-mtu.netdev',
1ca44d7d 521 '11-dummy.network',
dcd9f07c 522 '12-dummy.netdev',
6934ace0 523 '12-dummy.link',
dcd9f07c 524 '25-address-static.network',
1ca44d7d
YW
525 '25-veth.netdev',
526 'netdev-link-local-addressing-yes.network',
527 ]
528
529 def setUp(self):
ec38833c 530 remove_links(self.links)
aaae5713 531 stop_networkd(show_logs=False)
1ca44d7d
YW
532
533 def tearDown(self):
ec38833c
ZJS
534 remove_links(self.links)
535 remove_unit_from_networkd_path(self.units)
aaae5713 536 stop_networkd(show_logs=True)
1ca44d7d 537
6934ace0
YW
538 @expectedFailureIfAlternativeNameIsNotAvailable()
539 def test_altname(self):
540 copy_unit_to_networkd_unit_path('netdev-link-local-addressing-yes.network', '12-dummy.netdev', '12-dummy.link')
541 check_output('udevadm control --reload')
542 start_networkd()
543 self.wait_online(['dummy98:degraded'])
544
fc79e6ff 545 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
6934ace0
YW
546 self.assertRegex(output, 'hogehogehogehogehogehoge')
547
dcd9f07c
YW
548 def test_reconfigure(self):
549 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
550 start_networkd()
551 self.wait_online(['dummy98:routable'])
552
553 output = check_output('ip -4 address show dev dummy98')
554 print(output)
555 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
556 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
557 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
558
559 check_output('ip address del 10.1.2.3/16 dev dummy98')
560 check_output('ip address del 10.1.2.4/16 dev dummy98')
561 check_output('ip address del 10.2.2.4/16 dev dummy98')
562
563 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
564 self.wait_online(['dummy98:routable'])
565
566 output = check_output('ip -4 address show dev dummy98')
567 print(output)
568 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
569 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
570 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
571
66de8671
YW
572 def test_reload(self):
573 start_networkd(3)
574
575 copy_unit_to_networkd_unit_path('11-dummy.netdev')
576 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 577 self.wait_operstate('test1', 'off', setup_state='unmanaged')
66de8671
YW
578
579 copy_unit_to_networkd_unit_path('11-dummy.network')
580 check_output(*networkctl_cmd, 'reload', env=env)
581 self.wait_online(['test1:degraded'])
582
583 remove_unit_from_networkd_path(['11-dummy.network'])
584 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 585 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
66de8671
YW
586
587 remove_unit_from_networkd_path(['11-dummy.netdev'])
588 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 589 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
66de8671
YW
590
591 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
592 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 593 self.wait_operstate('test1', 'degraded')
66de8671 594
1ca44d7d 595 def test_glob(self):
ec38833c 596 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
2cf6fdff 597 start_networkd()
1ca44d7d 598
e2aea43f 599 self.wait_online(['test1:degraded'])
1ca44d7d 600
371810d1 601 output = check_output(*networkctl_cmd, 'list', env=env)
1ca44d7d
YW
602 self.assertRegex(output, '1 lo ')
603 self.assertRegex(output, 'test1')
604
371810d1 605 output = check_output(*networkctl_cmd, 'list', 'test1', env=env)
1ca44d7d
YW
606 self.assertNotRegex(output, '1 lo ')
607 self.assertRegex(output, 'test1')
608
371810d1 609 output = check_output(*networkctl_cmd, 'list', 'te*', env=env)
1ca44d7d
YW
610 self.assertNotRegex(output, '1 lo ')
611 self.assertRegex(output, 'test1')
612
fc79e6ff 613 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'te*', env=env)
1ca44d7d
YW
614 self.assertNotRegex(output, '1: lo ')
615 self.assertRegex(output, 'test1')
616
fc79e6ff 617 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'tes[a-z][0-9]', env=env)
1ca44d7d
YW
618 self.assertNotRegex(output, '1: lo ')
619 self.assertRegex(output, 'test1')
620
6d5b4efe 621 def test_mtu(self):
ec38833c 622 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
2cf6fdff 623 start_networkd()
6d5b4efe 624
e2aea43f 625 self.wait_online(['test1:degraded'])
6d5b4efe 626
fc79e6ff 627 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
6d5b4efe
YW
628 self.assertRegex(output, 'MTU: 1600')
629
e28fd95f
YW
630 def test_type(self):
631 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
632 start_networkd()
e2aea43f 633 self.wait_online(['test1:degraded'])
e28fd95f 634
fc79e6ff 635 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
e28fd95f
YW
636 print(output)
637 self.assertRegex(output, 'Type: ether')
638
fc79e6ff 639 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
e28fd95f
YW
640 print(output)
641 self.assertRegex(output, 'Type: loopback')
642
643 @expectedFailureIfLinkFileFieldIsNotSet()
644 def test_udev_link_file(self):
645 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
646 start_networkd()
e2aea43f 647 self.wait_online(['test1:degraded'])
e28fd95f 648
fc79e6ff 649 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
e28fd95f 650 print(output)
426654d7 651 self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
e28fd95f
YW
652 self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network')
653
fc79e6ff 654 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
e28fd95f 655 print(output)
426654d7 656 self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
e28fd95f
YW
657 self.assertRegex(output, r'Network File: n/a')
658
bee692fd 659 def test_delete_links(self):
ec38833c
ZJS
660 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
661 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 662 start_networkd()
bee692fd 663
e2aea43f 664 self.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
bee692fd 665
7a2f6fb6 666 check_output(*networkctl_cmd, 'delete', 'test1', 'veth99', env=env)
ec38833c
ZJS
667 self.assertFalse(link_exists('test1'))
668 self.assertFalse(link_exists('veth99'))
669 self.assertFalse(link_exists('veth-peer'))
bee692fd 670
1f0e3109
SS
671class NetworkdNetDevTests(unittest.TestCase, Utilities):
672
e64dc406
YW
673 links_remove_earlier = [
674 'xfrm99',
675 ]
676
677 links = [
09ea6724
YW
678 '6rdtun99',
679 'bond99',
680 'bridge99',
681 'dropin-test',
682 'dummy98',
6a97a864
YW
683 'erspan98',
684 'erspan99',
09ea6724 685 'geneve99',
4b6a6d1e 686 'gretap96',
6a97a864 687 'gretap98',
09ea6724 688 'gretap99',
4b6a6d1e 689 'gretun96',
6a97a864
YW
690 'gretun97',
691 'gretun98',
09ea6724 692 'gretun99',
b076d5d7 693 'ifb99',
6a97a864 694 'ip6gretap98',
09ea6724 695 'ip6gretap99',
42a29fcb 696 'ip6gretun96',
6a97a864
YW
697 'ip6gretun97',
698 'ip6gretun98',
699 'ip6gretun99',
700 'ip6tnl97',
701 'ip6tnl98',
09ea6724 702 'ip6tnl99',
4b6a6d1e 703 'ipiptun96',
6a97a864
YW
704 'ipiptun97',
705 'ipiptun98',
09ea6724
YW
706 'ipiptun99',
707 'ipvlan99',
956c8fec 708 'ipvtap99',
09ea6724
YW
709 'isataptun99',
710 'macvlan99',
711 'macvtap99',
811f33d0 712 'nlmon99',
4b6a6d1e 713 'sittun96',
6a97a864
YW
714 'sittun97',
715 'sittun98',
09ea6724
YW
716 'sittun99',
717 'tap99',
718 'test1',
719 'tun99',
720 'vcan99',
721 'veth99',
722 'vlan99',
723 'vrf99',
6a97a864
YW
724 'vti6tun97',
725 'vti6tun98',
09ea6724 726 'vti6tun99',
42a29fcb 727 'vtitun96',
6a97a864
YW
728 'vtitun97',
729 'vtitun98',
09ea6724 730 'vtitun99',
f63b14d3 731 'vxcan99',
09ea6724 732 'vxlan99',
da44fb8a 733 'wg98',
e64dc406
YW
734 'wg99',
735 ]
09ea6724
YW
736
737 units = [
738 '10-dropin-test.netdev',
739 '11-dummy.netdev',
03db80b2 740 '11-dummy.network',
09ea6724 741 '12-dummy.netdev',
6b9518a0
YW
742 '13-not-match-udev-property.network',
743 '14-match-udev-property.network',
753e0a24 744 '15-name-conflict-test.netdev',
09ea6724
YW
745 '21-macvlan.netdev',
746 '21-macvtap.netdev',
7f45d738 747 '21-vlan-test1.network',
09ea6724
YW
748 '21-vlan.netdev',
749 '21-vlan.network',
750 '25-6rd-tunnel.netdev',
751 '25-bond.netdev',
fde60a42 752 '25-bond-balanced-tlb.netdev',
09ea6724 753 '25-bridge.netdev',
1285edf3 754 '25-bridge-configure-without-carrier.network',
03db80b2 755 '25-bridge.network',
6a97a864 756 '25-erspan-tunnel-local-any.netdev',
09ea6724 757 '25-erspan-tunnel.netdev',
4b6a6d1e
YW
758 '25-fou-gretap.netdev',
759 '25-fou-gre.netdev',
760 '25-fou-ipip.netdev',
761 '25-fou-ipproto-gre.netdev',
762 '25-fou-ipproto-ipip.netdev',
763 '25-fou-sit.netdev',
09ea6724 764 '25-geneve.netdev',
6a97a864 765 '25-gretap-tunnel-local-any.netdev',
09ea6724 766 '25-gretap-tunnel.netdev',
42a29fcb 767 '25-gre-tunnel-any-any.netdev',
6a97a864
YW
768 '25-gre-tunnel-local-any.netdev',
769 '25-gre-tunnel-remote-any.netdev',
09ea6724 770 '25-gre-tunnel.netdev',
b076d5d7 771 '25-ifb.netdev',
6a97a864
YW
772 '25-ip6gretap-tunnel-local-any.netdev',
773 '25-ip6gretap-tunnel.netdev',
42a29fcb 774 '25-ip6gre-tunnel-any-any.netdev',
6a97a864
YW
775 '25-ip6gre-tunnel-local-any.netdev',
776 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 777 '25-ip6gre-tunnel.netdev',
42a29fcb 778 '25-ip6tnl-tunnel-any-any.netdev',
6a97a864 779 '25-ip6tnl-tunnel-local-any.netdev',
42a29fcb 780 '25-ip6tnl-tunnel-remote-any.netdev',
09ea6724 781 '25-ip6tnl-tunnel.netdev',
42a29fcb 782 '25-ipip-tunnel-any-any.netdev',
09ea6724 783 '25-ipip-tunnel-independent.netdev',
95082dbe 784 '25-ipip-tunnel-independent-loopback.netdev',
6a97a864
YW
785 '25-ipip-tunnel-local-any.netdev',
786 '25-ipip-tunnel-remote-any.netdev',
09ea6724
YW
787 '25-ipip-tunnel.netdev',
788 '25-ipvlan.netdev',
956c8fec 789 '25-ipvtap.netdev',
09ea6724 790 '25-isatap-tunnel.netdev',
02849d8b
YW
791 '25-macsec.key',
792 '25-macsec.netdev',
793 '25-macsec.network',
811f33d0 794 '25-nlmon.netdev',
42a29fcb 795 '25-sit-tunnel-any-any.netdev',
6a97a864
YW
796 '25-sit-tunnel-local-any.netdev',
797 '25-sit-tunnel-remote-any.netdev',
09ea6724
YW
798 '25-sit-tunnel.netdev',
799 '25-tap.netdev',
800 '25-tun.netdev',
11309591
YW
801 '25-tunnel-local-any.network',
802 '25-tunnel-remote-any.network',
803 '25-tunnel.network',
09ea6724
YW
804 '25-vcan.netdev',
805 '25-veth.netdev',
806 '25-vrf.netdev',
42a29fcb 807 '25-vti6-tunnel-any-any.netdev',
6a97a864
YW
808 '25-vti6-tunnel-local-any.netdev',
809 '25-vti6-tunnel-remote-any.netdev',
09ea6724 810 '25-vti6-tunnel.netdev',
42a29fcb 811 '25-vti-tunnel-any-any.netdev',
6a97a864
YW
812 '25-vti-tunnel-local-any.netdev',
813 '25-vti-tunnel-remote-any.netdev',
09ea6724 814 '25-vti-tunnel.netdev',
f63b14d3 815 '25-vxcan.netdev',
09ea6724 816 '25-vxlan.netdev',
da44fb8a
YW
817 '25-wireguard-23-peers.netdev',
818 '25-wireguard-23-peers.network',
9e5d79e7 819 '25-wireguard-preshared-key.txt',
39bcff3b 820 '25-wireguard-private-key.txt',
09ea6724 821 '25-wireguard.netdev',
5a0bd90b 822 '25-wireguard.network',
e64dc406
YW
823 '25-xfrm.netdev',
824 '25-xfrm-independent.netdev',
09ea6724 825 '6rd.network',
6730a1f3 826 'erspan.network',
09ea6724
YW
827 'gre.network',
828 'gretap.network',
829 'gretun.network',
830 'ip6gretap.network',
6a97a864 831 'ip6gretun.network',
09ea6724
YW
832 'ip6tnl.network',
833 'ipip.network',
834 'ipvlan.network',
956c8fec 835 'ipvtap.network',
09ea6724 836 'isatap.network',
02849d8b 837 'macsec.network',
09ea6724
YW
838 'macvlan.network',
839 'macvtap.network',
077f9abc 840 'netdev-link-local-addressing-yes.network',
09ea6724
YW
841 'sit.network',
842 'vti6.network',
843 'vti.network',
1c862fe0 844 'vxlan-test1.network',
e64dc406
YW
845 'vxlan.network',
846 'xfrm.network',
847 ]
1f0e3109 848
def9fc0d
YW
849 fou_ports = [
850 '55555',
851 '55556']
852
1f0e3109 853 def setUp(self):
ec38833c 854 remove_fou_ports(self.fou_ports)
e64dc406 855 remove_links(self.links_remove_earlier)
ec38833c 856 remove_links(self.links)
aaae5713 857 stop_networkd(show_logs=False)
1f0e3109
SS
858
859 def tearDown(self):
ec38833c 860 remove_fou_ports(self.fou_ports)
e64dc406 861 remove_links(self.links_remove_earlier)
ec38833c
ZJS
862 remove_links(self.links)
863 remove_unit_from_networkd_path(self.units)
aaae5713 864 stop_networkd(show_logs=True)
1f0e3109 865
1ca44d7d 866 def test_dropin_and_name_conflict(self):
ec38833c 867 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
2cf6fdff 868 start_networkd()
d80734f7 869
e2aea43f 870 self.wait_online(['dropin-test:off'], setup_state='unmanaged')
d80734f7 871
371810d1 872 output = check_output('ip link show dropin-test')
d80734f7
YW
873 print(output)
874 self.assertRegex(output, '00:50:56:c0:00:28')
875
6b9518a0
YW
876 def test_match_udev_property(self):
877 copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
878 start_networkd()
e2aea43f 879 self.wait_online(['dummy98:routable'])
6b9518a0 880
fc79e6ff 881 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
6b9518a0
YW
882 print(output)
883 self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
884
03db80b2 885 def test_wait_online_any(self):
ec38833c 886 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
2cf6fdff 887 start_networkd()
03db80b2 888
e2aea43f 889 self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
03db80b2 890
19cf3143
DS
891 self.wait_operstate('bridge99', '(off|no-carrier)', setup_state='configuring')
892 self.wait_operstate('test1', 'degraded')
03db80b2 893
1f0e3109 894 def test_bridge(self):
1285edf3 895 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
2cf6fdff 896 start_networkd()
1f0e3109 897
e2aea43f 898 self.wait_online(['bridge99:no-carrier'])
1f0e3109 899
3d165124 900 tick = os.sysconf('SC_CLK_TCK')
ec38833c
ZJS
901 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick))
902 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick))
c9047092
YW
903 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick))
904 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick))
905 self.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority')))
906 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier')))
907 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping')))
908 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
909 self.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
1f0e3109 910
fc79e6ff 911 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
36bc2ffb
YW
912 print(output)
913 self.assertRegex(output, 'Priority: 9')
914 self.assertRegex(output, 'STP: yes')
915 self.assertRegex(output, 'Multicast IGMP Version: 3')
916
1f0e3109 917 def test_bond(self):
ec38833c 918 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
2cf6fdff 919 start_networkd()
ec38833c 920
e2aea43f 921 self.wait_online(['bond99:off', 'bond98:off'], setup_state='unmanaged')
ec38833c
ZJS
922
923 self.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
924 self.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
925 self.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
926 self.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
927 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
928 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
929 self.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
930 self.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
931 self.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
932 self.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
933 self.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
934
935 self.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
936 self.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
fde60a42 937
1f0e3109 938 def test_vlan(self):
ec38833c
ZJS
939 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
940 '21-vlan.network', '21-vlan-test1.network')
2cf6fdff 941 start_networkd()
1f0e3109 942
e2aea43f 943 self.wait_online(['test1:degraded', 'vlan99:routable'])
1f0e3109 944
371810d1 945 output = check_output('ip -d link show test1')
72b7f1b9 946 print(output)
7d7be1b9 947 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 948
371810d1 949 output = check_output('ip -d link show vlan99')
14ecd604 950 print(output)
06895a1d
YW
951 self.assertRegex(output, ' mtu 2000 ')
952 self.assertRegex(output, 'REORDER_HDR')
953 self.assertRegex(output, 'LOOSE_BINDING')
954 self.assertRegex(output, 'GVRP')
955 self.assertRegex(output, 'MVRP')
956 self.assertRegex(output, ' id 99 ')
1f0e3109 957
371810d1 958 output = check_output('ip -4 address show dev test1')
7f45d738
YW
959 print(output)
960 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
961 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
962
371810d1 963 output = check_output('ip -4 address show dev vlan99')
7f45d738
YW
964 print(output)
965 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
966
1f0e3109 967 def test_macvtap(self):
460feb61
YW
968 for mode in ['private', 'vepa', 'bridge', 'passthru']:
969 with self.subTest(mode=mode):
970 if mode != 'private':
971 self.tearDown()
ec38833c
ZJS
972 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
973 '11-dummy.netdev', 'macvtap.network')
460feb61
YW
974 with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f:
975 f.write('[MACVTAP]\nMode=' + mode)
2cf6fdff 976 start_networkd()
1f0e3109 977
e2aea43f 978 self.wait_online(['macvtap99:degraded', 'test1:degraded'])
460feb61 979
371810d1 980 output = check_output('ip -d link show macvtap99')
460feb61
YW
981 print(output)
982 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
1f0e3109
SS
983
984 def test_macvlan(self):
dff9792b
YW
985 for mode in ['private', 'vepa', 'bridge', 'passthru']:
986 with self.subTest(mode=mode):
987 if mode != 'private':
988 self.tearDown()
ec38833c
ZJS
989 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
990 '11-dummy.netdev', 'macvlan.network')
dff9792b
YW
991 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
992 f.write('[MACVLAN]\nMode=' + mode)
2cf6fdff 993 start_networkd()
dff9792b 994
e2aea43f 995 self.wait_online(['macvlan99:degraded', 'test1:degraded'])
dff9792b 996
371810d1 997 output = check_output('ip -d link show test1')
dff9792b
YW
998 print(output)
999 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 1000
371810d1 1001 output = check_output('ip -d link show macvlan99')
dff9792b
YW
1002 print(output)
1003 self.assertRegex(output, ' mtu 2000 ')
1004 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
72b7f1b9 1005
7a0a37b2 1006 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109 1007 def test_ipvlan(self):
bc6dff6e
YW
1008 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
1009 with self.subTest(mode=mode, flag=flag):
1010 if mode != 'L2':
1011 self.tearDown()
ec38833c
ZJS
1012 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
1013 '11-dummy.netdev', 'ipvlan.network')
bc6dff6e
YW
1014 with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f:
1015 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
1f0e3109 1016
2cf6fdff 1017 start_networkd()
e2aea43f 1018 self.wait_online(['ipvlan99:degraded', 'test1:degraded'])
bc6dff6e 1019
371810d1 1020 output = check_output('ip -d link show ipvlan99')
bc6dff6e
YW
1021 print(output)
1022 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
1f0e3109 1023
956c8fec
YW
1024 @expectedFailureIfModuleIsNotAvailable('ipvtap')
1025 def test_ipvtap(self):
40921f08
YW
1026 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
1027 with self.subTest(mode=mode, flag=flag):
1028 if mode != 'L2':
1029 self.tearDown()
ec38833c
ZJS
1030 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
1031 '11-dummy.netdev', 'ipvtap.network')
40921f08
YW
1032 with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f:
1033 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
1034
2cf6fdff 1035 start_networkd()
e2aea43f 1036 self.wait_online(['ipvtap99:degraded', 'test1:degraded'])
956c8fec 1037
371810d1 1038 output = check_output('ip -d link show ipvtap99')
40921f08
YW
1039 print(output)
1040 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
956c8fec 1041
1f0e3109 1042 def test_veth(self):
ec38833c 1043 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1044 start_networkd()
1f0e3109 1045
e2aea43f 1046 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
671dacdf 1047
371810d1 1048 output = check_output('ip -d link show veth99')
671dacdf
YW
1049 print(output)
1050 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
371810d1 1051 output = check_output('ip -d link show veth-peer')
671dacdf
YW
1052 print(output)
1053 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
1f0e3109 1054
1f0e3109 1055 def test_tun(self):
ec38833c 1056 copy_unit_to_networkd_unit_path('25-tun.netdev')
2cf6fdff 1057 start_networkd()
1f0e3109 1058
e2aea43f 1059 self.wait_online(['tun99:off'], setup_state='unmanaged')
1f0e3109 1060
371810d1 1061 output = check_output('ip -d link show tun99')
2746d307
YW
1062 print(output)
1063 # Old ip command does not support IFF_ flags
426654d7 1064 self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
2746d307 1065
1f0e3109 1066 def test_tap(self):
ec38833c 1067 copy_unit_to_networkd_unit_path('25-tap.netdev')
2cf6fdff 1068 start_networkd()
1f0e3109 1069
e2aea43f 1070 self.wait_online(['tap99:off'], setup_state='unmanaged')
1f0e3109 1071
371810d1 1072 output = check_output('ip -d link show tap99')
2746d307
YW
1073 print(output)
1074 # Old ip command does not support IFF_ flags
426654d7 1075 self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
2746d307 1076
7a0a37b2 1077 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109 1078 def test_vrf(self):
ec38833c 1079 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1080 start_networkd()
1f0e3109 1081
e2aea43f 1082 self.wait_online(['vrf99:carrier'])
1f0e3109 1083
7a0a37b2 1084 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109 1085 def test_vcan(self):
ec38833c 1086 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1087 start_networkd()
1f0e3109 1088
e2aea43f 1089 self.wait_online(['vcan99:carrier'])
1f0e3109 1090
f63b14d3
YW
1091 @expectedFailureIfModuleIsNotAvailable('vxcan')
1092 def test_vxcan(self):
ec38833c 1093 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1094 start_networkd()
f63b14d3 1095
e2aea43f 1096 self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
f63b14d3 1097
7a3bc5a8
EV
1098 @expectedFailureIfModuleIsNotAvailable('wireguard')
1099 def test_wireguard(self):
ec38833c
ZJS
1100 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
1101 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
1102 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
2cf6fdff 1103 start_networkd()
e2aea43f 1104 self.wait_online(['wg99:carrier', 'wg98:routable'])
5a0bd90b 1105
7a3bc5a8 1106 if shutil.which('wg'):
371810d1 1107 call('wg')
5a0bd90b 1108
371810d1 1109 output = check_output('wg show wg99 listen-port')
06895a1d 1110 self.assertRegex(output, '51820')
371810d1 1111 output = check_output('wg show wg99 fwmark')
06895a1d 1112 self.assertRegex(output, '0x4d2')
371810d1 1113 output = check_output('wg show wg99 allowed-ips')
88aaf89e
ZJS
1114 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
1115 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
371810d1 1116 output = check_output('wg show wg99 persistent-keepalive')
88aaf89e 1117 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
371810d1 1118 output = check_output('wg show wg99 endpoints')
88aaf89e 1119 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
371810d1 1120 output = check_output('wg show wg99 private-key')
88aaf89e 1121 self.assertRegex(output, r'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
371810d1 1122 output = check_output('wg show wg99 preshared-keys')
88aaf89e
ZJS
1123 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
1124 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
7a3bc5a8 1125
371810d1 1126 output = check_output('wg show wg98 private-key')
88aaf89e 1127 self.assertRegex(output, r'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
da44fb8a 1128
1f0e3109 1129 def test_geneve(self):
ec38833c 1130 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1131 start_networkd()
1f0e3109 1132
e2aea43f 1133 self.wait_online(['geneve99:degraded'])
1f0e3109 1134
371810d1 1135 output = check_output('ip -d link show geneve99')
14ecd604 1136 print(output)
06895a1d
YW
1137 self.assertRegex(output, '192.168.22.1')
1138 self.assertRegex(output, '6082')
1139 self.assertRegex(output, 'udpcsum')
1140 self.assertRegex(output, 'udp6zerocsumrx')
1f0e3109
SS
1141
1142 def test_ipip_tunnel(self):
ec38833c
ZJS
1143 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
1144 '25-ipip-tunnel.netdev', '25-tunnel.network',
1145 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1146 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1147 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1148 start_networkd()
e2aea43f 1149 self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
6a97a864 1150
371810d1 1151 output = check_output('ip -d link show ipiptun99')
6a97a864 1152 print(output)
426654d7 1153 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
371810d1 1154 output = check_output('ip -d link show ipiptun98')
6a97a864 1155 print(output)
426654d7 1156 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
371810d1 1157 output = check_output('ip -d link show ipiptun97')
6a97a864 1158 print(output)
426654d7 1159 self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
42a29fcb
YW
1160 output = check_output('ip -d link show ipiptun96')
1161 print(output)
426654d7 1162 self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
1f0e3109
SS
1163
1164 def test_gre_tunnel(self):
ec38833c
ZJS
1165 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
1166 '25-gre-tunnel.netdev', '25-tunnel.network',
1167 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1168 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1169 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1170 start_networkd()
e2aea43f 1171 self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
6a97a864 1172
371810d1 1173 output = check_output('ip -d link show gretun99')
6a97a864
YW
1174 print(output)
1175 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
1176 self.assertRegex(output, 'ikey 1.2.3.103')
1177 self.assertRegex(output, 'okey 1.2.4.103')
1178 self.assertRegex(output, 'iseq')
1179 self.assertRegex(output, 'oseq')
371810d1 1180 output = check_output('ip -d link show gretun98')
6a97a864
YW
1181 print(output)
1182 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
1183 self.assertRegex(output, 'ikey 0.0.0.104')
1184 self.assertRegex(output, 'okey 0.0.0.104')
1185 self.assertNotRegex(output, 'iseq')
1186 self.assertNotRegex(output, 'oseq')
371810d1 1187 output = check_output('ip -d link show gretun97')
6a97a864
YW
1188 print(output)
1189 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
38f4bb44
YW
1190 self.assertRegex(output, 'ikey 0.0.0.105')
1191 self.assertRegex(output, 'okey 0.0.0.105')
1192 self.assertNotRegex(output, 'iseq')
1193 self.assertNotRegex(output, 'oseq')
42a29fcb
YW
1194 output = check_output('ip -d link show gretun96')
1195 print(output)
1196 self.assertRegex(output, 'gre remote any local any dev dummy98')
1197 self.assertRegex(output, 'ikey 0.0.0.106')
1198 self.assertRegex(output, 'okey 0.0.0.106')
1199 self.assertNotRegex(output, 'iseq')
1200 self.assertNotRegex(output, 'oseq')
6a97a864
YW
1201
1202 def test_ip6gre_tunnel(self):
ec38833c
ZJS
1203 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
1204 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1205 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1206 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1207 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
01943d43 1208 start_networkd(5)
6a97a864 1209
17bcf0a0
YW
1210 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1211
e39cc445
YW
1212 self.check_link_exists('dummy98')
1213 self.check_link_exists('ip6gretun99')
1214 self.check_link_exists('ip6gretun98')
1215 self.check_link_exists('ip6gretun97')
42a29fcb 1216 self.check_link_exists('ip6gretun96')
6a97a864 1217
371810d1 1218 output = check_output('ip -d link show ip6gretun99')
6a97a864
YW
1219 print(output)
1220 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1221 output = check_output('ip -d link show ip6gretun98')
6a97a864
YW
1222 print(output)
1223 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
371810d1 1224 output = check_output('ip -d link show ip6gretun97')
6a97a864
YW
1225 print(output)
1226 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
42a29fcb
YW
1227 output = check_output('ip -d link show ip6gretun96')
1228 print(output)
1229 self.assertRegex(output, 'ip6gre remote any local any dev dummy98')
1f0e3109 1230
11309591 1231 def test_gretap_tunnel(self):
ec38833c
ZJS
1232 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1233 '25-gretap-tunnel.netdev', '25-tunnel.network',
1234 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1235 start_networkd()
e2aea43f 1236 self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
6a97a864 1237
371810d1 1238 output = check_output('ip -d link show gretap99')
6a97a864
YW
1239 print(output)
1240 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
1241 self.assertRegex(output, 'ikey 0.0.0.106')
1242 self.assertRegex(output, 'okey 0.0.0.106')
1243 self.assertRegex(output, 'iseq')
1244 self.assertRegex(output, 'oseq')
371810d1 1245 output = check_output('ip -d link show gretap98')
6a97a864
YW
1246 print(output)
1247 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
1248 self.assertRegex(output, 'ikey 0.0.0.107')
1249 self.assertRegex(output, 'okey 0.0.0.107')
1250 self.assertRegex(output, 'iseq')
1251 self.assertRegex(output, 'oseq')
1f0e3109
SS
1252
1253 def test_ip6gretap_tunnel(self):
ec38833c
ZJS
1254 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1255 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1256 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1257 start_networkd()
e2aea43f 1258 self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
6a97a864 1259
371810d1 1260 output = check_output('ip -d link show ip6gretap99')
6a97a864
YW
1261 print(output)
1262 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1263 output = check_output('ip -d link show ip6gretap98')
6a97a864
YW
1264 print(output)
1265 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1f0e3109
SS
1266
1267 def test_vti_tunnel(self):
ec38833c
ZJS
1268 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1269 '25-vti-tunnel.netdev', '25-tunnel.network',
1270 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1271 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1272 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1273 start_networkd()
e2aea43f 1274 self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
6a97a864 1275
371810d1 1276 output = check_output('ip -d link show vtitun99')
6a97a864
YW
1277 print(output)
1278 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
371810d1 1279 output = check_output('ip -d link show vtitun98')
6a97a864
YW
1280 print(output)
1281 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
371810d1 1282 output = check_output('ip -d link show vtitun97')
6a97a864
YW
1283 print(output)
1284 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
42a29fcb
YW
1285 output = check_output('ip -d link show vtitun96')
1286 print(output)
1287 self.assertRegex(output, 'vti remote any local any dev dummy98')
1f0e3109
SS
1288
1289 def test_vti6_tunnel(self):
ec38833c
ZJS
1290 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1291 '25-vti6-tunnel.netdev', '25-tunnel.network',
1292 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1293 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
2cf6fdff 1294 start_networkd()
e2aea43f 1295 self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
6a97a864 1296
371810d1 1297 output = check_output('ip -d link show vti6tun99')
6a97a864
YW
1298 print(output)
1299 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1300 output = check_output('ip -d link show vti6tun98')
6a97a864 1301 print(output)
426654d7 1302 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1303 output = check_output('ip -d link show vti6tun97')
6a97a864 1304 print(output)
426654d7 1305 self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
1306
1307 def test_ip6tnl_tunnel(self):
ec38833c
ZJS
1308 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1309 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1310 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1311 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
2cf6fdff 1312 start_networkd()
e2aea43f 1313 self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
6a97a864 1314
371810d1 1315 output = check_output('ip -d link show ip6tnl99')
6a97a864
YW
1316 print(output)
1317 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1318 output = check_output('ip -d link show ip6tnl98')
6a97a864 1319 print(output)
426654d7 1320 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1321 output = check_output('ip -d link show ip6tnl97')
6a97a864 1322 print(output)
426654d7 1323 self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
1324
1325 def test_sit_tunnel(self):
ec38833c
ZJS
1326 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1327 '25-sit-tunnel.netdev', '25-tunnel.network',
1328 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1329 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1330 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1331 start_networkd()
e2aea43f 1332 self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
6a97a864 1333
371810d1 1334 output = check_output('ip -d link show sittun99')
6a97a864 1335 print(output)
426654d7 1336 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
371810d1 1337 output = check_output('ip -d link show sittun98')
6a97a864 1338 print(output)
426654d7 1339 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
371810d1 1340 output = check_output('ip -d link show sittun97')
6a97a864 1341 print(output)
426654d7 1342 self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
42a29fcb
YW
1343 output = check_output('ip -d link show sittun96')
1344 print(output)
426654d7 1345 self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
1f0e3109 1346
d0e728b6 1347 def test_isatap_tunnel(self):
ec38833c
ZJS
1348 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1349 '25-isatap-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1350 start_networkd()
e2aea43f 1351 self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
d0e728b6 1352
371810d1 1353 output = check_output('ip -d link show isataptun99')
14ecd604 1354 print(output)
d0e728b6
SS
1355 self.assertRegex(output, "isatap ")
1356
d29dc4f1 1357 def test_6rd_tunnel(self):
ec38833c
ZJS
1358 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1359 '25-6rd-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1360 start_networkd()
e2aea43f 1361 self.wait_online(['sittun99:routable', 'dummy98:degraded'])
d29dc4f1 1362
371810d1 1363 output = check_output('ip -d link show sittun99')
6a97a864
YW
1364 print(output)
1365 self.assertRegex(output, '6rd-prefix 2602::/24')
1366
7bea7f9b 1367 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b 1368 def test_erspan_tunnel(self):
ec38833c
ZJS
1369 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1370 '25-erspan-tunnel.netdev', '25-tunnel.network',
1371 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1372 start_networkd()
e2aea43f 1373 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
2266864b 1374
371810d1 1375 output = check_output('ip -d link show erspan99')
6a97a864
YW
1376 print(output)
1377 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
38f4bb44
YW
1378 self.assertRegex(output, 'ikey 0.0.0.101')
1379 self.assertRegex(output, 'okey 0.0.0.101')
1380 self.assertRegex(output, 'iseq')
1381 self.assertRegex(output, 'oseq')
371810d1 1382 output = check_output('ip -d link show erspan98')
2266864b 1383 print(output)
6a97a864
YW
1384 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
1385 self.assertRegex(output, '102')
38f4bb44
YW
1386 self.assertRegex(output, 'ikey 0.0.0.102')
1387 self.assertRegex(output, 'okey 0.0.0.102')
1388 self.assertRegex(output, 'iseq')
1389 self.assertRegex(output, 'oseq')
2266864b 1390
1f0e3109 1391 def test_tunnel_independent(self):
ec38833c 1392 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1393 start_networkd()
e40a58b5 1394
e2aea43f 1395 self.wait_online(['ipiptun99:carrier'])
1f0e3109 1396
95082dbe
YW
1397 def test_tunnel_independent_loopback(self):
1398 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1399 start_networkd()
1400
e2aea43f 1401 self.wait_online(['ipiptun99:carrier'])
95082dbe 1402
e64dc406
YW
1403 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1404 def test_xfrm(self):
1405 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1406 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1407 start_networkd()
1408
e2aea43f 1409 self.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
e64dc406
YW
1410
1411 output = check_output('ip link show dev xfrm99')
1412 print(output)
1413
1414 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1415 def test_xfrm_independent(self):
1416 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1417 start_networkd()
1418
e2aea43f 1419 self.wait_online(['xfrm99:degraded'])
e64dc406 1420
4b6a6d1e
YW
1421 @expectedFailureIfModuleIsNotAvailable('fou')
1422 def test_fou(self):
1423 # The following redundant check is necessary for CentOS CI.
1424 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1425 self.assertTrue(is_module_available('fou'))
1426
ec38833c
ZJS
1427 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1428 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1429 '25-fou-gre.netdev', '25-fou-gretap.netdev')
2cf6fdff 1430 start_networkd()
4b6a6d1e 1431
e2aea43f 1432 self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged')
4b6a6d1e 1433
371810d1 1434 output = check_output('ip fou show')
4b6a6d1e
YW
1435 print(output)
1436 self.assertRegex(output, 'port 55555 ipproto 4')
1437 self.assertRegex(output, 'port 55556 ipproto 47')
1438
371810d1 1439 output = check_output('ip -d link show ipiptun96')
4b6a6d1e
YW
1440 print(output)
1441 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1442 output = check_output('ip -d link show sittun96')
4b6a6d1e
YW
1443 print(output)
1444 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1445 output = check_output('ip -d link show gretun96')
4b6a6d1e
YW
1446 print(output)
1447 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
371810d1 1448 output = check_output('ip -d link show gretap96')
4b6a6d1e
YW
1449 print(output)
1450 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1451
1f0e3109 1452 def test_vxlan(self):
ec38833c
ZJS
1453 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1454 '11-dummy.netdev', 'vxlan-test1.network')
2cf6fdff 1455 start_networkd()
1f0e3109 1456
e2aea43f 1457 self.wait_online(['test1:degraded', 'vxlan99:degraded'])
1f0e3109 1458
371810d1 1459 output = check_output('ip -d link show vxlan99')
14ecd604 1460 print(output)
1c862fe0 1461 self.assertRegex(output, '999')
1f0e3109
SS
1462 self.assertRegex(output, '5555')
1463 self.assertRegex(output, 'l2miss')
1464 self.assertRegex(output, 'l3miss')
1465 self.assertRegex(output, 'udpcsum')
1466 self.assertRegex(output, 'udp6zerocsumtx')
1467 self.assertRegex(output, 'udp6zerocsumrx')
1468 self.assertRegex(output, 'remcsumtx')
1469 self.assertRegex(output, 'remcsumrx')
1470 self.assertRegex(output, 'gbp')
1471
371810d1 1472 output = check_output('bridge fdb show dev vxlan99')
1c862fe0
YW
1473 print(output)
1474 self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1475 self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1476 self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1477
fc79e6ff 1478 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'vxlan99', env=env)
36bc2ffb
YW
1479 print(output)
1480 self.assertRegex(output, 'VNI: 999')
1481 self.assertRegex(output, 'Destination Port: 5555')
1482 self.assertRegex(output, 'Underlying Device: test1')
1483
02849d8b 1484 def test_macsec(self):
ec38833c
ZJS
1485 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1486 'macsec.network', '12-dummy.netdev')
2cf6fdff 1487 start_networkd()
02849d8b 1488
e2aea43f 1489 self.wait_online(['dummy98:degraded', 'macsec99:routable'])
02849d8b 1490
371810d1 1491 output = check_output('ip -d link show macsec99')
02849d8b
YW
1492 print(output)
1493 self.assertRegex(output, 'macsec99@dummy98')
1494 self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
1495 self.assertRegex(output, 'encrypt on')
1496
371810d1 1497 output = check_output('ip macsec show macsec99')
02849d8b
YW
1498 print(output)
1499 self.assertRegex(output, 'encrypt on')
1500 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
1501 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1502 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1503 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on')
1504 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1505 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1506 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1507 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1508 self.assertNotRegex(output, 'key 02030405067080900000000000000000')
1509 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
1510 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1511
811f33d0 1512 def test_nlmon(self):
ec38833c 1513 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1514 start_networkd()
811f33d0 1515
e2aea43f 1516 self.wait_online(['nlmon99:carrier'])
02849d8b 1517
b076d5d7
YW
1518 @expectedFailureIfModuleIsNotAvailable('ifb')
1519 def test_ifb(self):
1520 copy_unit_to_networkd_unit_path('25-ifb.netdev', 'netdev-link-local-addressing-yes.network')
1521 start_networkd()
1522
1523 self.wait_online(['ifb99:degraded'])
1524
cff83db9
YW
1525class NetworkdL2TPTests(unittest.TestCase, Utilities):
1526
1527 links =[
1528 'l2tp-ses1',
1529 'l2tp-ses2',
1530 'l2tp-ses3',
1531 'l2tp-ses4',
1532 'test1']
1533
1534 units = [
1535 '11-dummy.netdev',
1536 '25-l2tp-dummy.network',
e2aea43f 1537 '25-l2tp.network',
cff83db9
YW
1538 '25-l2tp-ip.netdev',
1539 '25-l2tp-udp.netdev']
1540
1541 l2tp_tunnel_ids = [ '10' ]
1542
1543 def setUp(self):
ad78d7b0 1544 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c 1545 remove_links(self.links)
aaae5713 1546 stop_networkd(show_logs=False)
cff83db9
YW
1547
1548 def tearDown(self):
ad78d7b0 1549 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c
ZJS
1550 remove_links(self.links)
1551 remove_unit_from_networkd_path(self.units)
aaae5713 1552 stop_networkd(show_logs=True)
cff83db9
YW
1553
1554 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1555 def test_l2tp_udp(self):
e2aea43f
YW
1556 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1557 '25-l2tp-udp.netdev', '25-l2tp.network')
2cf6fdff 1558 start_networkd()
cff83db9 1559
e2aea43f 1560 self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
cff83db9 1561
371810d1 1562 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1563 print(output)
1564 self.assertRegex(output, "Tunnel 10, encap UDP")
1565 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1566 self.assertRegex(output, "Peer tunnel 11")
1567 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
1568 self.assertRegex(output, "UDP checksum: enabled")
1569
371810d1 1570 output = check_output('ip l2tp show session tid 10 session_id 15')
cff83db9
YW
1571 print(output)
1572 self.assertRegex(output, "Session 15 in tunnel 10")
1573 self.assertRegex(output, "Peer session 16, tunnel 11")
1574 self.assertRegex(output, "interface name: l2tp-ses1")
1575
371810d1 1576 output = check_output('ip l2tp show session tid 10 session_id 17')
cff83db9
YW
1577 print(output)
1578 self.assertRegex(output, "Session 17 in tunnel 10")
1579 self.assertRegex(output, "Peer session 18, tunnel 11")
1580 self.assertRegex(output, "interface name: l2tp-ses2")
1581
1582 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1583 def test_l2tp_ip(self):
e2aea43f
YW
1584 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1585 '25-l2tp-ip.netdev', '25-l2tp.network')
2cf6fdff 1586 start_networkd()
cff83db9 1587
e2aea43f 1588 self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
cff83db9 1589
371810d1 1590 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1591 print(output)
1592 self.assertRegex(output, "Tunnel 10, encap IP")
1593 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1594 self.assertRegex(output, "Peer tunnel 12")
1595
371810d1 1596 output = check_output('ip l2tp show session tid 10 session_id 25')
cff83db9
YW
1597 print(output)
1598 self.assertRegex(output, "Session 25 in tunnel 10")
1599 self.assertRegex(output, "Peer session 26, tunnel 12")
1600 self.assertRegex(output, "interface name: l2tp-ses3")
1601
371810d1 1602 output = check_output('ip l2tp show session tid 10 session_id 27')
cff83db9
YW
1603 print(output)
1604 self.assertRegex(output, "Session 27 in tunnel 10")
1605 self.assertRegex(output, "Peer session 28, tunnel 12")
1606 self.assertRegex(output, "interface name: l2tp-ses4")
1607
be68c2c9 1608class NetworkdNetworkTests(unittest.TestCase, Utilities):
09ea6724
YW
1609 links = [
1610 'bond199',
1611 'dummy98',
cd65d067 1612 'dummy99',
74761cf3 1613 'gretun97',
fb2ba330 1614 'ip6gretun97',
086bcf5d
YW
1615 'test1',
1616 'veth99',
40afe491 1617 'vrf99',
74761cf3 1618 ]
09ea6724
YW
1619
1620 units = [
1621 '11-dummy.netdev',
1622 '12-dummy.netdev',
1623 '23-active-slave.network',
1e498853 1624 '24-keep-configuration-static.network',
fdcd1ec5 1625 '24-search-domain.network',
dc7d3c5f
YW
1626 '25-address-dad-veth-peer.network',
1627 '25-address-dad-veth99.network',
09ea6724 1628 '25-address-link-section.network',
e4783b54 1629 '25-address-preferred-lifetime-zero.network',
b8102725 1630 '25-address-static.network',
cd65d067 1631 '25-bind-carrier.network',
09ea6724
YW
1632 '25-bond-active-backup-slave.netdev',
1633 '25-fibrule-invert.network',
1634 '25-fibrule-port-range.network',
6be8e78e 1635 '25-fibrule-uidrange.network',
74761cf3 1636 '25-gre-tunnel-remote-any.netdev',
fb2ba330 1637 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 1638 '25-ipv6-address-label-section.network',
ef3c8a92
YW
1639 '25-link-local-addressing-no.network',
1640 '25-link-local-addressing-yes.network',
1641 '25-link-section-unmanaged.network',
e4a71bf3 1642 '25-neighbor-section.network',
d1bdafd2 1643 '25-neighbor-next.network',
fb2ba330 1644 '25-neighbor-ipv6.network',
74761cf3
YW
1645 '25-neighbor-ip-dummy.network',
1646 '25-neighbor-ip.network',
086bcf5d 1647 '25-nexthop.network',
f6c6af38 1648 '25-qdisc-cake.network',
f1de1eb3 1649 '25-qdisc-clsact-and-htb.network',
557fa421 1650 '25-qdisc-drr.network',
ab9dc1db 1651 '25-qdisc-ingress-netem-compat.network',
be94e591 1652 '25-qdisc-pie.network',
20ca06a6 1653 '25-route-ipv6-src.network',
0ef830cf 1654 '25-route-static.network',
40afe491 1655 '25-route-vrf.network',
0b1cd3e2
WKI
1656 '25-gateway-static.network',
1657 '25-gateway-next-static.network',
4da33154 1658 '25-sysctl-disable-ipv6.network',
09ea6724 1659 '25-sysctl.network',
086bcf5d
YW
1660 '25-veth-peer.network',
1661 '25-veth.netdev',
40afe491 1662 '25-vrf.netdev',
7b3770a7 1663 '26-link-local-addressing-ipv6.network',
09ea6724 1664 'configure-without-carrier.network',
b677774d 1665 'routing-policy-rule-dummy98.network',
b8102725 1666 'routing-policy-rule-test1.network']
1f0e3109 1667
65c24cd0 1668 routing_policy_rule_tables = ['7', '8', '9']
5f68a6a4 1669 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
95c74b0a 1670
1f0e3109 1671 def setUp(self):
ec38833c
ZJS
1672 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1673 remove_routes(self.routes)
1674 remove_links(self.links)
aaae5713 1675 stop_networkd(show_logs=False)
1f0e3109
SS
1676
1677 def tearDown(self):
ec38833c
ZJS
1678 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1679 remove_routes(self.routes)
1680 remove_links(self.links)
1681 remove_unit_from_networkd_path(self.units)
aaae5713 1682 stop_networkd(show_logs=True)
1f0e3109 1683
b8102725 1684 def test_address_static(self):
ec38833c 1685 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
2cf6fdff 1686 start_networkd()
b8102725 1687
e2aea43f 1688 self.wait_online(['dummy98:routable'])
b8102725 1689
371810d1 1690 output = check_output('ip -4 address show dev dummy98')
b8102725
YW
1691 print(output)
1692 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1693 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1694 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1695
1696 # invalid sections
1697 self.assertNotRegex(output, '10.10.0.1/16')
1698 self.assertNotRegex(output, '10.10.0.2/16')
1699
371810d1 1700 output = check_output('ip -4 address show dev dummy98 label 32')
b8102725
YW
1701 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1702
371810d1 1703 output = check_output('ip -4 address show dev dummy98 label 33')
b8102725
YW
1704 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1705
371810d1 1706 output = check_output('ip -4 address show dev dummy98 label 34')
b8102725
YW
1707 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1708
371810d1 1709 output = check_output('ip -4 address show dev dummy98 label 35')
b8102725
YW
1710 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1711
371810d1 1712 output = check_output('ip -6 address show dev dummy98')
b8102725
YW
1713 print(output)
1714 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1715 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1716 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1717 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1718 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1719 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1720
1721 def test_address_preferred_lifetime_zero_ipv6(self):
e4783b54 1722 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
01943d43 1723 start_networkd(5)
1f0e3109 1724
e4783b54 1725 self.wait_online(['dummy98:routable'])
b8102725 1726
371810d1 1727 output = check_output('ip address show dummy98')
b8102725
YW
1728 print(output)
1729 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1730 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1f0e3109 1731
e4783b54
YW
1732 output = check_output('ip route show dev dummy98')
1733 print(output)
1734 self.assertRegex(output, 'default via 20.20.20.1 proto static')
1735
dc7d3c5f
YW
1736 def test_address_dad(self):
1737 copy_unit_to_networkd_unit_path('25-address-dad-veth99.network', '25-address-dad-veth-peer.network',
1738 '25-veth.netdev')
1739 start_networkd()
1740 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1741
1742 output = check_output('ip -4 address show dev veth99')
1743 print(output)
1744 self.assertRegex(output, '192.168.100.10/24')
1745
1746 output = check_output('ip -4 address show dev veth-peer')
1747 print(output)
1748 self.assertNotRegex(output, '192.168.100.10/24')
1749
1f0e3109 1750 def test_configure_without_carrier(self):
ec38833c 1751 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
2cf6fdff 1752 start_networkd()
e2aea43f 1753 self.wait_online(['test1:routable'])
e40a58b5 1754
fc79e6ff 1755 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
1f0e3109
SS
1756 print(output)
1757 self.assertRegex(output, '192.168.0.15')
1758 self.assertRegex(output, '192.168.0.1')
1759 self.assertRegex(output, 'routable')
1760
1f0e3109 1761 def test_routing_policy_rule(self):
ec38833c 1762 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
2cf6fdff 1763 start_networkd()
e2aea43f 1764 self.wait_online(['test1:degraded'])
e40a58b5 1765
65c24cd0 1766 output = check_output('ip rule list iif test1 priority 111')
1f0e3109 1767 print(output)
65c24cd0 1768 self.assertRegex(output, '111:')
1f0e3109 1769 self.assertRegex(output, 'from 192.168.100.18')
426654d7 1770 self.assertRegex(output, r'tos (0x08|throughput)\s')
1f0e3109
SS
1771 self.assertRegex(output, 'iif test1')
1772 self.assertRegex(output, 'oif test1')
1773 self.assertRegex(output, 'lookup 7')
1774
65c24cd0
YW
1775 output = check_output('ip rule list iif test1 priority 101')
1776 print(output)
1777 self.assertRegex(output, '101:')
1778 self.assertRegex(output, 'from all')
1779 self.assertRegex(output, 'iif test1')
1780 self.assertRegex(output, 'lookup 9')
1781
1782 output = check_output('ip -6 rule list iif test1 priority 100')
1783 print(output)
1784 self.assertRegex(output, '100:')
1785 self.assertRegex(output, 'from all')
1786 self.assertRegex(output, 'iif test1')
1787 self.assertRegex(output, 'lookup 8')
1788
1789 output = check_output('ip -6 rule list iif test1 priority 101')
1790 print(output)
1791 self.assertRegex(output, '101:')
1792 self.assertRegex(output, 'from all')
1793 self.assertRegex(output, 'iif test1')
1794 self.assertRegex(output, 'lookup 9')
1795
b677774d 1796 def test_routing_policy_rule_issue_11280(self):
ec38833c
ZJS
1797 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1798 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
b677774d 1799
b677774d
YW
1800 for trial in range(3):
1801 # Remove state files only first time
e2aea43f
YW
1802 start_networkd(3)
1803 self.wait_online(['test1:degraded', 'dummy98:degraded'])
df7f9afa 1804 time.sleep(1)
b677774d 1805
371810d1 1806 output = check_output('ip rule list table 7')
b677774d 1807 print(output)
426654d7 1808 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
b677774d 1809
371810d1 1810 output = check_output('ip rule list table 8')
b677774d 1811 print(output)
426654d7 1812 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
b677774d 1813
aaae5713
YW
1814 stop_networkd(remove_state_files=False)
1815
d586a2c3 1816 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0 1817 def test_routing_policy_rule_port_range(self):
ec38833c 1818 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
2cf6fdff 1819 start_networkd()
e2aea43f 1820 self.wait_online(['test1:degraded'])
e40a58b5 1821
371810d1 1822 output = check_output('ip rule')
926062f0
SS
1823 print(output)
1824 self.assertRegex(output, '111')
1825 self.assertRegex(output, 'from 192.168.100.18')
1826 self.assertRegex(output, '1123-1150')
1827 self.assertRegex(output, '3224-3290')
1828 self.assertRegex(output, 'tcp')
1829 self.assertRegex(output, 'lookup 7')
1f0e3109 1830
d586a2c3 1831 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd 1832 def test_routing_policy_rule_invert(self):
ec38833c 1833 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
2cf6fdff 1834 start_networkd()
e2aea43f 1835 self.wait_online(['test1:degraded'])
e40a58b5 1836
371810d1 1837 output = check_output('ip rule')
efecf9cd 1838 print(output)
efecf9cd
SS
1839 self.assertRegex(output, '111')
1840 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1841 self.assertRegex(output, 'tcp')
1842 self.assertRegex(output, 'lookup 7')
1843
6be8e78e
YW
1844 @expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
1845 def test_routing_policy_rule_uidrange(self):
1846 copy_unit_to_networkd_unit_path('25-fibrule-uidrange.network', '11-dummy.netdev')
1847 start_networkd()
1848 self.wait_online(['test1:degraded'])
1849
1850 output = check_output('ip rule')
1851 print(output)
1852 self.assertRegex(output, '111')
1853 self.assertRegex(output, 'from 192.168.100.18')
1854 self.assertRegex(output, 'lookup 7')
1855 self.assertRegex(output, 'uidrange 100-200')
1856
0ef830cf 1857 def test_route_static(self):
ec38833c 1858 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
2cf6fdff 1859 start_networkd()
e2aea43f
YW
1860 self.wait_online(['dummy98:routable'])
1861
fc79e6ff 1862 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
e2aea43f 1863 print(output)
0d34228f 1864
6d60f9db 1865 print('### ip -6 route show dev dummy98')
371810d1 1866 output = check_output('ip -6 route show dev dummy98')
0d34228f 1867 print(output)
0ef830cf
YW
1868 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1869 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1f0e3109 1870
6d60f9db 1871 print('### ip -6 route show dev dummy98 default')
371810d1 1872 output = check_output('ip -6 route show dev dummy98 default')
6d60f9db 1873 print(output)
0ef830cf 1874 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1f0e3109 1875
6d60f9db 1876 print('### ip -4 route show dev dummy98')
371810d1 1877 output = check_output('ip -4 route show dev dummy98')
1f0e3109 1878 print(output)
0ef830cf
YW
1879 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1880 self.assertRegex(output, '149.10.124.64 proto static scope link')
2b00dff8 1881 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
0ef830cf
YW
1882 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1883 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
6d60f9db 1884 self.assertRegex(output, 'multicast 149.10.123.4 proto static')
1f0e3109 1885
6d60f9db 1886 print('### ip -4 route show dev dummy98 default')
371810d1 1887 output = check_output('ip -4 route show dev dummy98 default')
6d60f9db 1888 print(output)
0ef830cf
YW
1889 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1890 self.assertRegex(output, 'default via 149.10.124.64 proto static')
6543b7fd 1891 self.assertRegex(output, 'default proto static')
1f0e3109 1892
6d60f9db
YW
1893 print('### ip -4 route show table local dev dummy98')
1894 output = check_output('ip -4 route show table local dev dummy98')
1895 print(output)
1896 self.assertRegex(output, 'local 149.10.123.1 proto static scope host')
1897 self.assertRegex(output, 'anycast 149.10.123.2 proto static scope link')
1898 self.assertRegex(output, 'broadcast 149.10.123.3 proto static scope link')
1899
1900 print('### ip route show type blackhole')
371810d1 1901 output = check_output('ip route show type blackhole')
1f0e3109 1902 print(output)
0ef830cf 1903 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
f5050e48 1904
6d60f9db 1905 print('### ip route show type unreachable')
371810d1 1906 output = check_output('ip route show type unreachable')
f5050e48 1907 print(output)
0ef830cf 1908 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
f5050e48 1909
6d60f9db 1910 print('### ip route show type prohibit')
371810d1 1911 output = check_output('ip route show type prohibit')
f5050e48 1912 print(output)
0ef830cf 1913 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
f5050e48 1914
a0ce990e
YW
1915 print('### ip route show 192.168.10.1')
1916 output = check_output('ip route show 192.168.10.1')
1917 print(output)
1918 self.assertRegex(output, '192.168.10.1 proto static')
1919 self.assertRegex(output, 'nexthop via 149.10.124.59 dev dummy98 weight 10')
1920 self.assertRegex(output, 'nexthop via 149.10.124.60 dev dummy98 weight 5')
1921
1922 print('### ip route show 192.168.10.2')
1923 output = check_output('ip route show 192.168.10.2')
1924 print(output)
1925 # old ip command does not show IPv6 gateways...
1926 self.assertRegex(output, '192.168.10.2 proto static')
1927 self.assertRegex(output, 'nexthop')
1928 self.assertRegex(output, 'dev dummy98 weight 10')
1929 self.assertRegex(output, 'dev dummy98 weight 5')
1930
1931 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
1932 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
1933 print(output)
1934 # old ip command does not show 'nexthop' keyword and weight...
1935 self.assertRegex(output, '2001:1234:5:7fff:ff:ff:ff:ff')
1936 self.assertRegex(output, 'via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98')
1937 self.assertRegex(output, 'via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98')
1938
40afe491
YW
1939 @expectedFailureIfModuleIsNotAvailable('vrf')
1940 def test_route_vrf(self):
1941 copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
1942 '25-vrf.netdev', '25-vrf.network')
1943 start_networkd()
1944 self.wait_online(['dummy98:routable', 'vrf99:carrier'])
1945
1946 output = check_output('ip route show vrf vrf99')
1947 print(output)
1948 self.assertRegex(output, 'default via 192.168.100.1')
1949
1950 output = check_output('ip route show')
1951 print(output)
1952 self.assertNotRegex(output, 'default via 192.168.100.1')
1953
0b1cd3e2
WKI
1954 def test_gateway_reconfigure(self):
1955 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
1956 start_networkd()
1957 self.wait_online(['dummy98:routable'])
1958 print('### ip -4 route show dev dummy98 default')
1959 output = check_output('ip -4 route show dev dummy98 default')
1960 print(output)
1961 self.assertRegex(output, 'default via 149.10.124.59 proto static')
1962 self.assertNotRegex(output, '149.10.124.60')
1963
1964 remove_unit_from_networkd_path(['25-gateway-static.network'])
1965 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
1966 restart_networkd(3)
1967 self.wait_online(['dummy98:routable'])
1968 print('### ip -4 route show dev dummy98 default')
1969 output = check_output('ip -4 route show dev dummy98 default')
1970 print(output)
1971 self.assertNotRegex(output, '149.10.124.59')
1972 self.assertRegex(output, 'default via 149.10.124.60 proto static')
1973
20ca06a6
DA
1974 def test_ip_route_ipv6_src_route(self):
1975 # a dummy device does not make the addresses go through tentative state, so we
1976 # reuse a bond from an earlier test, which does make the addresses go through
1977 # tentative state, and do our test on that
ec38833c 1978 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 1979 start_networkd()
e2aea43f 1980 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
20ca06a6 1981
371810d1 1982 output = check_output('ip -6 route list dev bond199')
20ca06a6
DA
1983 print(output)
1984 self.assertRegex(output, 'abcd::/16')
1985 self.assertRegex(output, 'src')
1986 self.assertRegex(output, '2001:1234:56:8f63::2')
1987
1f0e3109 1988 def test_ip_link_mac_address(self):
ec38833c 1989 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
2cf6fdff 1990 start_networkd()
e2aea43f 1991 self.wait_online(['dummy98:degraded'])
1f0e3109 1992
371810d1 1993 output = check_output('ip link show dummy98')
1f0e3109
SS
1994 print(output)
1995 self.assertRegex(output, '00:01:02:aa:bb:cc')
1996
1997 def test_ip_link_unmanaged(self):
ec38833c 1998 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
df7f9afa 1999 start_networkd(5)
1f0e3109 2000
e39cc445 2001 self.check_link_exists('dummy98')
1f0e3109 2002
19cf3143 2003 self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
1f0e3109
SS
2004
2005 def test_ipv6_address_label(self):
ec38833c 2006 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
2cf6fdff 2007 start_networkd()
e2aea43f 2008 self.wait_online(['dummy98:degraded'])
1f0e3109 2009
371810d1 2010 output = check_output('ip addrlabel list')
1f0e3109
SS
2011 print(output)
2012 self.assertRegex(output, '2004:da8:1::/64')
2013
d86f5c19 2014 def test_neighbor_section(self):
ec38833c 2015 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2cf6fdff 2016 start_networkd()
e2aea43f 2017 self.wait_online(['dummy98:degraded'], timeout='40s')
e4a71bf3 2018
d1bdafd2 2019 print('### ip neigh list dev dummy98')
df7f9afa 2020 output = check_output('ip neigh list dev dummy98')
e4a71bf3
WKI
2021 print(output)
2022 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 2023 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 2024
d1bdafd2
WKI
2025 def test_neighbor_reconfigure(self):
2026 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2027 start_networkd()
2028 self.wait_online(['dummy98:degraded'], timeout='40s')
2029
2030 print('### ip neigh list dev dummy98')
2031 output = check_output('ip neigh list dev dummy98')
2032 print(output)
2033 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2034 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2035
2036 remove_unit_from_networkd_path(['25-neighbor-section.network'])
2037 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
2038 restart_networkd(3)
2039 self.wait_online(['dummy98:degraded'], timeout='40s')
2040 print('### ip neigh list dev dummy98')
2041 output = check_output('ip neigh list dev dummy98')
2042 print(output)
2043 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2044 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
2045 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
2046
74761cf3 2047 def test_neighbor_gre(self):
fb2ba330
YW
2048 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
2049 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
74761cf3 2050 start_networkd()
fb2ba330 2051 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
74761cf3
YW
2052
2053 output = check_output('ip neigh list dev gretun97')
2054 print(output)
2055 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
fb2ba330
YW
2056
2057 output = check_output('ip neigh list dev ip6gretun97')
2058 print(output)
2059 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
74761cf3 2060
05514ae1 2061 def test_link_local_addressing(self):
ec38833c
ZJS
2062 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
2063 '25-link-local-addressing-no.network', '12-dummy.netdev')
2cf6fdff 2064 start_networkd()
e2aea43f 2065 self.wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1 2066
371810d1 2067 output = check_output('ip address show dev test1')
05514ae1
YW
2068 print(output)
2069 self.assertRegex(output, 'inet .* scope link')
2070 self.assertRegex(output, 'inet6 .* scope link')
2071
371810d1 2072 output = check_output('ip address show dev dummy98')
05514ae1
YW
2073 print(output)
2074 self.assertNotRegex(output, 'inet6* .* scope link')
2075
05514ae1
YW
2076 '''
2077 Documentation/networking/ip-sysctl.txt
2078
2079 addr_gen_mode - INTEGER
2080 Defines how link-local and autoconf addresses are generated.
2081
2082 0: generate address based on EUI64 (default)
2083 1: do no generate a link-local address, use EUI64 for addresses generated
2084 from autoconf
2085 2: generate stable privacy addresses, using the secret from
2086 stable_secret (RFC7217)
2087 3: generate stable privacy addresses, using a random secret if unset
2088 '''
2089
2090 test1_addr_gen_mode = ''
2091 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
2092 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
2093 try:
2094 f.readline()
2095 except IOError:
2096 # if stable_secret is unset, then EIO is returned
2097 test1_addr_gen_mode = '0'
2098 else:
2099 test1_addr_gen_mode = '2'
2100 else:
2101 test1_addr_gen_mode = '0'
2102
2103 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
ec38833c 2104 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
05514ae1
YW
2105
2106 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
ec38833c 2107 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
05514ae1 2108
7b3770a7
YW
2109 def test_link_local_addressing_remove_ipv6ll(self):
2110 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
2111 start_networkd()
2112 self.wait_online(['dummy98:degraded'])
2113
2114 output = check_output('ip address show dev dummy98')
2115 print(output)
2116 self.assertRegex(output, 'inet6 .* scope link')
2117
2118 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
2119 restart_networkd(1)
2120 self.wait_online(['dummy98:carrier'])
2121
2122 output = check_output('ip address show dev dummy98')
2123 print(output)
2124 self.assertNotRegex(output, 'inet6* .* scope link')
2125
1f0e3109 2126 def test_sysctl(self):
ec38833c 2127 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
2cf6fdff 2128 start_networkd()
e2aea43f 2129 self.wait_online(['dummy98:degraded'])
ec38833c
ZJS
2130
2131 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
2132 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
2133 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
2134 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
2135 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
2136 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
2137 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1f0e3109 2138
4da33154 2139 def test_sysctl_disable_ipv6(self):
ec38833c 2140 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
4da33154
YW
2141
2142 print('## Disable ipv6')
cefd6b3d
ZJS
2143 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
2144 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
4da33154 2145
2cf6fdff 2146 start_networkd()
e2aea43f 2147 self.wait_online(['dummy98:routable'])
4da33154 2148
371810d1 2149 output = check_output('ip -4 address show dummy98')
4da33154
YW
2150 print(output)
2151 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2152 output = check_output('ip -6 address show dummy98')
4da33154 2153 print(output)
57ad7607
ZJS
2154 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2155 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2156 output = check_output('ip -4 route show dev dummy98')
2157 print(output)
2158 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2159 output = check_output('ip -6 route show dev dummy98')
2160 print(output)
57ad7607 2161 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
4da33154 2162
cefd6b3d 2163 check_output('ip link del dummy98')
4da33154
YW
2164
2165 print('## Enable ipv6')
cefd6b3d
ZJS
2166 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
2167 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
4da33154 2168
e2aea43f
YW
2169 restart_networkd(3)
2170 self.wait_online(['dummy98:routable'])
4da33154 2171
371810d1 2172 output = check_output('ip -4 address show dummy98')
4da33154
YW
2173 print(output)
2174 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2175 output = check_output('ip -6 address show dummy98')
4da33154 2176 print(output)
4933b97d 2177 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
4da33154 2178 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2179 output = check_output('ip -4 route show dev dummy98')
2180 print(output)
2181 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
2182 output = check_output('ip -6 route show dev dummy98')
2183 print(output)
2184 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
4da33154 2185
cd65d067 2186 def test_bind_carrier(self):
bc942f69
YW
2187 check_output('ip link add dummy98 type dummy')
2188 check_output('ip link set dummy98 up')
2189 time.sleep(2)
2190
ec38833c 2191 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
2cf6fdff 2192 start_networkd()
e2aea43f 2193 self.wait_online(['test1:routable'])
cd65d067 2194
371810d1 2195 output = check_output('ip address show test1')
cd65d067
YW
2196 print(output)
2197 self.assertRegex(output, 'UP,LOWER_UP')
2198 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2199 self.wait_operstate('test1', 'routable')
cd65d067 2200
cefd6b3d
ZJS
2201 check_output('ip link add dummy99 type dummy')
2202 check_output('ip link set dummy99 up')
b117044c 2203 time.sleep(2)
371810d1 2204 output = check_output('ip address show test1')
cd65d067
YW
2205 print(output)
2206 self.assertRegex(output, 'UP,LOWER_UP')
2207 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2208 self.wait_operstate('test1', 'routable')
cd65d067 2209
cefd6b3d 2210 check_output('ip link del dummy98')
b117044c 2211 time.sleep(2)
371810d1 2212 output = check_output('ip address show test1')
cd65d067
YW
2213 print(output)
2214 self.assertRegex(output, 'UP,LOWER_UP')
2215 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2216 self.wait_operstate('test1', 'routable')
cd65d067 2217
bc942f69 2218 check_output('ip link set dummy99 down')
b117044c 2219 time.sleep(2)
371810d1 2220 output = check_output('ip address show test1')
cd65d067
YW
2221 print(output)
2222 self.assertNotRegex(output, 'UP,LOWER_UP')
2223 self.assertRegex(output, 'DOWN')
2224 self.assertNotRegex(output, '192.168.10')
19cf3143 2225 self.wait_operstate('test1', 'off')
cd65d067 2226
bc942f69 2227 check_output('ip link set dummy99 up')
b117044c 2228 time.sleep(2)
371810d1 2229 output = check_output('ip address show test1')
cd65d067
YW
2230 print(output)
2231 self.assertRegex(output, 'UP,LOWER_UP')
2232 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2233 self.wait_operstate('test1', 'routable')
cd65d067 2234
fdcd1ec5 2235 def test_domain(self):
ec38833c 2236 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2cf6fdff 2237 start_networkd()
e2aea43f 2238 self.wait_online(['dummy98:routable'])
fdcd1ec5 2239
fc79e6ff 2240 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
fdcd1ec5
YW
2241 print(output)
2242 self.assertRegex(output, 'Address: 192.168.42.100')
2243 self.assertRegex(output, 'DNS: 192.168.42.1')
2244 self.assertRegex(output, 'Search Domains: one')
2245
1e498853
YW
2246 def test_keep_configuration_static(self):
2247 check_output('systemctl stop systemd-networkd')
2248
2249 check_output('ip link add name dummy98 type dummy')
2250 check_output('ip address add 10.1.2.3/16 dev dummy98')
2251 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2252 output = check_output('ip address show dummy98')
2253 print(output)
2254 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2255 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2256 output = check_output('ip route show dev dummy98')
2257 print(output)
2258
2259 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2cf6fdff 2260 start_networkd()
e2aea43f 2261 self.wait_online(['dummy98:routable'])
1e498853
YW
2262
2263 output = check_output('ip address show dummy98')
2264 print(output)
2265 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2266 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2267
086bcf5d
YW
2268 @expectedFailureIfNexthopIsNotAvailable()
2269 def test_nexthop(self):
2270 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2271 start_networkd()
2272 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2273
2274 output = check_output('ip nexthop list dev veth99')
2275 print(output)
2276 self.assertRegex(output, '192.168.5.1')
2277
ef3c8a92 2278 def test_qdisc(self):
f1de1eb3
YW
2279 copy_unit_to_networkd_unit_path('25-qdisc-clsact-and-htb.network', '12-dummy.netdev',
2280 '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')
2281 check_output('modprobe sch_teql max_equalizers=2')
ef3c8a92
YW
2282 start_networkd()
2283
1b628c4f 2284 self.wait_online(['dummy98:routable', 'test1:routable'])
ef3c8a92 2285
f1de1eb3
YW
2286 output = check_output('tc qdisc show dev test1')
2287 print(output)
2288 self.assertRegex(output, 'qdisc netem')
2289 self.assertRegex(output, 'limit 100 delay 50.0ms 10.0ms loss 20%')
2290 self.assertRegex(output, 'qdisc ingress')
2291
ef3c8a92
YW
2292 output = check_output('tc qdisc show dev dummy98')
2293 print(output)
f1de1eb3
YW
2294 self.assertRegex(output, 'qdisc clsact')
2295
2296 self.assertRegex(output, 'qdisc htb 2: root')
2297 self.assertRegex(output, r'default (0x30|30)')
2298
2299 self.assertRegex(output, 'qdisc netem 30: parent 2:30')
ef3c8a92 2300 self.assertRegex(output, 'limit 100 delay 50.0ms 10.0ms loss 20%')
40821c2a 2301 self.assertRegex(output, 'qdisc fq_codel')
9401e488 2302 self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10.0ms ce_threshold 100.0ms interval 200.0ms memory_limit 64Mb ecn')
ef3c8a92 2303
f1de1eb3 2304 self.assertRegex(output, 'qdisc teql1 31: parent 2:31')
0baddbd5 2305
f1de1eb3 2306 self.assertRegex(output, 'qdisc fq 32: parent 2:32')
a05a6e8b
YW
2307 self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511')
2308 self.assertRegex(output, 'quantum 1500')
2309 self.assertRegex(output, 'initial_quantum 13000')
2310 self.assertRegex(output, 'maxrate 1Mbit')
ab9dc1db 2311
f1de1eb3 2312 self.assertRegex(output, 'qdisc codel 33: parent 2:33')
a3d35654 2313 self.assertRegex(output, 'limit 2000p target 10.0ms ce_threshold 100.0ms interval 50.0ms ecn')
ab9dc1db 2314
f1de1eb3
YW
2315 self.assertRegex(output, 'qdisc fq_codel 34: parent 2:34')
2316 self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10.0ms ce_threshold 100.0ms interval 200.0ms memory_limit 64Mb ecn')
ab9dc1db 2317
f1de1eb3
YW
2318 self.assertRegex(output, 'qdisc tbf 35: parent 2:35')
2319 self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70.0ms')
ab9dc1db 2320
f1de1eb3
YW
2321 self.assertRegex(output, 'qdisc sfq 36: parent 2:36')
2322 self.assertRegex(output, 'perturb 5sec')
3d55b5a9 2323
bc0769c9
YW
2324 self.assertRegex(output, 'qdisc pfifo 37: parent 2:37')
2325 self.assertRegex(output, 'limit 100000p')
2326
95edcf3f
YW
2327 self.assertRegex(output, 'qdisc gred 38: parent 2:38')
2328 self.assertRegex(output, 'vqs 12 default 10 grio')
2329
f2c5c129
YW
2330 self.assertRegex(output, 'qdisc sfb 39: parent 2:39')
2331 self.assertRegex(output, 'limit 200000')
2332
f1de1eb3 2333 output = check_output('tc class show dev dummy98')
ab9dc1db 2334 print(output)
f1de1eb3
YW
2335 self.assertRegex(output, 'class htb 2:30 root leaf 30:')
2336 self.assertRegex(output, 'class htb 2:31 root leaf 31:')
2337 self.assertRegex(output, 'class htb 2:32 root leaf 32:')
2338 self.assertRegex(output, 'class htb 2:33 root leaf 33:')
2339 self.assertRegex(output, 'class htb 2:34 root leaf 34:')
2340 self.assertRegex(output, 'class htb 2:35 root leaf 35:')
2341 self.assertRegex(output, 'class htb 2:36 root leaf 36:')
bc0769c9 2342 self.assertRegex(output, 'class htb 2:37 root leaf 37:')
95edcf3f 2343 self.assertRegex(output, 'class htb 2:38 root leaf 38:')
f2c5c129 2344 self.assertRegex(output, 'class htb 2:39 root leaf 39:')
f1de1eb3 2345 self.assertRegex(output, 'prio 1 rate 1Mbit ceil 500Kbit')
0baddbd5 2346
557fa421
YW
2347 def test_qdisc2(self):
2348 copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev')
2349 start_networkd()
2350
2351 self.wait_online(['dummy98:routable'])
2352
2353 output = check_output('tc qdisc show dev dummy98')
2354 print(output)
2355 self.assertRegex(output, 'qdisc drr 2: root')
2356 output = check_output('tc class show dev dummy98')
2357 print(output)
2358 self.assertRegex(output, 'class drr 2:30 root quantum 2000b')
2359
f6c6af38
YW
2360 @expectedFailureIfCAKEIsNotAvailable()
2361 def test_qdisc_cake(self):
2362 copy_unit_to_networkd_unit_path('25-qdisc-cake.network', '12-dummy.netdev')
3d55b5a9 2363 start_networkd()
3d55b5a9
YW
2364 self.wait_online(['dummy98:routable'])
2365
2366 output = check_output('tc qdisc show dev dummy98')
2367 print(output)
f6c6af38
YW
2368 self.assertRegex(output, 'qdisc cake 3a: root')
2369 self.assertRegex(output, 'bandwidth 500Mbit')
2370 self.assertRegex(output, 'overhead 128')
3d55b5a9 2371
be94e591
YW
2372 @expectedFailureIfPIEIsNotAvailable()
2373 def test_qdisc_pie(self):
2374 copy_unit_to_networkd_unit_path('25-qdisc-pie.network', '12-dummy.netdev')
2375 start_networkd()
2376 self.wait_online(['dummy98:routable'])
2377
2378 output = check_output('tc qdisc show dev dummy98')
2379 print(output)
2380 self.assertRegex(output, 'qdisc pie 3a: root')
2381 self.assertRegex(output, 'limit 200000')
2382
336d18f0
YW
2383class NetworkdStateFileTests(unittest.TestCase, Utilities):
2384 links = [
2385 'dummy98',
2386 ]
2387
2388 units = [
2389 '12-dummy.netdev',
2390 'state-file-tests.network',
2391 ]
2392
2393 def setUp(self):
2394 remove_links(self.links)
2395 stop_networkd(show_logs=False)
2396
2397 def tearDown(self):
2398 remove_links(self.links)
2399 remove_unit_from_networkd_path(self.units)
2400 stop_networkd(show_logs=True)
2401
2402 def test_state_file(self):
2403 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2404 start_networkd()
2405 self.wait_online(['dummy98:routable'])
2406
2407 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
2408 print(output)
2409 ifindex = output.split()[0]
2410
2411 path = os.path.join('/run/systemd/netif/links/', ifindex)
2412 self.assertTrue(os.path.exists(path))
2413 time.sleep(2)
2414
2415 with open(path) as f:
2416 data = f.read()
2417 self.assertRegex(data, r'ADMIN_STATE=configured')
2418 self.assertRegex(data, r'OPER_STATE=routable')
2419 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
2420 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2421 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2422 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2423 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2424 self.assertRegex(data, r'DOMAINS=hogehoge')
2425 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2426 self.assertRegex(data, r'LLMNR=no')
2427 self.assertRegex(data, r'MDNS=yes')
2428 self.assertRegex(data, r'DNSSEC=no')
426654d7 2429 self.assertRegex(data, r'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
336d18f0
YW
2430
2431 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env)
2432 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
2433 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
2434 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
2435 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
2436 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
2437 time.sleep(2)
2438
2439 with open(path) as f:
2440 data = f.read()
2441 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2442 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2443 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2444 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2445 self.assertRegex(data, r'LLMNR=yes')
2446 self.assertRegex(data, r'MDNS=no')
2447 self.assertRegex(data, r'DNSSEC=yes')
2448
2449 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
2450 time.sleep(2)
2451
2452 with open(path) as f:
2453 data = f.read()
2454 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2455 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2456 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2457 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2458 self.assertRegex(data, r'LLMNR=yes')
2459 self.assertRegex(data, r'MDNS=no')
2460 self.assertRegex(data, r'DNSSEC=yes')
2461
2462 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
2463 time.sleep(2)
2464
2465 with open(path) as f:
2466 data = f.read()
2467 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2468 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2469 self.assertRegex(data, r'DOMAINS=hogehoge')
2470 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2471 self.assertRegex(data, r'LLMNR=no')
2472 self.assertRegex(data, r'MDNS=yes')
2473 self.assertRegex(data, r'DNSSEC=no')
2474
be68c2c9 2475class NetworkdBondTests(unittest.TestCase, Utilities):
c3a8853f 2476 links = [
c2990ec3 2477 'bond199',
c3a8853f 2478 'bond99',
cc3e488c
YW
2479 'dummy98',
2480 'test1']
c3a8853f
YW
2481
2482 units = [
cc3e488c
YW
2483 '11-dummy.netdev',
2484 '12-dummy.netdev',
c2990ec3
YW
2485 '23-active-slave.network',
2486 '23-bond199.network',
2487 '23-primary-slave.network',
c2990ec3 2488 '25-bond-active-backup-slave.netdev',
c3a8853f 2489 '25-bond.netdev',
c3a8853f 2490 'bond99.network',
cc3e488c 2491 'bond-slave.network']
c3a8853f
YW
2492
2493 def setUp(self):
ec38833c 2494 remove_links(self.links)
aaae5713 2495 stop_networkd(show_logs=False)
c3a8853f
YW
2496
2497 def tearDown(self):
ec38833c
ZJS
2498 remove_links(self.links)
2499 remove_unit_from_networkd_path(self.units)
aaae5713 2500 stop_networkd(show_logs=True)
c3a8853f 2501
c2990ec3 2502 def test_bond_active_slave(self):
ec38833c 2503 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 2504 start_networkd()
e2aea43f 2505 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 2506
371810d1 2507 output = check_output('ip -d link show bond199')
c2990ec3
YW
2508 print(output)
2509 self.assertRegex(output, 'active_slave dummy98')
2510
2511 def test_bond_primary_slave(self):
35a78c51 2512 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 2513 start_networkd()
e2aea43f 2514 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 2515
371810d1 2516 output = check_output('ip -d link show bond199')
c2990ec3 2517 print(output)
35a78c51 2518 self.assertRegex(output, 'primary dummy98')
c2990ec3 2519
cc3e488c 2520 def test_bond_operstate(self):
ec38833c
ZJS
2521 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2522 'bond99.network','bond-slave.network')
2cf6fdff 2523 start_networkd()
e2aea43f 2524 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
c3a8853f 2525
371810d1 2526 output = check_output('ip -d link show dummy98')
c3a8853f 2527 print(output)
cc3e488c 2528 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 2529
371810d1 2530 output = check_output('ip -d link show test1')
c3a8853f
YW
2531 print(output)
2532 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2533
371810d1 2534 output = check_output('ip -d link show bond99')
c3a8853f
YW
2535 print(output)
2536 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
2537
19cf3143
DS
2538 self.wait_operstate('dummy98', 'enslaved')
2539 self.wait_operstate('test1', 'enslaved')
2540 self.wait_operstate('bond99', 'routable')
c3a8853f 2541
cefd6b3d 2542 check_output('ip link set dummy98 down')
c3a8853f 2543
19cf3143
DS
2544 self.wait_operstate('dummy98', 'off')
2545 self.wait_operstate('test1', 'enslaved')
2546 self.wait_operstate('bond99', 'degraded-carrier')
c3a8853f 2547
cefd6b3d 2548 check_output('ip link set dummy98 up')
c3a8853f 2549
19cf3143
DS
2550 self.wait_operstate('dummy98', 'enslaved')
2551 self.wait_operstate('test1', 'enslaved')
2552 self.wait_operstate('bond99', 'routable')
c3a8853f 2553
cefd6b3d
ZJS
2554 check_output('ip link set dummy98 down')
2555 check_output('ip link set test1 down')
cc3e488c 2556
19cf3143
DS
2557 self.wait_operstate('dummy98', 'off')
2558 self.wait_operstate('test1', 'off')
2700d2c7 2559
a4632dc7 2560 if not self.wait_operstate('bond99', 'no-carrier', setup_timeout=30, fail_assert=False):
2700d2c7
YW
2561 # Huh? Kernel does not recognize that all slave interfaces are down?
2562 # Let's confirm that networkd's operstate is consistent with ip's result.
2563 self.assertNotRegex(output, 'NO-CARRIER')
cc3e488c 2564
be68c2c9 2565class NetworkdBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
2566 links = [
2567 'bridge99',
2568 'dummy98',
2569 'test1']
2570
2571 units = [
2572 '11-dummy.netdev',
2573 '12-dummy.netdev',
2574 '26-bridge.netdev',
2575 '26-bridge-slave-interface-1.network',
2576 '26-bridge-slave-interface-2.network',
6f943798
YW
2577 '26-bridge-vlan-master.network',
2578 '26-bridge-vlan-slave.network',
804b6cd2 2579 'bridge99-ignore-carrier-loss.network',
09ea6724 2580 'bridge99.network']
1f0e3109 2581
8d17c386
YW
2582 routing_policy_rule_tables = ['100']
2583
1f0e3109 2584 def setUp(self):
8d17c386 2585 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c 2586 remove_links(self.links)
aaae5713 2587 stop_networkd(show_logs=False)
1f0e3109
SS
2588
2589 def tearDown(self):
8d17c386 2590 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c
ZJS
2591 remove_links(self.links)
2592 remove_unit_from_networkd_path(self.units)
aaae5713 2593 stop_networkd(show_logs=True)
1f0e3109 2594
6f943798
YW
2595 def test_bridge_vlan(self):
2596 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2597 '26-bridge.netdev', '26-bridge-vlan-master.network')
2598 start_networkd()
e2aea43f 2599 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
6f943798
YW
2600
2601 output = check_output('bridge vlan show dev test1')
2602 print(output)
2603 self.assertNotRegex(output, '4063')
2604 for i in range(4064, 4095):
2605 self.assertRegex(output, f'{i}')
2606 self.assertNotRegex(output, '4095')
2607
2608 output = check_output('bridge vlan show dev bridge99')
2609 print(output)
2610 self.assertNotRegex(output, '4059')
2611 for i in range(4060, 4095):
2612 self.assertRegex(output, f'{i}')
2613 self.assertNotRegex(output, '4095')
2614
1f0e3109 2615 def test_bridge_property(self):
ec38833c
ZJS
2616 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2617 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2618 'bridge99.network')
2cf6fdff 2619 start_networkd()
e2aea43f 2620 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
1f0e3109 2621
371810d1 2622 output = check_output('ip -d link show test1')
1f0e3109
SS
2623 print(output)
2624 self.assertRegex(output, 'master')
2625 self.assertRegex(output, 'bridge')
2626
371810d1 2627 output = check_output('ip -d link show dummy98')
1f0e3109
SS
2628 print(output)
2629 self.assertRegex(output, 'master')
2630 self.assertRegex(output, 'bridge')
2631
371810d1 2632 output = check_output('ip addr show bridge99')
1f0e3109 2633 print(output)
2be6c5d2 2634 self.assertRegex(output, '192.168.0.15/24')
1f0e3109 2635
371810d1 2636 output = check_output('bridge -d link show dummy98')
1f0e3109 2637 print(output)
ec38833c 2638 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
5424fd95
YW
2639 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2640 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
ec38833c
ZJS
2641 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2642 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
5424fd95
YW
2643 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2644 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2645 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
7f15b714 2646 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
ec38833c
ZJS
2647 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2648 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
5424fd95
YW
2649 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2650 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2651 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
4d7ed14f 2652
5424fd95
YW
2653 output = check_output('bridge -d link show test1')
2654 print(output)
2655 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
1f0e3109 2656
371810d1 2657 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
2658 time.sleep(1)
2659
371810d1 2660 output = check_output('ip addr show bridge99')
2be6c5d2
YW
2661 print(output)
2662 self.assertRegex(output, '192.168.0.16/24')
2663
e3cbaeab
YW
2664 # for issue #6088
2665 print('### ip -6 route list table all dev bridge99')
2666 output = check_output('ip -6 route list table all dev bridge99')
2667 print(output)
2668 self.assertRegex(output, 'ff00::/8 table local metric 256 pref medium')
2669
371810d1 2670 self.assertEqual(call('ip link del test1'), 0)
2be6c5d2 2671
19cf3143 2672 self.wait_operstate('bridge99', 'degraded-carrier')
2be6c5d2 2673
cefd6b3d 2674 check_output('ip link del dummy98')
804b6cd2 2675
19cf3143 2676 self.wait_operstate('bridge99', 'no-carrier')
2be6c5d2 2677
371810d1 2678 output = check_output('ip address show bridge99')
804b6cd2
YW
2679 print(output)
2680 self.assertRegex(output, 'NO-CARRIER')
2681 self.assertNotRegex(output, '192.168.0.15/24')
2682 self.assertNotRegex(output, '192.168.0.16/24')
2683
e3cbaeab
YW
2684 print('### ip -6 route list table all dev bridge99')
2685 output = check_output('ip -6 route list table all dev bridge99')
2686 print(output)
426654d7 2687 self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
e3cbaeab 2688
804b6cd2 2689 def test_bridge_ignore_carrier_loss(self):
ec38833c
ZJS
2690 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2691 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2692 'bridge99-ignore-carrier-loss.network')
2cf6fdff 2693 start_networkd()
e2aea43f 2694 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
804b6cd2 2695
371810d1 2696 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
2697 time.sleep(1)
2698
371810d1
ZJS
2699 check_output('ip link del test1')
2700 check_output('ip link del dummy98')
804b6cd2
YW
2701 time.sleep(3)
2702
371810d1 2703 output = check_output('ip address show bridge99')
804b6cd2
YW
2704 print(output)
2705 self.assertRegex(output, 'NO-CARRIER')
2706 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2707 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
2708
6609924c 2709 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
ec38833c
ZJS
2710 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2711 'bridge99-ignore-carrier-loss.network')
2cf6fdff 2712 start_networkd()
e2aea43f 2713 self.wait_online(['bridge99:no-carrier'])
6609924c 2714
90e3bcbd
YW
2715 for trial in range(4):
2716 check_output('ip link add dummy98 type dummy')
2717 check_output('ip link set dummy98 up')
2718 if trial < 3:
2719 check_output('ip link del dummy98')
6609924c 2720
e2aea43f 2721 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
6609924c 2722
371810d1 2723 output = check_output('ip address show bridge99')
6609924c
YW
2724 print(output)
2725 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2726
371810d1 2727 output = check_output('ip rule list table 100')
6609924c
YW
2728 print(output)
2729 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
2730
be68c2c9 2731class NetworkdLLDPTests(unittest.TestCase, Utilities):
1f0e3109
SS
2732 links = ['veth99']
2733
09ea6724
YW
2734 units = [
2735 '23-emit-lldp.network',
2736 '24-lldp.network',
2737 '25-veth.netdev']
1f0e3109
SS
2738
2739 def setUp(self):
ec38833c 2740 remove_links(self.links)
aaae5713 2741 stop_networkd(show_logs=False)
1f0e3109
SS
2742
2743 def tearDown(self):
ec38833c
ZJS
2744 remove_links(self.links)
2745 remove_unit_from_networkd_path(self.units)
aaae5713 2746 stop_networkd(show_logs=True)
1f0e3109
SS
2747
2748 def test_lldp(self):
ec38833c 2749 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2cf6fdff 2750 start_networkd()
e2aea43f 2751 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1f0e3109 2752
371810d1 2753 output = check_output(*networkctl_cmd, 'lldp', env=env)
1f0e3109
SS
2754 print(output)
2755 self.assertRegex(output, 'veth-peer')
2756 self.assertRegex(output, 'veth99')
2757
be68c2c9 2758class NetworkdRATests(unittest.TestCase, Utilities):
1f0e3109
SS
2759 links = ['veth99']
2760
09ea6724
YW
2761 units = [
2762 '25-veth.netdev',
2763 'ipv6-prefix.network',
87bbebea 2764 'ipv6-prefix-veth.network',
e2c4070e 2765 'ipv6-prefix-veth-token-static.network',
b241fa00 2766 'ipv6-prefix-veth-token-static-explicit.network',
c24c83dc 2767 'ipv6-prefix-veth-token-static-multiple.network',
87bbebea 2768 'ipv6-prefix-veth-token-prefixstable.network']
1f0e3109
SS
2769
2770 def setUp(self):
ec38833c 2771 remove_links(self.links)
aaae5713 2772 stop_networkd(show_logs=False)
1f0e3109
SS
2773
2774 def tearDown(self):
ec38833c
ZJS
2775 remove_links(self.links)
2776 remove_unit_from_networkd_path(self.units)
aaae5713 2777 stop_networkd(show_logs=True)
1f0e3109
SS
2778
2779 def test_ipv6_prefix_delegation(self):
ec38833c 2780 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2cf6fdff 2781 start_networkd()
e2aea43f 2782 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1f0e3109 2783
41fd8fe7
YW
2784 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2785 print(output)
2786 self.assertRegex(output, 'fe80::')
2787 self.assertRegex(output, '2002:da8:1::1')
2788
fc79e6ff 2789 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2790 print(output)
2791 self.assertRegex(output, '2002:da8:1:0')
2792
e2c4070e
YW
2793 def test_ipv6_token_static(self):
2794 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static.network')
87bbebea 2795 start_networkd()
b241fa00
KF
2796 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2797
2798 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2799 print(output)
2800 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2801
2802 def test_ipv6_token_static_explicit(self):
2803 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-explicit.network')
2804 start_networkd()
87bbebea
YW
2805 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2806
2807 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2808 print(output)
2809 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2810
c24c83dc
KF
2811 def test_ipv6_token_static_multiple(self):
2812 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-multiple.network')
2813 start_networkd()
2814 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2815
2816 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2817 print(output)
2818 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2819 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe')
2820
87bbebea
YW
2821 def test_ipv6_token_prefixstable(self):
2822 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network')
2823 start_networkd()
2824 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2825
2826 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2827 print(output)
2828 self.assertRegex(output, '2002:da8:1:0')
2829
be68c2c9 2830class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
fdcd1ec5 2831 links = ['veth99']
09ea6724
YW
2832
2833 units = [
09ea6724
YW
2834 '25-veth.netdev',
2835 'dhcp-client.network',
2836 'dhcp-client-timezone-router.network',
2837 'dhcp-server.network',
2838 'dhcp-server-timezone-router.network']
1f0e3109
SS
2839
2840 def setUp(self):
ec38833c 2841 remove_links(self.links)
aaae5713 2842 stop_networkd(show_logs=False)
1f0e3109
SS
2843
2844 def tearDown(self):
ec38833c
ZJS
2845 remove_links(self.links)
2846 remove_unit_from_networkd_path(self.units)
aaae5713 2847 stop_networkd(show_logs=True)
1f0e3109
SS
2848
2849 def test_dhcp_server(self):
ec38833c 2850 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2cf6fdff 2851 start_networkd()
e2aea43f 2852 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2853
fc79e6ff 2854 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2855 print(output)
2856 self.assertRegex(output, '192.168.5.*')
2857 self.assertRegex(output, 'Gateway: 192.168.5.1')
2858 self.assertRegex(output, 'DNS: 192.168.5.1')
2859 self.assertRegex(output, 'NTP: 192.168.5.1')
2860
1f0e3109 2861 def test_emit_router_timezone(self):
ec38833c 2862 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2cf6fdff 2863 start_networkd()
e2aea43f 2864 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2865
fc79e6ff 2866 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2867 print(output)
2868 self.assertRegex(output, 'Gateway: 192.168.5.*')
2869 self.assertRegex(output, '192.168.5.*')
2870 self.assertRegex(output, 'Europe/Berlin')
2871
be68c2c9 2872class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
09ea6724 2873 links = [
18c613dc
YW
2874 'veth99',
2875 'vrf99']
09ea6724
YW
2876
2877 units = [
2878 '25-veth.netdev',
18c613dc
YW
2879 '25-vrf.netdev',
2880 '25-vrf.network',
09ea6724 2881 'dhcp-client-anonymize.network',
0fd8b718 2882 'dhcp-client-decline.network',
214c5bae
YW
2883 'dhcp-client-gateway-ipv4.network',
2884 'dhcp-client-gateway-ipv6.network',
af3b1498 2885 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
2886 'dhcp-client-ipv4-dhcp-settings.network',
2887 'dhcp-client-ipv4-only-ipv6-disabled.network',
2888 'dhcp-client-ipv4-only.network',
4c2e1833 2889 'dhcp-client-ipv4-use-routes-no.network',
09ea6724
YW
2890 'dhcp-client-ipv6-only.network',
2891 'dhcp-client-ipv6-rapid-commit.network',
1e498853
YW
2892 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2893 'dhcp-client-keep-configuration-dhcp.network',
09ea6724 2894 'dhcp-client-listen-port.network',
c1b01a62
YW
2895 'dhcp-client-reassign-static-routes-ipv4.network',
2896 'dhcp-client-reassign-static-routes-ipv6.network',
09ea6724
YW
2897 'dhcp-client-route-metric.network',
2898 'dhcp-client-route-table.network',
e2d5aab3
YW
2899 'dhcp-client-use-dns-ipv4-and-ra.network',
2900 'dhcp-client-use-dns-ipv4.network',
2901 'dhcp-client-use-dns-no.network',
2902 'dhcp-client-use-dns-yes.network',
e0c1341d 2903 'dhcp-client-use-domains.network',
c38d2d4d 2904 'dhcp-client-use-routes-no.network',
18c613dc 2905 'dhcp-client-vrf.network',
117a55c7
YW
2906 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2907 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
4c882c16 2908 'dhcp-client-with-static-address.network',
3e9d5552 2909 'dhcp-client.network',
0fd8b718 2910 'dhcp-server-decline.network',
09ea6724 2911 'dhcp-server-veth-peer.network',
30d3b54e 2912 'dhcp-v4-server-veth-peer.network',
e0c1341d 2913 'dhcp-client-use-domains.network',
30d3b54e 2914 'static.network']
1f0e3109
SS
2915
2916 def setUp(self):
ec38833c
ZJS
2917 stop_dnsmasq(dnsmasq_pid_file)
2918 remove_links(self.links)
aaae5713 2919 stop_networkd(show_logs=False)
1f0e3109
SS
2920
2921 def tearDown(self):
ec38833c
ZJS
2922 stop_dnsmasq(dnsmasq_pid_file)
2923 remove_lease_file()
2924 remove_log_file()
2925 remove_links(self.links)
2926 remove_unit_from_networkd_path(self.units)
aaae5713 2927 stop_networkd(show_logs=True)
1f0e3109
SS
2928
2929 def test_dhcp_client_ipv6_only(self):
ec38833c 2930 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109 2931
2cf6fdff 2932 start_networkd()
e2aea43f 2933 self.wait_online(['veth-peer:carrier'])
ec38833c 2934 start_dnsmasq()
e2aea43f 2935 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2936
fc79e6ff 2937 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2938 print(output)
2939 self.assertRegex(output, '2600::')
2940 self.assertNotRegex(output, '192.168.5')
2941
3a956d38 2942 # Confirm that ipv6 token is not set in the kernel
371810d1 2943 output = check_output('ip token show dev veth99')
3a956d38
YW
2944 print(output)
2945 self.assertRegex(output, 'token :: dev veth99')
2946
1f0e3109 2947 def test_dhcp_client_ipv4_only(self):
ec38833c 2948 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109 2949
2cf6fdff 2950 start_networkd()
e2aea43f 2951 self.wait_online(['veth-peer:carrier'])
195a18c1 2952 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
e2aea43f 2953 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2954
fc79e6ff 2955 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2956 print(output)
2957 self.assertNotRegex(output, '2600::')
2958 self.assertRegex(output, '192.168.5')
195a18c1
YW
2959 self.assertRegex(output, '192.168.5.6')
2960 self.assertRegex(output, '192.168.5.7')
2961
2962 # checking routes to DNS servers
2963 output = check_output('ip route show dev veth99')
2964 print(output)
2965 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2966 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2967 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2968
2969 stop_dnsmasq(dnsmasq_pid_file)
2970 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
2971
2972 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2973 print('Wait for the dynamic address to be renewed')
2974 time.sleep(125)
2975
2976 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2977
fc79e6ff 2978 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
195a18c1
YW
2979 print(output)
2980 self.assertNotRegex(output, '2600::')
2981 self.assertRegex(output, '192.168.5')
2982 self.assertNotRegex(output, '192.168.5.6')
2983 self.assertRegex(output, '192.168.5.7')
2984 self.assertRegex(output, '192.168.5.8')
2985
2986 # checking routes to DNS servers
2987 output = check_output('ip route show dev veth99')
2988 print(output)
2989 self.assertNotRegex(output, r'192.168.5.6')
2990 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2991 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2992 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
1f0e3109 2993
4c2e1833
YW
2994 def test_dhcp_client_ipv4_use_routes_no(self):
2995 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-use-routes-no.network')
2996
2997 start_networkd()
2998 self.wait_online(['veth-peer:carrier'])
2999 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
3000 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3001
3002 output = check_output('ip route show dev veth99')
3003 print(output)
3004 self.assertNotRegex(output, r'192.168.5.5')
3005 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
3006 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
3007
1f0e3109 3008 def test_dhcp_client_ipv4_ipv6(self):
ec38833c
ZJS
3009 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
3010 'dhcp-client-ipv4-only.network')
2cf6fdff 3011 start_networkd()
e2aea43f 3012 self.wait_online(['veth-peer:carrier'])
ec38833c 3013 start_dnsmasq()
e2aea43f 3014 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
3015
3016 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3017 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3018 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 3019
fc79e6ff 3020 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3021 print(output)
3022 self.assertRegex(output, '2600::')
3023 self.assertRegex(output, '192.168.5')
3024
3025 def test_dhcp_client_settings(self):
ec38833c 3026 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 3027
2cf6fdff 3028 start_networkd()
e2aea43f 3029 self.wait_online(['veth-peer:carrier'])
ec38833c 3030 start_dnsmasq()
e2aea43f 3031 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3032
0ae7a66d 3033 print('## ip address show dev veth99')
371810d1 3034 output = check_output('ip address show dev veth99')
1f0e3109
SS
3035 print(output)
3036 self.assertRegex(output, '12:34:56:78:9a:bc')
3037 self.assertRegex(output, '192.168.5')
3038 self.assertRegex(output, '1492')
3039
0ae7a66d 3040 print('## ip route show table main dev veth99')
371810d1 3041 output = check_output('ip route show table main dev veth99')
1f0e3109 3042 print(output)
156ddf8d 3043 # See issue #8726
dd9b10c8
YW
3044 main_table_is_empty = output == ''
3045 if not main_table_is_empty:
3046 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 3047
0ae7a66d 3048 print('## ip route show table 211 dev veth99')
371810d1 3049 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
3050 print(output)
3051 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
dd9b10c8
YW
3052 if main_table_is_empty:
3053 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
0ae7a66d
YW
3054 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
3055 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
3056
3057 print('## dnsmasq log')
ec38833c
ZJS
3058 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
3059 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
3060 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
3061 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
3062
3063 def test_dhcp6_client_settings_rapidcommit_true(self):
ec38833c 3064 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2cf6fdff 3065 start_networkd()
e2aea43f 3066 self.wait_online(['veth-peer:carrier'])
ec38833c 3067 start_dnsmasq()
e2aea43f 3068 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3069
371810d1 3070 output = check_output('ip address show dev veth99')
1f0e3109
SS
3071 print(output)
3072 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 3073 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
3074
3075 def test_dhcp6_client_settings_rapidcommit_false(self):
ec38833c 3076 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2cf6fdff 3077 start_networkd()
e2aea43f 3078 self.wait_online(['veth-peer:carrier'])
ec38833c 3079 start_dnsmasq()
e2aea43f 3080 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3081
371810d1 3082 output = check_output('ip address show dev veth99')
1f0e3109
SS
3083 print(output)
3084 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 3085 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
3086
3087 def test_dhcp_client_settings_anonymize(self):
ec38833c 3088 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2cf6fdff 3089 start_networkd()
e2aea43f 3090 self.wait_online(['veth-peer:carrier'])
ec38833c 3091 start_dnsmasq()
e2aea43f 3092 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3093
ec38833c
ZJS
3094 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
3095 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
3096 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
3097
3098 def test_dhcp_client_listen_port(self):
ec38833c 3099 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2cf6fdff 3100 start_networkd()
e2aea43f 3101 self.wait_online(['veth-peer:carrier'])
ec38833c 3102 start_dnsmasq('--dhcp-alternate-port=67,5555')
e2aea43f 3103 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47 3104
371810d1 3105 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
3106 print(output)
3107 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109 3108
4c882c16
YW
3109 def test_dhcp_client_with_static_address(self):
3110 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
3111 'dhcp-client-with-static-address.network')
3112 start_networkd()
e2aea43f 3113 self.wait_online(['veth-peer:carrier'])
4c882c16 3114 start_dnsmasq()
e2aea43f 3115 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4c882c16
YW
3116
3117 output = check_output('ip address show dev veth99 scope global')
3118 print(output)
3119 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3120 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
3121
3122 output = check_output('ip route show dev veth99')
3123 print(output)
3124 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
3125 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
3126 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
3127 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
3128
1f0e3109 3129 def test_dhcp_route_table_id(self):
ec38833c 3130 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2cf6fdff 3131 start_networkd()
e2aea43f 3132 self.wait_online(['veth-peer:carrier'])
ec38833c 3133 start_dnsmasq()
e2aea43f 3134 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3135
371810d1 3136 output = check_output('ip route show table 12')
1f0e3109 3137 print(output)
1f0e3109
SS
3138 self.assertRegex(output, 'veth99 proto dhcp')
3139 self.assertRegex(output, '192.168.5.1')
3140
3141 def test_dhcp_route_metric(self):
ec38833c 3142 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2cf6fdff 3143 start_networkd()
e2aea43f 3144 self.wait_online(['veth-peer:carrier'])
ec38833c 3145 start_dnsmasq()
e2aea43f 3146 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3147
371810d1 3148 output = check_output('ip route show dev veth99')
1f0e3109 3149 print(output)
1f0e3109
SS
3150 self.assertRegex(output, 'metric 24')
3151
c1b01a62 3152 def test_dhcp_client_reassign_static_routes_ipv4(self):
c38d2d4d 3153 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
c1b01a62 3154 'dhcp-client-reassign-static-routes-ipv4.network')
c38d2d4d 3155 start_networkd()
e2aea43f 3156 self.wait_online(['veth-peer:carrier'])
c38d2d4d 3157 start_dnsmasq(lease_time='2m')
e2aea43f 3158 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c38d2d4d
YW
3159
3160 output = check_output('ip address show dev veth99 scope global')
3161 print(output)
3162 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3163
3164 output = check_output('ip route show dev veth99')
3165 print(output)
3166 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3167 self.assertRegex(output, r'192.168.5.0/24 proto static')
3168 self.assertRegex(output, r'192.168.6.0/24 proto static')
3169 self.assertRegex(output, r'192.168.7.0/24 proto static')
3170
c1b01a62
YW
3171 stop_dnsmasq(dnsmasq_pid_file)
3172 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
3173
c38d2d4d
YW
3174 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3175 print('Wait for the dynamic address to be renewed')
3176 time.sleep(125)
3177
e2aea43f 3178 self.wait_online(['veth99:routable'])
c38d2d4d
YW
3179
3180 output = check_output('ip route show dev veth99')
3181 print(output)
3182 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3183 self.assertRegex(output, r'192.168.5.0/24 proto static')
3184 self.assertRegex(output, r'192.168.6.0/24 proto static')
3185 self.assertRegex(output, r'192.168.7.0/24 proto static')
3186
c1b01a62
YW
3187 def test_dhcp_client_reassign_static_routes_ipv6(self):
3188 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3189 'dhcp-client-reassign-static-routes-ipv6.network')
3190 start_networkd()
e2aea43f 3191 self.wait_online(['veth-peer:carrier'])
c1b01a62 3192 start_dnsmasq(lease_time='2m')
e2aea43f 3193 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c1b01a62
YW
3194
3195 output = check_output('ip address show dev veth99 scope global')
3196 print(output)
426654d7 3197 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
c1b01a62
YW
3198
3199 output = check_output('ip -6 route show dev veth99')
3200 print(output)
3201 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3202 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3203
3204 stop_dnsmasq(dnsmasq_pid_file)
3205 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
3206
3207 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3208 print('Wait for the dynamic address to be renewed')
3209 time.sleep(125)
3210
e2aea43f 3211 self.wait_online(['veth99:routable'])
c1b01a62
YW
3212
3213 output = check_output('ip -6 route show dev veth99')
3214 print(output)
3215 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3216 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3217
1e498853
YW
3218 def test_dhcp_keep_configuration_dhcp(self):
3219 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2cf6fdff 3220 start_networkd()
e2aea43f 3221 self.wait_online(['veth-peer:carrier'])
1e498853 3222 start_dnsmasq(lease_time='2m')
e2aea43f 3223 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3224
1e498853
YW
3225 output = check_output('ip address show dev veth99 scope global')
3226 print(output)
3227 self.assertRegex(output, r'192.168.5.*')
3228
fc79e6ff 3229 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 3230 print(output)
1e498853 3231 self.assertRegex(output, r'192.168.5.*')
e40a58b5 3232
5238e957 3233 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
ec38833c 3234 stop_dnsmasq(dnsmasq_pid_file)
1f0e3109
SS
3235
3236 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 3237 print('Wait for the dynamic address to be expired')
1f0e3109
SS
3238 time.sleep(125)
3239
1e498853
YW
3240 print('The lease address should be kept after lease expired')
3241 output = check_output('ip address show dev veth99 scope global')
3242 print(output)
3243 self.assertRegex(output, r'192.168.5.*')
3244
fc79e6ff 3245 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 3246 print(output)
1e498853
YW
3247 self.assertRegex(output, r'192.168.5.*')
3248
3249 check_output('systemctl stop systemd-networkd')
3250
3251 print('The lease address should be kept after networkd stopped')
3252 output = check_output('ip address show dev veth99 scope global')
3253 print(output)
3254 self.assertRegex(output, r'192.168.5.*')
3255
fc79e6ff 3256 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
3257 print(output)
3258 self.assertRegex(output, r'192.168.5.*')
3259
e2aea43f
YW
3260 start_networkd(3)
3261 self.wait_online(['veth-peer:routable'])
1e498853
YW
3262
3263 print('Still the lease address should be kept after networkd restarted')
3264 output = check_output('ip address show dev veth99 scope global')
3265 print(output)
3266 self.assertRegex(output, r'192.168.5.*')
3267
fc79e6ff 3268 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
3269 print(output)
3270 self.assertRegex(output, r'192.168.5.*')
3271
3272 def test_dhcp_keep_configuration_dhcp_on_stop(self):
3273 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2cf6fdff 3274 start_networkd()
e2aea43f 3275 self.wait_online(['veth-peer:carrier'])
1e498853 3276 start_dnsmasq(lease_time='2m')
e2aea43f 3277 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853
YW
3278
3279 output = check_output('ip address show dev veth99 scope global')
3280 print(output)
3281 self.assertRegex(output, r'192.168.5.*')
3282
3283 stop_dnsmasq(dnsmasq_pid_file)
3284 check_output('systemctl stop systemd-networkd')
3285
3286 output = check_output('ip address show dev veth99 scope global')
3287 print(output)
3288 self.assertRegex(output, r'192.168.5.*')
3289
e2aea43f
YW
3290 restart_networkd(3)
3291 self.wait_online(['veth-peer:routable'])
1e498853
YW
3292
3293 output = check_output('ip address show dev veth99 scope global')
3294 print(output)
3295 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 3296
30d3b54e 3297 def test_dhcp_client_reuse_address_as_static(self):
ec38833c 3298 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2cf6fdff 3299 start_networkd()
e2aea43f 3300 self.wait_online(['veth-peer:carrier'])
ec38833c 3301 start_dnsmasq()
e2aea43f 3302 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
3303
3304 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3305 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3306 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 3307
371810d1 3308 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
3309 print(output)
3310 self.assertRegex(output, '192.168.5')
3311 self.assertRegex(output, '2600::')
3312
2629df47
YW
3313 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
3314 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
3315 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
3316 print(static_network)
3317
ec38833c 3318 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
3319
3320 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
3321 f.write(static_network)
3322
2629df47
YW
3323 # When networkd started, the links are already configured, so let's wait for 5 seconds
3324 # the links to be re-configured.
aaae5713 3325 restart_networkd(5)
e2aea43f 3326 self.wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 3327
371810d1 3328 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
3329 print(output)
3330 self.assertRegex(output, '192.168.5')
3331 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3332
371810d1 3333 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
3334 print(output)
3335 self.assertRegex(output, '2600::')
3336 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3337
18c613dc
YW
3338 @expectedFailureIfModuleIsNotAvailable('vrf')
3339 def test_dhcp_client_vrf(self):
ec38833c
ZJS
3340 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
3341 '25-vrf.netdev', '25-vrf.network')
2cf6fdff 3342 start_networkd()
e2aea43f 3343 self.wait_online(['veth-peer:carrier'])
ec38833c 3344 start_dnsmasq()
e2aea43f 3345 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
3346
3347 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3348 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3349 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
3350
3351 print('## ip -d link show dev vrf99')
371810d1 3352 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
3353 print(output)
3354 self.assertRegex(output, 'vrf table 42')
3355
3356 print('## ip address show vrf vrf99')
371810d1 3357 output = check_output('ip address show vrf vrf99')
d90f4f7d
YW
3358 print(output)
3359 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3360 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
426654d7 3361 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
d90f4f7d 3362 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
3363
3364 print('## ip address show dev veth99')
371810d1 3365 output = check_output('ip address show dev veth99')
18c613dc 3366 print(output)
18c613dc
YW
3367 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3368 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
426654d7 3369 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
3370 self.assertRegex(output, 'inet6 .* scope link')
3371
3372 print('## ip route show vrf vrf99')
371810d1 3373 output = check_output('ip route show vrf vrf99')
18c613dc
YW
3374 print(output)
3375 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
18c613dc
YW
3376 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3377 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3378 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3379 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3380
3381 print('## ip route show table main dev veth99')
371810d1 3382 output = check_output('ip route show table main dev veth99')
18c613dc
YW
3383 print(output)
3384 self.assertEqual(output, '')
3385
214c5bae
YW
3386 def test_dhcp_client_gateway_ipv4(self):
3387 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3388 'dhcp-client-gateway-ipv4.network')
3389 start_networkd()
3390 self.wait_online(['veth-peer:carrier'])
3391 start_dnsmasq()
3392 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3393
3394 output = check_output('ip route list dev veth99 10.0.0.0/8')
3395 print(output)
3396 self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static')
3397
3398 def test_dhcp_client_gateway_ipv6(self):
3399 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3400 'dhcp-client-gateway-ipv6.network')
3401 start_networkd()
3402 self.wait_online(['veth-peer:carrier'])
3403 start_dnsmasq()
3404 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3405
3406 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
3407 print(output)
3408 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
3409
af3b1498 3410 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
3411 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3412 'dhcp-client-gateway-onlink-implicit.network')
2cf6fdff 3413 start_networkd()
e2aea43f 3414 self.wait_online(['veth-peer:carrier'])
ec38833c 3415 start_dnsmasq()
e2aea43f 3416 self.wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 3417
fc79e6ff 3418 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
af3b1498
YW
3419 print(output)
3420 self.assertRegex(output, '192.168.5')
3421
371810d1 3422 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
3423 print(output)
3424 self.assertRegex(output, 'onlink')
371810d1 3425 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
3426 print(output)
3427 self.assertRegex(output, 'onlink')
3428
117a55c7 3429 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
ec38833c
ZJS
3430 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3431 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
2cf6fdff 3432 start_networkd()
e2aea43f 3433 self.wait_online(['veth-peer:carrier'])
ec38833c 3434 start_dnsmasq(lease_time='2m')
e2aea43f 3435 self.wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 3436
371810d1 3437 output = check_output('ip address show dev veth99')
63c598ed
YW
3438 print(output)
3439
371810d1 3440 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 3441 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3442 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 3443 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3444 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 3445 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3446 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
3447 self.assertNotRegex(output, 'inet .* scope link')
3448
3449 print('Wait for the dynamic address to be expired')
3450 time.sleep(130)
3451
371810d1 3452 output = check_output('ip address show dev veth99')
63c598ed
YW
3453 print(output)
3454
371810d1 3455 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 3456 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3457 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 3458 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3459 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 3460 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3461 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
3462 self.assertNotRegex(output, 'inet .* scope link')
3463
ec38833c 3464 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 3465
117a55c7 3466 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
ec38833c
ZJS
3467 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3468 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
2cf6fdff 3469 start_networkd()
e2aea43f 3470 self.wait_online(['veth99:degraded', 'veth-peer:routable'])
117a55c7 3471
371810d1 3472 output = check_output('ip address show dev veth99')
117a55c7
YW
3473 print(output)
3474
371810d1 3475 output = check_output('ip -6 address show dev veth99 scope global dynamic')
117a55c7 3476 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3477 output = check_output('ip -6 address show dev veth99 scope link')
117a55c7 3478 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3479 output = check_output('ip -4 address show dev veth99 scope global dynamic')
117a55c7 3480 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3481 output = check_output('ip -4 address show dev veth99 scope link')
117a55c7
YW
3482 self.assertRegex(output, 'inet .* scope link')
3483
b6efd661 3484 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
3485 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3486 'dhcp-client-ipv4-only-ipv6-disabled.network')
2cf6fdff 3487 start_networkd()
e2aea43f 3488 self.wait_online(['veth-peer:carrier'])
ec38833c 3489 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
e2aea43f 3490 self.wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
3491
3492 # test for issue #12490
3493
371810d1 3494 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
3495 print(output)
3496 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3497 address1=None
3498 for line in output.splitlines():
3499 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3500 address1 = line.split()[1].split('/')[0]
3501 break
3502
371810d1 3503 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
3504 print(output)
3505 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3506 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3507
ec38833c
ZJS
3508 stop_dnsmasq(dnsmasq_pid_file)
3509 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
3510
3511 print('Wait for the dynamic address to be expired')
3512 time.sleep(130)
3513
371810d1 3514 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
3515 print(output)
3516 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3517 address2=None
3518 for line in output.splitlines():
3519 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3520 address2 = line.split()[1].split('/')[0]
3521 break
3522
3523 self.assertNotEqual(address1, address2)
3524
371810d1 3525 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
3526 print(output)
3527 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3528 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3529 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3530 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3531
e2d5aab3
YW
3532 def test_dhcp_client_use_dns_yes(self):
3533 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3534
3535 start_networkd()
e2aea43f 3536 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3537 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3538 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3539
3540 # link become 'routable' when at least one protocol provide an valid address.
3541 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3542 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3543
693283cd 3544 time.sleep(3)
e2d5aab3
YW
3545 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3546 print(output)
3547 self.assertRegex(output, '192.168.5.1')
3548 self.assertRegex(output, '2600::1')
3549
3550 def test_dhcp_client_use_dns_no(self):
3551 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3552
3553 start_networkd()
e2aea43f 3554 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3555 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3556 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3557
3558 # link become 'routable' when at least one protocol provide an valid address.
3559 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3560 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3561
693283cd 3562 time.sleep(3)
e2d5aab3
YW
3563 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3564 print(output)
3565 self.assertNotRegex(output, '192.168.5.1')
3566 self.assertNotRegex(output, '2600::1')
3567
3568 def test_dhcp_client_use_dns_ipv4(self):
3569 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3570
3571 start_networkd()
e2aea43f 3572 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3573 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3574 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3575
3576 # link become 'routable' when at least one protocol provide an valid address.
3577 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3578 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3579
693283cd 3580 time.sleep(3)
e2d5aab3
YW
3581 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3582 print(output)
3583 self.assertRegex(output, '192.168.5.1')
3584 self.assertNotRegex(output, '2600::1')
3585
3586 def test_dhcp_client_use_dns_ipv4_and_ra(self):
3587 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3588
3589 start_networkd()
e2aea43f 3590 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3591 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3592 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3593
3594 # link become 'routable' when at least one protocol provide an valid address.
3595 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3596 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3597
693283cd 3598 time.sleep(3)
e2d5aab3
YW
3599 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3600 print(output)
3601 self.assertRegex(output, '192.168.5.1')
3602 self.assertRegex(output, '2600::1')
3603
e0c1341d
YW
3604 def test_dhcp_client_use_domains(self):
3605 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3606
3607 start_networkd()
e2aea43f 3608 self.wait_online(['veth-peer:carrier'])
e0c1341d 3609 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
e2aea43f 3610 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e0c1341d 3611
fc79e6ff 3612 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
e0c1341d
YW
3613 print(output)
3614 self.assertRegex(output, 'Search Domains: example.com')
3615
3616 time.sleep(3)
3617 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3618 print(output)
3619 self.assertRegex(output, 'example.com')
3620
0fd8b718
YW
3621 def test_dhcp_client_decline(self):
3622 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
3623
3624 start_networkd()
3625 self.wait_online(['veth-peer:carrier'])
3626 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env)
3627 self.assertTrue(rc == 1)
3628
9633f977
SS
3629class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
3630 links = ['veth99']
3631
3632 units = [
3633 '25-veth.netdev',
3634 'ipv6ra-prefix-client.network',
3635 'ipv6ra-prefix.network'
3636 ]
3637
3638 def setUp(self):
3639 remove_links(self.links)
3640 stop_networkd(show_logs=False)
3641
3642 def tearDown(self):
3643 remove_log_file()
3644 remove_links(self.links)
3645 remove_unit_from_networkd_path(self.units)
3646 stop_networkd(show_logs=True)
3647
3648 def test_ipv6_route_prefix(self):
3649 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3650
3651 start_networkd()
9633f977
SS
3652 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3653
3c874fd7 3654 output = check_output('ip -6 route show dev veth-peer')
9633f977
SS
3655 print(output)
3656 self.assertRegex(output, '2001:db8:0:1::/64 proto ra')
3657
3c874fd7
YW
3658 output = check_output('ip addr show dev veth99')
3659 print(output)
3660 self.assertNotRegex(output, '2001:db8:0:1')
3661 self.assertRegex(output, '2001:db8:0:2')
3662
7db05447
DS
3663class NetworkdMTUTests(unittest.TestCase, Utilities):
3664 links = ['dummy98']
3665
3666 units = [
3667 '12-dummy.netdev',
3668 '12-dummy-mtu.netdev',
3669 '12-dummy-mtu.link',
3670 '12-dummy.network',
3671 ]
3672
3673 def setUp(self):
3674 remove_links(self.links)
3675 stop_networkd(show_logs=False)
3676
3677 def tearDown(self):
3678 remove_log_file()
3679 remove_links(self.links)
3680 remove_unit_from_networkd_path(self.units)
3681 stop_networkd(show_logs=True)
3682
3683 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
3684 if not ipv6_mtu:
3685 ipv6_mtu = mtu
3686
3687 # test normal start
3688 start_networkd()
3689 self.wait_online(['dummy98:routable'])
3690 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3691 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3692
3693 # test normal restart
3694 restart_networkd()
3695 self.wait_online(['dummy98:routable'])
3696 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3697 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3698
3699 if reset:
3700 self.reset_check_mtu(mtu, ipv6_mtu)
3701
3702 def reset_check_mtu(self, mtu, ipv6_mtu=None):
3703 ''' test setting mtu/ipv6_mtu with interface already up '''
3704 stop_networkd()
3705
3706 # note - changing the device mtu resets the ipv6 mtu
3707 run('ip link set up mtu 1501 dev dummy98')
3708 run('ip link set up mtu 1500 dev dummy98')
3709 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
3710 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
3711
3712 self.check_mtu(mtu, ipv6_mtu, reset=False)
3713
3714 def test_mtu_network(self):
3715 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
3716 self.check_mtu('1600')
3717
3718 def test_mtu_netdev(self):
3719 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
3720 # note - MTU set by .netdev happens ONLY at device creation!
3721 self.check_mtu('1600', reset=False)
3722
3723 def test_mtu_link(self):
3724 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
3725 # must reload udev because it only picks up new files after 3 second delay
3726 call('udevadm control --reload')
3727 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
3728 self.check_mtu('1600', reset=False)
3729
3730 def test_ipv6_mtu(self):
3731 ''' set ipv6 mtu without setting device mtu '''
3732 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
3733 self.check_mtu('1500', '1400')
3734
3735 def test_ipv6_mtu_toolarge(self):
3736 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
3737 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3738 self.check_mtu('1500', '1500')
3739
3740 def test_mtu_network_ipv6_mtu(self):
3741 ''' set ipv6 mtu and set device mtu via network file '''
3742 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
3743 self.check_mtu('1600', '1550')
3744
3745 def test_mtu_netdev_ipv6_mtu(self):
3746 ''' set ipv6 mtu and set device mtu via netdev file '''
3747 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3748 self.check_mtu('1600', '1550', reset=False)
3749
3750 def test_mtu_link_ipv6_mtu(self):
3751 ''' set ipv6 mtu and set device mtu via link file '''
3752 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
3753 # must reload udev because it only picks up new files after 3 second delay
3754 call('udevadm control --reload')
3755 self.check_mtu('1600', '1550', reset=False)
3756
3757
1f0e3109 3758if __name__ == '__main__':
9c1ae484
YW
3759 parser = argparse.ArgumentParser()
3760 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
3761 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
b6d587d1 3762 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
641aa412 3763 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
9c1ae484
YW
3764 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
3765 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
b6d587d1
YW
3766 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
3767 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
9c1ae484
YW
3768 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
3769 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 3770 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 3771 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 3772 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
9c1ae484
YW
3773 ns, args = parser.parse_known_args(namespace=unittest)
3774
3775 if ns.build_dir:
641aa412 3776 if ns.networkd_bin or ns.resolved_bin or ns.udevd_bin or ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin:
b6d587d1 3777 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
9c1ae484 3778 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
b6d587d1 3779 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
641aa412 3780 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
9c1ae484
YW
3781 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
3782 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
b6d587d1
YW
3783 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
3784 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
9c1ae484
YW
3785 else:
3786 if ns.networkd_bin:
3787 networkd_bin = ns.networkd_bin
b6d587d1
YW
3788 if ns.resolved_bin:
3789 resolved_bin = ns.resolved_bin
641aa412
YW
3790 if ns.udevd_bin:
3791 udevd_bin = ns.udevd_bin
9c1ae484
YW
3792 if ns.wait_online_bin:
3793 wait_online_bin = ns.wait_online_bin
3794 if ns.networkctl_bin:
3795 networkctl_bin = ns.networkctl_bin
b6d587d1
YW
3796 if ns.resolvectl_bin:
3797 resolvectl_bin = ns.resolvectl_bin
3798 if ns.timedatectl_bin:
3799 timedatectl_bin = ns.timedatectl_bin
9c1ae484
YW
3800
3801 use_valgrind = ns.use_valgrind
3802 enable_debug = ns.enable_debug
94c03122 3803 asan_options = ns.asan_options
fa4c6095 3804 lsan_options = ns.lsan_options
94c03122 3805 ubsan_options = ns.ubsan_options
9c1ae484
YW
3806
3807 if use_valgrind:
3808 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
b6d587d1
YW
3809 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
3810 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
9c1ae484
YW
3811 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
3812 else:
3813 networkctl_cmd = [networkctl_bin]
b6d587d1
YW
3814 resolvectl_cmd = [resolvectl_bin]
3815 timedatectl_cmd = [timedatectl_bin]
9c1ae484
YW
3816 wait_online_cmd = [wait_online_bin]
3817
3818 if enable_debug:
3819 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
3820 if asan_options:
3821 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
3822 if lsan_options:
3823 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
3824 if ubsan_options:
3825 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
3826
3827 sys.argv[1:] = args
1f0e3109
SS
3828 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
3829 verbosity=3))