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