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