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