]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
network: TC - introduce pfifo_head_drop
[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
7b1a31a3
YW
2333 self.assertRegex(output, 'qdisc bfifo 3a: parent 2:3a')
2334 self.assertRegex(output, 'limit 1000000')
2335
f1de1eb3 2336 output = check_output('tc class show dev dummy98')
ab9dc1db 2337 print(output)
f1de1eb3
YW
2338 self.assertRegex(output, 'class htb 2:30 root leaf 30:')
2339 self.assertRegex(output, 'class htb 2:31 root leaf 31:')
2340 self.assertRegex(output, 'class htb 2:32 root leaf 32:')
2341 self.assertRegex(output, 'class htb 2:33 root leaf 33:')
2342 self.assertRegex(output, 'class htb 2:34 root leaf 34:')
2343 self.assertRegex(output, 'class htb 2:35 root leaf 35:')
2344 self.assertRegex(output, 'class htb 2:36 root leaf 36:')
bc0769c9 2345 self.assertRegex(output, 'class htb 2:37 root leaf 37:')
95edcf3f 2346 self.assertRegex(output, 'class htb 2:38 root leaf 38:')
f2c5c129 2347 self.assertRegex(output, 'class htb 2:39 root leaf 39:')
7b1a31a3 2348 self.assertRegex(output, 'class htb 2:3a root leaf 3a:')
f1de1eb3 2349 self.assertRegex(output, 'prio 1 rate 1Mbit ceil 500Kbit')
0baddbd5 2350
557fa421
YW
2351 def test_qdisc2(self):
2352 copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev')
2353 start_networkd()
2354
2355 self.wait_online(['dummy98:routable'])
2356
2357 output = check_output('tc qdisc show dev dummy98')
2358 print(output)
2359 self.assertRegex(output, 'qdisc drr 2: root')
2360 output = check_output('tc class show dev dummy98')
2361 print(output)
2362 self.assertRegex(output, 'class drr 2:30 root quantum 2000b')
2363
f6c6af38
YW
2364 @expectedFailureIfCAKEIsNotAvailable()
2365 def test_qdisc_cake(self):
2366 copy_unit_to_networkd_unit_path('25-qdisc-cake.network', '12-dummy.netdev')
3d55b5a9 2367 start_networkd()
3d55b5a9
YW
2368 self.wait_online(['dummy98:routable'])
2369
2370 output = check_output('tc qdisc show dev dummy98')
2371 print(output)
f6c6af38
YW
2372 self.assertRegex(output, 'qdisc cake 3a: root')
2373 self.assertRegex(output, 'bandwidth 500Mbit')
2374 self.assertRegex(output, 'overhead 128')
3d55b5a9 2375
be94e591
YW
2376 @expectedFailureIfPIEIsNotAvailable()
2377 def test_qdisc_pie(self):
2378 copy_unit_to_networkd_unit_path('25-qdisc-pie.network', '12-dummy.netdev')
2379 start_networkd()
2380 self.wait_online(['dummy98:routable'])
2381
2382 output = check_output('tc qdisc show dev dummy98')
2383 print(output)
2384 self.assertRegex(output, 'qdisc pie 3a: root')
2385 self.assertRegex(output, 'limit 200000')
2386
336d18f0
YW
2387class NetworkdStateFileTests(unittest.TestCase, Utilities):
2388 links = [
2389 'dummy98',
2390 ]
2391
2392 units = [
2393 '12-dummy.netdev',
2394 'state-file-tests.network',
2395 ]
2396
2397 def setUp(self):
2398 remove_links(self.links)
2399 stop_networkd(show_logs=False)
2400
2401 def tearDown(self):
2402 remove_links(self.links)
2403 remove_unit_from_networkd_path(self.units)
2404 stop_networkd(show_logs=True)
2405
2406 def test_state_file(self):
2407 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2408 start_networkd()
2409 self.wait_online(['dummy98:routable'])
2410
2411 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
2412 print(output)
2413 ifindex = output.split()[0]
2414
2415 path = os.path.join('/run/systemd/netif/links/', ifindex)
2416 self.assertTrue(os.path.exists(path))
2417 time.sleep(2)
2418
2419 with open(path) as f:
2420 data = f.read()
2421 self.assertRegex(data, r'ADMIN_STATE=configured')
2422 self.assertRegex(data, r'OPER_STATE=routable')
2423 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
2424 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2425 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2426 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2427 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2428 self.assertRegex(data, r'DOMAINS=hogehoge')
2429 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2430 self.assertRegex(data, r'LLMNR=no')
2431 self.assertRegex(data, r'MDNS=yes')
2432 self.assertRegex(data, r'DNSSEC=no')
426654d7 2433 self.assertRegex(data, r'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
336d18f0
YW
2434
2435 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env)
2436 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
2437 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
2438 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
2439 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
2440 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
2441 time.sleep(2)
2442
2443 with open(path) as f:
2444 data = f.read()
2445 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2446 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2447 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2448 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2449 self.assertRegex(data, r'LLMNR=yes')
2450 self.assertRegex(data, r'MDNS=no')
2451 self.assertRegex(data, r'DNSSEC=yes')
2452
2453 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
2454 time.sleep(2)
2455
2456 with open(path) as f:
2457 data = f.read()
2458 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2459 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2460 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2461 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2462 self.assertRegex(data, r'LLMNR=yes')
2463 self.assertRegex(data, r'MDNS=no')
2464 self.assertRegex(data, r'DNSSEC=yes')
2465
2466 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
2467 time.sleep(2)
2468
2469 with open(path) as f:
2470 data = f.read()
2471 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2472 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2473 self.assertRegex(data, r'DOMAINS=hogehoge')
2474 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2475 self.assertRegex(data, r'LLMNR=no')
2476 self.assertRegex(data, r'MDNS=yes')
2477 self.assertRegex(data, r'DNSSEC=no')
2478
be68c2c9 2479class NetworkdBondTests(unittest.TestCase, Utilities):
c3a8853f 2480 links = [
c2990ec3 2481 'bond199',
c3a8853f 2482 'bond99',
cc3e488c
YW
2483 'dummy98',
2484 'test1']
c3a8853f
YW
2485
2486 units = [
cc3e488c
YW
2487 '11-dummy.netdev',
2488 '12-dummy.netdev',
c2990ec3
YW
2489 '23-active-slave.network',
2490 '23-bond199.network',
2491 '23-primary-slave.network',
c2990ec3 2492 '25-bond-active-backup-slave.netdev',
c3a8853f 2493 '25-bond.netdev',
c3a8853f 2494 'bond99.network',
cc3e488c 2495 'bond-slave.network']
c3a8853f
YW
2496
2497 def setUp(self):
ec38833c 2498 remove_links(self.links)
aaae5713 2499 stop_networkd(show_logs=False)
c3a8853f
YW
2500
2501 def tearDown(self):
ec38833c
ZJS
2502 remove_links(self.links)
2503 remove_unit_from_networkd_path(self.units)
aaae5713 2504 stop_networkd(show_logs=True)
c3a8853f 2505
c2990ec3 2506 def test_bond_active_slave(self):
ec38833c 2507 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 2508 start_networkd()
e2aea43f 2509 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 2510
371810d1 2511 output = check_output('ip -d link show bond199')
c2990ec3
YW
2512 print(output)
2513 self.assertRegex(output, 'active_slave dummy98')
2514
2515 def test_bond_primary_slave(self):
35a78c51 2516 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 2517 start_networkd()
e2aea43f 2518 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 2519
371810d1 2520 output = check_output('ip -d link show bond199')
c2990ec3 2521 print(output)
35a78c51 2522 self.assertRegex(output, 'primary dummy98')
c2990ec3 2523
cc3e488c 2524 def test_bond_operstate(self):
ec38833c
ZJS
2525 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2526 'bond99.network','bond-slave.network')
2cf6fdff 2527 start_networkd()
e2aea43f 2528 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
c3a8853f 2529
371810d1 2530 output = check_output('ip -d link show dummy98')
c3a8853f 2531 print(output)
cc3e488c 2532 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 2533
371810d1 2534 output = check_output('ip -d link show test1')
c3a8853f
YW
2535 print(output)
2536 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2537
371810d1 2538 output = check_output('ip -d link show bond99')
c3a8853f
YW
2539 print(output)
2540 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
2541
19cf3143
DS
2542 self.wait_operstate('dummy98', 'enslaved')
2543 self.wait_operstate('test1', 'enslaved')
2544 self.wait_operstate('bond99', 'routable')
c3a8853f 2545
cefd6b3d 2546 check_output('ip link set dummy98 down')
c3a8853f 2547
19cf3143
DS
2548 self.wait_operstate('dummy98', 'off')
2549 self.wait_operstate('test1', 'enslaved')
2550 self.wait_operstate('bond99', 'degraded-carrier')
c3a8853f 2551
cefd6b3d 2552 check_output('ip link set dummy98 up')
c3a8853f 2553
19cf3143
DS
2554 self.wait_operstate('dummy98', 'enslaved')
2555 self.wait_operstate('test1', 'enslaved')
2556 self.wait_operstate('bond99', 'routable')
c3a8853f 2557
cefd6b3d
ZJS
2558 check_output('ip link set dummy98 down')
2559 check_output('ip link set test1 down')
cc3e488c 2560
19cf3143
DS
2561 self.wait_operstate('dummy98', 'off')
2562 self.wait_operstate('test1', 'off')
2700d2c7 2563
a4632dc7 2564 if not self.wait_operstate('bond99', 'no-carrier', setup_timeout=30, fail_assert=False):
2700d2c7
YW
2565 # Huh? Kernel does not recognize that all slave interfaces are down?
2566 # Let's confirm that networkd's operstate is consistent with ip's result.
2567 self.assertNotRegex(output, 'NO-CARRIER')
cc3e488c 2568
be68c2c9 2569class NetworkdBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
2570 links = [
2571 'bridge99',
2572 'dummy98',
2573 'test1']
2574
2575 units = [
2576 '11-dummy.netdev',
2577 '12-dummy.netdev',
2578 '26-bridge.netdev',
2579 '26-bridge-slave-interface-1.network',
2580 '26-bridge-slave-interface-2.network',
6f943798
YW
2581 '26-bridge-vlan-master.network',
2582 '26-bridge-vlan-slave.network',
804b6cd2 2583 'bridge99-ignore-carrier-loss.network',
09ea6724 2584 'bridge99.network']
1f0e3109 2585
8d17c386
YW
2586 routing_policy_rule_tables = ['100']
2587
1f0e3109 2588 def setUp(self):
8d17c386 2589 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c 2590 remove_links(self.links)
aaae5713 2591 stop_networkd(show_logs=False)
1f0e3109
SS
2592
2593 def tearDown(self):
8d17c386 2594 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c
ZJS
2595 remove_links(self.links)
2596 remove_unit_from_networkd_path(self.units)
aaae5713 2597 stop_networkd(show_logs=True)
1f0e3109 2598
6f943798
YW
2599 def test_bridge_vlan(self):
2600 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2601 '26-bridge.netdev', '26-bridge-vlan-master.network')
2602 start_networkd()
e2aea43f 2603 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
6f943798
YW
2604
2605 output = check_output('bridge vlan show dev test1')
2606 print(output)
2607 self.assertNotRegex(output, '4063')
2608 for i in range(4064, 4095):
2609 self.assertRegex(output, f'{i}')
2610 self.assertNotRegex(output, '4095')
2611
2612 output = check_output('bridge vlan show dev bridge99')
2613 print(output)
2614 self.assertNotRegex(output, '4059')
2615 for i in range(4060, 4095):
2616 self.assertRegex(output, f'{i}')
2617 self.assertNotRegex(output, '4095')
2618
1f0e3109 2619 def test_bridge_property(self):
ec38833c
ZJS
2620 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2621 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2622 'bridge99.network')
2cf6fdff 2623 start_networkd()
e2aea43f 2624 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
1f0e3109 2625
371810d1 2626 output = check_output('ip -d link show test1')
1f0e3109
SS
2627 print(output)
2628 self.assertRegex(output, 'master')
2629 self.assertRegex(output, 'bridge')
2630
371810d1 2631 output = check_output('ip -d link show dummy98')
1f0e3109
SS
2632 print(output)
2633 self.assertRegex(output, 'master')
2634 self.assertRegex(output, 'bridge')
2635
371810d1 2636 output = check_output('ip addr show bridge99')
1f0e3109 2637 print(output)
2be6c5d2 2638 self.assertRegex(output, '192.168.0.15/24')
1f0e3109 2639
371810d1 2640 output = check_output('bridge -d link show dummy98')
1f0e3109 2641 print(output)
ec38833c 2642 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
5424fd95
YW
2643 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2644 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
ec38833c
ZJS
2645 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2646 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
5424fd95
YW
2647 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2648 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2649 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
7f15b714 2650 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
ec38833c
ZJS
2651 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2652 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
5424fd95
YW
2653 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2654 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2655 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
4d7ed14f 2656
5424fd95
YW
2657 output = check_output('bridge -d link show test1')
2658 print(output)
2659 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
1f0e3109 2660
371810d1 2661 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
2662 time.sleep(1)
2663
371810d1 2664 output = check_output('ip addr show bridge99')
2be6c5d2
YW
2665 print(output)
2666 self.assertRegex(output, '192.168.0.16/24')
2667
e3cbaeab
YW
2668 # for issue #6088
2669 print('### ip -6 route list table all dev bridge99')
2670 output = check_output('ip -6 route list table all dev bridge99')
2671 print(output)
2672 self.assertRegex(output, 'ff00::/8 table local metric 256 pref medium')
2673
371810d1 2674 self.assertEqual(call('ip link del test1'), 0)
2be6c5d2 2675
19cf3143 2676 self.wait_operstate('bridge99', 'degraded-carrier')
2be6c5d2 2677
cefd6b3d 2678 check_output('ip link del dummy98')
804b6cd2 2679
19cf3143 2680 self.wait_operstate('bridge99', 'no-carrier')
2be6c5d2 2681
371810d1 2682 output = check_output('ip address show bridge99')
804b6cd2
YW
2683 print(output)
2684 self.assertRegex(output, 'NO-CARRIER')
2685 self.assertNotRegex(output, '192.168.0.15/24')
2686 self.assertNotRegex(output, '192.168.0.16/24')
2687
e3cbaeab
YW
2688 print('### ip -6 route list table all dev bridge99')
2689 output = check_output('ip -6 route list table all dev bridge99')
2690 print(output)
426654d7 2691 self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
e3cbaeab 2692
804b6cd2 2693 def test_bridge_ignore_carrier_loss(self):
ec38833c
ZJS
2694 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2695 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2696 'bridge99-ignore-carrier-loss.network')
2cf6fdff 2697 start_networkd()
e2aea43f 2698 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
804b6cd2 2699
371810d1 2700 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
2701 time.sleep(1)
2702
371810d1
ZJS
2703 check_output('ip link del test1')
2704 check_output('ip link del dummy98')
804b6cd2
YW
2705 time.sleep(3)
2706
371810d1 2707 output = check_output('ip address show bridge99')
804b6cd2
YW
2708 print(output)
2709 self.assertRegex(output, 'NO-CARRIER')
2710 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2711 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
2712
6609924c 2713 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
ec38833c
ZJS
2714 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2715 'bridge99-ignore-carrier-loss.network')
2cf6fdff 2716 start_networkd()
e2aea43f 2717 self.wait_online(['bridge99:no-carrier'])
6609924c 2718
90e3bcbd
YW
2719 for trial in range(4):
2720 check_output('ip link add dummy98 type dummy')
2721 check_output('ip link set dummy98 up')
2722 if trial < 3:
2723 check_output('ip link del dummy98')
6609924c 2724
e2aea43f 2725 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
6609924c 2726
371810d1 2727 output = check_output('ip address show bridge99')
6609924c
YW
2728 print(output)
2729 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2730
371810d1 2731 output = check_output('ip rule list table 100')
6609924c
YW
2732 print(output)
2733 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
2734
be68c2c9 2735class NetworkdLLDPTests(unittest.TestCase, Utilities):
1f0e3109
SS
2736 links = ['veth99']
2737
09ea6724
YW
2738 units = [
2739 '23-emit-lldp.network',
2740 '24-lldp.network',
2741 '25-veth.netdev']
1f0e3109
SS
2742
2743 def setUp(self):
ec38833c 2744 remove_links(self.links)
aaae5713 2745 stop_networkd(show_logs=False)
1f0e3109
SS
2746
2747 def tearDown(self):
ec38833c
ZJS
2748 remove_links(self.links)
2749 remove_unit_from_networkd_path(self.units)
aaae5713 2750 stop_networkd(show_logs=True)
1f0e3109
SS
2751
2752 def test_lldp(self):
ec38833c 2753 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2cf6fdff 2754 start_networkd()
e2aea43f 2755 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1f0e3109 2756
371810d1 2757 output = check_output(*networkctl_cmd, 'lldp', env=env)
1f0e3109
SS
2758 print(output)
2759 self.assertRegex(output, 'veth-peer')
2760 self.assertRegex(output, 'veth99')
2761
be68c2c9 2762class NetworkdRATests(unittest.TestCase, Utilities):
1f0e3109
SS
2763 links = ['veth99']
2764
09ea6724
YW
2765 units = [
2766 '25-veth.netdev',
2767 'ipv6-prefix.network',
87bbebea 2768 'ipv6-prefix-veth.network',
e2c4070e 2769 'ipv6-prefix-veth-token-static.network',
b241fa00 2770 'ipv6-prefix-veth-token-static-explicit.network',
c24c83dc 2771 'ipv6-prefix-veth-token-static-multiple.network',
87bbebea 2772 'ipv6-prefix-veth-token-prefixstable.network']
1f0e3109
SS
2773
2774 def setUp(self):
ec38833c 2775 remove_links(self.links)
aaae5713 2776 stop_networkd(show_logs=False)
1f0e3109
SS
2777
2778 def tearDown(self):
ec38833c
ZJS
2779 remove_links(self.links)
2780 remove_unit_from_networkd_path(self.units)
aaae5713 2781 stop_networkd(show_logs=True)
1f0e3109
SS
2782
2783 def test_ipv6_prefix_delegation(self):
ec38833c 2784 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2cf6fdff 2785 start_networkd()
e2aea43f 2786 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1f0e3109 2787
41fd8fe7
YW
2788 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2789 print(output)
2790 self.assertRegex(output, 'fe80::')
2791 self.assertRegex(output, '2002:da8:1::1')
2792
fc79e6ff 2793 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2794 print(output)
2795 self.assertRegex(output, '2002:da8:1:0')
2796
e2c4070e
YW
2797 def test_ipv6_token_static(self):
2798 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static.network')
87bbebea 2799 start_networkd()
b241fa00
KF
2800 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2801
2802 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2803 print(output)
2804 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2805
2806 def test_ipv6_token_static_explicit(self):
2807 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-explicit.network')
2808 start_networkd()
87bbebea
YW
2809 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2810
2811 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2812 print(output)
2813 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2814
c24c83dc
KF
2815 def test_ipv6_token_static_multiple(self):
2816 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-multiple.network')
2817 start_networkd()
2818 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2819
2820 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2821 print(output)
2822 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
2823 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe')
2824
87bbebea
YW
2825 def test_ipv6_token_prefixstable(self):
2826 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network')
2827 start_networkd()
2828 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2829
2830 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
2831 print(output)
2832 self.assertRegex(output, '2002:da8:1:0')
2833
be68c2c9 2834class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
fdcd1ec5 2835 links = ['veth99']
09ea6724
YW
2836
2837 units = [
09ea6724
YW
2838 '25-veth.netdev',
2839 'dhcp-client.network',
2840 'dhcp-client-timezone-router.network',
2841 'dhcp-server.network',
2842 'dhcp-server-timezone-router.network']
1f0e3109
SS
2843
2844 def setUp(self):
ec38833c 2845 remove_links(self.links)
aaae5713 2846 stop_networkd(show_logs=False)
1f0e3109
SS
2847
2848 def tearDown(self):
ec38833c
ZJS
2849 remove_links(self.links)
2850 remove_unit_from_networkd_path(self.units)
aaae5713 2851 stop_networkd(show_logs=True)
1f0e3109
SS
2852
2853 def test_dhcp_server(self):
ec38833c 2854 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2cf6fdff 2855 start_networkd()
e2aea43f 2856 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2857
fc79e6ff 2858 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2859 print(output)
2860 self.assertRegex(output, '192.168.5.*')
2861 self.assertRegex(output, 'Gateway: 192.168.5.1')
2862 self.assertRegex(output, 'DNS: 192.168.5.1')
2863 self.assertRegex(output, 'NTP: 192.168.5.1')
2864
1f0e3109 2865 def test_emit_router_timezone(self):
ec38833c 2866 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2cf6fdff 2867 start_networkd()
e2aea43f 2868 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2869
fc79e6ff 2870 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2871 print(output)
2872 self.assertRegex(output, 'Gateway: 192.168.5.*')
2873 self.assertRegex(output, '192.168.5.*')
2874 self.assertRegex(output, 'Europe/Berlin')
2875
be68c2c9 2876class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
09ea6724 2877 links = [
18c613dc
YW
2878 'veth99',
2879 'vrf99']
09ea6724
YW
2880
2881 units = [
2882 '25-veth.netdev',
18c613dc
YW
2883 '25-vrf.netdev',
2884 '25-vrf.network',
09ea6724 2885 'dhcp-client-anonymize.network',
0fd8b718 2886 'dhcp-client-decline.network',
214c5bae
YW
2887 'dhcp-client-gateway-ipv4.network',
2888 'dhcp-client-gateway-ipv6.network',
af3b1498 2889 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
2890 'dhcp-client-ipv4-dhcp-settings.network',
2891 'dhcp-client-ipv4-only-ipv6-disabled.network',
2892 'dhcp-client-ipv4-only.network',
4c2e1833 2893 'dhcp-client-ipv4-use-routes-no.network',
09ea6724
YW
2894 'dhcp-client-ipv6-only.network',
2895 'dhcp-client-ipv6-rapid-commit.network',
1e498853
YW
2896 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2897 'dhcp-client-keep-configuration-dhcp.network',
09ea6724 2898 'dhcp-client-listen-port.network',
c1b01a62
YW
2899 'dhcp-client-reassign-static-routes-ipv4.network',
2900 'dhcp-client-reassign-static-routes-ipv6.network',
09ea6724
YW
2901 'dhcp-client-route-metric.network',
2902 'dhcp-client-route-table.network',
e2d5aab3
YW
2903 'dhcp-client-use-dns-ipv4-and-ra.network',
2904 'dhcp-client-use-dns-ipv4.network',
2905 'dhcp-client-use-dns-no.network',
2906 'dhcp-client-use-dns-yes.network',
e0c1341d 2907 'dhcp-client-use-domains.network',
c38d2d4d 2908 'dhcp-client-use-routes-no.network',
18c613dc 2909 'dhcp-client-vrf.network',
117a55c7
YW
2910 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2911 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
4c882c16 2912 'dhcp-client-with-static-address.network',
3e9d5552 2913 'dhcp-client.network',
0fd8b718 2914 'dhcp-server-decline.network',
09ea6724 2915 'dhcp-server-veth-peer.network',
30d3b54e 2916 'dhcp-v4-server-veth-peer.network',
e0c1341d 2917 'dhcp-client-use-domains.network',
30d3b54e 2918 'static.network']
1f0e3109
SS
2919
2920 def setUp(self):
ec38833c
ZJS
2921 stop_dnsmasq(dnsmasq_pid_file)
2922 remove_links(self.links)
aaae5713 2923 stop_networkd(show_logs=False)
1f0e3109
SS
2924
2925 def tearDown(self):
ec38833c
ZJS
2926 stop_dnsmasq(dnsmasq_pid_file)
2927 remove_lease_file()
2928 remove_log_file()
2929 remove_links(self.links)
2930 remove_unit_from_networkd_path(self.units)
aaae5713 2931 stop_networkd(show_logs=True)
1f0e3109
SS
2932
2933 def test_dhcp_client_ipv6_only(self):
ec38833c 2934 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109 2935
2cf6fdff 2936 start_networkd()
e2aea43f 2937 self.wait_online(['veth-peer:carrier'])
ec38833c 2938 start_dnsmasq()
e2aea43f 2939 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2940
fc79e6ff 2941 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2942 print(output)
2943 self.assertRegex(output, '2600::')
2944 self.assertNotRegex(output, '192.168.5')
2945
3a956d38 2946 # Confirm that ipv6 token is not set in the kernel
371810d1 2947 output = check_output('ip token show dev veth99')
3a956d38
YW
2948 print(output)
2949 self.assertRegex(output, 'token :: dev veth99')
2950
1f0e3109 2951 def test_dhcp_client_ipv4_only(self):
ec38833c 2952 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109 2953
2cf6fdff 2954 start_networkd()
e2aea43f 2955 self.wait_online(['veth-peer:carrier'])
195a18c1 2956 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
e2aea43f 2957 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2958
fc79e6ff 2959 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
2960 print(output)
2961 self.assertNotRegex(output, '2600::')
2962 self.assertRegex(output, '192.168.5')
195a18c1
YW
2963 self.assertRegex(output, '192.168.5.6')
2964 self.assertRegex(output, '192.168.5.7')
2965
2966 # checking routes to DNS servers
2967 output = check_output('ip route show dev veth99')
2968 print(output)
2969 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2970 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2971 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2972
2973 stop_dnsmasq(dnsmasq_pid_file)
2974 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
2975
2976 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2977 print('Wait for the dynamic address to be renewed')
2978 time.sleep(125)
2979
2980 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2981
fc79e6ff 2982 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
195a18c1
YW
2983 print(output)
2984 self.assertNotRegex(output, '2600::')
2985 self.assertRegex(output, '192.168.5')
2986 self.assertNotRegex(output, '192.168.5.6')
2987 self.assertRegex(output, '192.168.5.7')
2988 self.assertRegex(output, '192.168.5.8')
2989
2990 # checking routes to DNS servers
2991 output = check_output('ip route show dev veth99')
2992 print(output)
2993 self.assertNotRegex(output, r'192.168.5.6')
2994 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2995 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2996 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
1f0e3109 2997
4c2e1833
YW
2998 def test_dhcp_client_ipv4_use_routes_no(self):
2999 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-use-routes-no.network')
3000
3001 start_networkd()
3002 self.wait_online(['veth-peer:carrier'])
3003 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
3004 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3005
3006 output = check_output('ip route show dev veth99')
3007 print(output)
3008 self.assertNotRegex(output, r'192.168.5.5')
3009 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
3010 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
3011
1f0e3109 3012 def test_dhcp_client_ipv4_ipv6(self):
ec38833c
ZJS
3013 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
3014 'dhcp-client-ipv4-only.network')
2cf6fdff 3015 start_networkd()
e2aea43f 3016 self.wait_online(['veth-peer:carrier'])
ec38833c 3017 start_dnsmasq()
e2aea43f 3018 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
3019
3020 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3021 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3022 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 3023
fc79e6ff 3024 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3025 print(output)
3026 self.assertRegex(output, '2600::')
3027 self.assertRegex(output, '192.168.5')
3028
3029 def test_dhcp_client_settings(self):
ec38833c 3030 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 3031
2cf6fdff 3032 start_networkd()
e2aea43f 3033 self.wait_online(['veth-peer:carrier'])
ec38833c 3034 start_dnsmasq()
e2aea43f 3035 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3036
0ae7a66d 3037 print('## ip address show dev veth99')
371810d1 3038 output = check_output('ip address show dev veth99')
1f0e3109
SS
3039 print(output)
3040 self.assertRegex(output, '12:34:56:78:9a:bc')
3041 self.assertRegex(output, '192.168.5')
3042 self.assertRegex(output, '1492')
3043
0ae7a66d 3044 print('## ip route show table main dev veth99')
371810d1 3045 output = check_output('ip route show table main dev veth99')
1f0e3109 3046 print(output)
156ddf8d 3047 # See issue #8726
dd9b10c8
YW
3048 main_table_is_empty = output == ''
3049 if not main_table_is_empty:
3050 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 3051
0ae7a66d 3052 print('## ip route show table 211 dev veth99')
371810d1 3053 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
3054 print(output)
3055 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
dd9b10c8
YW
3056 if main_table_is_empty:
3057 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
0ae7a66d
YW
3058 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
3059 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
3060
3061 print('## dnsmasq log')
ec38833c
ZJS
3062 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
3063 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
3064 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
3065 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
3066
3067 def test_dhcp6_client_settings_rapidcommit_true(self):
ec38833c 3068 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2cf6fdff 3069 start_networkd()
e2aea43f 3070 self.wait_online(['veth-peer:carrier'])
ec38833c 3071 start_dnsmasq()
e2aea43f 3072 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3073
371810d1 3074 output = check_output('ip address show dev veth99')
1f0e3109
SS
3075 print(output)
3076 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 3077 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
3078
3079 def test_dhcp6_client_settings_rapidcommit_false(self):
ec38833c 3080 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2cf6fdff 3081 start_networkd()
e2aea43f 3082 self.wait_online(['veth-peer:carrier'])
ec38833c 3083 start_dnsmasq()
e2aea43f 3084 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3085
371810d1 3086 output = check_output('ip address show dev veth99')
1f0e3109
SS
3087 print(output)
3088 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 3089 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
3090
3091 def test_dhcp_client_settings_anonymize(self):
ec38833c 3092 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2cf6fdff 3093 start_networkd()
e2aea43f 3094 self.wait_online(['veth-peer:carrier'])
ec38833c 3095 start_dnsmasq()
e2aea43f 3096 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3097
ec38833c
ZJS
3098 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
3099 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
3100 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
3101
3102 def test_dhcp_client_listen_port(self):
ec38833c 3103 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2cf6fdff 3104 start_networkd()
e2aea43f 3105 self.wait_online(['veth-peer:carrier'])
ec38833c 3106 start_dnsmasq('--dhcp-alternate-port=67,5555')
e2aea43f 3107 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47 3108
371810d1 3109 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
3110 print(output)
3111 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109 3112
4c882c16
YW
3113 def test_dhcp_client_with_static_address(self):
3114 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
3115 'dhcp-client-with-static-address.network')
3116 start_networkd()
e2aea43f 3117 self.wait_online(['veth-peer:carrier'])
4c882c16 3118 start_dnsmasq()
e2aea43f 3119 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4c882c16
YW
3120
3121 output = check_output('ip address show dev veth99 scope global')
3122 print(output)
3123 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3124 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
3125
3126 output = check_output('ip route show dev veth99')
3127 print(output)
3128 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
3129 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
3130 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
3131 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
3132
1f0e3109 3133 def test_dhcp_route_table_id(self):
ec38833c 3134 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2cf6fdff 3135 start_networkd()
e2aea43f 3136 self.wait_online(['veth-peer:carrier'])
ec38833c 3137 start_dnsmasq()
e2aea43f 3138 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3139
371810d1 3140 output = check_output('ip route show table 12')
1f0e3109 3141 print(output)
1f0e3109
SS
3142 self.assertRegex(output, 'veth99 proto dhcp')
3143 self.assertRegex(output, '192.168.5.1')
3144
3145 def test_dhcp_route_metric(self):
ec38833c 3146 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2cf6fdff 3147 start_networkd()
e2aea43f 3148 self.wait_online(['veth-peer:carrier'])
ec38833c 3149 start_dnsmasq()
e2aea43f 3150 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3151
371810d1 3152 output = check_output('ip route show dev veth99')
1f0e3109 3153 print(output)
1f0e3109
SS
3154 self.assertRegex(output, 'metric 24')
3155
c1b01a62 3156 def test_dhcp_client_reassign_static_routes_ipv4(self):
c38d2d4d 3157 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
c1b01a62 3158 'dhcp-client-reassign-static-routes-ipv4.network')
c38d2d4d 3159 start_networkd()
e2aea43f 3160 self.wait_online(['veth-peer:carrier'])
c38d2d4d 3161 start_dnsmasq(lease_time='2m')
e2aea43f 3162 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c38d2d4d
YW
3163
3164 output = check_output('ip address show dev veth99 scope global')
3165 print(output)
3166 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3167
3168 output = check_output('ip route show dev veth99')
3169 print(output)
3170 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3171 self.assertRegex(output, r'192.168.5.0/24 proto static')
3172 self.assertRegex(output, r'192.168.6.0/24 proto static')
3173 self.assertRegex(output, r'192.168.7.0/24 proto static')
3174
c1b01a62
YW
3175 stop_dnsmasq(dnsmasq_pid_file)
3176 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
3177
c38d2d4d
YW
3178 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3179 print('Wait for the dynamic address to be renewed')
3180 time.sleep(125)
3181
e2aea43f 3182 self.wait_online(['veth99:routable'])
c38d2d4d
YW
3183
3184 output = check_output('ip route show dev veth99')
3185 print(output)
3186 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3187 self.assertRegex(output, r'192.168.5.0/24 proto static')
3188 self.assertRegex(output, r'192.168.6.0/24 proto static')
3189 self.assertRegex(output, r'192.168.7.0/24 proto static')
3190
c1b01a62
YW
3191 def test_dhcp_client_reassign_static_routes_ipv6(self):
3192 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3193 'dhcp-client-reassign-static-routes-ipv6.network')
3194 start_networkd()
e2aea43f 3195 self.wait_online(['veth-peer:carrier'])
c1b01a62 3196 start_dnsmasq(lease_time='2m')
e2aea43f 3197 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c1b01a62
YW
3198
3199 output = check_output('ip address show dev veth99 scope global')
3200 print(output)
426654d7 3201 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
c1b01a62
YW
3202
3203 output = check_output('ip -6 route show dev veth99')
3204 print(output)
3205 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3206 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3207
3208 stop_dnsmasq(dnsmasq_pid_file)
3209 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
3210
3211 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3212 print('Wait for the dynamic address to be renewed')
3213 time.sleep(125)
3214
e2aea43f 3215 self.wait_online(['veth99:routable'])
c1b01a62
YW
3216
3217 output = check_output('ip -6 route show dev veth99')
3218 print(output)
3219 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3220 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3221
1e498853
YW
3222 def test_dhcp_keep_configuration_dhcp(self):
3223 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2cf6fdff 3224 start_networkd()
e2aea43f 3225 self.wait_online(['veth-peer:carrier'])
1e498853 3226 start_dnsmasq(lease_time='2m')
e2aea43f 3227 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3228
1e498853
YW
3229 output = check_output('ip address show dev veth99 scope global')
3230 print(output)
3231 self.assertRegex(output, r'192.168.5.*')
3232
fc79e6ff 3233 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 3234 print(output)
1e498853 3235 self.assertRegex(output, r'192.168.5.*')
e40a58b5 3236
5238e957 3237 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
ec38833c 3238 stop_dnsmasq(dnsmasq_pid_file)
1f0e3109
SS
3239
3240 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 3241 print('Wait for the dynamic address to be expired')
1f0e3109
SS
3242 time.sleep(125)
3243
1e498853
YW
3244 print('The lease address should be kept after lease expired')
3245 output = check_output('ip address show dev veth99 scope global')
3246 print(output)
3247 self.assertRegex(output, r'192.168.5.*')
3248
fc79e6ff 3249 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 3250 print(output)
1e498853
YW
3251 self.assertRegex(output, r'192.168.5.*')
3252
3253 check_output('systemctl stop systemd-networkd')
3254
3255 print('The lease address should be kept after networkd stopped')
3256 output = check_output('ip address show dev veth99 scope global')
3257 print(output)
3258 self.assertRegex(output, r'192.168.5.*')
3259
fc79e6ff 3260 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
3261 print(output)
3262 self.assertRegex(output, r'192.168.5.*')
3263
e2aea43f
YW
3264 start_networkd(3)
3265 self.wait_online(['veth-peer:routable'])
1e498853
YW
3266
3267 print('Still the lease address should be kept after networkd restarted')
3268 output = check_output('ip address show dev veth99 scope global')
3269 print(output)
3270 self.assertRegex(output, r'192.168.5.*')
3271
fc79e6ff 3272 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
3273 print(output)
3274 self.assertRegex(output, r'192.168.5.*')
3275
3276 def test_dhcp_keep_configuration_dhcp_on_stop(self):
3277 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2cf6fdff 3278 start_networkd()
e2aea43f 3279 self.wait_online(['veth-peer:carrier'])
1e498853 3280 start_dnsmasq(lease_time='2m')
e2aea43f 3281 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853
YW
3282
3283 output = check_output('ip address show dev veth99 scope global')
3284 print(output)
3285 self.assertRegex(output, r'192.168.5.*')
3286
3287 stop_dnsmasq(dnsmasq_pid_file)
3288 check_output('systemctl stop systemd-networkd')
3289
3290 output = check_output('ip address show dev veth99 scope global')
3291 print(output)
3292 self.assertRegex(output, r'192.168.5.*')
3293
e2aea43f
YW
3294 restart_networkd(3)
3295 self.wait_online(['veth-peer:routable'])
1e498853
YW
3296
3297 output = check_output('ip address show dev veth99 scope global')
3298 print(output)
3299 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 3300
30d3b54e 3301 def test_dhcp_client_reuse_address_as_static(self):
ec38833c 3302 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2cf6fdff 3303 start_networkd()
e2aea43f 3304 self.wait_online(['veth-peer:carrier'])
ec38833c 3305 start_dnsmasq()
e2aea43f 3306 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
3307
3308 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3309 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3310 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 3311
371810d1 3312 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
3313 print(output)
3314 self.assertRegex(output, '192.168.5')
3315 self.assertRegex(output, '2600::')
3316
2629df47
YW
3317 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
3318 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
3319 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
3320 print(static_network)
3321
ec38833c 3322 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
3323
3324 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
3325 f.write(static_network)
3326
2629df47
YW
3327 # When networkd started, the links are already configured, so let's wait for 5 seconds
3328 # the links to be re-configured.
aaae5713 3329 restart_networkd(5)
e2aea43f 3330 self.wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 3331
371810d1 3332 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
3333 print(output)
3334 self.assertRegex(output, '192.168.5')
3335 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3336
371810d1 3337 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
3338 print(output)
3339 self.assertRegex(output, '2600::')
3340 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3341
18c613dc
YW
3342 @expectedFailureIfModuleIsNotAvailable('vrf')
3343 def test_dhcp_client_vrf(self):
ec38833c
ZJS
3344 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
3345 '25-vrf.netdev', '25-vrf.network')
2cf6fdff 3346 start_networkd()
e2aea43f 3347 self.wait_online(['veth-peer:carrier'])
ec38833c 3348 start_dnsmasq()
e2aea43f 3349 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
3350
3351 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3352 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3353 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
3354
3355 print('## ip -d link show dev vrf99')
371810d1 3356 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
3357 print(output)
3358 self.assertRegex(output, 'vrf table 42')
3359
3360 print('## ip address show vrf vrf99')
371810d1 3361 output = check_output('ip address show vrf vrf99')
d90f4f7d
YW
3362 print(output)
3363 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3364 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
426654d7 3365 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
d90f4f7d 3366 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
3367
3368 print('## ip address show dev veth99')
371810d1 3369 output = check_output('ip address show dev veth99')
18c613dc 3370 print(output)
18c613dc
YW
3371 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3372 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
426654d7 3373 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
3374 self.assertRegex(output, 'inet6 .* scope link')
3375
3376 print('## ip route show vrf vrf99')
371810d1 3377 output = check_output('ip route show vrf vrf99')
18c613dc
YW
3378 print(output)
3379 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
18c613dc
YW
3380 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3381 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3382 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3383 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3384
3385 print('## ip route show table main dev veth99')
371810d1 3386 output = check_output('ip route show table main dev veth99')
18c613dc
YW
3387 print(output)
3388 self.assertEqual(output, '')
3389
214c5bae
YW
3390 def test_dhcp_client_gateway_ipv4(self):
3391 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3392 'dhcp-client-gateway-ipv4.network')
3393 start_networkd()
3394 self.wait_online(['veth-peer:carrier'])
3395 start_dnsmasq()
3396 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3397
3398 output = check_output('ip route list dev veth99 10.0.0.0/8')
3399 print(output)
3400 self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static')
3401
3402 def test_dhcp_client_gateway_ipv6(self):
3403 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3404 'dhcp-client-gateway-ipv6.network')
3405 start_networkd()
3406 self.wait_online(['veth-peer:carrier'])
3407 start_dnsmasq()
3408 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3409
3410 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
3411 print(output)
3412 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
3413
af3b1498 3414 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
3415 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3416 'dhcp-client-gateway-onlink-implicit.network')
2cf6fdff 3417 start_networkd()
e2aea43f 3418 self.wait_online(['veth-peer:carrier'])
ec38833c 3419 start_dnsmasq()
e2aea43f 3420 self.wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 3421
fc79e6ff 3422 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
af3b1498
YW
3423 print(output)
3424 self.assertRegex(output, '192.168.5')
3425
371810d1 3426 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
3427 print(output)
3428 self.assertRegex(output, 'onlink')
371810d1 3429 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
3430 print(output)
3431 self.assertRegex(output, 'onlink')
3432
117a55c7 3433 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
ec38833c
ZJS
3434 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3435 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
2cf6fdff 3436 start_networkd()
e2aea43f 3437 self.wait_online(['veth-peer:carrier'])
ec38833c 3438 start_dnsmasq(lease_time='2m')
e2aea43f 3439 self.wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 3440
371810d1 3441 output = check_output('ip address show dev veth99')
63c598ed
YW
3442 print(output)
3443
371810d1 3444 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 3445 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3446 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 3447 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3448 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 3449 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3450 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
3451 self.assertNotRegex(output, 'inet .* scope link')
3452
3453 print('Wait for the dynamic address to be expired')
3454 time.sleep(130)
3455
371810d1 3456 output = check_output('ip address show dev veth99')
63c598ed
YW
3457 print(output)
3458
371810d1 3459 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 3460 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3461 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 3462 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3463 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 3464 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3465 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
3466 self.assertNotRegex(output, 'inet .* scope link')
3467
ec38833c 3468 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 3469
117a55c7 3470 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
ec38833c
ZJS
3471 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3472 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
2cf6fdff 3473 start_networkd()
e2aea43f 3474 self.wait_online(['veth99:degraded', 'veth-peer:routable'])
117a55c7 3475
371810d1 3476 output = check_output('ip address show dev veth99')
117a55c7
YW
3477 print(output)
3478
371810d1 3479 output = check_output('ip -6 address show dev veth99 scope global dynamic')
117a55c7 3480 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 3481 output = check_output('ip -6 address show dev veth99 scope link')
117a55c7 3482 self.assertRegex(output, 'inet6 .* scope link')
371810d1 3483 output = check_output('ip -4 address show dev veth99 scope global dynamic')
117a55c7 3484 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 3485 output = check_output('ip -4 address show dev veth99 scope link')
117a55c7
YW
3486 self.assertRegex(output, 'inet .* scope link')
3487
b6efd661 3488 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
3489 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3490 'dhcp-client-ipv4-only-ipv6-disabled.network')
2cf6fdff 3491 start_networkd()
e2aea43f 3492 self.wait_online(['veth-peer:carrier'])
ec38833c 3493 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
e2aea43f 3494 self.wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
3495
3496 # test for issue #12490
3497
371810d1 3498 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
3499 print(output)
3500 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3501 address1=None
3502 for line in output.splitlines():
3503 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3504 address1 = line.split()[1].split('/')[0]
3505 break
3506
371810d1 3507 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
3508 print(output)
3509 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3510 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3511
ec38833c
ZJS
3512 stop_dnsmasq(dnsmasq_pid_file)
3513 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
3514
3515 print('Wait for the dynamic address to be expired')
3516 time.sleep(130)
3517
371810d1 3518 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
3519 print(output)
3520 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3521 address2=None
3522 for line in output.splitlines():
3523 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3524 address2 = line.split()[1].split('/')[0]
3525 break
3526
3527 self.assertNotEqual(address1, address2)
3528
371810d1 3529 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
3530 print(output)
3531 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3532 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3533 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3534 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3535
e2d5aab3
YW
3536 def test_dhcp_client_use_dns_yes(self):
3537 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3538
3539 start_networkd()
e2aea43f 3540 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3541 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3542 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3543
3544 # link become 'routable' when at least one protocol provide an valid address.
3545 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3546 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3547
693283cd 3548 time.sleep(3)
e2d5aab3
YW
3549 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3550 print(output)
3551 self.assertRegex(output, '192.168.5.1')
3552 self.assertRegex(output, '2600::1')
3553
3554 def test_dhcp_client_use_dns_no(self):
3555 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3556
3557 start_networkd()
e2aea43f 3558 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3559 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3560 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3561
3562 # link become 'routable' when at least one protocol provide an valid address.
3563 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3564 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3565
693283cd 3566 time.sleep(3)
e2d5aab3
YW
3567 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3568 print(output)
3569 self.assertNotRegex(output, '192.168.5.1')
3570 self.assertNotRegex(output, '2600::1')
3571
3572 def test_dhcp_client_use_dns_ipv4(self):
3573 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3574
3575 start_networkd()
e2aea43f 3576 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3577 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3578 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3579
3580 # link become 'routable' when at least one protocol provide an valid address.
3581 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3582 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3583
693283cd 3584 time.sleep(3)
e2d5aab3
YW
3585 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3586 print(output)
3587 self.assertRegex(output, '192.168.5.1')
3588 self.assertNotRegex(output, '2600::1')
3589
3590 def test_dhcp_client_use_dns_ipv4_and_ra(self):
3591 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3592
3593 start_networkd()
e2aea43f 3594 self.wait_online(['veth-peer:carrier'])
e2d5aab3 3595 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 3596 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
3597
3598 # link become 'routable' when at least one protocol provide an valid address.
3599 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3600 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 3601
693283cd 3602 time.sleep(3)
e2d5aab3
YW
3603 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3604 print(output)
3605 self.assertRegex(output, '192.168.5.1')
3606 self.assertRegex(output, '2600::1')
3607
e0c1341d
YW
3608 def test_dhcp_client_use_domains(self):
3609 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3610
3611 start_networkd()
e2aea43f 3612 self.wait_online(['veth-peer:carrier'])
e0c1341d 3613 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
e2aea43f 3614 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e0c1341d 3615
fc79e6ff 3616 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
e0c1341d
YW
3617 print(output)
3618 self.assertRegex(output, 'Search Domains: example.com')
3619
3620 time.sleep(3)
3621 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3622 print(output)
3623 self.assertRegex(output, 'example.com')
3624
0fd8b718
YW
3625 def test_dhcp_client_decline(self):
3626 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
3627
3628 start_networkd()
3629 self.wait_online(['veth-peer:carrier'])
3630 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env)
3631 self.assertTrue(rc == 1)
3632
9633f977
SS
3633class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
3634 links = ['veth99']
3635
3636 units = [
3637 '25-veth.netdev',
3638 'ipv6ra-prefix-client.network',
3639 'ipv6ra-prefix.network'
3640 ]
3641
3642 def setUp(self):
3643 remove_links(self.links)
3644 stop_networkd(show_logs=False)
3645
3646 def tearDown(self):
3647 remove_log_file()
3648 remove_links(self.links)
3649 remove_unit_from_networkd_path(self.units)
3650 stop_networkd(show_logs=True)
3651
3652 def test_ipv6_route_prefix(self):
3653 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3654
3655 start_networkd()
9633f977
SS
3656 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3657
3c874fd7 3658 output = check_output('ip -6 route show dev veth-peer')
9633f977
SS
3659 print(output)
3660 self.assertRegex(output, '2001:db8:0:1::/64 proto ra')
3661
3c874fd7
YW
3662 output = check_output('ip addr show dev veth99')
3663 print(output)
3664 self.assertNotRegex(output, '2001:db8:0:1')
3665 self.assertRegex(output, '2001:db8:0:2')
3666
7db05447
DS
3667class NetworkdMTUTests(unittest.TestCase, Utilities):
3668 links = ['dummy98']
3669
3670 units = [
3671 '12-dummy.netdev',
3672 '12-dummy-mtu.netdev',
3673 '12-dummy-mtu.link',
3674 '12-dummy.network',
3675 ]
3676
3677 def setUp(self):
3678 remove_links(self.links)
3679 stop_networkd(show_logs=False)
3680
3681 def tearDown(self):
3682 remove_log_file()
3683 remove_links(self.links)
3684 remove_unit_from_networkd_path(self.units)
3685 stop_networkd(show_logs=True)
3686
3687 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
3688 if not ipv6_mtu:
3689 ipv6_mtu = mtu
3690
3691 # test normal start
3692 start_networkd()
3693 self.wait_online(['dummy98:routable'])
3694 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3695 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3696
3697 # test normal restart
3698 restart_networkd()
3699 self.wait_online(['dummy98:routable'])
3700 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3701 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3702
3703 if reset:
3704 self.reset_check_mtu(mtu, ipv6_mtu)
3705
3706 def reset_check_mtu(self, mtu, ipv6_mtu=None):
3707 ''' test setting mtu/ipv6_mtu with interface already up '''
3708 stop_networkd()
3709
3710 # note - changing the device mtu resets the ipv6 mtu
3711 run('ip link set up mtu 1501 dev dummy98')
3712 run('ip link set up mtu 1500 dev dummy98')
3713 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
3714 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
3715
3716 self.check_mtu(mtu, ipv6_mtu, reset=False)
3717
3718 def test_mtu_network(self):
3719 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
3720 self.check_mtu('1600')
3721
3722 def test_mtu_netdev(self):
3723 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
3724 # note - MTU set by .netdev happens ONLY at device creation!
3725 self.check_mtu('1600', reset=False)
3726
3727 def test_mtu_link(self):
3728 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
3729 # must reload udev because it only picks up new files after 3 second delay
3730 call('udevadm control --reload')
3731 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
3732 self.check_mtu('1600', reset=False)
3733
3734 def test_ipv6_mtu(self):
3735 ''' set ipv6 mtu without setting device mtu '''
3736 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
3737 self.check_mtu('1500', '1400')
3738
3739 def test_ipv6_mtu_toolarge(self):
3740 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
3741 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3742 self.check_mtu('1500', '1500')
3743
3744 def test_mtu_network_ipv6_mtu(self):
3745 ''' set ipv6 mtu and set device mtu via network file '''
3746 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
3747 self.check_mtu('1600', '1550')
3748
3749 def test_mtu_netdev_ipv6_mtu(self):
3750 ''' set ipv6 mtu and set device mtu via netdev file '''
3751 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
3752 self.check_mtu('1600', '1550', reset=False)
3753
3754 def test_mtu_link_ipv6_mtu(self):
3755 ''' set ipv6 mtu and set device mtu via link file '''
3756 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
3757 # must reload udev because it only picks up new files after 3 second delay
3758 call('udevadm control --reload')
3759 self.check_mtu('1600', '1550', reset=False)
3760
3761
1f0e3109 3762if __name__ == '__main__':
9c1ae484
YW
3763 parser = argparse.ArgumentParser()
3764 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
3765 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
b6d587d1 3766 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
641aa412 3767 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
9c1ae484
YW
3768 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
3769 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
b6d587d1
YW
3770 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
3771 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
9c1ae484
YW
3772 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
3773 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 3774 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 3775 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 3776 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
9c1ae484
YW
3777 ns, args = parser.parse_known_args(namespace=unittest)
3778
3779 if ns.build_dir:
641aa412 3780 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 3781 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
9c1ae484 3782 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
b6d587d1 3783 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
641aa412 3784 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
9c1ae484
YW
3785 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
3786 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
b6d587d1
YW
3787 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
3788 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
9c1ae484
YW
3789 else:
3790 if ns.networkd_bin:
3791 networkd_bin = ns.networkd_bin
b6d587d1
YW
3792 if ns.resolved_bin:
3793 resolved_bin = ns.resolved_bin
641aa412
YW
3794 if ns.udevd_bin:
3795 udevd_bin = ns.udevd_bin
9c1ae484
YW
3796 if ns.wait_online_bin:
3797 wait_online_bin = ns.wait_online_bin
3798 if ns.networkctl_bin:
3799 networkctl_bin = ns.networkctl_bin
b6d587d1
YW
3800 if ns.resolvectl_bin:
3801 resolvectl_bin = ns.resolvectl_bin
3802 if ns.timedatectl_bin:
3803 timedatectl_bin = ns.timedatectl_bin
9c1ae484
YW
3804
3805 use_valgrind = ns.use_valgrind
3806 enable_debug = ns.enable_debug
94c03122 3807 asan_options = ns.asan_options
fa4c6095 3808 lsan_options = ns.lsan_options
94c03122 3809 ubsan_options = ns.ubsan_options
9c1ae484
YW
3810
3811 if use_valgrind:
3812 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
b6d587d1
YW
3813 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
3814 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
9c1ae484
YW
3815 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
3816 else:
3817 networkctl_cmd = [networkctl_bin]
b6d587d1
YW
3818 resolvectl_cmd = [resolvectl_bin]
3819 timedatectl_cmd = [timedatectl_bin]
9c1ae484
YW
3820 wait_online_cmd = [wait_online_bin]
3821
3822 if enable_debug:
3823 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
3824 if asan_options:
3825 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
3826 if lsan_options:
3827 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
3828 if ubsan_options:
3829 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
3830
3831 sys.argv[1:] = args
1f0e3109
SS
3832 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
3833 verbosity=3))