]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
network: NetLabel integration
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
CommitLineData
1f0e3109 1#!/usr/bin/env python3
db9ecf05 2# SPDX-License-Identifier: LGPL-2.1-or-later
87bf983c
FS
3# pylint: disable=line-too-long,too-many-lines,too-many-branches,too-many-statements,too-many-arguments
4# pylint: disable=too-many-public-methods,too-many-boolean-expressions,invalid-name
5# pylint: disable=missing-function-docstring,missing-class-docstring,missing-module-docstring
1f0e3109
SS
6# systemd-networkd tests
7
0f1853e2
DDM
8# These tests can be executed in the systemd mkosi image when booted in QEMU. After booting the QEMU VM,
9# simply run this file which can be found in the VM at /root/src/test/test-network/systemd-networkd-tests.py.
10
9c1ae484 11import argparse
dded88ac 12import errno
7c0d36ff 13import itertools
1f0e3109 14import os
a962d857 15import pathlib
ae014ecb 16import psutil
201bf07f 17import re
1f0e3109
SS
18import shutil
19import signal
a9bc5e37
YW
20import subprocess
21import sys
a9bc5e37
YW
22import time
23import unittest
a962d857
YW
24
25network_unit_dir = '/run/systemd/network'
26networkd_conf_dropin_dir = '/run/systemd/networkd.conf.d'
27networkd_ci_temp_dir = '/run/networkd-ci'
28udev_rules_dir = '/run/udev/rules.d'
29
30dnsmasq_pid_file = '/run/networkd-ci/test-dnsmasq.pid'
31dnsmasq_log_file = '/run/networkd-ci/test-dnsmasq.log'
32dnsmasq_lease_file = '/run/networkd-ci/test-dnsmasq.lease'
33
34isc_dhcpd_pid_file = '/run/networkd-ci/test-isc-dhcpd.pid'
35isc_dhcpd_lease_file = '/run/networkd-ci/test-isc-dhcpd.lease'
36
37systemd_lib_paths = ['/usr/lib/systemd', '/lib/systemd']
38which_paths = ':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
39
40networkd_bin = shutil.which('systemd-networkd', path=which_paths)
41resolved_bin = shutil.which('systemd-resolved', path=which_paths)
b05c4d6b 42timesyncd_bin = shutil.which('systemd-timesyncd', path=which_paths)
a962d857
YW
43udevd_bin = shutil.which('systemd-udevd', path=which_paths)
44wait_online_bin = shutil.which('systemd-networkd-wait-online', path=which_paths)
45networkctl_bin = shutil.which('networkctl', path=which_paths)
46resolvectl_bin = shutil.which('resolvectl', path=which_paths)
47timedatectl_bin = shutil.which('timedatectl', path=which_paths)
b05c4d6b 48udevadm_bin = shutil.which('udevadm', path=which_paths)
a962d857
YW
49
50use_valgrind = False
b05c4d6b 51valgrind_cmd = ''
a962d857 52enable_debug = True
9c1ae484 53env = {}
163d095f 54wait_online_env = {}
a962d857
YW
55asan_options = None
56lsan_options = None
57ubsan_options = None
58with_coverage = False
59
60active_units = []
61protected_links = {
62 'erspan0',
63 'gre0',
64 'gretap0',
65 'ifb0',
66 'ifb1',
67 'ip6_vti0',
68 'ip6gre0',
69 'ip6tnl0',
70 'ip_vti0',
71 'lo',
72 'sit0',
73 'tunl0',
74}
75saved_routes = None
76saved_ipv4_rules = None
77saved_ipv6_rules = None
f54dce2d 78saved_timezone = None
a962d857
YW
79
80def rm_f(path):
81 if os.path.exists(path):
82 os.remove(path)
83
84def rm_rf(path):
85 shutil.rmtree(path, ignore_errors=True)
86
87def cp(src, dst):
88 shutil.copy(src, dst)
89
90def cp_r(src, dst):
91 shutil.copytree(src, dst, copy_function=shutil.copy)
92
93def mkdir_p(path):
94 os.makedirs(path, exist_ok=True)
95
96def touch(path):
97 pathlib.Path(path).touch()
98
66504b22 99def check_output(*command, **kwargs):
a962d857
YW
100 # This checks the result and returns stdout (and stderr) on success.
101 command = command[0].split() + list(command[1:])
17479d51
YW
102 ret = subprocess.run(command, check=False, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs)
103 if ret.returncode == 0:
104 return ret.stdout.rstrip()
105 # When returncode != 0, print stdout and stderr, then trigger CalledProcessError.
106 print(ret.stdout)
107 ret.check_returncode()
2225e7fd 108
66504b22 109def call(*command, **kwargs):
b5dac5b0 110 # This returns returncode. stdout and stderr are merged and shown in console
371810d1 111 command = command[0].split() + list(command[1:])
66504b22 112 return subprocess.run(command, check=False, universal_newlines=True, stderr=subprocess.STDOUT, **kwargs).returncode
371810d1 113
66504b22 114def call_quiet(*command, **kwargs):
371810d1 115 command = command[0].split() + list(command[1:])
66504b22 116 return subprocess.run(command, check=False, universal_newlines=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, **kwargs).returncode
371810d1 117
66504b22 118def run(*command, **kwargs):
a962d857 119 # This returns CompletedProcess instance.
371810d1 120 command = command[0].split() + list(command[1:])
66504b22 121 return subprocess.run(command, check=False, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
371810d1 122
59edcf2b
YW
123def is_module_available(*module_names):
124 for module_name in module_names:
125 lsmod_output = check_output('lsmod')
126 module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE)
127 if not module_re.search(lsmod_output) and call_quiet('modprobe', module_name) != 0:
128 return False
129 return True
130
131def expectedFailureIfModuleIsNotAvailable(*module_names):
7a0a37b2 132 def f(func):
59edcf2b 133 return func if is_module_available(*module_names) else unittest.expectedFailure(func)
7a0a37b2
EV
134
135 return f
136
2f0260c1
YW
137def expectedFailureIfERSPANv0IsNotSupported():
138 # erspan version 0 is supported since f989d546a2d5a9f001f6f8be49d98c10ab9b1897 (v5.8)
7bea7f9b 139 def f(func):
a962d857
YW
140 rc = call_quiet('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 0')
141 remove_link('erspan99')
142 return func if rc == 0 else unittest.expectedFailure(func)
2f0260c1
YW
143
144 return f
145
146def expectedFailureIfERSPANv2IsNotSupported():
147 # erspan version 2 is supported since f551c91de262ba36b20c3ac19538afb4f4507441 (v4.16)
148 def f(func):
a962d857
YW
149 rc = call_quiet('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 2')
150 remove_link('erspan99')
151 return func if rc == 0 else unittest.expectedFailure(func)
7bea7f9b
SS
152
153 return f
154
d586a2c3
YW
155def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
156 def f(func):
a962d857
YW
157 rc = call_quiet('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
158 call_quiet('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
159 return func if rc == 0 else unittest.expectedFailure(func)
d586a2c3
YW
160
161 return f
162
163def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
164 def f(func):
a962d857
YW
165 rc = call_quiet('ip rule add not from 192.168.100.19 ipproto tcp table 7')
166 call_quiet('ip rule del not from 192.168.100.19 ipproto tcp table 7')
167 return func if rc == 0 else unittest.expectedFailure(func)
d586a2c3
YW
168
169 return f
170
6be8e78e
YW
171def expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable():
172 def f(func):
a962d857
YW
173 supported = False
174 if call_quiet('ip rule add from 192.168.100.19 table 7 uidrange 200-300') == 0:
175 ret = run('ip rule list from 192.168.100.19 table 7')
176 supported = ret.returncode == 0 and 'uidrange 200-300' in ret.stdout
177 call_quiet('ip rule del from 192.168.100.19 table 7 uidrange 200-300')
178 return func if supported else unittest.expectedFailure(func)
6be8e78e
YW
179
180 return f
181
e28fd95f
YW
182def expectedFailureIfLinkFileFieldIsNotSet():
183 def f(func):
a962d857
YW
184 call_quiet('ip link add name dummy99 type dummy')
185 ret = run('udevadm info -w10s /sys/class/net/dummy99')
186 supported = ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout
187 remove_link('dummy99')
188 return func if supported else unittest.expectedFailure(func)
e28fd95f
YW
189
190 return f
191
086bcf5d
YW
192def expectedFailureIfNexthopIsNotAvailable():
193 def f(func):
a962d857
YW
194 rc = call_quiet('ip nexthop list')
195 return func if rc == 0 else unittest.expectedFailure(func)
086bcf5d
YW
196
197 return f
198
297f9d86
YW
199def expectedFailureIfRTA_VIAIsNotSupported():
200 def f(func):
a962d857
YW
201 call_quiet('ip link add dummy98 type dummy')
202 call_quiet('ip link set up dev dummy98')
203 call_quiet('ip route add 2001:1234:5:8fff:ff:ff:ff:fe/128 dev dummy98')
204 rc = call_quiet('ip route add 10.10.10.10 via inet6 2001:1234:5:8fff:ff:ff:ff:fe dev dummy98')
205 remove_link('dummy98')
206 return func if rc == 0 else unittest.expectedFailure(func)
297f9d86
YW
207
208 return f
209
6934ace0
YW
210def expectedFailureIfAlternativeNameIsNotAvailable():
211 def f(func):
a962d857
YW
212 call_quiet('ip link add dummy98 type dummy')
213 supported = \
214 call_quiet('ip link prop add dev dummy98 altname hogehogehogehogehoge') == 0 and \
215 call_quiet('ip link show dev hogehogehogehogehoge') == 0
216 remove_link('dummy98')
217 return func if supported else unittest.expectedFailure(func)
6934ace0
YW
218
219 return f
220
3d2c2692
YW
221def expectedFailureIfNetdevsimWithSRIOVIsNotAvailable():
222 def f(func):
a962d857
YW
223 def finalize(func, supported):
224 call_quiet('rmmod netdevsim')
225 return func if supported else unittest.expectedFailure(func)
226
227 call_quiet('rmmod netdevsim')
228 if call_quiet('modprobe netdevsim') != 0:
229 return finalize(func, False)
3d2c2692
YW
230
231 try:
d45476ef 232 with open('/sys/bus/netdevsim/new_device', mode='w', encoding='utf-8') as f:
3d2c2692 233 f.write('99 1')
54e2f32f 234 except OSError:
a962d857 235 return finalize(func, False)
3d2c2692 236
a962d857
YW
237 if not os.path.exists('/sys/bus/netdevsim/devices/netdevsim99/sriov_numvfs'):
238 return finalize(func, False)
3d2c2692 239
a962d857
YW
240 # Also checks if udevd supports .link files, as it seems disabled on CentOS CI (Arch).
241 rc = call_quiet('udevadm info -w10s /sys/class/net/eni99np1')
242 return finalize(func, rc == 0)
3d2c2692
YW
243
244 return f
245
32ab27af 246def udev_reload():
b05c4d6b 247 check_output(*udevadm_cmd, 'control', '--reload')
32ab27af 248
a962d857
YW
249def copy_network_unit(*units, copy_dropins=True):
250 """
251 Copy networkd unit files into the testbed.
1f0e3109 252
a962d857 253 Any networkd unit file type can be specified, as well as drop-in files.
1f0e3109 254
a962d857
YW
255 By default, all drop-ins for a specified unit file are copied in;
256 to avoid that specify dropins=False.
3e3b0d2a 257
a962d857
YW
258 When a drop-in file is specified, its unit file is also copied in automatically.
259 """
32ab27af 260 has_link = False
a962d857
YW
261 mkdir_p(network_unit_dir)
262 for unit in units:
263 if copy_dropins and os.path.exists(os.path.join(networkd_ci_temp_dir, unit + '.d')):
264 cp_r(os.path.join(networkd_ci_temp_dir, unit + '.d'), os.path.join(network_unit_dir, unit + '.d'))
32ab27af 265
a962d857
YW
266 if unit.endswith('.conf'):
267 dropin = unit
268 unit = os.path.dirname(dropin).rstrip('.d')
269 dropindir = os.path.join(network_unit_dir, unit + '.d')
270 mkdir_p(dropindir)
271 cp(os.path.join(networkd_ci_temp_dir, dropin), dropindir)
32ab27af 272
a962d857
YW
273 cp(os.path.join(networkd_ci_temp_dir, unit), network_unit_dir)
274
32ab27af
YW
275 if unit.endswith('.link'):
276 has_link = True
277
278 if has_link:
279 udev_reload()
280
a962d857
YW
281def remove_network_unit(*units):
282 """
283 Remove previously copied unit files from the testbed.
284
285 Drop-ins will be removed automatically.
286 """
32ab27af 287 has_link = False
a962d857
YW
288 for unit in units:
289 rm_f(os.path.join(network_unit_dir, unit))
290 rm_rf(os.path.join(network_unit_dir, unit + '.d'))
291
32ab27af
YW
292 if unit.endswith('.link') or unit.endswith('.link.d'):
293 has_link = True
294
295 if has_link:
296 udev_reload()
297
a962d857 298def clear_network_units():
32ab27af
YW
299 has_link = False
300 if os.path.exists(network_unit_dir):
301 units = os.listdir(network_unit_dir)
302 for unit in units:
303 if unit.endswith('.link') or unit.endswith('.link.d'):
304 has_link = True
305
a962d857
YW
306 rm_rf(network_unit_dir)
307
32ab27af
YW
308 if has_link:
309 udev_reload()
310
a962d857
YW
311def copy_networkd_conf_dropin(*dropins):
312 """Copy networkd.conf dropin files into the testbed."""
313 mkdir_p(networkd_conf_dropin_dir)
314 for dropin in dropins:
315 cp(os.path.join(networkd_ci_temp_dir, dropin), networkd_conf_dropin_dir)
316
317def remove_networkd_conf_dropin(*dropins):
318 """Remove previously copied networkd.conf dropin files from the testbed."""
319 for dropin in dropins:
320 rm_f(os.path.join(networkd_conf_dropin_dir, dropin))
321
322def clear_networkd_conf_dropins():
323 rm_rf(networkd_conf_dropin_dir)
324
325def copy_udev_rule(*rules):
326 """Copy udev rules"""
327 mkdir_p(udev_rules_dir)
328 for rule in rules:
329 cp(os.path.join(networkd_ci_temp_dir, rule), udev_rules_dir)
330
331def remove_udev_rule(*rules):
332 """Remove previously copied udev rules"""
333 for rule in rules:
334 rm_f(os.path.join(udev_rules_dir, rule))
335
336def clear_udev_rules():
337 rm_rf(udev_rules_dir)
338
339def save_active_units():
87b308c8 340 for u in ['systemd-networkd.socket', 'systemd-networkd.service',
b05c4d6b 341 'systemd-resolved.service', 'systemd-timesyncd.service',
f7ada4b8 342 'firewalld.service']:
2225e7fd 343 if call(f'systemctl is-active --quiet {u}') == 0:
a962d857
YW
344 call(f'systemctl stop {u}')
345 active_units.append(u)
346
347def restore_active_units():
348 if 'systemd-networkd.socket' in active_units:
349 call('systemctl stop systemd-networkd.socket systemd-networkd.service')
a962d857
YW
350 for u in active_units:
351 call(f'systemctl restart {u}')
352
93f5ae6b
YW
353def create_unit_dropin(unit, contents):
354 mkdir_p(f'/run/systemd/system/{unit}.d')
355 with open(f'/run/systemd/system/{unit}.d/00-override.conf', mode='w', encoding='utf-8') as f:
356 f.write('\n'.join(contents))
357
b05c4d6b
YW
358def create_service_dropin(service, command, reload_command=None, additional_settings=None):
359 drop_in = [
360 '[Service]',
361 'ExecStart=',
362 f'ExecStart=!!{valgrind_cmd}{command}',
363 ]
364 if reload_command:
365 drop_in += [
366 'ExecReload=',
367 f'ExecReload={valgrind_cmd}{reload_command}',
368 ]
369 if enable_debug:
370 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
371 if asan_options:
372 drop_in += [f'Environment=ASAN_OPTIONS="{asan_options}"']
373 if lsan_options:
374 drop_in += [f'Environment=LSAN_OPTIONS="{lsan_options}"']
375 if ubsan_options:
376 drop_in += [f'Environment=UBSAN_OPTIONS="{ubsan_options}"']
377 if asan_options or lsan_options or ubsan_options:
378 drop_in += ['SystemCallFilter=']
379 if use_valgrind or asan_options or lsan_options or ubsan_options:
380 drop_in += ['MemoryDenyWriteExecute=no']
381 if use_valgrind:
382 drop_in += [
383 'Environment=SYSTEMD_MEMPOOL=0',
384 'PrivateTmp=yes',
385 ]
386 if with_coverage:
387 drop_in += [
388 'ProtectSystem=no',
389 'ProtectHome=no',
390 ]
391 if additional_settings:
392 drop_in += additional_settings
393
93f5ae6b 394 create_unit_dropin(f'{service}.service', drop_in)
b05c4d6b 395
a962d857
YW
396def link_exists(link):
397 return os.path.exists(os.path.join('/sys/class/net', link, 'ifindex'))
398
399def remove_link(*links, protect=False):
400 for link in links:
401 if protect and link in protected_links:
402 continue
403 if link_exists(link):
404 call(f'ip link del dev {link}')
405
406def save_existing_links():
407 links = os.listdir('/sys/class/net')
408 for link in links:
409 if link_exists(link):
410 protected_links.add(link)
411
412 print('### The following links will be protected:')
413 print(', '.join(sorted(list(protected_links))))
414
415def flush_links():
416 links = os.listdir('/sys/class/net')
417 remove_link(*links, protect=True)
418
419def flush_nexthops():
420 # Currently, the 'ip nexthop' command does not have 'save' and 'restore'.
421 # Hence, we cannot restore nexthops in a simple way.
422 # Let's assume there is no nexthop used in the system
423 call_quiet('ip nexthop flush')
424
425def save_routes():
426 # pylint: disable=global-statement
427 global saved_routes
428 saved_routes = check_output('ip route show table all')
429 print('### The following routes will be protected:')
430 print(saved_routes)
431
432def flush_routes():
433 have = False
434 output = check_output('ip route show table all')
435 for line in output.splitlines():
436 if line in saved_routes:
437 continue
438 if 'proto kernel' in line:
439 continue
440 if ' dev ' in line and not ' dev lo ' in line:
441 continue
442 if not have:
443 have = True
444 print('### Removing routes that did not exist when the test started.')
445 print(f'# {line}')
446 call(f'ip route del {line}')
447
448def save_routing_policy_rules():
449 # pylint: disable=global-statement
450 global saved_ipv4_rules, saved_ipv6_rules
451 def save(ipv):
452 output = check_output(f'ip -{ipv} rule show')
453 print(f'### The following IPv{ipv} routing policy rules will be protected:')
454 print(output)
455 return output
456
457 saved_ipv4_rules = save(4)
458 saved_ipv6_rules = save(6)
459
460def flush_routing_policy_rules():
461 def flush(ipv, saved_rules):
462 have = False
463 output = check_output(f'ip -{ipv} rule show')
464 for line in output.splitlines():
465 if line in saved_rules:
466 continue
467 if not have:
468 have = True
469 print(f'### Removing IPv{ipv} routing policy rules that did not exist when the test started.')
470 print(f'# {line}')
e755ad61 471 words = line.replace('lookup [l3mdev-table]', 'l3mdev').split()
a962d857
YW
472 priority = words[0].rstrip(':')
473 call(f'ip -{ipv} rule del priority {priority} ' + ' '.join(words[1:]))
474
475 flush(4, saved_ipv4_rules)
476 flush(6, saved_ipv6_rules)
477
478def flush_fou_ports():
479 ret = run('ip fou show')
480 if ret.returncode != 0:
481 return # fou may not be supported
482 for line in ret.stdout.splitlines():
483 port = line.split()[1]
484 call(f'ip fou del port {port}')
485
486def flush_l2tp_tunnels():
e11d0e39 487 tids = []
49ad2872
YW
488 ret = run('ip l2tp show tunnel')
489 if ret.returncode != 0:
490 return # l2tp may not be supported
491 for line in ret.stdout.splitlines():
a962d857
YW
492 words = line.split()
493 if words[0] == 'Tunnel':
494 tid = words[1].rstrip(',')
495 call(f'ip l2tp del tunnel tunnel_id {tid}')
e11d0e39
YW
496 tids.append(tid)
497
498 # Removing L2TP tunnel is asynchronous and slightly takes a time.
499 for tid in tids:
500 for _ in range(50):
501 r = run(f'ip l2tp show tunnel tunnel_id {tid}')
502 if r.returncode != 0 or len(r.stdout.rstrip()) == 0:
503 break
504 time.sleep(.2)
505 else:
506 print(f'Cannot remove L2TP tunnel {tid}, ignoring.')
a962d857 507
f54dce2d
YW
508def save_timezone():
509 global saved_timezone
67a9b3ec 510 r = run(*timedatectl_cmd, 'show', '--value', '--property', 'Timezone', env=env)
f54dce2d
YW
511 if r.returncode == 0:
512 saved_timezone = r.stdout.rstrip()
513 print(f'### Saved timezone: {saved_timezone}')
514
515def restore_timezone():
516 if saved_timezone:
67a9b3ec 517 call(*timedatectl_cmd, 'set-timezone', f'{saved_timezone}', env=env)
f54dce2d 518
a962d857
YW
519def read_link_attr(*args):
520 with open(os.path.join('/sys/class/net', *args), encoding='utf-8') as f:
521 return f.readline().strip()
522
523def read_link_state_file(link):
524 ifindex = read_link_attr(link, 'ifindex')
525 path = os.path.join('/run/systemd/netif/links', ifindex)
526 with open(path, encoding='utf-8') as f:
527 return f.read()
528
529def read_ip_sysctl_attr(link, attribute, ipv):
530 with open(os.path.join('/proc/sys/net', ipv, 'conf', link, attribute), encoding='utf-8') as f:
531 return f.readline().strip()
532
533def read_ipv6_sysctl_attr(link, attribute):
534 return read_ip_sysctl_attr(link, attribute, 'ipv6')
535
536def read_ipv4_sysctl_attr(link, attribute):
537 return read_ip_sysctl_attr(link, attribute, 'ipv4')
538
539def start_dnsmasq(*additional_options, interface='veth-peer', lease_time='2m', ipv4_range='192.168.5.10,192.168.5.200', ipv4_router='192.168.5.1', ipv6_range='2600::10,2600::20'):
540 command = (
541 'dnsmasq',
542 f'--log-facility={dnsmasq_log_file}',
543 '--log-queries=extra',
544 '--log-dhcp',
545 f'--pid-file={dnsmasq_pid_file}',
546 '--conf-file=/dev/null',
547 '--bind-interfaces',
548 f'--interface={interface}',
549 f'--dhcp-leasefile={dnsmasq_lease_file}',
550 '--enable-ra',
551 f'--dhcp-range={ipv6_range},{lease_time}',
552 f'--dhcp-range={ipv4_range},{lease_time}',
553 '--dhcp-option=option:mtu,1492',
554 f'--dhcp-option=option:router,{ipv4_router}',
555 '--port=0',
556 '--no-resolv',
557 ) + additional_options
558 check_output(*command)
559
560def stop_by_pid_file(pid_file):
561 if not os.path.exists(pid_file):
562 return
563 with open(pid_file, 'r', encoding='utf-8') as f:
564 pid = f.read().rstrip(' \t\r\n\0')
565 os.kill(int(pid), signal.SIGTERM)
566 for _ in range(25):
567 try:
568 os.kill(int(pid), 0)
569 print(f"PID {pid} is still alive, waiting...")
570 time.sleep(.2)
571 except OSError as e:
572 if e.errno == errno.ESRCH:
573 break
574 print(f"Unexpected exception when waiting for {pid} to die: {e.errno}")
575 os.remove(pid_file)
576
577def stop_dnsmasq():
578 stop_by_pid_file(dnsmasq_pid_file)
579 rm_f(dnsmasq_lease_file)
580 rm_f(dnsmasq_log_file)
581
582def read_dnsmasq_log_file():
583 with open(dnsmasq_log_file, encoding='utf-8') as f:
584 return f.read()
585
586def start_isc_dhcpd(conf_file, ipv, interface='veth-peer'):
587 conf_file_path = os.path.join(networkd_ci_temp_dir, conf_file)
588 isc_dhcpd_command = f'dhcpd {ipv} -cf {conf_file_path} -lf {isc_dhcpd_lease_file} -pf {isc_dhcpd_pid_file} {interface}'
589 touch(isc_dhcpd_lease_file)
590 check_output(isc_dhcpd_command)
591
592def stop_isc_dhcpd():
593 stop_by_pid_file(isc_dhcpd_pid_file)
594 rm_f(isc_dhcpd_lease_file)
595
5bd2a7c5
YW
596def networkd_invocation_id():
597 return check_output('systemctl show --value -p InvocationID systemd-networkd.service')
598
599def read_networkd_log(invocation_id=None):
600 if not invocation_id:
601 invocation_id = networkd_invocation_id()
602 return check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id)
603
a962d857
YW
604def stop_networkd(show_logs=True):
605 if show_logs:
5bd2a7c5 606 invocation_id = networkd_invocation_id()
a962d857
YW
607 check_output('systemctl stop systemd-networkd.socket')
608 check_output('systemctl stop systemd-networkd.service')
609 if show_logs:
5bd2a7c5 610 print(read_networkd_log(invocation_id))
a962d857
YW
611
612def start_networkd():
613 check_output('systemctl start systemd-networkd')
614
615def restart_networkd(show_logs=True):
85b1a14d 616 if show_logs:
5bd2a7c5 617 invocation_id = networkd_invocation_id()
85b1a14d
YW
618 check_output('systemctl restart systemd-networkd.service')
619 if show_logs:
5bd2a7c5 620 print(read_networkd_log(invocation_id))
a962d857 621
ae014ecb
YW
622def networkd_pid():
623 return int(check_output('systemctl show --value -p MainPID systemd-networkd.service'))
624
a962d857
YW
625def networkctl_reconfigure(*links):
626 check_output(*networkctl_cmd, 'reconfigure', *links, env=env)
627
628def networkctl_reload(sleep_time=1):
629 check_output(*networkctl_cmd, 'reload', env=env)
630 # 'networkctl reload' asynchronously reconfigure links.
631 # Hence, we need to wait for a short time for link to be in configuring state.
632 if sleep_time > 0:
633 time.sleep(sleep_time)
634
635def setup_common():
636 print()
637
638def tear_down_common():
639 # 1. stop DHCP servers
640 stop_dnsmasq()
641 stop_isc_dhcpd()
642
643 # 2. remove modules
644 call_quiet('rmmod netdevsim')
645 call_quiet('rmmod sch_teql')
646
647 # 3. remove network namespace
648 call_quiet('ip netns del ns99')
649
650 # 4. remove links
e11d0e39 651 flush_l2tp_tunnels()
a962d857
YW
652 flush_links()
653
654 # 5. stop networkd
249b7ecc 655 stop_networkd()
a962d857
YW
656
657 # 6. remove configs
658 clear_network_units()
659 clear_networkd_conf_dropins()
660
661 # 7. flush settings
662 flush_fou_ports()
a962d857
YW
663 flush_nexthops()
664 flush_routing_policy_rules()
665 flush_routes()
666
667def setUpModule():
668 rm_rf(networkd_ci_temp_dir)
669 cp_r(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_temp_dir)
670
671 clear_network_units()
672 clear_networkd_conf_dropins()
673 clear_udev_rules()
674
675 copy_udev_rule('00-debug-net.rules')
676
677 # Save current state
678 save_active_units()
679 save_existing_links()
680 save_routes()
681 save_routing_policy_rules()
f54dce2d 682 save_timezone()
c0bf6733 683
b05c4d6b
YW
684 create_service_dropin('systemd-networkd', networkd_bin,
685 f'{networkctl_bin} reload',
686 ['[Service]', 'Restart=no', '[Unit]', 'StartLimitIntervalSec=0'])
687 create_service_dropin('systemd-resolved', resolved_bin)
688 create_service_dropin('systemd-timesyncd', timesyncd_bin)
b6d587d1 689
b05c4d6b
YW
690 # TODO: also run udevd with sanitizers, valgrind, or coverage
691 #create_service_dropin('systemd-udevd', udevd_bin,
692 # f'{udevadm_bin} control --reload --timeout 0')
93f5ae6b
YW
693 create_unit_dropin(
694 'systemd-udevd.service',
695 [
696 '[Service]',
697 'ExecStart=',
698 f'ExecStart=!!{udevd_bin}',
699 'ExecReload=',
700 f'ExecReload={udevadm_bin} control --reload --timeout 0',
701 ]
702 )
703 create_unit_dropin(
704 'systemd-networkd.socket',
705 [
706 '[Unit]',
707 'StartLimitIntervalSec=0',
708 ]
709 )
641aa412 710
371810d1
ZJS
711 check_output('systemctl daemon-reload')
712 print(check_output('systemctl cat systemd-networkd.service'))
b6d587d1 713 print(check_output('systemctl cat systemd-resolved.service'))
b05c4d6b 714 print(check_output('systemctl cat systemd-timesyncd.service'))
641aa412 715 print(check_output('systemctl cat systemd-udevd.service'))
a962d857 716 check_output('systemctl restart systemd-resolved.service')
b05c4d6b 717 check_output('systemctl restart systemd-timesyncd.service')
a962d857 718 check_output('systemctl restart systemd-udevd.service')
9c1ae484 719
1f0e3109 720def tearDownModule():
a962d857
YW
721 rm_rf(networkd_ci_temp_dir)
722 clear_udev_rules()
723 clear_network_units()
724 clear_networkd_conf_dropins()
725
f54dce2d
YW
726 restore_timezone()
727
a962d857 728 rm_rf('/run/systemd/system/systemd-networkd.service.d')
93f5ae6b 729 rm_rf('/run/systemd/system/systemd-networkd.socket.d')
a962d857 730 rm_rf('/run/systemd/system/systemd-resolved.service.d')
b05c4d6b 731 rm_rf('/run/systemd/system/systemd-timesyncd.service.d')
a962d857 732 rm_rf('/run/systemd/system/systemd-udevd.service.d')
371810d1 733 check_output('systemctl daemon-reload')
87b308c8 734 check_output('systemctl restart systemd-udevd.service')
a962d857 735 restore_active_units()
ec38833c 736
a962d857
YW
737class Utilities():
738 # pylint: disable=no-member
caad88a2 739
a962d857
YW
740 def check_link_exists(self, link, expected=True):
741 if expected:
742 self.assertTrue(link_exists(link))
743 else:
744 self.assertFalse(link_exists(link))
caad88a2 745
a962d857
YW
746 def check_link_attr(self, *args):
747 self.assertEqual(read_link_attr(*args[:-1]), args[-1])
aaae5713 748
a962d857
YW
749 def check_bridge_port_attr(self, master, port, attribute, expected, allow_enoent=False):
750 path = os.path.join('/sys/devices/virtual/net', master, 'lower_' + port, 'brport', attribute)
751 if allow_enoent and not os.path.exists(path):
752 return
753 with open(path, encoding='utf-8') as f:
754 self.assertEqual(f.readline().strip(), expected)
aaae5713 755
a962d857
YW
756 def check_ipv4_sysctl_attr(self, link, attribute, expected):
757 self.assertEqual(read_ipv4_sysctl_attr(link, attribute), expected)
ec38833c 758
a962d857
YW
759 def check_ipv6_sysctl_attr(self, link, attribute, expected):
760 self.assertEqual(read_ipv6_sysctl_attr(link, attribute), expected)
aaae5713 761
a962d857
YW
762 def wait_links(self, *links, timeout=20, fail_assert=True):
763 def links_exist(*links):
764 for link in links:
765 if not link_exists(link):
766 return False
767 return True
524cc9d1 768
a962d857
YW
769 for iteration in range(timeout + 1):
770 if iteration > 0:
771 time.sleep(1)
2be0b6fc 772
a962d857
YW
773 if links_exist(*links):
774 return True
775 if fail_assert:
776 self.fail('Timed out waiting for all links to be created: ' + ', '.join(list(links)))
777 return False
0fc0d85f 778
cfbdc438
YW
779 def wait_activated(self, link, state='down', timeout=20, fail_assert=True):
780 # wait for the interface is activated.
781 invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value')
782 needle = f'{link}: Bringing link {state}'
783 flag = state.upper()
a962d857 784 for iteration in range(timeout + 1):
459c35d4
YW
785 if iteration != 0:
786 time.sleep(1)
787 if not link_exists(link):
788 continue
cfbdc438
YW
789 output = check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id)
790 if needle in output and flag in check_output(f'ip link show {link}'):
791 return True
cfbdc438
YW
792 if fail_assert:
793 self.fail(f'Timed out waiting for {link} activated.')
794 return False
795
a4632dc7
DS
796 def wait_operstate(self, link, operstate='degraded', setup_state='configured', setup_timeout=5, fail_assert=True):
797 """Wait for the link to reach the specified operstate and/or setup state.
798
799 Specify None or '' for either operstate or setup_state to ignore that state.
800 This will recheck until the state conditions are met or the timeout expires.
801
802 If the link successfully matches the requested state, this returns True.
803 If this times out waiting for the link to match, the behavior depends on the
804 'fail_assert' parameter; if True, this causes a test assertion failure,
805 otherwise this returns False. The default is to cause assertion failure.
806
807 Note that this function matches on *exactly* the given operstate and setup_state.
808 To wait for a link to reach *or exceed* a given operstate, use wait_online().
809 """
810 if not operstate:
811 operstate = r'\S+'
812 if not setup_state:
813 setup_state = r'\S+'
814
815 for secs in range(setup_timeout + 1):
459c35d4
YW
816 if secs != 0:
817 time.sleep(1)
818 if not link_exists(link):
819 continue
a4632dc7 820 output = check_output(*networkctl_cmd, '-n', '0', 'status', link, env=env)
a4632dc7
DS
821 if re.search(rf'(?m)^\s*State:\s+{operstate}\s+\({setup_state}\)\s*$', output):
822 return True
894ff7d1
YW
823
824 print(output)
a4632dc7
DS
825 if fail_assert:
826 self.fail(f'Timed out waiting for {link} to reach state {operstate}/{setup_state}')
827 return False
2be0b6fc 828
70448bb1 829 def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, ipv4=False, ipv6=False, setup_state='configured', setup_timeout=5):
0c020321
DS
830 """Wait for the link(s) to reach the specified operstate and/or setup state.
831
832 This is similar to wait_operstate() but can be used for multiple links,
833 and it also calls systemd-networkd-wait-online to wait for the given operstate.
834 The operstate should be specified in the link name, like 'eth0:degraded'.
835 If just a link name is provided, wait-online's default operstate to wait for is degraded.
836
837 The 'timeout' parameter controls the systemd-networkd-wait-online timeout, and the
838 'setup_timeout' controls the per-link timeout waiting for the setup_state.
839
840 Set 'bool_any' to True to wait for any (instead of all) of the given links.
841 If this is set, no setup_state checks are done.
842
70448bb1
L
843 Set 'ipv4' or 'ipv6' to True to wait for IPv4 address or IPv6 address, respectively, of each of the given links.
844 This is applied only for the operational state 'degraded' or above.
845
0c020321
DS
846 Note that this function waits for the link(s) to reach *or exceed* the given operstate.
847 However, the setup_state, if specified, must be matched *exactly*.
848
849 This returns if the link(s) reached the requested operstate/setup_state; otherwise it
850 raises CalledProcessError or fails test assertion.
851 """
e2aea43f
YW
852 args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
853 if bool_any:
854 args += ['--any']
70448bb1
L
855 if ipv4:
856 args += ['--ipv4']
857 if ipv6:
858 args += ['--ipv6']
e2aea43f 859 try:
163d095f 860 check_output(*args, env=wait_online_env)
a962d857 861 except subprocess.CalledProcessError as e:
17479d51 862 # show detailed status on failure
e2aea43f 863 for link in links_with_operstate:
66dc5d82
YW
864 name = link.split(':')[0]
865 if link_exists(name):
a962d857 866 call(*networkctl_cmd, '-n', '0', 'status', name, env=env)
e2aea43f 867 raise
fd372b1a 868 if not bool_any and setup_state:
0c020321
DS
869 for link in links_with_operstate:
870 self.wait_operstate(link.split(':')[0], None, setup_state, setup_timeout)
e2aea43f 871
53c32c2b 872 def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
2629df47
YW
873 for i in range(timeout_sec):
874 if i > 0:
875 time.sleep(1)
371810d1 876 output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
571f9539 877 if re.search(address_regex, output) and 'tentative' not in output:
2629df47 878 break
240e4137
YW
879
880 self.assertRegex(output, address_regex)
881
882 def wait_address_dropped(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
883 for i in range(timeout_sec):
884 if i > 0:
885 time.sleep(1)
886 output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
887 if not re.search(address_regex, output):
888 break
889
890 self.assertNotRegex(output, address_regex)
2629df47 891
1ca44d7d
YW
892class NetworkctlTests(unittest.TestCase, Utilities):
893
1ca44d7d 894 def setUp(self):
a962d857 895 setup_common()
1ca44d7d
YW
896
897 def tearDown(self):
a962d857 898 tear_down_common()
1ca44d7d 899
6934ace0
YW
900 @expectedFailureIfAlternativeNameIsNotAvailable()
901 def test_altname(self):
a962d857 902 copy_network_unit('26-netdev-link-local-addressing-yes.network', '12-dummy.netdev', '12-dummy.link')
6934ace0
YW
903 start_networkd()
904 self.wait_online(['dummy98:degraded'])
905
fc79e6ff 906 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
6934ace0
YW
907 self.assertRegex(output, 'hogehogehogehogehogehoge')
908
dcd9f07c 909 def test_reconfigure(self):
a962d857 910 copy_network_unit('25-address-static.network', '12-dummy.netdev')
dcd9f07c
YW
911 start_networkd()
912 self.wait_online(['dummy98:routable'])
913
914 output = check_output('ip -4 address show dev dummy98')
915 print(output)
3bad5487
YW
916 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
917 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
918 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
dcd9f07c
YW
919
920 check_output('ip address del 10.1.2.3/16 dev dummy98')
921 check_output('ip address del 10.1.2.4/16 dev dummy98')
922 check_output('ip address del 10.2.2.4/16 dev dummy98')
923
a962d857 924 networkctl_reconfigure('dummy98')
dcd9f07c
YW
925 self.wait_online(['dummy98:routable'])
926
927 output = check_output('ip -4 address show dev dummy98')
928 print(output)
3bad5487
YW
929 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
930 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
931 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
932
a962d857 933 remove_network_unit('25-address-static.network')
3bad5487 934
a962d857 935 networkctl_reload()
3bad5487
YW
936 self.wait_operstate('dummy98', 'degraded', setup_state='unmanaged')
937
938 output = check_output('ip -4 address show dev dummy98')
939 print(output)
940 self.assertNotIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
941 self.assertNotIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
942 self.assertNotIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
943
a962d857
YW
944 copy_network_unit('25-address-static.network')
945 networkctl_reload()
3bad5487
YW
946 self.wait_online(['dummy98:routable'])
947
948 output = check_output('ip -4 address show dev dummy98')
949 print(output)
950 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
951 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
952 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
dcd9f07c 953
66de8671 954 def test_reload(self):
a962d857 955 start_networkd()
66de8671 956
a962d857
YW
957 copy_network_unit('11-dummy.netdev')
958 networkctl_reload()
19cf3143 959 self.wait_operstate('test1', 'off', setup_state='unmanaged')
66de8671 960
a962d857
YW
961 copy_network_unit('11-dummy.network')
962 networkctl_reload()
66de8671
YW
963 self.wait_online(['test1:degraded'])
964
a962d857
YW
965 remove_network_unit('11-dummy.network')
966 networkctl_reload()
19cf3143 967 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
66de8671 968
a962d857
YW
969 remove_network_unit('11-dummy.netdev')
970 networkctl_reload()
19cf3143 971 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
66de8671 972
a962d857
YW
973 copy_network_unit('11-dummy.netdev', '11-dummy.network')
974 networkctl_reload()
19cf3143 975 self.wait_operstate('test1', 'degraded')
66de8671 976
1ca44d7d 977 def test_glob(self):
a962d857 978 copy_network_unit('11-dummy.netdev', '11-dummy.network')
2cf6fdff 979 start_networkd()
1ca44d7d 980
e2aea43f 981 self.wait_online(['test1:degraded'])
1ca44d7d 982
371810d1 983 output = check_output(*networkctl_cmd, 'list', env=env)
1ca44d7d
YW
984 self.assertRegex(output, '1 lo ')
985 self.assertRegex(output, 'test1')
986
371810d1 987 output = check_output(*networkctl_cmd, 'list', 'test1', env=env)
1ca44d7d
YW
988 self.assertNotRegex(output, '1 lo ')
989 self.assertRegex(output, 'test1')
990
371810d1 991 output = check_output(*networkctl_cmd, 'list', 'te*', env=env)
1ca44d7d
YW
992 self.assertNotRegex(output, '1 lo ')
993 self.assertRegex(output, 'test1')
994
fc79e6ff 995 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'te*', env=env)
1ca44d7d
YW
996 self.assertNotRegex(output, '1: lo ')
997 self.assertRegex(output, 'test1')
998
fc79e6ff 999 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'tes[a-z][0-9]', env=env)
1ca44d7d
YW
1000 self.assertNotRegex(output, '1: lo ')
1001 self.assertRegex(output, 'test1')
1002
6d5b4efe 1003 def test_mtu(self):
a962d857 1004 copy_network_unit('11-dummy-mtu.netdev', '11-dummy.network')
2cf6fdff 1005 start_networkd()
6d5b4efe 1006
e2aea43f 1007 self.wait_online(['test1:degraded'])
6d5b4efe 1008
fc79e6ff 1009 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
6d5b4efe
YW
1010 self.assertRegex(output, 'MTU: 1600')
1011
e28fd95f 1012 def test_type(self):
a962d857 1013 copy_network_unit('11-dummy.netdev', '11-dummy.network')
e28fd95f 1014 start_networkd()
e2aea43f 1015 self.wait_online(['test1:degraded'])
e28fd95f 1016
fc79e6ff 1017 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
e28fd95f
YW
1018 print(output)
1019 self.assertRegex(output, 'Type: ether')
1020
fc79e6ff 1021 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
e28fd95f
YW
1022 print(output)
1023 self.assertRegex(output, 'Type: loopback')
1024
1025 @expectedFailureIfLinkFileFieldIsNotSet()
1026 def test_udev_link_file(self):
a962d857 1027 copy_network_unit('11-dummy.netdev', '11-dummy.network')
e28fd95f 1028 start_networkd()
e2aea43f 1029 self.wait_online(['test1:degraded'])
e28fd95f 1030
fc79e6ff 1031 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
e28fd95f 1032 print(output)
426654d7 1033 self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
e28fd95f
YW
1034 self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network')
1035
fc79e6ff 1036 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
e28fd95f 1037 print(output)
70f32a26 1038 self.assertRegex(output, r'Link File: n/a')
e28fd95f
YW
1039 self.assertRegex(output, r'Network File: n/a')
1040
bee692fd 1041 def test_delete_links(self):
a962d857
YW
1042 copy_network_unit('11-dummy.netdev', '11-dummy.network',
1043 '25-veth.netdev', '26-netdev-link-local-addressing-yes.network')
2cf6fdff 1044 start_networkd()
bee692fd 1045
e2aea43f 1046 self.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
bee692fd 1047
7a2f6fb6 1048 check_output(*networkctl_cmd, 'delete', 'test1', 'veth99', env=env)
a962d857
YW
1049 self.check_link_exists('test1', expected=False)
1050 self.check_link_exists('veth99', expected=False)
1051 self.check_link_exists('veth-peer', expected=False)
bee692fd 1052
1f0e3109
SS
1053class NetworkdNetDevTests(unittest.TestCase, Utilities):
1054
1f0e3109 1055 def setUp(self):
a962d857 1056 setup_common()
1f0e3109
SS
1057
1058 def tearDown(self):
a962d857 1059 tear_down_common()
1f0e3109 1060
1ca44d7d 1061 def test_dropin_and_name_conflict(self):
a962d857 1062 copy_network_unit('10-dropin-test.netdev', '15-name-conflict-test.netdev')
2cf6fdff 1063 start_networkd()
d80734f7 1064
e2aea43f 1065 self.wait_online(['dropin-test:off'], setup_state='unmanaged')
d80734f7 1066
371810d1 1067 output = check_output('ip link show dropin-test')
d80734f7 1068 print(output)
45aa0e84 1069 self.assertRegex(output, '00:50:56:c0:00:28')
d80734f7 1070
6b9518a0 1071 def test_match_udev_property(self):
a962d857 1072 copy_network_unit('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
6b9518a0 1073 start_networkd()
e2aea43f 1074 self.wait_online(['dummy98:routable'])
6b9518a0 1075
fc79e6ff 1076 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
6b9518a0
YW
1077 print(output)
1078 self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
1079
03db80b2 1080 def test_wait_online_any(self):
a962d857 1081 copy_network_unit('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
2cf6fdff 1082 start_networkd()
03db80b2 1083
e2aea43f 1084 self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
03db80b2 1085
19cf3143
DS
1086 self.wait_operstate('bridge99', '(off|no-carrier)', setup_state='configuring')
1087 self.wait_operstate('test1', 'degraded')
03db80b2 1088
13060471
YW
1089 @expectedFailureIfModuleIsNotAvailable('bareudp')
1090 def test_bareudp(self):
a962d857 1091 copy_network_unit('25-bareudp.netdev', '26-netdev-link-local-addressing-yes.network')
13060471
YW
1092 start_networkd()
1093
1094 self.wait_online(['bareudp99:degraded'])
1095
1096 output = check_output('ip -d link show bareudp99')
1097 print(output)
1098 self.assertRegex(output, 'dstport 1000 ')
1099 self.assertRegex(output, 'ethertype ip ')
1100
c0267a59
AW
1101 @expectedFailureIfModuleIsNotAvailable('batman-adv')
1102 def test_batadv(self):
a962d857 1103 copy_network_unit('25-batadv.netdev', '26-netdev-link-local-addressing-yes.network')
c0267a59
AW
1104 start_networkd()
1105
1106 self.wait_online(['batadv99:degraded'])
1107
1108 output = check_output('ip -d link show batadv99')
1109 print(output)
1110 self.assertRegex(output, 'batadv')
1111
1f0e3109 1112 def test_bridge(self):
a962d857 1113 copy_network_unit('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
2cf6fdff 1114 start_networkd()
1f0e3109 1115
e2aea43f 1116 self.wait_online(['bridge99:no-carrier'])
1f0e3109 1117
3d165124 1118 tick = os.sysconf('SC_CLK_TCK')
ec38833c
ZJS
1119 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick))
1120 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick))
c9047092
YW
1121 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick))
1122 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick))
1123 self.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority')))
1124 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier')))
1125 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping')))
1126 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
1127 self.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
1f0e3109 1128
fc79e6ff 1129 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
36bc2ffb
YW
1130 print(output)
1131 self.assertRegex(output, 'Priority: 9')
1132 self.assertRegex(output, 'STP: yes')
1133 self.assertRegex(output, 'Multicast IGMP Version: 3')
1134
b6d5dab7
YW
1135 output = check_output('ip -d link show bridge99')
1136 print(output)
1137 self.assertIn('vlan_filtering 1 ', output)
1138 self.assertIn('vlan_protocol 802.1ad ', output)
1139 self.assertIn('vlan_default_pvid 9 ', output)
1140
1f0e3109 1141 def test_bond(self):
a962d857 1142 copy_network_unit('25-bond.netdev', '25-bond-balanced-tlb.netdev')
2cf6fdff 1143 start_networkd()
ec38833c 1144
e2aea43f 1145 self.wait_online(['bond99:off', 'bond98:off'], setup_state='unmanaged')
ec38833c 1146
a962d857
YW
1147 self.check_link_attr('bond99', 'bonding', 'mode', '802.3ad 4')
1148 self.check_link_attr('bond99', 'bonding', 'xmit_hash_policy', 'layer3+4 1')
1149 self.check_link_attr('bond99', 'bonding', 'miimon', '1000')
1150 self.check_link_attr('bond99', 'bonding', 'lacp_rate', 'fast 1')
1151 self.check_link_attr('bond99', 'bonding', 'updelay', '2000')
1152 self.check_link_attr('bond99', 'bonding', 'downdelay', '2000')
1153 self.check_link_attr('bond99', 'bonding', 'resend_igmp', '4')
1154 self.check_link_attr('bond99', 'bonding', 'min_links', '1')
1155 self.check_link_attr('bond99', 'bonding', 'ad_actor_sys_prio', '1218')
1156 self.check_link_attr('bond99', 'bonding', 'ad_user_port_key', '811')
1157 self.check_link_attr('bond99', 'bonding', 'ad_actor_system', '00:11:22:33:44:55')
1158
1159 self.check_link_attr('bond98', 'bonding', 'mode', 'balance-tlb 5')
1160 self.check_link_attr('bond98', 'bonding', 'tlb_dynamic_lb', '1')
fde60a42 1161
acfe3b65
YW
1162 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bond99', env=env)
1163 print(output)
1164 self.assertIn('Mode: 802.3ad', output)
1165 self.assertIn('Miimon: 1s', output)
1166 self.assertIn('Updelay: 2s', output)
1167 self.assertIn('Downdelay: 2s', output)
1168
1169 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bond98', env=env)
1170 print(output)
1171 self.assertIn('Mode: balance-tlb', output)
1172
1f0e3109 1173 def test_vlan(self):
a962d857
YW
1174 copy_network_unit('21-vlan.netdev', '11-dummy.netdev',
1175 '21-vlan.network', '21-vlan-test1.network')
2cf6fdff 1176 start_networkd()
1f0e3109 1177
e2aea43f 1178 self.wait_online(['test1:degraded', 'vlan99:routable'])
1f0e3109 1179
371810d1 1180 output = check_output('ip -d link show test1')
72b7f1b9 1181 print(output)
7d7be1b9 1182 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 1183
371810d1 1184 output = check_output('ip -d link show vlan99')
14ecd604 1185 print(output)
06895a1d
YW
1186 self.assertRegex(output, ' mtu 2000 ')
1187 self.assertRegex(output, 'REORDER_HDR')
1188 self.assertRegex(output, 'LOOSE_BINDING')
1189 self.assertRegex(output, 'GVRP')
1190 self.assertRegex(output, 'MVRP')
1191 self.assertRegex(output, ' id 99 ')
1f0e3109 1192
371810d1 1193 output = check_output('ip -4 address show dev test1')
7f45d738
YW
1194 print(output)
1195 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
1196 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
1197
371810d1 1198 output = check_output('ip -4 address show dev vlan99')
7f45d738
YW
1199 print(output)
1200 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
1201
b249834b
YW
1202 def test_vlan_on_bond(self):
1203 # For issue #24377 (https://github.com/systemd/systemd/issues/24377),
1204 # which is fixed by b05e52000b4eee764b383cc3031da0a3739e996e (PR#24020).
1205
1206 copy_network_unit('21-bond-802.3ad.netdev', '21-bond-802.3ad.network',
1207 '21-vlan-on-bond.netdev', '21-vlan-on-bond.network')
1208 start_networkd()
1209 self.wait_online(['bond99:off'])
1210 self.wait_operstate('vlan99', operstate='off', setup_state='configuring', setup_timeout=10)
1211
1212 # The commit b05e52000b4eee764b383cc3031da0a3739e996e adds ", ignoring". To make it easily confirmed
1213 # that the issue is fixed by the commit, let's allow to match both string.
1214 log_re = re.compile('vlan99: Could not bring up interface(, ignoring|): Network is down$', re.MULTILINE)
1215 for i in range(20):
1216 if i > 0:
1217 time.sleep(0.5)
1218 if log_re.search(read_networkd_log()):
1219 break
1220 else:
1221 self.fail()
1222
1223 copy_network_unit('11-dummy.netdev', '12-dummy.netdev', '21-dummy-bond-slave.network')
1224 networkctl_reload()
1225 self.wait_online(['test1:enslaved', 'dummy98:enslaved', 'bond99:carrier', 'vlan99:routable'])
1226
1f0e3109 1227 def test_macvtap(self):
a962d857 1228 first = True
460feb61 1229 for mode in ['private', 'vepa', 'bridge', 'passthru']:
a962d857
YW
1230 if first:
1231 first = False
1232 else:
1233 self.tearDown()
1234
1235 print(f'### test_macvtap(mode={mode})')
460feb61 1236 with self.subTest(mode=mode):
a962d857
YW
1237 copy_network_unit('21-macvtap.netdev', '26-netdev-link-local-addressing-yes.network',
1238 '11-dummy.netdev', '25-macvtap.network')
1239 with open(os.path.join(network_unit_dir, '21-macvtap.netdev'), mode='a', encoding='utf-8') as f:
460feb61 1240 f.write('[MACVTAP]\nMode=' + mode)
2cf6fdff 1241 start_networkd()
1f0e3109 1242
c918b70a
TY
1243 self.wait_online(['macvtap99:degraded',
1244 'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
460feb61 1245
371810d1 1246 output = check_output('ip -d link show macvtap99')
460feb61
YW
1247 print(output)
1248 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
1f0e3109
SS
1249
1250 def test_macvlan(self):
a962d857 1251 first = True
dff9792b 1252 for mode in ['private', 'vepa', 'bridge', 'passthru']:
a962d857
YW
1253 if first:
1254 first = False
1255 else:
1256 self.tearDown()
1257
1258 print(f'### test_macvlan(mode={mode})')
dff9792b 1259 with self.subTest(mode=mode):
a962d857
YW
1260 copy_network_unit('21-macvlan.netdev', '26-netdev-link-local-addressing-yes.network',
1261 '11-dummy.netdev', '25-macvlan.network')
1262 with open(os.path.join(network_unit_dir, '21-macvlan.netdev'), mode='a', encoding='utf-8') as f:
dff9792b 1263 f.write('[MACVLAN]\nMode=' + mode)
2cf6fdff 1264 start_networkd()
dff9792b 1265
c918b70a
TY
1266 self.wait_online(['macvlan99:degraded',
1267 'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
dff9792b 1268
371810d1 1269 output = check_output('ip -d link show test1')
dff9792b
YW
1270 print(output)
1271 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 1272
371810d1 1273 output = check_output('ip -d link show macvlan99')
dff9792b
YW
1274 print(output)
1275 self.assertRegex(output, ' mtu 2000 ')
1276 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
72b7f1b9 1277
a962d857 1278 remove_link('test1')
1d0c9bd7
YW
1279 time.sleep(1)
1280
a962d857 1281 check_output("ip link add test1 type dummy")
c918b70a
TY
1282 self.wait_online(['macvlan99:degraded',
1283 'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
1d0c9bd7
YW
1284
1285 output = check_output('ip -d link show test1')
1286 print(output)
1287 self.assertRegex(output, ' mtu 2000 ')
1288
1289 output = check_output('ip -d link show macvlan99')
1290 print(output)
1291 self.assertRegex(output, ' mtu 2000 ')
1292 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
1293
7a0a37b2 1294 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109 1295 def test_ipvlan(self):
a962d857 1296 first = True
bc6dff6e 1297 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
a962d857
YW
1298 if first:
1299 first = False
1300 else:
1301 self.tearDown()
1302
1303 print(f'### test_ipvlan(mode={mode}, flag={flag})')
bc6dff6e 1304 with self.subTest(mode=mode, flag=flag):
a962d857
YW
1305 copy_network_unit('25-ipvlan.netdev', '26-netdev-link-local-addressing-yes.network',
1306 '11-dummy.netdev', '25-ipvlan.network')
1307 with open(os.path.join(network_unit_dir, '25-ipvlan.netdev'), mode='a', encoding='utf-8') as f:
bc6dff6e 1308 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
1f0e3109 1309
2cf6fdff 1310 start_networkd()
e2aea43f 1311 self.wait_online(['ipvlan99:degraded', 'test1:degraded'])
bc6dff6e 1312
371810d1 1313 output = check_output('ip -d link show ipvlan99')
bc6dff6e
YW
1314 print(output)
1315 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
1f0e3109 1316
956c8fec
YW
1317 @expectedFailureIfModuleIsNotAvailable('ipvtap')
1318 def test_ipvtap(self):
a962d857 1319 first = True
40921f08 1320 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
a962d857
YW
1321 if first:
1322 first = False
1323 else:
1324 self.tearDown()
1325
1326 print(f'### test_ipvtap(mode={mode}, flag={flag})')
40921f08 1327 with self.subTest(mode=mode, flag=flag):
a962d857
YW
1328 copy_network_unit('25-ipvtap.netdev', '26-netdev-link-local-addressing-yes.network',
1329 '11-dummy.netdev', '25-ipvtap.network')
1330 with open(os.path.join(network_unit_dir, '25-ipvtap.netdev'), mode='a', encoding='utf-8') as f:
40921f08
YW
1331 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
1332
2cf6fdff 1333 start_networkd()
e2aea43f 1334 self.wait_online(['ipvtap99:degraded', 'test1:degraded'])
956c8fec 1335
371810d1 1336 output = check_output('ip -d link show ipvtap99')
40921f08
YW
1337 print(output)
1338 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
956c8fec 1339
1f0e3109 1340 def test_veth(self):
a962d857
YW
1341 copy_network_unit('25-veth.netdev', '26-netdev-link-local-addressing-yes.network',
1342 '25-veth-mtu.netdev')
2cf6fdff 1343 start_networkd()
1f0e3109 1344
0874be35 1345 self.wait_online(['veth99:degraded', 'veth-peer:degraded', 'veth-mtu:degraded', 'veth-mtu-peer:degraded'])
671dacdf 1346
371810d1 1347 output = check_output('ip -d link show veth99')
671dacdf
YW
1348 print(output)
1349 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
371810d1 1350 output = check_output('ip -d link show veth-peer')
671dacdf
YW
1351 print(output)
1352 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
1f0e3109 1353
0874be35
YW
1354 output = check_output('ip -d link show veth-mtu')
1355 print(output)
1356 self.assertRegex(output, 'link/ether 12:34:56:78:9a:be')
1357 self.assertRegex(output, 'mtu 1800')
1358 output = check_output('ip -d link show veth-mtu-peer')
1359 print(output)
1360 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bf')
1361 self.assertRegex(output, 'mtu 1800')
1362
5cdc7c89 1363 def test_tuntap(self):
ae014ecb 1364 copy_network_unit('25-tun.netdev', '25-tap.netdev', '26-netdev-link-local-addressing-yes.network')
2cf6fdff 1365 start_networkd()
1f0e3109 1366
ae014ecb
YW
1367 self.wait_online(['testtun99:degraded', 'testtap99:degraded'])
1368
1369 pid = networkd_pid()
1370 name = psutil.Process(pid).name()[:15]
1371
1372 output = check_output('ip -d tuntap show')
1373 print(output)
1374 self.assertRegex(output, f'(?m)testtap99: tap pi (multi_queue |)vnet_hdr persist filter *(0x100|)\n\tAttached to processes:{name}\({pid}\)systemd\(1\)$')
1375 self.assertRegex(output, f'(?m)testtun99: tun pi (multi_queue |)vnet_hdr persist filter *(0x100|)\n\tAttached to processes:{name}\({pid}\)systemd\(1\)$')
1f0e3109 1376
5cdc7c89 1377 output = check_output('ip -d link show testtun99')
2746d307
YW
1378 print(output)
1379 # Old ip command does not support IFF_ flags
426654d7 1380 self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
ae014ecb 1381 self.assertIn('UP,LOWER_UP', output)
2746d307 1382
5cdc7c89 1383 output = check_output('ip -d link show testtap99')
2746d307 1384 print(output)
426654d7 1385 self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
ae014ecb
YW
1386 self.assertIn('UP,LOWER_UP', output)
1387
1388 remove_network_unit('26-netdev-link-local-addressing-yes.network')
1389
1390 restart_networkd()
1391 self.wait_online(['testtun99:degraded', 'testtap99:degraded'], setup_state='unmanaged')
1392
1393 pid = networkd_pid()
1394 name = psutil.Process(pid).name()[:15]
1395
1396 output = check_output('ip -d tuntap show')
1397 print(output)
1398 self.assertRegex(output, f'(?m)testtap99: tap pi (multi_queue |)vnet_hdr persist filter *(0x100|)\n\tAttached to processes:{name}\({pid}\)systemd\(1\)$')
1399 self.assertRegex(output, f'(?m)testtun99: tun pi (multi_queue |)vnet_hdr persist filter *(0x100|)\n\tAttached to processes:{name}\({pid}\)systemd\(1\)$')
1400
1401 output = check_output('ip -d link show testtun99')
1402 print(output)
1403 self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
1404 self.assertIn('UP,LOWER_UP', output)
1405
1406 output = check_output('ip -d link show testtap99')
1407 print(output)
1408 self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
1409 self.assertIn('UP,LOWER_UP', output)
1410
1411 clear_network_units()
1412 restart_networkd()
1413 self.wait_online(['testtun99:off', 'testtap99:off'], setup_state='unmanaged')
1414
1415 output = check_output('ip -d tuntap show')
1416 print(output)
1417 self.assertRegex(output, f'(?m)testtap99: tap pi (multi_queue |)vnet_hdr persist filter *(0x100|)\n\tAttached to processes:$')
1418 self.assertRegex(output, f'(?m)testtun99: tun pi (multi_queue |)vnet_hdr persist filter *(0x100|)\n\tAttached to processes:$')
1419
1420 for i in range(10):
1421 if i != 0:
1422 time.sleep(1)
1423 output = check_output('ip -d link show testtun99')
1424 print(output)
1425 self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
1426 if 'NO-CARRIER' in output:
1427 break
1428 else:
1429 self.fail()
1430
1431 for i in range(10):
1432 if i != 0:
1433 time.sleep(1)
1434 output = check_output('ip -d link show testtap99')
1435 print(output)
1436 self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
1437 if 'NO-CARRIER' in output:
1438 break
1439 else:
1440 self.fail()
2746d307 1441
7a0a37b2 1442 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109 1443 def test_vrf(self):
a962d857 1444 copy_network_unit('25-vrf.netdev', '26-netdev-link-local-addressing-yes.network')
2cf6fdff 1445 start_networkd()
1f0e3109 1446
e2aea43f 1447 self.wait_online(['vrf99:carrier'])
1f0e3109 1448
7a0a37b2 1449 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109 1450 def test_vcan(self):
a962d857 1451 copy_network_unit('25-vcan.netdev', '26-netdev-link-local-addressing-yes.network')
2cf6fdff 1452 start_networkd()
1f0e3109 1453
e2aea43f 1454 self.wait_online(['vcan99:carrier'])
1f0e3109 1455
f63b14d3
YW
1456 @expectedFailureIfModuleIsNotAvailable('vxcan')
1457 def test_vxcan(self):
a962d857 1458 copy_network_unit('25-vxcan.netdev', '26-netdev-link-local-addressing-yes.network')
2cf6fdff 1459 start_networkd()
f63b14d3 1460
e2aea43f 1461 self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
f63b14d3 1462
7a3bc5a8
EV
1463 @expectedFailureIfModuleIsNotAvailable('wireguard')
1464 def test_wireguard(self):
a962d857
YW
1465 copy_network_unit('25-wireguard.netdev', '25-wireguard.network',
1466 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
1467 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt',
1468 '25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network')
2cf6fdff 1469 start_networkd()
84d32bf5
YW
1470 self.wait_online(['wg99:routable', 'wg98:routable', 'wg97:carrier'])
1471
1472 output = check_output('ip -4 address show dev wg99')
1473 print(output)
1474 self.assertIn('inet 192.168.124.1/24 scope global wg99', output)
5a0bd90b 1475
e4e0b239
YW
1476 output = check_output('ip -4 address show dev wg99')
1477 print(output)
1478 self.assertIn('inet 169.254.11.1/24 scope link wg99', output)
1479
1480 output = check_output('ip -6 address show dev wg99')
1481 print(output)
1482 self.assertIn('inet6 fe80::1/64 scope link', output)
1483
045db4fa
YW
1484 output = check_output('ip -4 address show dev wg98')
1485 print(output)
1486 self.assertIn('inet 192.168.123.123/24 scope global wg98', output)
1487
1488 output = check_output('ip -6 address show dev wg98')
1489 print(output)
1490 self.assertIn('inet6 fd8d:4d6d:3ccb:500::1/64 scope global', output)
1491
6387cac3
YW
1492 output = check_output('ip -4 route show dev wg99 table 1234')
1493 print(output)
1494 self.assertIn('192.168.26.0/24 proto static metric 123', output)
1495
1496 output = check_output('ip -6 route show dev wg99 table 1234')
1497 print(output)
1498 self.assertIn('fd31:bf08:57cb::/48 proto static metric 123 pref medium', output)
1499
1500 output = check_output('ip -6 route show dev wg98 table 1234')
1501 print(output)
1502 self.assertIn('fd8d:4d6d:3ccb:500:c79:2339:edce:ece1 proto static metric 123 pref medium', output)
1503 self.assertIn('fd8d:4d6d:3ccb:500:1dbf:ca8a:32d3:dd81 proto static metric 123 pref medium', output)
1504 self.assertIn('fd8d:4d6d:3ccb:500:1e54:1415:35d0:a47c proto static metric 123 pref medium', output)
1505 self.assertIn('fd8d:4d6d:3ccb:500:270d:b5dd:4a3f:8909 proto static metric 123 pref medium', output)
1506 self.assertIn('fd8d:4d6d:3ccb:500:5660:679d:3532:94d8 proto static metric 123 pref medium', output)
1507 self.assertIn('fd8d:4d6d:3ccb:500:6825:573f:30f3:9472 proto static metric 123 pref medium', output)
1508 self.assertIn('fd8d:4d6d:3ccb:500:6f2e:6888:c6fd:dfb9 proto static metric 123 pref medium', output)
1509 self.assertIn('fd8d:4d6d:3ccb:500:8d4d:bab:7280:a09a proto static metric 123 pref medium', output)
1510 self.assertIn('fd8d:4d6d:3ccb:500:900c:d437:ec27:8822 proto static metric 123 pref medium', output)
1511 self.assertIn('fd8d:4d6d:3ccb:500:9742:9931:5217:18d5 proto static metric 123 pref medium', output)
1512 self.assertIn('fd8d:4d6d:3ccb:500:9c11:d820:2e96:9be0 proto static metric 123 pref medium', output)
1513 self.assertIn('fd8d:4d6d:3ccb:500:a072:80da:de4f:add1 proto static metric 123 pref medium', output)
1514 self.assertIn('fd8d:4d6d:3ccb:500:a3f3:df38:19b0:721 proto static metric 123 pref medium', output)
1515 self.assertIn('fd8d:4d6d:3ccb:500:a94b:cd6a:a32d:90e6 proto static metric 123 pref medium', output)
1516 self.assertIn('fd8d:4d6d:3ccb:500:b39c:9cdc:755a:ead3 proto static metric 123 pref medium', output)
1517 self.assertIn('fd8d:4d6d:3ccb:500:b684:4f81:2e3e:132e proto static metric 123 pref medium', output)
1518 self.assertIn('fd8d:4d6d:3ccb:500:bad5:495d:8e9c:3427 proto static metric 123 pref medium', output)
1519 self.assertIn('fd8d:4d6d:3ccb:500:bfe5:c3c3:5d77:fcb proto static metric 123 pref medium', output)
1520 self.assertIn('fd8d:4d6d:3ccb:500:c624:6bf7:4c09:3b59 proto static metric 123 pref medium', output)
1521 self.assertIn('fd8d:4d6d:3ccb:500:d4f9:5dc:9296:a1a proto static metric 123 pref medium', output)
1522 self.assertIn('fd8d:4d6d:3ccb:500:dcdd:d33b:90c9:6088 proto static metric 123 pref medium', output)
1523 self.assertIn('fd8d:4d6d:3ccb:500:e2e1:ae15:103f:f376 proto static metric 123 pref medium', output)
1524 self.assertIn('fd8d:4d6d:3ccb:500:f349:c4f0:10c1:6b4 proto static metric 123 pref medium', output)
1525 self.assertIn('fd8d:4d6d:3ccb:c79:2339:edce::/96 proto static metric 123 pref medium', output)
1526 self.assertIn('fd8d:4d6d:3ccb:1dbf:ca8a:32d3::/96 proto static metric 123 pref medium', output)
1527 self.assertIn('fd8d:4d6d:3ccb:1e54:1415:35d0::/96 proto static metric 123 pref medium', output)
1528 self.assertIn('fd8d:4d6d:3ccb:270d:b5dd:4a3f::/96 proto static metric 123 pref medium', output)
1529 self.assertIn('fd8d:4d6d:3ccb:5660:679d:3532::/96 proto static metric 123 pref medium', output)
1530 self.assertIn('fd8d:4d6d:3ccb:6825:573f:30f3::/96 proto static metric 123 pref medium', output)
1531 self.assertIn('fd8d:4d6d:3ccb:6f2e:6888:c6fd::/96 proto static metric 123 pref medium', output)
1532 self.assertIn('fd8d:4d6d:3ccb:8d4d:bab:7280::/96 proto static metric 123 pref medium', output)
1533 self.assertIn('fd8d:4d6d:3ccb:900c:d437:ec27::/96 proto static metric 123 pref medium', output)
1534 self.assertIn('fd8d:4d6d:3ccb:9742:9931:5217::/96 proto static metric 123 pref medium', output)
1535 self.assertIn('fd8d:4d6d:3ccb:9c11:d820:2e96::/96 proto static metric 123 pref medium', output)
1536 self.assertIn('fd8d:4d6d:3ccb:a072:80da:de4f::/96 proto static metric 123 pref medium', output)
1537 self.assertIn('fd8d:4d6d:3ccb:a3f3:df38:19b0::/96 proto static metric 123 pref medium', output)
1538 self.assertIn('fd8d:4d6d:3ccb:a94b:cd6a:a32d::/96 proto static metric 123 pref medium', output)
1539 self.assertIn('fd8d:4d6d:3ccb:b39c:9cdc:755a::/96 proto static metric 123 pref medium', output)
1540 self.assertIn('fd8d:4d6d:3ccb:b684:4f81:2e3e::/96 proto static metric 123 pref medium', output)
1541 self.assertIn('fd8d:4d6d:3ccb:bad5:495d:8e9c::/96 proto static metric 123 pref medium', output)
1542 self.assertIn('fd8d:4d6d:3ccb:bfe5:c3c3:5d77::/96 proto static metric 123 pref medium', output)
1543 self.assertIn('fd8d:4d6d:3ccb:c624:6bf7:4c09::/96 proto static metric 123 pref medium', output)
1544 self.assertIn('fd8d:4d6d:3ccb:d4f9:5dc:9296::/96 proto static metric 123 pref medium', output)
1545 self.assertIn('fd8d:4d6d:3ccb:dcdd:d33b:90c9::/96 proto static metric 123 pref medium', output)
1546 self.assertIn('fd8d:4d6d:3ccb:e2e1:ae15:103f::/96 proto static metric 123 pref medium', output)
1547 self.assertIn('fd8d:4d6d:3ccb:f349:c4f0:10c1::/96 proto static metric 123 pref medium', output)
1548
7a3bc5a8 1549 if shutil.which('wg'):
371810d1 1550 call('wg')
5a0bd90b 1551
371810d1 1552 output = check_output('wg show wg99 listen-port')
84d32bf5 1553 self.assertEqual(output, '51820')
371810d1 1554 output = check_output('wg show wg99 fwmark')
84d32bf5
YW
1555 self.assertEqual(output, '0x4d2')
1556 output = check_output('wg show wg99 private-key')
1557 self.assertEqual(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong=')
371810d1 1558 output = check_output('wg show wg99 allowed-ips')
84d32bf5
YW
1559 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t192.168.124.3/32', output)
1560 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\t192.168.124.2/32', output)
1561 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128', output)
1562 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48', output)
371810d1 1563 output = check_output('wg show wg99 persistent-keepalive')
84d32bf5
YW
1564 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\toff', output)
1565 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\toff', output)
1566 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\toff', output)
1567 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20', output)
371810d1 1568 output = check_output('wg show wg99 endpoints')
84d32bf5
YW
1569 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t(none)', output)
1570 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\t(none)', output)
1571 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\t(none)', output)
1572 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820', output)
371810d1 1573 output = check_output('wg show wg99 preshared-keys')
84d32bf5
YW
1574 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t6Fsg8XN0DE6aPQgAX4r2oazEYJOGqyHUz3QRH/jCB+I=', output)
1575 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\tit7nd33chCT/tKT2ZZWfYyp43Zs+6oif72hexnSNMqA=', output)
1576 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tcPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=', output)
1577 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\tIIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=', output)
7a3bc5a8 1578
371810d1 1579 output = check_output('wg show wg98 private-key')
84d32bf5 1580 self.assertEqual(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr+WHtZLZ90FU=')
da44fb8a 1581
da3509f0 1582 output = check_output('wg show wg97 listen-port')
84d32bf5 1583 self.assertEqual(output, '51821')
da3509f0 1584 output = check_output('wg show wg97 fwmark')
84d32bf5 1585 self.assertEqual(output, '0x4d3')
da3509f0 1586
1f0e3109 1587 def test_geneve(self):
a962d857 1588 copy_network_unit('25-geneve.netdev', '26-netdev-link-local-addressing-yes.network')
2cf6fdff 1589 start_networkd()
1f0e3109 1590
e2aea43f 1591 self.wait_online(['geneve99:degraded'])
1f0e3109 1592
371810d1 1593 output = check_output('ip -d link show geneve99')
14ecd604 1594 print(output)
06895a1d
YW
1595 self.assertRegex(output, '192.168.22.1')
1596 self.assertRegex(output, '6082')
1597 self.assertRegex(output, 'udpcsum')
1598 self.assertRegex(output, 'udp6zerocsumrx')
1f0e3109
SS
1599
1600 def test_ipip_tunnel(self):
a962d857
YW
1601 copy_network_unit('12-dummy.netdev', '25-ipip.network',
1602 '25-ipip-tunnel.netdev', '25-tunnel.network',
1603 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1604 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1605 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1606 start_networkd()
e2aea43f 1607 self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
6a97a864 1608
371810d1 1609 output = check_output('ip -d link show ipiptun99')
6a97a864 1610 print(output)
426654d7 1611 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
371810d1 1612 output = check_output('ip -d link show ipiptun98')
6a97a864 1613 print(output)
426654d7 1614 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
371810d1 1615 output = check_output('ip -d link show ipiptun97')
6a97a864 1616 print(output)
426654d7 1617 self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
42a29fcb
YW
1618 output = check_output('ip -d link show ipiptun96')
1619 print(output)
426654d7 1620 self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
1f0e3109
SS
1621
1622 def test_gre_tunnel(self):
a962d857
YW
1623 copy_network_unit('12-dummy.netdev', '25-gretun.network',
1624 '25-gre-tunnel.netdev', '25-tunnel.network',
1625 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1626 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1627 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1628 start_networkd()
e2aea43f 1629 self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
6a97a864 1630
371810d1 1631 output = check_output('ip -d link show gretun99')
6a97a864
YW
1632 print(output)
1633 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
1634 self.assertRegex(output, 'ikey 1.2.3.103')
1635 self.assertRegex(output, 'okey 1.2.4.103')
1636 self.assertRegex(output, 'iseq')
1637 self.assertRegex(output, 'oseq')
371810d1 1638 output = check_output('ip -d link show gretun98')
6a97a864
YW
1639 print(output)
1640 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
1641 self.assertRegex(output, 'ikey 0.0.0.104')
1642 self.assertRegex(output, 'okey 0.0.0.104')
1643 self.assertNotRegex(output, 'iseq')
1644 self.assertNotRegex(output, 'oseq')
371810d1 1645 output = check_output('ip -d link show gretun97')
6a97a864
YW
1646 print(output)
1647 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
38f4bb44
YW
1648 self.assertRegex(output, 'ikey 0.0.0.105')
1649 self.assertRegex(output, 'okey 0.0.0.105')
1650 self.assertNotRegex(output, 'iseq')
1651 self.assertNotRegex(output, 'oseq')
42a29fcb
YW
1652 output = check_output('ip -d link show gretun96')
1653 print(output)
1654 self.assertRegex(output, 'gre remote any local any dev dummy98')
1655 self.assertRegex(output, 'ikey 0.0.0.106')
1656 self.assertRegex(output, 'okey 0.0.0.106')
1657 self.assertNotRegex(output, 'iseq')
1658 self.assertNotRegex(output, 'oseq')
6a97a864
YW
1659
1660 def test_ip6gre_tunnel(self):
a962d857
YW
1661 copy_network_unit('12-dummy.netdev', '25-ip6gretun.network',
1662 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1663 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1664 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1665 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1666 start_networkd()
6a97a864 1667
17bcf0a0
YW
1668 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1669
a962d857 1670 self.wait_links('dummy98', 'ip6gretun99', 'ip6gretun98', 'ip6gretun97', 'ip6gretun96')
6a97a864 1671
371810d1 1672 output = check_output('ip -d link show ip6gretun99')
6a97a864
YW
1673 print(output)
1674 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1675 output = check_output('ip -d link show ip6gretun98')
6a97a864
YW
1676 print(output)
1677 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
371810d1 1678 output = check_output('ip -d link show ip6gretun97')
6a97a864
YW
1679 print(output)
1680 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
42a29fcb
YW
1681 output = check_output('ip -d link show ip6gretun96')
1682 print(output)
1683 self.assertRegex(output, 'ip6gre remote any local any dev dummy98')
1f0e3109 1684
11309591 1685 def test_gretap_tunnel(self):
a962d857
YW
1686 copy_network_unit('12-dummy.netdev', '25-gretap.network',
1687 '25-gretap-tunnel.netdev', '25-tunnel.network',
1688 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1689 start_networkd()
e2aea43f 1690 self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
6a97a864 1691
371810d1 1692 output = check_output('ip -d link show gretap99')
6a97a864
YW
1693 print(output)
1694 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
1695 self.assertRegex(output, 'ikey 0.0.0.106')
1696 self.assertRegex(output, 'okey 0.0.0.106')
1697 self.assertRegex(output, 'iseq')
1698 self.assertRegex(output, 'oseq')
371810d1 1699 output = check_output('ip -d link show gretap98')
6a97a864
YW
1700 print(output)
1701 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
1702 self.assertRegex(output, 'ikey 0.0.0.107')
1703 self.assertRegex(output, 'okey 0.0.0.107')
1704 self.assertRegex(output, 'iseq')
1705 self.assertRegex(output, 'oseq')
1f0e3109
SS
1706
1707 def test_ip6gretap_tunnel(self):
a962d857
YW
1708 copy_network_unit('12-dummy.netdev', '25-ip6gretap.network',
1709 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1710 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1711 start_networkd()
e2aea43f 1712 self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
6a97a864 1713
371810d1 1714 output = check_output('ip -d link show ip6gretap99')
6a97a864
YW
1715 print(output)
1716 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1717 output = check_output('ip -d link show ip6gretap98')
6a97a864
YW
1718 print(output)
1719 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1f0e3109
SS
1720
1721 def test_vti_tunnel(self):
a962d857
YW
1722 copy_network_unit('12-dummy.netdev', '25-vti.network',
1723 '25-vti-tunnel.netdev', '25-tunnel.network',
1724 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1725 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1726 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1727 start_networkd()
e2aea43f 1728 self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
6a97a864 1729
371810d1 1730 output = check_output('ip -d link show vtitun99')
6a97a864
YW
1731 print(output)
1732 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
371810d1 1733 output = check_output('ip -d link show vtitun98')
6a97a864
YW
1734 print(output)
1735 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
371810d1 1736 output = check_output('ip -d link show vtitun97')
6a97a864
YW
1737 print(output)
1738 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
42a29fcb
YW
1739 output = check_output('ip -d link show vtitun96')
1740 print(output)
1741 self.assertRegex(output, 'vti remote any local any dev dummy98')
1f0e3109
SS
1742
1743 def test_vti6_tunnel(self):
a962d857
YW
1744 copy_network_unit('12-dummy.netdev', '25-vti6.network',
1745 '25-vti6-tunnel.netdev', '25-tunnel.network',
1746 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1747 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
2cf6fdff 1748 start_networkd()
e2aea43f 1749 self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
6a97a864 1750
371810d1 1751 output = check_output('ip -d link show vti6tun99')
6a97a864
YW
1752 print(output)
1753 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1754 output = check_output('ip -d link show vti6tun98')
6a97a864 1755 print(output)
426654d7 1756 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1757 output = check_output('ip -d link show vti6tun97')
6a97a864 1758 print(output)
426654d7 1759 self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
1760
1761 def test_ip6tnl_tunnel(self):
a962d857
YW
1762 copy_network_unit('12-dummy.netdev', '25-ip6tnl.network',
1763 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1764 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1765 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1766 '25-veth.netdev', '25-ip6tnl-slaac.network', '25-ipv6-prefix.network',
1767 '25-ip6tnl-tunnel-local-slaac.netdev', '25-ip6tnl-tunnel-local-slaac.network',
1768 '25-ip6tnl-tunnel-external.netdev', '26-netdev-link-local-addressing-yes.network')
2cf6fdff 1769 start_networkd()
7809cab7
YW
1770 self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable',
1771 'ip6tnl-slaac:degraded', 'ip6tnl-external:degraded',
da7d6848 1772 'dummy98:degraded', 'veth99:routable', 'veth-peer:degraded'])
6a97a864 1773
371810d1 1774 output = check_output('ip -d link show ip6tnl99')
6a97a864 1775 print(output)
da7d6848 1776 self.assertIn('ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98', output)
371810d1 1777 output = check_output('ip -d link show ip6tnl98')
6a97a864 1778 print(output)
426654d7 1779 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1780 output = check_output('ip -d link show ip6tnl97')
6a97a864 1781 print(output)
426654d7 1782 self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
7809cab7
YW
1783 output = check_output('ip -d link show ip6tnl-external')
1784 print(output)
1785 self.assertIn('ip6tnl-external@NONE:', output)
1786 self.assertIn('ip6tnl external ', output)
da7d6848
YW
1787 output = check_output('ip -d link show ip6tnl-slaac')
1788 print(output)
1789 self.assertIn('ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2002:da8:1:0:1034:56ff:fe78:9abc dev veth99', output)
1790
1791 output = check_output('ip -6 address show veth99')
1792 print(output)
1793 self.assertIn('inet6 2002:da8:1:0:1034:56ff:fe78:9abc/64 scope global dynamic', output)
1794
1795 output = check_output('ip -4 route show default')
1796 print(output)
1797 self.assertIn('default dev ip6tnl-slaac proto static', output)
1f0e3109
SS
1798
1799 def test_sit_tunnel(self):
a962d857
YW
1800 copy_network_unit('12-dummy.netdev', '25-sit.network',
1801 '25-sit-tunnel.netdev', '25-tunnel.network',
1802 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1803 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1804 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1805 start_networkd()
e2aea43f 1806 self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
6a97a864 1807
371810d1 1808 output = check_output('ip -d link show sittun99')
6a97a864 1809 print(output)
426654d7 1810 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
371810d1 1811 output = check_output('ip -d link show sittun98')
6a97a864 1812 print(output)
426654d7 1813 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
371810d1 1814 output = check_output('ip -d link show sittun97')
6a97a864 1815 print(output)
426654d7 1816 self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
42a29fcb
YW
1817 output = check_output('ip -d link show sittun96')
1818 print(output)
426654d7 1819 self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
1f0e3109 1820
d0e728b6 1821 def test_isatap_tunnel(self):
a962d857
YW
1822 copy_network_unit('12-dummy.netdev', '25-isatap.network',
1823 '25-isatap-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1824 start_networkd()
e2aea43f 1825 self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
d0e728b6 1826
371810d1 1827 output = check_output('ip -d link show isataptun99')
14ecd604 1828 print(output)
d0e728b6
SS
1829 self.assertRegex(output, "isatap ")
1830
d29dc4f1 1831 def test_6rd_tunnel(self):
a962d857
YW
1832 copy_network_unit('12-dummy.netdev', '25-6rd.network',
1833 '25-6rd-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1834 start_networkd()
e2aea43f 1835 self.wait_online(['sittun99:routable', 'dummy98:degraded'])
d29dc4f1 1836
371810d1 1837 output = check_output('ip -d link show sittun99')
6a97a864
YW
1838 print(output)
1839 self.assertRegex(output, '6rd-prefix 2602::/24')
1840
2f0260c1
YW
1841 @expectedFailureIfERSPANv0IsNotSupported()
1842 def test_erspan_tunnel_v0(self):
a962d857
YW
1843 copy_network_unit('12-dummy.netdev', '25-erspan.network',
1844 '25-erspan0-tunnel.netdev', '25-tunnel.network',
1845 '25-erspan0-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1846 start_networkd()
e2aea43f 1847 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
2266864b 1848
371810d1 1849 output = check_output('ip -d link show erspan99')
6a97a864 1850 print(output)
2f0260c1
YW
1851 self.assertIn('erspan remote 172.16.1.100 local 172.16.1.200', output)
1852 self.assertIn('erspan_ver 0', output)
1853 self.assertNotIn('erspan_index 123', output)
1854 self.assertNotIn('erspan_dir ingress', output)
1855 self.assertNotIn('erspan_hwid 1f', output)
1856 self.assertIn('ikey 0.0.0.101', output)
1857 self.assertIn('iseq', output)
371810d1 1858 output = check_output('ip -d link show erspan98')
2266864b 1859 print(output)
2f0260c1
YW
1860 self.assertIn('erspan remote 172.16.1.100 local any', output)
1861 self.assertIn('erspan_ver 0', output)
1862 self.assertNotIn('erspan_index 124', output)
1863 self.assertNotIn('erspan_dir egress', output)
1864 self.assertNotIn('erspan_hwid 2f', output)
1865 self.assertIn('ikey 0.0.0.102', output)
1866 self.assertIn('iseq', output)
1867
1868 def test_erspan_tunnel_v1(self):
a962d857
YW
1869 copy_network_unit('12-dummy.netdev', '25-erspan.network',
1870 '25-erspan1-tunnel.netdev', '25-tunnel.network',
1871 '25-erspan1-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2f0260c1
YW
1872 start_networkd()
1873 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
1874
1875 output = check_output('ip -d link show erspan99')
1876 print(output)
1877 self.assertIn('erspan remote 172.16.1.100 local 172.16.1.200', output)
1878 self.assertIn('erspan_ver 1', output)
1879 self.assertIn('erspan_index 123', output)
1880 self.assertNotIn('erspan_dir ingress', output)
1881 self.assertNotIn('erspan_hwid 1f', output)
1882 self.assertIn('ikey 0.0.0.101', output)
1883 self.assertIn('okey 0.0.0.101', output)
1884 self.assertIn('iseq', output)
1885 self.assertIn('oseq', output)
1886 output = check_output('ip -d link show erspan98')
1887 print(output)
1888 self.assertIn('erspan remote 172.16.1.100 local any', output)
1889 self.assertIn('erspan_ver 1', output)
1890 self.assertIn('erspan_index 124', output)
1891 self.assertNotIn('erspan_dir egress', output)
1892 self.assertNotIn('erspan_hwid 2f', output)
1893 self.assertIn('ikey 0.0.0.102', output)
1894 self.assertIn('okey 0.0.0.102', output)
1895 self.assertIn('iseq', output)
1896 self.assertIn('oseq', output)
1897
1898 @expectedFailureIfERSPANv2IsNotSupported()
1899 def test_erspan_tunnel_v2(self):
a962d857
YW
1900 copy_network_unit('12-dummy.netdev', '25-erspan.network',
1901 '25-erspan2-tunnel.netdev', '25-tunnel.network',
1902 '25-erspan2-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2f0260c1
YW
1903 start_networkd()
1904 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
1905
1906 output = check_output('ip -d link show erspan99')
1907 print(output)
1908 self.assertIn('erspan remote 172.16.1.100 local 172.16.1.200', output)
1909 self.assertIn('erspan_ver 2', output)
1910 self.assertNotIn('erspan_index 123', output)
1911 self.assertIn('erspan_dir ingress', output)
1912 self.assertIn('erspan_hwid 0x1f', output)
1913 self.assertIn('ikey 0.0.0.101', output)
1914 self.assertIn('okey 0.0.0.101', output)
1915 self.assertIn('iseq', output)
1916 self.assertIn('oseq', output)
1917 output = check_output('ip -d link show erspan98')
1918 print(output)
1919 self.assertIn('erspan remote 172.16.1.100 local any', output)
1920 self.assertIn('erspan_ver 2', output)
1921 self.assertNotIn('erspan_index 124', output)
1922 self.assertIn('erspan_dir egress', output)
1923 self.assertIn('erspan_hwid 0x2f', output)
1924 self.assertIn('ikey 0.0.0.102', output)
1925 self.assertIn('okey 0.0.0.102', output)
1926 self.assertIn('iseq', output)
1927 self.assertIn('oseq', output)
2266864b 1928
1f0e3109 1929 def test_tunnel_independent(self):
a962d857 1930 copy_network_unit('25-ipip-tunnel-independent.netdev', '26-netdev-link-local-addressing-yes.network')
2cf6fdff 1931 start_networkd()
e40a58b5 1932
e2aea43f 1933 self.wait_online(['ipiptun99:carrier'])
1f0e3109 1934
95082dbe 1935 def test_tunnel_independent_loopback(self):
a962d857 1936 copy_network_unit('25-ipip-tunnel-independent-loopback.netdev', '26-netdev-link-local-addressing-yes.network')
95082dbe
YW
1937 start_networkd()
1938
e2aea43f 1939 self.wait_online(['ipiptun99:carrier'])
95082dbe 1940
e64dc406
YW
1941 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1942 def test_xfrm(self):
a962d857
YW
1943 copy_network_unit('12-dummy.netdev', '25-xfrm.network',
1944 '25-xfrm.netdev', '25-xfrm-independent.netdev',
1945 '26-netdev-link-local-addressing-yes.network')
e64dc406
YW
1946 start_networkd()
1947
020483b2 1948 self.wait_online(['dummy98:degraded', 'xfrm98:degraded', 'xfrm99:degraded'])
e64dc406 1949
020483b2 1950 output = check_output('ip -d link show dev xfrm98')
e64dc406 1951 print(output)
020483b2
YW
1952 self.assertIn('xfrm98@dummy98:', output)
1953 self.assertIn('xfrm if_id 0x98 ', output)
e64dc406 1954
020483b2
YW
1955 output = check_output('ip -d link show dev xfrm99')
1956 print(output)
1957 self.assertIn('xfrm99@lo:', output)
1958 self.assertIn('xfrm if_id 0x99 ', output)
e64dc406 1959
4b6a6d1e
YW
1960 @expectedFailureIfModuleIsNotAvailable('fou')
1961 def test_fou(self):
1962 # The following redundant check is necessary for CentOS CI.
1963 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1964 self.assertTrue(is_module_available('fou'))
1965
a962d857
YW
1966 copy_network_unit('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1967 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1968 '25-fou-gre.netdev', '25-fou-gretap.netdev')
2cf6fdff 1969 start_networkd()
4b6a6d1e 1970
e2aea43f 1971 self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged')
4b6a6d1e 1972
371810d1 1973 output = check_output('ip fou show')
4b6a6d1e
YW
1974 print(output)
1975 self.assertRegex(output, 'port 55555 ipproto 4')
1976 self.assertRegex(output, 'port 55556 ipproto 47')
1977
371810d1 1978 output = check_output('ip -d link show ipiptun96')
4b6a6d1e
YW
1979 print(output)
1980 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1981 output = check_output('ip -d link show sittun96')
4b6a6d1e
YW
1982 print(output)
1983 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1984 output = check_output('ip -d link show gretun96')
4b6a6d1e
YW
1985 print(output)
1986 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
371810d1 1987 output = check_output('ip -d link show gretap96')
4b6a6d1e
YW
1988 print(output)
1989 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1990
1f0e3109 1991 def test_vxlan(self):
a962d857
YW
1992 copy_network_unit('11-dummy.netdev', '25-vxlan-test1.network',
1993 '25-vxlan.netdev', '25-vxlan.network',
1994 '25-vxlan-ipv6.netdev', '25-vxlan-ipv6.network',
1995 '25-vxlan-independent.netdev', '26-netdev-link-local-addressing-yes.network',
1996 '25-veth.netdev', '25-vxlan-veth99.network', '25-ipv6-prefix.network',
1997 '25-vxlan-local-slaac.netdev', '25-vxlan-local-slaac.network')
2cf6fdff 1998 start_networkd()
1f0e3109 1999
49ad8da7
YW
2000 self.wait_online(['test1:degraded', 'veth99:routable', 'veth-peer:degraded',
2001 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded', 'vxlan-slaac:degraded'])
1f0e3109 2002
371810d1 2003 output = check_output('ip -d link show vxlan99')
14ecd604 2004 print(output)
cca07d91
YW
2005 self.assertIn('999', output)
2006 self.assertIn('5555', output)
2007 self.assertIn('l2miss', output)
2008 self.assertIn('l3miss', output)
2009 self.assertIn('udpcsum', output)
2010 self.assertIn('udp6zerocsumtx', output)
2011 self.assertIn('udp6zerocsumrx', output)
2012 self.assertIn('remcsumtx', output)
2013 self.assertIn('remcsumrx', output)
2014 self.assertIn('gbp', output)
1f0e3109 2015
371810d1 2016 output = check_output('bridge fdb show dev vxlan99')
1c862fe0 2017 print(output)
cca07d91
YW
2018 self.assertIn('00:11:22:33:44:55 dst 10.0.0.5 self permanent', output)
2019 self.assertIn('00:11:22:33:44:66 dst 10.0.0.6 self permanent', output)
2020 self.assertIn('00:11:22:33:44:77 dst 10.0.0.7 via test1 self permanent', output)
1c862fe0 2021
fc79e6ff 2022 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'vxlan99', env=env)
36bc2ffb 2023 print(output)
cca07d91
YW
2024 self.assertIn('VNI: 999', output)
2025 self.assertIn('Destination Port: 5555', output)
2026 self.assertIn('Underlying Device: test1', output)
2027
2028 output = check_output('bridge fdb show dev vxlan97')
2029 print(output)
2030 self.assertIn('00:00:00:00:00:00 dst fe80::23b:d2ff:fe95:967f via test1 self permanent', output)
2031 self.assertIn('00:00:00:00:00:00 dst fe80::27c:16ff:fec0:6c74 via test1 self permanent', output)
2032 self.assertIn('00:00:00:00:00:00 dst fe80::2a2:e4ff:fef9:2269 via test1 self permanent', output)
36bc2ffb 2033
49ad8da7
YW
2034 output = check_output('ip -d link show vxlan-slaac')
2035 print(output)
2036 self.assertIn('vxlan id 4831584 local 2002:da8:1:0:1034:56ff:fe78:9abc dev veth99', output)
2037
2038 output = check_output('ip -6 address show veth99')
2039 print(output)
2040 self.assertIn('inet6 2002:da8:1:0:1034:56ff:fe78:9abc/64 scope global dynamic', output)
2041
e2bf0a72 2042 @unittest.skip(reason="Causes kernel panic on recent kernels: https://bugzilla.kernel.org/show_bug.cgi?id=208315")
02849d8b 2043 def test_macsec(self):
a962d857
YW
2044 copy_network_unit('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
2045 '26-macsec.network', '12-dummy.netdev')
2cf6fdff 2046 start_networkd()
02849d8b 2047
e2aea43f 2048 self.wait_online(['dummy98:degraded', 'macsec99:routable'])
02849d8b 2049
371810d1 2050 output = check_output('ip -d link show macsec99')
02849d8b
YW
2051 print(output)
2052 self.assertRegex(output, 'macsec99@dummy98')
2053 self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
2054 self.assertRegex(output, 'encrypt on')
2055
371810d1 2056 output = check_output('ip macsec show macsec99')
02849d8b
YW
2057 print(output)
2058 self.assertRegex(output, 'encrypt on')
2059 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
2060 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
2061 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
2062 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on')
2063 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
2064 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
2065 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
2066 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
2067 self.assertNotRegex(output, 'key 02030405067080900000000000000000')
2068 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
2069 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
2070
811f33d0 2071 def test_nlmon(self):
a962d857 2072 copy_network_unit('25-nlmon.netdev', '26-netdev-link-local-addressing-yes.network')
2cf6fdff 2073 start_networkd()
811f33d0 2074
e2aea43f 2075 self.wait_online(['nlmon99:carrier'])
02849d8b 2076
b076d5d7
YW
2077 @expectedFailureIfModuleIsNotAvailable('ifb')
2078 def test_ifb(self):
a962d857 2079 copy_network_unit('25-ifb.netdev', '26-netdev-link-local-addressing-yes.network')
b076d5d7
YW
2080 start_networkd()
2081
2082 self.wait_online(['ifb99:degraded'])
2083
cff83db9
YW
2084class NetworkdL2TPTests(unittest.TestCase, Utilities):
2085
cff83db9 2086 def setUp(self):
a962d857 2087 setup_common()
cff83db9
YW
2088
2089 def tearDown(self):
a962d857 2090 tear_down_common()
cff83db9 2091
59edcf2b 2092 @expectedFailureIfModuleIsNotAvailable('l2tp_eth', 'l2tp_netlink')
cff83db9 2093 def test_l2tp_udp(self):
a962d857
YW
2094 copy_network_unit('11-dummy.netdev', '25-l2tp-dummy.network',
2095 '25-l2tp-udp.netdev', '25-l2tp.network')
2cf6fdff 2096 start_networkd()
cff83db9 2097
e2aea43f 2098 self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
cff83db9 2099
371810d1 2100 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
2101 print(output)
2102 self.assertRegex(output, "Tunnel 10, encap UDP")
2103 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
2104 self.assertRegex(output, "Peer tunnel 11")
2105 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
2106 self.assertRegex(output, "UDP checksum: enabled")
2107
371810d1 2108 output = check_output('ip l2tp show session tid 10 session_id 15')
cff83db9
YW
2109 print(output)
2110 self.assertRegex(output, "Session 15 in tunnel 10")
2111 self.assertRegex(output, "Peer session 16, tunnel 11")
2112 self.assertRegex(output, "interface name: l2tp-ses1")
2113
371810d1 2114 output = check_output('ip l2tp show session tid 10 session_id 17')
cff83db9
YW
2115 print(output)
2116 self.assertRegex(output, "Session 17 in tunnel 10")
2117 self.assertRegex(output, "Peer session 18, tunnel 11")
2118 self.assertRegex(output, "interface name: l2tp-ses2")
2119
59edcf2b 2120 @expectedFailureIfModuleIsNotAvailable('l2tp_eth', 'l2tp_ip', 'l2tp_netlink')
cff83db9 2121 def test_l2tp_ip(self):
a962d857
YW
2122 copy_network_unit('11-dummy.netdev', '25-l2tp-dummy.network',
2123 '25-l2tp-ip.netdev', '25-l2tp.network')
2cf6fdff 2124 start_networkd()
cff83db9 2125
e2aea43f 2126 self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
cff83db9 2127
371810d1 2128 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
2129 print(output)
2130 self.assertRegex(output, "Tunnel 10, encap IP")
2131 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
2132 self.assertRegex(output, "Peer tunnel 12")
2133
371810d1 2134 output = check_output('ip l2tp show session tid 10 session_id 25')
cff83db9
YW
2135 print(output)
2136 self.assertRegex(output, "Session 25 in tunnel 10")
2137 self.assertRegex(output, "Peer session 26, tunnel 12")
2138 self.assertRegex(output, "interface name: l2tp-ses3")
2139
371810d1 2140 output = check_output('ip l2tp show session tid 10 session_id 27')
cff83db9
YW
2141 print(output)
2142 self.assertRegex(output, "Session 27 in tunnel 10")
2143 self.assertRegex(output, "Peer session 28, tunnel 12")
2144 self.assertRegex(output, "interface name: l2tp-ses4")
2145
be68c2c9 2146class NetworkdNetworkTests(unittest.TestCase, Utilities):
95c74b0a 2147
1f0e3109 2148 def setUp(self):
a962d857 2149 setup_common()
1f0e3109
SS
2150
2151 def tearDown(self):
a962d857 2152 tear_down_common()
1f0e3109 2153
b8102725 2154 def test_address_static(self):
6dcc087c 2155 # test for #22515. The address will be removed and replaced with /64 prefix.
a962d857
YW
2156 check_output('ip link add dummy98 type dummy')
2157 check_output('ip link set dev dummy98 up')
2158 check_output('ip -6 address add 2001:db8:0:f101::15/128 dev dummy98')
6dcc087c 2159 self.wait_address('dummy98', '2001:db8:0:f101::15/128', ipv='-6')
a962d857 2160 check_output('ip -4 address add 10.3.2.3/16 brd 10.3.255.250 scope global label dummy98:hoge dev dummy98')
6dcc087c
YW
2161 self.wait_address('dummy98', '10.3.2.3/16 brd 10.3.255.250', ipv='-4')
2162
a962d857 2163 copy_network_unit('25-address-static.network', '12-dummy.netdev')
2cf6fdff 2164 start_networkd()
b8102725 2165
e2aea43f 2166 self.wait_online(['dummy98:routable'])
b8102725 2167
371810d1 2168 output = check_output('ip -4 address show dev dummy98')
b8102725 2169 print(output)
4a704501
YW
2170 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
2171 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
2172 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
2173 self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output)
045db4fa 2174 self.assertIn('inet 10.8.8.1/16 scope global dummy98', output)
1ac845ff
YW
2175 self.assertIn('inet 10.8.8.2/16 brd 10.8.8.128 scope global secondary dummy98', output)
2176 self.assertRegex(output, 'inet 10.9.0.1/16 (metric 128 |)brd 10.9.255.255 scope global dummy98')
b8102725 2177
766f8f38 2178 # test for ENOBUFS issue #17012
a962d857 2179 for i in range(1, 254):
4a704501 2180 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
766f8f38 2181
b8102725 2182 # invalid sections
4a704501
YW
2183 self.assertNotIn('10.10.0.1/16', output)
2184 self.assertNotIn('10.10.0.2/16', output)
b8102725 2185
371810d1 2186 output = check_output('ip -4 address show dev dummy98 label 32')
4a704501 2187 self.assertIn('inet 10.3.2.3/16 brd 10.3.255.255 scope global 32', output)
b8102725 2188
371810d1 2189 output = check_output('ip -4 address show dev dummy98 label 33')
4a704501 2190 self.assertIn('inet 10.4.2.3 peer 10.4.2.4/16 scope global 33', output)
b8102725 2191
371810d1 2192 output = check_output('ip -4 address show dev dummy98 label 34')
4a704501 2193 self.assertRegex(output, r'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
b8102725 2194
371810d1 2195 output = check_output('ip -4 address show dev dummy98 label 35')
4a704501 2196 self.assertRegex(output, r'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
b8102725 2197
1ac845ff
YW
2198 output = check_output('ip -4 route show dev dummy98')
2199 print(output)
2200 self.assertIn('10.9.0.0/16 proto kernel scope link src 10.9.0.1 metric 128', output)
2201
371810d1 2202 output = check_output('ip -6 address show dev dummy98')
b8102725 2203 print(output)
4a704501
YW
2204 self.assertIn('inet6 2001:db8:0:f101::15/64 scope global', output)
2205 self.assertIn('inet6 2001:db8:0:f101::16/64 scope global', output)
2206 self.assertIn('inet6 2001:db8:0:f102::15/64 scope global', output)
2207 self.assertIn('inet6 2001:db8:0:f102::16/64 scope global', output)
2208 self.assertIn('inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global', output)
2209 self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output)
2210 self.assertRegex(output, r'inet6 fd[0-9a-f:]*1/64 scope global')
b8102725 2211
40971657
YW
2212 # Tests for #20891.
2213 # 1. set preferred lifetime forever to drop the deprecated flag for testing #20891.
a962d857
YW
2214 check_output('ip address change 10.7.8.9/16 dev dummy98 preferred_lft forever')
2215 check_output('ip address change 2001:db8:1:f101::1/64 dev dummy98 preferred_lft forever')
40971657
YW
2216 output = check_output('ip -4 address show dev dummy98')
2217 print(output)
2218 self.assertNotIn('deprecated', output)
2219 output = check_output('ip -6 address show dev dummy98')
2220 print(output)
2221 self.assertNotIn('deprecated', output)
2222
5b47f35d 2223 # 2. reconfigure the interface.
a962d857 2224 networkctl_reconfigure('dummy98')
766f8f38
YW
2225 self.wait_online(['dummy98:routable'])
2226
40971657
YW
2227 # 3. check the deprecated flag is set for the address configured with PreferredLifetime=0
2228 output = check_output('ip -4 address show dev dummy98')
2229 print(output)
2230 self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output)
2231 output = check_output('ip -6 address show dev dummy98')
2232 print(output)
2233 self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output)
2234
766f8f38
YW
2235 # test for ENOBUFS issue #17012
2236 output = check_output('ip -4 address show dev dummy98')
a962d857 2237 for i in range(1, 254):
4a704501 2238 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
e4783b54 2239
146726b2
YW
2240 # TODO: check json string
2241 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
2242
44924431
YW
2243 def test_address_ipv4acd(self):
2244 check_output('ip netns add ns99')
2245 check_output('ip link add veth99 type veth peer veth-peer')
2246 check_output('ip link set veth-peer netns ns99')
2247 check_output('ip link set veth99 up')
2248 check_output('ip netns exec ns99 ip link set veth-peer up')
2249 check_output('ip netns exec ns99 ip address add 192.168.100.10/24 dev veth-peer')
2250
a962d857 2251 copy_network_unit('25-address-ipv4acd-veth99.network', copy_dropins=False)
dc7d3c5f 2252 start_networkd()
44924431 2253 self.wait_online(['veth99:routable'])
dc7d3c5f
YW
2254
2255 output = check_output('ip -4 address show dev veth99')
2256 print(output)
44924431
YW
2257 self.assertNotIn('192.168.100.10/24', output)
2258 self.assertIn('192.168.100.11/24', output)
dc7d3c5f 2259
a962d857
YW
2260 copy_network_unit('25-address-ipv4acd-veth99.network.d/conflict-address.conf')
2261 networkctl_reload()
37611ccb 2262 self.wait_operstate('veth99', operstate='routable', setup_state='configuring', setup_timeout=10)
44924431
YW
2263
2264 output = check_output('ip -4 address show dev veth99')
dc7d3c5f 2265 print(output)
44924431
YW
2266 self.assertNotIn('192.168.100.10/24', output)
2267 self.assertIn('192.168.100.11/24', output)
dc7d3c5f 2268
21266e60
YW
2269 def test_address_peer_ipv4(self):
2270 # test for issue #17304
a962d857 2271 copy_network_unit('25-address-peer-ipv4.network', '12-dummy.netdev')
21266e60
YW
2272
2273 for trial in range(2):
2274 if trial == 0:
2275 start_networkd()
2276 else:
2277 restart_networkd()
2278
2279 self.wait_online(['dummy98:routable'])
2280
2281 output = check_output('ip -4 address show dev dummy98')
2282 self.assertIn('inet 100.64.0.1 peer 100.64.0.2/32 scope global', output)
2283
c9d223e8
YW
2284 @expectedFailureIfModuleIsNotAvailable('vrf')
2285 def test_prefix_route(self):
a962d857
YW
2286 copy_network_unit('25-prefix-route-with-vrf.network', '12-dummy.netdev',
2287 '25-prefix-route-without-vrf.network', '11-dummy.netdev',
2288 '25-vrf.netdev', '25-vrf.network')
c9d223e8
YW
2289 for trial in range(2):
2290 if trial == 0:
2291 start_networkd()
2292 else:
a962d857 2293 restart_networkd()
c9d223e8
YW
2294
2295 self.wait_online(['dummy98:routable', 'test1:routable', 'vrf99:carrier'])
2296
2297 output = check_output('ip route show table 42 dev dummy98')
2298 print('### ip route show table 42 dev dummy98')
2299 print(output)
2300 self.assertRegex(output, 'local 10.20.22.1 proto kernel scope host src 10.20.22.1')
c9d223e8
YW
2301 self.assertRegex(output, '10.20.33.0/24 proto kernel scope link src 10.20.33.1')
2302 self.assertRegex(output, 'local 10.20.33.1 proto kernel scope host src 10.20.33.1')
2303 self.assertRegex(output, 'broadcast 10.20.33.255 proto kernel scope link src 10.20.33.1')
2304 self.assertRegex(output, 'local 10.20.44.1 proto kernel scope host src 10.20.44.1')
c9d223e8
YW
2305 self.assertRegex(output, 'local 10.20.55.1 proto kernel scope host src 10.20.55.1')
2306 self.assertRegex(output, 'broadcast 10.20.55.255 proto kernel scope link src 10.20.55.1')
2307 output = check_output('ip -6 route show table 42 dev dummy98')
2308 print('### ip -6 route show table 42 dev dummy98')
2309 print(output)
2310 if trial == 0:
2311 # Kernel's bug?
2312 self.assertRegex(output, 'local fdde:11:22::1 proto kernel metric 0 pref medium')
2313 #self.assertRegex(output, 'fdde:11:22::1 proto kernel metric 256 pref medium')
2314 self.assertRegex(output, 'local fdde:11:33::1 proto kernel metric 0 pref medium')
2315 self.assertRegex(output, 'fdde:11:33::/64 proto kernel metric 256 pref medium')
2316 self.assertRegex(output, 'local fdde:11:44::1 proto kernel metric 0 pref medium')
2317 self.assertRegex(output, 'local fdde:11:55::1 proto kernel metric 0 pref medium')
2318 self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
beb75dd3 2319 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
c9d223e8
YW
2320
2321 print()
2322
2323 output = check_output('ip route show dev test1')
2324 print('### ip route show dev test1')
2325 print(output)
2326 self.assertRegex(output, '10.21.33.0/24 proto kernel scope link src 10.21.33.1')
2327 output = check_output('ip route show table local dev test1')
2328 print('### ip route show table local dev test1')
2329 print(output)
2330 self.assertRegex(output, 'local 10.21.22.1 proto kernel scope host src 10.21.22.1')
c9d223e8
YW
2331 self.assertRegex(output, 'local 10.21.33.1 proto kernel scope host src 10.21.33.1')
2332 self.assertRegex(output, 'broadcast 10.21.33.255 proto kernel scope link src 10.21.33.1')
2333 self.assertRegex(output, 'local 10.21.44.1 proto kernel scope host src 10.21.44.1')
c9d223e8
YW
2334 self.assertRegex(output, 'local 10.21.55.1 proto kernel scope host src 10.21.55.1')
2335 self.assertRegex(output, 'broadcast 10.21.55.255 proto kernel scope link src 10.21.55.1')
2336 output = check_output('ip -6 route show dev test1')
2337 print('### ip -6 route show dev test1')
2338 print(output)
2339 self.assertRegex(output, 'fdde:12:22::1 proto kernel metric 256 pref medium')
2340 self.assertRegex(output, 'fdde:12:33::/64 proto kernel metric 256 pref medium')
2341 self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
2342 output = check_output('ip -6 route show table local dev test1')
2343 print('### ip -6 route show table local dev test1')
2344 print(output)
2345 self.assertRegex(output, 'local fdde:12:22::1 proto kernel metric 0 pref medium')
2346 self.assertRegex(output, 'local fdde:12:33::1 proto kernel metric 0 pref medium')
2347 self.assertRegex(output, 'local fdde:12:44::1 proto kernel metric 0 pref medium')
2348 self.assertRegex(output, 'local fdde:12:55::1 proto kernel metric 0 pref medium')
beb75dd3 2349 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
c9d223e8 2350
1f0e3109 2351 def test_configure_without_carrier(self):
a962d857 2352 copy_network_unit('11-dummy.netdev')
2cf6fdff 2353 start_networkd()
9bacf431
DS
2354 self.wait_operstate('test1', 'off', '')
2355 check_output('ip link set dev test1 up carrier off')
2356
a962d857 2357 copy_network_unit('25-test1.network.d/configure-without-carrier.conf', copy_dropins=False)
9bacf431
DS
2358 restart_networkd()
2359 self.wait_online(['test1:no-carrier'])
2360
2361 carrier_map = {'on': '1', 'off': '0'}
2362 routable_map = {'on': 'routable', 'off': 'no-carrier'}
2363 for carrier in ['off', 'on', 'off']:
2364 with self.subTest(carrier=carrier):
2365 if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
2366 check_output(f'ip link set dev test1 carrier {carrier}')
705c7b18 2367 self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}'])
9bacf431
DS
2368
2369 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
2370 print(output)
2371 self.assertRegex(output, '192.168.0.15')
2372 self.assertRegex(output, '192.168.0.1')
2373 self.assertRegex(output, routable_map[carrier])
e40a58b5 2374
9bacf431 2375 def test_configure_without_carrier_yes_ignore_carrier_loss_no(self):
a962d857 2376 copy_network_unit('11-dummy.netdev')
9bacf431
DS
2377 start_networkd()
2378 self.wait_operstate('test1', 'off', '')
2379 check_output('ip link set dev test1 up carrier off')
2380
a962d857 2381 copy_network_unit('25-test1.network')
9bacf431
DS
2382 restart_networkd()
2383 self.wait_online(['test1:no-carrier'])
2384
2385 carrier_map = {'on': '1', 'off': '0'}
2386 routable_map = {'on': 'routable', 'off': 'no-carrier'}
2387 for (carrier, have_config) in [('off', True), ('on', True), ('off', False)]:
2388 with self.subTest(carrier=carrier, have_config=have_config):
2389 if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
2390 check_output(f'ip link set dev test1 carrier {carrier}')
705c7b18 2391 self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}'])
9bacf431
DS
2392
2393 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
2394 print(output)
2395 if have_config:
2396 self.assertRegex(output, '192.168.0.15')
2397 self.assertRegex(output, '192.168.0.1')
2398 else:
2399 self.assertNotRegex(output, '192.168.0.15')
2400 self.assertNotRegex(output, '192.168.0.1')
2401 self.assertRegex(output, routable_map[carrier])
1f0e3109 2402
1f0e3109 2403 def test_routing_policy_rule(self):
a962d857 2404 copy_network_unit('25-routing-policy-rule-test1.network', '11-dummy.netdev')
2cf6fdff 2405 start_networkd()
e2aea43f 2406 self.wait_online(['test1:degraded'])
e40a58b5 2407
65c24cd0 2408 output = check_output('ip rule list iif test1 priority 111')
1f0e3109 2409 print(output)
65c24cd0 2410 self.assertRegex(output, '111:')
1f0e3109 2411 self.assertRegex(output, 'from 192.168.100.18')
426654d7 2412 self.assertRegex(output, r'tos (0x08|throughput)\s')
1f0e3109
SS
2413 self.assertRegex(output, 'iif test1')
2414 self.assertRegex(output, 'oif test1')
2415 self.assertRegex(output, 'lookup 7')
2416
65c24cd0
YW
2417 output = check_output('ip rule list iif test1 priority 101')
2418 print(output)
2419 self.assertRegex(output, '101:')
2420 self.assertRegex(output, 'from all')
2421 self.assertRegex(output, 'iif test1')
2422 self.assertRegex(output, 'lookup 9')
2423
2424 output = check_output('ip -6 rule list iif test1 priority 100')
2425 print(output)
2426 self.assertRegex(output, '100:')
2427 self.assertRegex(output, 'from all')
2428 self.assertRegex(output, 'iif test1')
2429 self.assertRegex(output, 'lookup 8')
2430
2e8a32af
HV
2431 output = check_output('ip rule list iif test1 priority 102')
2432 print(output)
2433 self.assertRegex(output, '102:')
2434 self.assertRegex(output, 'from 0.0.0.0/8')
2435 self.assertRegex(output, 'iif test1')
2436 self.assertRegex(output, 'lookup 10')
2437
146726b2
YW
2438 # TODO: check json string
2439 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
2440
b677774d 2441 def test_routing_policy_rule_issue_11280(self):
a962d857
YW
2442 copy_network_unit('25-routing-policy-rule-test1.network', '11-dummy.netdev',
2443 '25-routing-policy-rule-dummy98.network', '12-dummy.netdev')
b677774d 2444
a962d857
YW
2445 for trial in range(3):
2446 restart_networkd(show_logs=(trial > 0))
e2aea43f 2447 self.wait_online(['test1:degraded', 'dummy98:degraded'])
b677774d 2448
371810d1 2449 output = check_output('ip rule list table 7')
b677774d 2450 print(output)
426654d7 2451 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
b677774d 2452
371810d1 2453 output = check_output('ip rule list table 8')
b677774d 2454 print(output)
426654d7 2455 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
b677774d 2456
87adeabf 2457 def test_routing_policy_rule_reconfigure(self):
a962d857 2458 copy_network_unit('25-routing-policy-rule-reconfigure2.network', '11-dummy.netdev')
87adeabf
YW
2459 start_networkd()
2460 self.wait_online(['test1:degraded'])
2461
2462 output = check_output('ip rule list table 1011')
2463 print(output)
49ff3f34
YW
2464 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2465 self.assertIn('10112: from all oif test1 lookup 1011', output)
2466 self.assertIn('10113: from all iif test1 lookup 1011', output)
2467 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2468
2469 output = check_output('ip -6 rule list table 1011')
2470 print(output)
2471 self.assertIn('10112: from all oif test1 lookup 1011', output)
2472
a962d857
YW
2473 copy_network_unit('25-routing-policy-rule-reconfigure1.network', '11-dummy.netdev')
2474 networkctl_reload()
49ff3f34
YW
2475 self.wait_online(['test1:degraded'])
2476
2477 output = check_output('ip rule list table 1011')
2478 print(output)
2479 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2480 self.assertIn('10112: from all oif test1 lookup 1011', output)
2481 self.assertIn('10113: from all iif test1 lookup 1011', output)
2482 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2483
2484 output = check_output('ip -6 rule list table 1011')
2485 print(output)
2486 self.assertNotIn('10112: from all oif test1 lookup 1011', output)
2487 self.assertIn('10113: from all iif test1 lookup 1011', output)
87adeabf 2488
a962d857
YW
2489 call('ip rule delete priority 10111')
2490 call('ip rule delete priority 10112')
2491 call('ip rule delete priority 10113')
2492 call('ip rule delete priority 10114')
2493 call('ip -6 rule delete priority 10113')
87adeabf
YW
2494
2495 output = check_output('ip rule list table 1011')
2496 print(output)
2497 self.assertEqual(output, '')
2498
49ff3f34
YW
2499 output = check_output('ip -6 rule list table 1011')
2500 print(output)
2501 self.assertEqual(output, '')
87adeabf 2502
a962d857 2503 networkctl_reconfigure('test1')
87adeabf
YW
2504 self.wait_online(['test1:degraded'])
2505
2506 output = check_output('ip rule list table 1011')
2507 print(output)
49ff3f34
YW
2508 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2509 self.assertIn('10112: from all oif test1 lookup 1011', output)
2510 self.assertIn('10113: from all iif test1 lookup 1011', output)
2511 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2512
2513 output = check_output('ip -6 rule list table 1011')
2514 print(output)
2515 self.assertIn('10113: from all iif test1 lookup 1011', output)
87adeabf 2516
d586a2c3 2517 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0 2518 def test_routing_policy_rule_port_range(self):
a962d857 2519 copy_network_unit('25-fibrule-port-range.network', '11-dummy.netdev')
2cf6fdff 2520 start_networkd()
e2aea43f 2521 self.wait_online(['test1:degraded'])
e40a58b5 2522
371810d1 2523 output = check_output('ip rule')
926062f0
SS
2524 print(output)
2525 self.assertRegex(output, '111')
2526 self.assertRegex(output, 'from 192.168.100.18')
2527 self.assertRegex(output, '1123-1150')
2528 self.assertRegex(output, '3224-3290')
2529 self.assertRegex(output, 'tcp')
2530 self.assertRegex(output, 'lookup 7')
1f0e3109 2531
d586a2c3 2532 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd 2533 def test_routing_policy_rule_invert(self):
a962d857 2534 copy_network_unit('25-fibrule-invert.network', '11-dummy.netdev')
2cf6fdff 2535 start_networkd()
e2aea43f 2536 self.wait_online(['test1:degraded'])
e40a58b5 2537
371810d1 2538 output = check_output('ip rule')
efecf9cd 2539 print(output)
efecf9cd
SS
2540 self.assertRegex(output, '111')
2541 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
2542 self.assertRegex(output, 'tcp')
2543 self.assertRegex(output, 'lookup 7')
2544
6be8e78e
YW
2545 @expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
2546 def test_routing_policy_rule_uidrange(self):
a962d857 2547 copy_network_unit('25-fibrule-uidrange.network', '11-dummy.netdev')
6be8e78e
YW
2548 start_networkd()
2549 self.wait_online(['test1:degraded'])
2550
2551 output = check_output('ip rule')
2552 print(output)
2553 self.assertRegex(output, '111')
2554 self.assertRegex(output, 'from 192.168.100.18')
2555 self.assertRegex(output, 'lookup 7')
2556 self.assertRegex(output, 'uidrange 100-200')
2557
1d26d4cd
YW
2558 def _test_route_static(self, manage_foreign_routes):
2559 if not manage_foreign_routes:
2560 copy_networkd_conf_dropin('networkd-manage-foreign-routes-no.conf')
2561
a962d857 2562 copy_network_unit('25-route-static.network', '12-dummy.netdev')
2cf6fdff 2563 start_networkd()
e2aea43f
YW
2564 self.wait_online(['dummy98:routable'])
2565
fc79e6ff 2566 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
e2aea43f 2567 print(output)
0d34228f 2568
6d60f9db 2569 print('### ip -6 route show dev dummy98')
371810d1 2570 output = check_output('ip -6 route show dev dummy98')
0d34228f 2571 print(output)
0b5dc249
YW
2572 self.assertIn('2001:1234:5:8fff:ff:ff:ff:ff proto static', output)
2573 self.assertIn('2001:1234:5:8f63::1 proto kernel', output)
180c5116 2574 self.assertIn('2001:1234:5:afff:ff:ff:ff:ff via fe80:0:222:4dff:ff:ff:ff:ff proto static', output)
1f0e3109 2575
d9005dec
YW
2576 print('### ip -6 route show default')
2577 output = check_output('ip -6 route show default')
6d60f9db 2578 print(output)
0b5dc249
YW
2579 self.assertIn('default', output)
2580 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff', output)
1f0e3109 2581
6d60f9db 2582 print('### ip -4 route show dev dummy98')
371810d1 2583 output = check_output('ip -4 route show dev dummy98')
1f0e3109 2584 print(output)
0b5dc249
YW
2585 self.assertIn('149.10.124.48/28 proto kernel scope link src 149.10.124.58', output)
2586 self.assertIn('149.10.124.64 proto static scope link', output)
2587 self.assertIn('169.254.0.0/16 proto static scope link metric 2048', output)
902bbdc4
YW
2588 self.assertIn('192.168.1.1 proto static scope link initcwnd 20', output)
2589 self.assertIn('192.168.1.2 proto static scope link initrwnd 30', output)
2590 self.assertIn('192.168.1.3 proto static scope link advmss 30', output)
0b5dc249 2591 self.assertIn('multicast 149.10.123.4 proto static', output)
1f0e3109 2592
6d60f9db 2593 print('### ip -4 route show dev dummy98 default')
371810d1 2594 output = check_output('ip -4 route show dev dummy98 default')
6d60f9db 2595 print(output)
0b5dc249
YW
2596 self.assertIn('default via 149.10.125.65 proto static onlink', output)
2597 self.assertIn('default via 149.10.124.64 proto static', output)
2598 self.assertIn('default proto static', output)
1f0e3109 2599
6d60f9db
YW
2600 print('### ip -4 route show table local dev dummy98')
2601 output = check_output('ip -4 route show table local dev dummy98')
2602 print(output)
0b5dc249
YW
2603 self.assertIn('local 149.10.123.1 proto static scope host', output)
2604 self.assertIn('anycast 149.10.123.2 proto static scope link', output)
2605 self.assertIn('broadcast 149.10.123.3 proto static scope link', output)
6d60f9db
YW
2606
2607 print('### ip route show type blackhole')
371810d1 2608 output = check_output('ip route show type blackhole')
1f0e3109 2609 print(output)
0b5dc249 2610 self.assertIn('blackhole 202.54.1.2 proto static', output)
f5050e48 2611
6d60f9db 2612 print('### ip route show type unreachable')
371810d1 2613 output = check_output('ip route show type unreachable')
f5050e48 2614 print(output)
0b5dc249 2615 self.assertIn('unreachable 202.54.1.3 proto static', output)
f5050e48 2616
6d60f9db 2617 print('### ip route show type prohibit')
371810d1 2618 output = check_output('ip route show type prohibit')
f5050e48 2619 print(output)
0b5dc249 2620 self.assertIn('prohibit 202.54.1.4 proto static', output)
f5050e48 2621
452d86a5
YW
2622 print('### ip -6 route show type blackhole')
2623 output = check_output('ip -6 route show type blackhole')
2624 print(output)
2625 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output)
2626
2627 print('### ip -6 route show type unreachable')
2628 output = check_output('ip -6 route show type unreachable')
2629 print(output)
2630 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output)
2631
2632 print('### ip -6 route show type prohibit')
2633 output = check_output('ip -6 route show type prohibit')
2634 print(output)
2635 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
2636
a0ce990e
YW
2637 print('### ip route show 192.168.10.1')
2638 output = check_output('ip route show 192.168.10.1')
2639 print(output)
0b5dc249
YW
2640 self.assertIn('192.168.10.1 proto static', output)
2641 self.assertIn('nexthop via 149.10.124.59 dev dummy98 weight 10', output)
2642 self.assertIn('nexthop via 149.10.124.60 dev dummy98 weight 5', output)
a0ce990e
YW
2643
2644 print('### ip route show 192.168.10.2')
2645 output = check_output('ip route show 192.168.10.2')
2646 print(output)
2647 # old ip command does not show IPv6 gateways...
0b5dc249
YW
2648 self.assertIn('192.168.10.2 proto static', output)
2649 self.assertIn('nexthop', output)
2650 self.assertIn('dev dummy98 weight 10', output)
2651 self.assertIn('dev dummy98 weight 5', output)
a0ce990e
YW
2652
2653 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2654 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2655 print(output)
2656 # old ip command does not show 'nexthop' keyword and weight...
0b5dc249
YW
2657 self.assertIn('2001:1234:5:7fff:ff:ff:ff:ff', output)
2658 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98', output)
2659 self.assertIn('via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98', output)
a0ce990e 2660
146726b2
YW
2661 # TODO: check json string
2662 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
2663
a962d857
YW
2664 copy_network_unit('25-address-static.network')
2665 networkctl_reload()
43d4bc9f
YW
2666 self.wait_online(['dummy98:routable'])
2667
2668 # check all routes managed by Manager are removed
2669 print('### ip route show type blackhole')
2670 output = check_output('ip route show type blackhole')
2671 print(output)
2672 self.assertEqual(output, '')
2673
2674 print('### ip route show type unreachable')
2675 output = check_output('ip route show type unreachable')
2676 print(output)
2677 self.assertEqual(output, '')
2678
2679 print('### ip route show type prohibit')
2680 output = check_output('ip route show type prohibit')
2681 print(output)
2682 self.assertEqual(output, '')
2683
452d86a5
YW
2684 print('### ip -6 route show type blackhole')
2685 output = check_output('ip -6 route show type blackhole')
2686 print(output)
2687 self.assertEqual(output, '')
2688
2689 print('### ip -6 route show type unreachable')
2690 output = check_output('ip -6 route show type unreachable')
2691 print(output)
2692 self.assertEqual(output, '')
2693
2694 print('### ip -6 route show type prohibit')
2695 output = check_output('ip -6 route show type prohibit')
2696 print(output)
2697 self.assertEqual(output, '')
2698
a962d857
YW
2699 remove_network_unit('25-address-static.network')
2700 networkctl_reload()
43d4bc9f
YW
2701 self.wait_online(['dummy98:routable'])
2702
2703 # check all routes managed by Manager are reconfigured
2704 print('### ip route show type blackhole')
2705 output = check_output('ip route show type blackhole')
2706 print(output)
0b5dc249 2707 self.assertIn('blackhole 202.54.1.2 proto static', output)
43d4bc9f
YW
2708
2709 print('### ip route show type unreachable')
2710 output = check_output('ip route show type unreachable')
2711 print(output)
0b5dc249 2712 self.assertIn('unreachable 202.54.1.3 proto static', output)
43d4bc9f
YW
2713
2714 print('### ip route show type prohibit')
2715 output = check_output('ip route show type prohibit')
2716 print(output)
0b5dc249 2717 self.assertIn('prohibit 202.54.1.4 proto static', output)
43d4bc9f 2718
452d86a5
YW
2719 print('### ip -6 route show type blackhole')
2720 output = check_output('ip -6 route show type blackhole')
2721 print(output)
2722 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output)
2723
2724 print('### ip -6 route show type unreachable')
2725 output = check_output('ip -6 route show type unreachable')
2726 print(output)
2727 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output)
2728
2729 print('### ip -6 route show type prohibit')
2730 output = check_output('ip -6 route show type prohibit')
2731 print(output)
2732 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
2733
a962d857 2734 remove_link('dummy98')
43d4bc9f
YW
2735 time.sleep(2)
2736
2737 # check all routes managed by Manager are removed
2738 print('### ip route show type blackhole')
2739 output = check_output('ip route show type blackhole')
2740 print(output)
2741 self.assertEqual(output, '')
2742
2743 print('### ip route show type unreachable')
2744 output = check_output('ip route show type unreachable')
2745 print(output)
2746 self.assertEqual(output, '')
2747
2748 print('### ip route show type prohibit')
2749 output = check_output('ip route show type prohibit')
2750 print(output)
2751 self.assertEqual(output, '')
2752
452d86a5
YW
2753 print('### ip -6 route show type blackhole')
2754 output = check_output('ip -6 route show type blackhole')
2755 print(output)
2756 self.assertEqual(output, '')
2757
2758 print('### ip -6 route show type unreachable')
2759 output = check_output('ip -6 route show type unreachable')
2760 print(output)
2761 self.assertEqual(output, '')
2762
2763 print('### ip -6 route show type prohibit')
2764 output = check_output('ip -6 route show type prohibit')
2765 print(output)
2766 self.assertEqual(output, '')
2767
1d26d4cd
YW
2768 self.tearDown()
2769
2770 def test_route_static(self):
a962d857 2771 first = True
1d26d4cd 2772 for manage_foreign_routes in [True, False]:
a962d857
YW
2773 if first:
2774 first = False
2775 else:
2776 self.tearDown()
2777
2778 print(f'### test_route_static(manage_foreign_routes={manage_foreign_routes})')
1d26d4cd
YW
2779 with self.subTest(manage_foreign_routes=manage_foreign_routes):
2780 self._test_route_static(manage_foreign_routes)
2781
297f9d86
YW
2782 @expectedFailureIfRTA_VIAIsNotSupported()
2783 def test_route_via_ipv6(self):
a962d857 2784 copy_network_unit('25-route-via-ipv6.network', '12-dummy.netdev')
297f9d86
YW
2785 start_networkd()
2786 self.wait_online(['dummy98:routable'])
2787
2788 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
2789 print(output)
2790
2791 print('### ip -6 route show dev dummy98')
2792 output = check_output('ip -6 route show dev dummy98')
2793 print(output)
2794 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
2795 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
2796
2797 print('### ip -4 route show dev dummy98')
2798 output = check_output('ip -4 route show dev dummy98')
2799 print(output)
2800 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
2801 self.assertRegex(output, '149.10.124.66 via inet6 2001:1234:5:8fff:ff:ff:ff:ff proto static')
2802
93e898d6
YW
2803 @expectedFailureIfModuleIsNotAvailable('tcp_dctcp')
2804 def test_route_congctl(self):
2805 copy_network_unit('25-route-congctl.network', '12-dummy.netdev')
2806 start_networkd()
2807 self.wait_online(['dummy98:routable'])
2808
2809 print('### ip -6 route show dev dummy98 2001:1234:5:8fff:ff:ff:ff:ff')
2810 output = check_output('ip -6 route show dev dummy98 2001:1234:5:8fff:ff:ff:ff:ff')
2811 print(output)
2812 self.assertIn('2001:1234:5:8fff:ff:ff:ff:ff proto static', output)
2813 self.assertIn('congctl dctcp', output)
2814
2815 print('### ip -4 route show dev dummy98 149.10.124.66')
2816 output = check_output('ip -4 route show dev dummy98 149.10.124.66')
2817 print(output)
2818 self.assertIn('149.10.124.66 proto static', output)
2819 self.assertIn('congctl dctcp', output)
2820
40afe491
YW
2821 @expectedFailureIfModuleIsNotAvailable('vrf')
2822 def test_route_vrf(self):
a962d857
YW
2823 copy_network_unit('25-route-vrf.network', '12-dummy.netdev',
2824 '25-vrf.netdev', '25-vrf.network')
40afe491
YW
2825 start_networkd()
2826 self.wait_online(['dummy98:routable', 'vrf99:carrier'])
2827
2828 output = check_output('ip route show vrf vrf99')
2829 print(output)
2830 self.assertRegex(output, 'default via 192.168.100.1')
2831
2832 output = check_output('ip route show')
2833 print(output)
2834 self.assertNotRegex(output, 'default via 192.168.100.1')
2835
0b1cd3e2 2836 def test_gateway_reconfigure(self):
a962d857 2837 copy_network_unit('25-gateway-static.network', '12-dummy.netdev')
0b1cd3e2
WKI
2838 start_networkd()
2839 self.wait_online(['dummy98:routable'])
2840 print('### ip -4 route show dev dummy98 default')
2841 output = check_output('ip -4 route show dev dummy98 default')
2842 print(output)
a962d857
YW
2843 self.assertIn('default via 149.10.124.59 proto static', output)
2844 self.assertNotIn('149.10.124.60', output)
0b1cd3e2 2845
a962d857
YW
2846 remove_network_unit('25-gateway-static.network')
2847 copy_network_unit('25-gateway-next-static.network')
2848 networkctl_reload()
0b1cd3e2
WKI
2849 self.wait_online(['dummy98:routable'])
2850 print('### ip -4 route show dev dummy98 default')
2851 output = check_output('ip -4 route show dev dummy98 default')
2852 print(output)
a962d857
YW
2853 self.assertNotIn('149.10.124.59', output)
2854 self.assertIn('default via 149.10.124.60 proto static', output)
0b1cd3e2 2855
20ca06a6
DA
2856 def test_ip_route_ipv6_src_route(self):
2857 # a dummy device does not make the addresses go through tentative state, so we
2858 # reuse a bond from an earlier test, which does make the addresses go through
2859 # tentative state, and do our test on that
a962d857 2860 copy_network_unit('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 2861 start_networkd()
e2aea43f 2862 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
20ca06a6 2863
371810d1 2864 output = check_output('ip -6 route list dev bond199')
20ca06a6
DA
2865 print(output)
2866 self.assertRegex(output, 'abcd::/16')
2867 self.assertRegex(output, 'src')
2868 self.assertRegex(output, '2001:1234:56:8f63::2')
2869
1f0e3109 2870 def test_ip_link_mac_address(self):
a962d857 2871 copy_network_unit('25-address-link-section.network', '12-dummy.netdev')
2cf6fdff 2872 start_networkd()
e2aea43f 2873 self.wait_online(['dummy98:degraded'])
1f0e3109 2874
371810d1 2875 output = check_output('ip link show dummy98')
1f0e3109 2876 print(output)
45aa0e84 2877 self.assertRegex(output, '00:01:02:aa:bb:cc')
1f0e3109
SS
2878
2879 def test_ip_link_unmanaged(self):
a962d857
YW
2880 copy_network_unit('25-link-section-unmanaged.network', '12-dummy.netdev')
2881 start_networkd()
1f0e3109 2882
19cf3143 2883 self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
1f0e3109
SS
2884
2885 def test_ipv6_address_label(self):
a962d857 2886 copy_network_unit('25-ipv6-address-label-section.network', '12-dummy.netdev')
2cf6fdff 2887 start_networkd()
e2aea43f 2888 self.wait_online(['dummy98:degraded'])
1f0e3109 2889
371810d1 2890 output = check_output('ip addrlabel list')
1f0e3109
SS
2891 print(output)
2892 self.assertRegex(output, '2004:da8:1::/64')
2893
cff0cadc 2894 def test_ipv6_proxy_ndp(self):
a962d857 2895 copy_network_unit('25-ipv6-proxy-ndp.network', '12-dummy.netdev')
cff0cadc
YW
2896 start_networkd()
2897
2898 self.wait_online(['dummy98:routable'])
2899
2900 output = check_output('ip neighbor show proxy dev dummy98')
2901 print(output)
a962d857 2902 for i in range(1, 5):
cff0cadc
YW
2903 self.assertRegex(output, f'2607:5300:203:5215:{i}::1 *proxy')
2904
d86f5c19 2905 def test_neighbor_section(self):
a962d857 2906 copy_network_unit('25-neighbor-section.network', '12-dummy.netdev')
2cf6fdff 2907 start_networkd()
e2aea43f 2908 self.wait_online(['dummy98:degraded'], timeout='40s')
e4a71bf3 2909
d1bdafd2 2910 print('### ip neigh list dev dummy98')
df7f9afa 2911 output = check_output('ip neigh list dev dummy98')
e4a71bf3
WKI
2912 print(output)
2913 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 2914 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 2915
146726b2
YW
2916 # TODO: check json string
2917 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
2918
d1bdafd2 2919 def test_neighbor_reconfigure(self):
a962d857 2920 copy_network_unit('25-neighbor-section.network', '12-dummy.netdev')
d1bdafd2
WKI
2921 start_networkd()
2922 self.wait_online(['dummy98:degraded'], timeout='40s')
2923
2924 print('### ip neigh list dev dummy98')
2925 output = check_output('ip neigh list dev dummy98')
2926 print(output)
2927 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2928 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2929
a962d857
YW
2930 remove_network_unit('25-neighbor-section.network')
2931 copy_network_unit('25-neighbor-next.network')
2932 networkctl_reload()
d1bdafd2
WKI
2933 self.wait_online(['dummy98:degraded'], timeout='40s')
2934 print('### ip neigh list dev dummy98')
2935 output = check_output('ip neigh list dev dummy98')
2936 print(output)
2937 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2938 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
2939 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
2940
74761cf3 2941 def test_neighbor_gre(self):
a962d857
YW
2942 copy_network_unit('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
2943 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
74761cf3 2944 start_networkd()
fb2ba330 2945 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
74761cf3
YW
2946
2947 output = check_output('ip neigh list dev gretun97')
2948 print(output)
2949 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
fb2ba330
YW
2950
2951 output = check_output('ip neigh list dev ip6gretun97')
2952 print(output)
2953 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
74761cf3 2954
146726b2
YW
2955 # TODO: check json string
2956 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
2957
05514ae1 2958 def test_link_local_addressing(self):
a962d857
YW
2959 copy_network_unit('25-link-local-addressing-yes.network', '11-dummy.netdev',
2960 '25-link-local-addressing-no.network', '12-dummy.netdev')
2cf6fdff 2961 start_networkd()
e2aea43f 2962 self.wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1 2963
371810d1 2964 output = check_output('ip address show dev test1')
05514ae1
YW
2965 print(output)
2966 self.assertRegex(output, 'inet .* scope link')
2967 self.assertRegex(output, 'inet6 .* scope link')
2968
371810d1 2969 output = check_output('ip address show dev dummy98')
05514ae1
YW
2970 print(output)
2971 self.assertNotRegex(output, 'inet6* .* scope link')
2972
f7805a6c
FS
2973 # Documentation/networking/ip-sysctl.txt
2974 #
2975 # addr_gen_mode - INTEGER
2976 # Defines how link-local and autoconf addresses are generated.
2977 #
2978 # 0: generate address based on EUI64 (default)
2979 # 1: do no generate a link-local address, use EUI64 for addresses generated
2980 # from autoconf
2981 # 2: generate stable privacy addresses, using the secret from
2982 # stable_secret (RFC7217)
2983 # 3: generate stable privacy addresses, using a random secret if unset
05514ae1 2984
a962d857
YW
2985 self.check_ipv6_sysctl_attr('test1', 'stable_secret', '0123:4567:89ab:cdef:0123:4567:89ab:cdef')
2986 self.check_ipv6_sysctl_attr('test1', 'addr_gen_mode', '2')
2987 self.check_ipv6_sysctl_attr('dummy98', 'addr_gen_mode', '1')
05514ae1 2988
2becdbcc 2989 def test_link_local_addressing_ipv6ll(self):
a962d857 2990 copy_network_unit('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
7b3770a7
YW
2991 start_networkd()
2992 self.wait_online(['dummy98:degraded'])
2993
2becdbcc 2994 # An IPv6LL address exists by default.
7b3770a7
YW
2995 output = check_output('ip address show dev dummy98')
2996 print(output)
2997 self.assertRegex(output, 'inet6 .* scope link')
2998
a962d857
YW
2999 copy_network_unit('25-link-local-addressing-no.network')
3000 networkctl_reload()
7b3770a7
YW
3001 self.wait_online(['dummy98:carrier'])
3002
2becdbcc 3003 # Check if the IPv6LL address is removed.
7b3770a7
YW
3004 output = check_output('ip address show dev dummy98')
3005 print(output)
2becdbcc
YW
3006 self.assertNotRegex(output, 'inet6 .* scope link')
3007
a962d857
YW
3008 remove_network_unit('25-link-local-addressing-no.network')
3009 networkctl_reload()
2becdbcc
YW
3010 self.wait_online(['dummy98:degraded'])
3011
3012 # Check if a new IPv6LL address is assigned.
3013 output = check_output('ip address show dev dummy98')
3014 print(output)
3015 self.assertRegex(output, 'inet6 .* scope link')
7b3770a7 3016
1f0e3109 3017 def test_sysctl(self):
a962d857 3018 copy_network_unit('25-sysctl.network', '12-dummy.netdev')
2cf6fdff 3019 start_networkd()
e2aea43f 3020 self.wait_online(['dummy98:degraded'])
ec38833c 3021
a962d857
YW
3022 self.check_ipv6_sysctl_attr('dummy98', 'forwarding', '1')
3023 self.check_ipv6_sysctl_attr('dummy98', 'use_tempaddr', '2')
3024 self.check_ipv6_sysctl_attr('dummy98', 'dad_transmits', '3')
3025 self.check_ipv6_sysctl_attr('dummy98', 'hop_limit', '5')
3026 self.check_ipv6_sysctl_attr('dummy98', 'proxy_ndp', '1')
3027 self.check_ipv4_sysctl_attr('dummy98', 'forwarding', '1')
3028 self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp', '1')
3029 self.check_ipv4_sysctl_attr('dummy98', 'accept_local', '1')
1f0e3109 3030
4da33154 3031 def test_sysctl_disable_ipv6(self):
a962d857 3032 copy_network_unit('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
4da33154
YW
3033
3034 print('## Disable ipv6')
cefd6b3d
ZJS
3035 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
3036 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
4da33154 3037
2cf6fdff 3038 start_networkd()
e2aea43f 3039 self.wait_online(['dummy98:routable'])
4da33154 3040
371810d1 3041 output = check_output('ip -4 address show dummy98')
4da33154
YW
3042 print(output)
3043 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 3044 output = check_output('ip -6 address show dummy98')
4da33154 3045 print(output)
57ad7607
ZJS
3046 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
3047 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
3048 output = check_output('ip -4 route show dev dummy98')
3049 print(output)
3d2c2692 3050 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
d9005dec 3051 output = check_output('ip -6 route show default')
4933b97d 3052 print(output)
d9005dec
YW
3053 self.assertRegex(output, 'default')
3054 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
4da33154 3055
a962d857 3056 remove_link('dummy98')
4da33154
YW
3057
3058 print('## Enable ipv6')
cefd6b3d
ZJS
3059 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
3060 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
4da33154 3061
a962d857 3062 restart_networkd()
e2aea43f 3063 self.wait_online(['dummy98:routable'])
4da33154 3064
371810d1 3065 output = check_output('ip -4 address show dummy98')
4da33154
YW
3066 print(output)
3067 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 3068 output = check_output('ip -6 address show dummy98')
4da33154 3069 print(output)
4933b97d 3070 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
4da33154 3071 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
3072 output = check_output('ip -4 route show dev dummy98')
3073 print(output)
3d2c2692 3074 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
d9005dec 3075 output = check_output('ip -6 route show default')
4933b97d 3076 print(output)
d9005dec 3077 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
4da33154 3078
cd65d067 3079 def test_bind_carrier(self):
bc942f69
YW
3080 check_output('ip link add dummy98 type dummy')
3081 check_output('ip link set dummy98 up')
3082 time.sleep(2)
3083
a962d857 3084 copy_network_unit('25-bind-carrier.network', '11-dummy.netdev')
2cf6fdff 3085 start_networkd()
e2aea43f 3086 self.wait_online(['test1:routable'])
cd65d067 3087
371810d1 3088 output = check_output('ip address show test1')
cd65d067
YW
3089 print(output)
3090 self.assertRegex(output, 'UP,LOWER_UP')
3091 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 3092 self.wait_operstate('test1', 'routable')
cd65d067 3093
cefd6b3d
ZJS
3094 check_output('ip link add dummy99 type dummy')
3095 check_output('ip link set dummy99 up')
b117044c 3096 time.sleep(2)
371810d1 3097 output = check_output('ip address show test1')
cd65d067
YW
3098 print(output)
3099 self.assertRegex(output, 'UP,LOWER_UP')
3100 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 3101 self.wait_operstate('test1', 'routable')
cd65d067 3102
a962d857 3103 remove_link('dummy98')
b117044c 3104 time.sleep(2)
371810d1 3105 output = check_output('ip address show test1')
cd65d067
YW
3106 print(output)
3107 self.assertRegex(output, 'UP,LOWER_UP')
3108 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 3109 self.wait_operstate('test1', 'routable')
cd65d067 3110
bc942f69 3111 check_output('ip link set dummy99 down')
b117044c 3112 time.sleep(2)
371810d1 3113 output = check_output('ip address show test1')
cd65d067
YW
3114 print(output)
3115 self.assertNotRegex(output, 'UP,LOWER_UP')
3116 self.assertRegex(output, 'DOWN')
3117 self.assertNotRegex(output, '192.168.10')
19cf3143 3118 self.wait_operstate('test1', 'off')
cd65d067 3119
bc942f69 3120 check_output('ip link set dummy99 up')
b117044c 3121 time.sleep(2)
371810d1 3122 output = check_output('ip address show test1')
cd65d067
YW
3123 print(output)
3124 self.assertRegex(output, 'UP,LOWER_UP')
3125 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 3126 self.wait_operstate('test1', 'routable')
cd65d067 3127
a962d857 3128 def _test_activation_policy(self, interface, test):
2236d75d
DS
3129 conffile = '25-activation-policy.network'
3130 if test:
3131 conffile = f'{conffile}.d/{test}.conf'
ee9918ae 3132 if interface == 'vlan99':
a962d857
YW
3133 copy_network_unit('21-vlan.netdev', '21-vlan-test1.network')
3134 copy_network_unit('11-dummy.netdev', conffile, copy_dropins=False)
2236d75d
DS
3135 start_networkd()
3136
3137 always = test.startswith('always')
ebb5036f 3138 initial_up = test != 'manual' and not test.endswith('down') # note: default is up
2236d75d
DS
3139 expect_up = initial_up
3140 next_up = not expect_up
3141
cfbdc438 3142 if test.endswith('down'):
ee9918ae 3143 self.wait_activated(interface)
cfbdc438 3144
2236d75d
DS
3145 for iteration in range(4):
3146 with self.subTest(iteration=iteration, expect_up=expect_up):
3147 operstate = 'routable' if expect_up else 'off'
618da3e7 3148 setup_state = 'configured' if expect_up else ('configuring' if iteration == 0 else None)
ee9918ae 3149 self.wait_operstate(interface, operstate, setup_state=setup_state, setup_timeout=20)
2236d75d
DS
3150
3151 if expect_up:
ee9918ae
YW
3152 self.assertIn('UP', check_output(f'ip link show {interface}'))
3153 self.assertIn('192.168.10.30/24', check_output(f'ip address show {interface}'))
3154 self.assertIn('default via 192.168.10.1', check_output(f'ip route show dev {interface}'))
2236d75d 3155 else:
ee9918ae 3156 self.assertIn('DOWN', check_output(f'ip link show {interface}'))
2236d75d
DS
3157
3158 if next_up:
ee9918ae 3159 check_output(f'ip link set dev {interface} up')
2236d75d 3160 else:
ee9918ae 3161 check_output(f'ip link set dev {interface} down')
2236d75d
DS
3162 expect_up = initial_up if always else next_up
3163 next_up = not next_up
073ad7ed
YW
3164 if always:
3165 time.sleep(1)
2236d75d 3166
2236d75d 3167 def test_activation_policy(self):
a962d857 3168 first = True
ee9918ae 3169 for interface in ['test1', 'vlan99']:
a962d857
YW
3170 for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']:
3171 if first:
3172 first = False
3173 else:
3174 self.tearDown()
3175
3176 print(f'### test_activation_policy(interface={interface}, test={test})')
3177 with self.subTest(interface=interface, test=test):
3178 self._test_activation_policy(interface, test)
2236d75d 3179
61764fe4 3180 def _test_activation_policy_required_for_online(self, policy, required):
61764fe4
DS
3181 conffile = '25-activation-policy.network'
3182 units = ['11-dummy.netdev', '12-dummy.netdev', '12-dummy.network', conffile]
3183 if policy:
3184 units += [f'{conffile}.d/{policy}.conf']
3185 if required:
3186 units += [f'{conffile}.d/required-{required}.conf']
a962d857 3187 copy_network_unit(*units, copy_dropins=False)
61764fe4
DS
3188 start_networkd()
3189
cfbdc438
YW
3190 if policy.endswith('down'):
3191 self.wait_activated('test1')
3192
61764fe4
DS
3193 if policy.endswith('down') or policy == 'manual':
3194 self.wait_operstate('test1', 'off', setup_state='configuring')
3195 else:
3196 self.wait_online(['test1'])
3197
3198 if policy == 'always-down':
3199 # if always-down, required for online is forced to no
3200 expected = False
3201 elif required:
3202 # otherwise if required for online is specified, it should match that
3203 expected = required == 'yes'
3204 elif policy:
3205 # otherwise if only policy specified, required for online defaults to
3206 # true if policy is up, always-up, or bound
3207 expected = policy.endswith('up') or policy == 'bound'
3208 else:
3209 # default is true, if neither are specified
3210 expected = True
3211
3212 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
3213 print(output)
3214
3215 yesno = 'yes' if expected else 'no'
3216 self.assertRegex(output, f'Required For Online: {yesno}')
3217
61764fe4 3218 def test_activation_policy_required_for_online(self):
a962d857 3219 first = True
61764fe4
DS
3220 for policy in ['up', 'always-up', 'manual', 'always-down', 'down', 'bound', '']:
3221 for required in ['yes', 'no', '']:
a962d857
YW
3222 if first:
3223 first = False
3224 else:
3225 self.tearDown()
3226
3227 print(f'### test_activation_policy_required_for_online(policy={policy}, required={required})')
61764fe4
DS
3228 with self.subTest(policy=policy, required=required):
3229 self._test_activation_policy_required_for_online(policy, required)
3230
fdcd1ec5 3231 def test_domain(self):
a962d857 3232 copy_network_unit('12-dummy.netdev', '24-search-domain.network')
2cf6fdff 3233 start_networkd()
e2aea43f 3234 self.wait_online(['dummy98:routable'])
fdcd1ec5 3235
fc79e6ff 3236 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
fdcd1ec5
YW
3237 print(output)
3238 self.assertRegex(output, 'Address: 192.168.42.100')
3239 self.assertRegex(output, 'DNS: 192.168.42.1')
3240 self.assertRegex(output, 'Search Domains: one')
3241
1e498853 3242 def test_keep_configuration_static(self):
1e498853
YW
3243 check_output('ip link add name dummy98 type dummy')
3244 check_output('ip address add 10.1.2.3/16 dev dummy98')
3245 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
3246 output = check_output('ip address show dummy98')
3247 print(output)
3248 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
3249 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
3250 output = check_output('ip route show dev dummy98')
3251 print(output)
3252
a962d857 3253 copy_network_unit('24-keep-configuration-static.network')
2cf6fdff 3254 start_networkd()
e2aea43f 3255 self.wait_online(['dummy98:routable'])
1e498853
YW
3256
3257 output = check_output('ip address show dummy98')
3258 print(output)
3259 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
3260 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
3261
086bcf5d
YW
3262 @expectedFailureIfNexthopIsNotAvailable()
3263 def test_nexthop(self):
9c8f90d0
YW
3264 def check_nexthop(self):
3265 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
086bcf5d 3266
9c8f90d0
YW
3267 output = check_output('ip nexthop list dev veth99')
3268 print(output)
3269 self.assertIn('id 1 via 192.168.5.1 dev veth99', output)
3270 self.assertIn('id 2 via 2001:1234:5:8f63::2 dev veth99', output)
3271 self.assertIn('id 3 dev veth99', output)
3272 self.assertIn('id 4 dev veth99', output)
3273 self.assertRegex(output, 'id 5 via 192.168.10.1 dev veth99 .*onlink')
180c5116 3274 self.assertIn('id 8 via fe80:0:222:4dff:ff:ff:ff:ff dev veth99', output)
9c8f90d0
YW
3275 self.assertRegex(output, r'id [0-9]* via 192.168.5.2 dev veth99')
3276
3277 output = check_output('ip nexthop list dev dummy98')
3278 print(output)
3279 self.assertIn('id 20 via 192.168.20.1 dev dummy98', output)
086bcf5d 3280
9c8f90d0
YW
3281 # kernel manages blackhole nexthops on lo
3282 output = check_output('ip nexthop list dev lo')
3283 print(output)
3284 self.assertIn('id 6 blackhole', output)
3285 self.assertIn('id 7 blackhole', output)
69a91c70 3286
9c8f90d0
YW
3287 # group nexthops are shown with -0 option
3288 output = check_output('ip -0 nexthop list id 21')
3289 print(output)
3290 self.assertRegex(output, r'id 21 group (1,3/20|20/1,3)')
cee0f719 3291
9c8f90d0
YW
3292 output = check_output('ip route show dev veth99 10.10.10.10')
3293 print(output)
3294 self.assertEqual('10.10.10.10 nhid 1 via 192.168.5.1 proto static', output)
cee0f719 3295
9c8f90d0
YW
3296 output = check_output('ip route show dev veth99 10.10.10.11')
3297 print(output)
3298 self.assertEqual('10.10.10.11 nhid 2 via inet6 2001:1234:5:8f63::2 proto static', output)
e2d9bc5c 3299
9c8f90d0
YW
3300 output = check_output('ip route show dev veth99 10.10.10.12')
3301 print(output)
3302 self.assertEqual('10.10.10.12 nhid 5 via 192.168.10.1 proto static onlink', output)
cee0f719 3303
9c8f90d0
YW
3304 output = check_output('ip -6 route show dev veth99 2001:1234:5:8f62::1')
3305 print(output)
3306 self.assertEqual('2001:1234:5:8f62::1 nhid 2 via 2001:1234:5:8f63::2 proto static metric 1024 pref medium', output)
69a91c70 3307
9c8f90d0
YW
3308 output = check_output('ip route show 10.10.10.13')
3309 print(output)
3310 self.assertEqual('blackhole 10.10.10.13 nhid 6 dev lo proto static', output)
3311
3312 output = check_output('ip -6 route show 2001:1234:5:8f62::2')
3313 print(output)
3314 self.assertEqual('blackhole 2001:1234:5:8f62::2 nhid 7 dev lo proto static metric 1024 pref medium', output)
3315
3316 output = check_output('ip route show 10.10.10.14')
3317 print(output)
3318 self.assertIn('10.10.10.14 nhid 21 proto static', output)
3319 self.assertIn('nexthop via 192.168.20.1 dev dummy98 weight 1', output)
3320 self.assertIn('nexthop via 192.168.5.1 dev veth99 weight 3', output)
3321
146726b2
YW
3322 # TODO: check json string
3323 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
3324
a962d857
YW
3325 copy_network_unit('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network',
3326 '12-dummy.netdev', '25-nexthop-dummy.network')
9c8f90d0
YW
3327 start_networkd()
3328
3329 check_nexthop(self)
69a91c70 3330
a962d857
YW
3331 remove_network_unit('25-nexthop.network')
3332 copy_network_unit('25-nexthop-nothing.network')
3333 networkctl_reload()
932e157b
YW
3334 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3335
9947c7ba
YW
3336 output = check_output('ip nexthop list dev veth99')
3337 print(output)
3338 self.assertEqual(output, '')
3339 output = check_output('ip nexthop list dev lo')
3340 print(output)
3341 self.assertEqual(output, '')
3342
a962d857
YW
3343 remove_network_unit('25-nexthop-nothing.network')
3344 copy_network_unit('25-nexthop.network')
3345 networkctl_reconfigure('dummy98')
3346 networkctl_reload()
9947c7ba 3347
9c8f90d0 3348 check_nexthop(self)
932e157b 3349
a962d857 3350 remove_link('veth99')
9947c7ba
YW
3351 time.sleep(2)
3352
3353 output = check_output('ip nexthop list dev lo')
3354 print(output)
3355 self.assertEqual(output, '')
3356
23b38192
YW
3357class NetworkdTCTests(unittest.TestCase, Utilities):
3358
3359 def setUp(self):
3360 setup_common()
3361
3362 def tearDown(self):
3363 tear_down_common()
3364
4c7d13f4
YW
3365 @expectedFailureIfModuleIsNotAvailable('sch_cake')
3366 def test_qdisc_cake(self):
3367 copy_network_unit('25-qdisc-cake.network', '12-dummy.netdev')
ef3c8a92 3368 start_networkd()
4c7d13f4 3369 self.wait_online(['dummy98:routable'])
ef3c8a92 3370
4c7d13f4 3371 output = check_output('tc qdisc show dev dummy98')
f1de1eb3 3372 print(output)
4c7d13f4
YW
3373 self.assertIn('qdisc cake 3a: root', output)
3374 self.assertIn('bandwidth 500Mbit', output)
3375 self.assertIn('autorate-ingress', output)
3376 self.assertIn('diffserv8', output)
3377 self.assertIn('dual-dsthost', output)
3378 self.assertIn(' nat', output)
3379 self.assertIn(' wash', output)
3380 self.assertIn(' split-gso', output)
3381 self.assertIn(' raw', output)
3382 self.assertIn(' atm', output)
3383 self.assertIn('overhead 128', output)
3384 self.assertIn('mpu 20', output)
3385 self.assertIn('fwmark 0xff00', output)
3386
3387 @expectedFailureIfModuleIsNotAvailable('sch_codel')
3388 def test_qdisc_codel(self):
3389 copy_network_unit('25-qdisc-codel.network', '12-dummy.netdev')
3390 start_networkd()
3391 self.wait_online(['dummy98:routable'])
f1de1eb3 3392
ef3c8a92
YW
3393 output = check_output('tc qdisc show dev dummy98')
3394 print(output)
4c7d13f4
YW
3395 self.assertRegex(output, 'qdisc codel 33: root')
3396 self.assertRegex(output, 'limit 2000p target 10(.0)?ms ce_threshold 100(.0)?ms interval 50(.0)?ms ecn')
f1de1eb3 3397
4c7d13f4
YW
3398 @expectedFailureIfModuleIsNotAvailable('sch_drr')
3399 def test_qdisc_drr(self):
3400 copy_network_unit('25-qdisc-drr.network', '12-dummy.netdev')
3401 start_networkd()
3402 self.wait_online(['dummy98:routable'])
f1de1eb3 3403
4c7d13f4
YW
3404 output = check_output('tc qdisc show dev dummy98')
3405 print(output)
3406 self.assertRegex(output, 'qdisc drr 2: root')
3407 output = check_output('tc class show dev dummy98')
3408 print(output)
3409 self.assertRegex(output, 'class drr 2:30 root quantum 2000b')
ef3c8a92 3410
4c7d13f4
YW
3411 @expectedFailureIfModuleIsNotAvailable('sch_ets')
3412 def test_qdisc_ets(self):
3413 copy_network_unit('25-qdisc-ets.network', '12-dummy.netdev')
3414 start_networkd()
3415 self.wait_online(['dummy98:routable'])
3416
3417 output = check_output('tc qdisc show dev dummy98')
3418 print(output)
3419
3420 self.assertRegex(output, 'qdisc ets 3a: root')
3421 self.assertRegex(output, 'bands 10 strict 3')
3422 self.assertRegex(output, 'quanta 1 2 3 4 5')
3423 self.assertRegex(output, 'priomap 3 4 5 6 7')
3424
3425 @expectedFailureIfModuleIsNotAvailable('sch_fq')
3426 def test_qdisc_fq(self):
3427 copy_network_unit('25-qdisc-fq.network', '12-dummy.netdev')
3428 start_networkd()
3429 self.wait_online(['dummy98:routable'])
0baddbd5 3430
4c7d13f4
YW
3431 output = check_output('tc qdisc show dev dummy98')
3432 print(output)
3433 self.assertRegex(output, 'qdisc fq 32: root')
a05a6e8b
YW
3434 self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511')
3435 self.assertRegex(output, 'quantum 1500')
3436 self.assertRegex(output, 'initial_quantum 13000')
3437 self.assertRegex(output, 'maxrate 1Mbit')
ab9dc1db 3438
4c7d13f4
YW
3439 @expectedFailureIfModuleIsNotAvailable('sch_fq_codel')
3440 def test_qdisc_fq_codel(self):
3441 copy_network_unit('25-qdisc-fq_codel.network', '12-dummy.netdev')
3442 start_networkd()
3443 self.wait_online(['dummy98:routable'])
ab9dc1db 3444
4c7d13f4
YW
3445 output = check_output('tc qdisc show dev dummy98')
3446 print(output)
3447 self.assertRegex(output, 'qdisc fq_codel 34: root')
7887e580 3448 self.assertRegex(output, 'limit 20480p flows 2048 quantum 1400 target 10(.0)?ms ce_threshold 100(.0)?ms interval 200(.0)?ms memory_limit 64Mb ecn')
ab9dc1db 3449
4c7d13f4
YW
3450 @expectedFailureIfModuleIsNotAvailable('sch_fq_pie')
3451 def test_qdisc_fq_pie(self):
3452 copy_network_unit('25-qdisc-fq_pie.network', '12-dummy.netdev')
3453 start_networkd()
3454 self.wait_online(['dummy98:routable'])
ab9dc1db 3455
4c7d13f4
YW
3456 output = check_output('tc qdisc show dev dummy98')
3457 print(output)
3d55b5a9 3458
4c7d13f4
YW
3459 self.assertRegex(output, 'qdisc fq_pie 3a: root')
3460 self.assertRegex(output, 'limit 200000p')
bc0769c9 3461
4c7d13f4
YW
3462 @expectedFailureIfModuleIsNotAvailable('sch_gred')
3463 def test_qdisc_gred(self):
3464 copy_network_unit('25-qdisc-gred.network', '12-dummy.netdev')
3465 start_networkd()
3466 self.wait_online(['dummy98:routable'])
3467
3468 output = check_output('tc qdisc show dev dummy98')
3469 print(output)
3470 self.assertRegex(output, 'qdisc gred 38: root')
95edcf3f
YW
3471 self.assertRegex(output, 'vqs 12 default 10 grio')
3472
4c7d13f4
YW
3473 @expectedFailureIfModuleIsNotAvailable('sch_hhf')
3474 def test_qdisc_hhf(self):
3475 copy_network_unit('25-qdisc-hhf.network', '12-dummy.netdev')
3476 start_networkd()
3477 self.wait_online(['dummy98:routable'])
3478
3479 output = check_output('tc qdisc show dev dummy98')
3480 print(output)
3481 self.assertRegex(output, 'qdisc hhf 3a: root')
3482 self.assertRegex(output, 'limit 1022p')
3483
3484 @expectedFailureIfModuleIsNotAvailable('sch_htb')
3485 def test_qdisc_htb_fifo(self):
3486 copy_network_unit('25-qdisc-htb-fifo.network', '12-dummy.netdev')
3487 start_networkd()
3488 self.wait_online(['dummy98:routable'])
3489
3490 output = check_output('tc qdisc show dev dummy98')
3491 print(output)
3492 self.assertRegex(output, 'qdisc htb 2: root')
3493 self.assertRegex(output, r'default (0x30|30)')
3494
3495 self.assertRegex(output, 'qdisc pfifo 37: parent 2:37')
3496 self.assertRegex(output, 'limit 100000p')
f2c5c129 3497
7b1a31a3
YW
3498 self.assertRegex(output, 'qdisc bfifo 3a: parent 2:3a')
3499 self.assertRegex(output, 'limit 1000000')
3500
73136507
YW
3501 self.assertRegex(output, 'qdisc pfifo_head_drop 3b: parent 2:3b')
3502 self.assertRegex(output, 'limit 1023p')
3503
41bb371b
YW
3504 self.assertRegex(output, 'qdisc pfifo_fast 3c: parent 2:3c')
3505
2ee7e54b 3506 output = check_output('tc -d class show dev dummy98')
ab9dc1db 3507 print(output)
bc0769c9 3508 self.assertRegex(output, 'class htb 2:37 root leaf 37:')
7b1a31a3 3509 self.assertRegex(output, 'class htb 2:3a root leaf 3a:')
73136507 3510 self.assertRegex(output, 'class htb 2:3b root leaf 3b:')
41bb371b 3511 self.assertRegex(output, 'class htb 2:3c root leaf 3c:')
2ee7e54b
YW
3512 self.assertRegex(output, 'prio 1 quantum 4000 rate 1Mbit overhead 100 ceil 500Kbit')
3513 self.assertRegex(output, 'burst 123456')
3514 self.assertRegex(output, 'cburst 123457')
0baddbd5 3515
4c7d13f4
YW
3516 @expectedFailureIfModuleIsNotAvailable('sch_ingress')
3517 def test_qdisc_ingress(self):
3518 copy_network_unit('25-qdisc-clsact.network', '12-dummy.netdev',
3519 '25-qdisc-ingress.network', '11-dummy.netdev')
557fa421 3520 start_networkd()
891ff963 3521 self.wait_online(['dummy98:routable', 'test1:routable'])
557fa421
YW
3522
3523 output = check_output('tc qdisc show dev dummy98')
3524 print(output)
4c7d13f4 3525 self.assertRegex(output, 'qdisc clsact')
557fa421 3526
891ff963
YW
3527 output = check_output('tc qdisc show dev test1')
3528 print(output)
4c7d13f4 3529 self.assertRegex(output, 'qdisc ingress')
891ff963 3530
4c7d13f4
YW
3531 @expectedFailureIfModuleIsNotAvailable('sch_netem')
3532 def test_qdisc_netem(self):
3533 copy_network_unit('25-qdisc-netem.network', '12-dummy.netdev',
3534 '25-qdisc-netem-compat.network', '11-dummy.netdev')
3d55b5a9 3535 start_networkd()
4c7d13f4 3536 self.wait_online(['dummy98:routable', 'test1:routable'])
3d55b5a9
YW
3537
3538 output = check_output('tc qdisc show dev dummy98')
3539 print(output)
4c7d13f4
YW
3540 self.assertRegex(output, 'qdisc netem 30: root')
3541 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
3542
3543 output = check_output('tc qdisc show dev test1')
3544 print(output)
3545 self.assertRegex(output, 'qdisc netem [0-9a-f]*: root')
3546 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
3d55b5a9 3547
854f9899 3548 @expectedFailureIfModuleIsNotAvailable('sch_pie')
be94e591 3549 def test_qdisc_pie(self):
a962d857 3550 copy_network_unit('25-qdisc-pie.network', '12-dummy.netdev')
be94e591
YW
3551 start_networkd()
3552 self.wait_online(['dummy98:routable'])
3553
3554 output = check_output('tc qdisc show dev dummy98')
3555 print(output)
3556 self.assertRegex(output, 'qdisc pie 3a: root')
3557 self.assertRegex(output, 'limit 200000')
3558
4c7d13f4
YW
3559 @expectedFailureIfModuleIsNotAvailable('sch_qfq')
3560 def test_qdisc_qfq(self):
3561 copy_network_unit('25-qdisc-qfq.network', '12-dummy.netdev')
970ab1fc
YW
3562 start_networkd()
3563 self.wait_online(['dummy98:routable'])
3564
3565 output = check_output('tc qdisc show dev dummy98')
3566 print(output)
4c7d13f4
YW
3567 self.assertRegex(output, 'qdisc qfq 2: root')
3568 output = check_output('tc class show dev dummy98')
3569 print(output)
3570 self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000')
3571 self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000')
970ab1fc 3572
4c7d13f4
YW
3573 @expectedFailureIfModuleIsNotAvailable('sch_sfb')
3574 def test_qdisc_sfb(self):
3575 copy_network_unit('25-qdisc-sfb.network', '12-dummy.netdev')
b753e835
YW
3576 start_networkd()
3577 self.wait_online(['dummy98:routable'])
3578
3579 output = check_output('tc qdisc show dev dummy98')
3580 print(output)
4c7d13f4
YW
3581 self.assertRegex(output, 'qdisc sfb 39: root')
3582 self.assertRegex(output, 'limit 200000')
1578266b 3583
4c7d13f4
YW
3584 @expectedFailureIfModuleIsNotAvailable('sch_sfq')
3585 def test_qdisc_sfq(self):
3586 copy_network_unit('25-qdisc-sfq.network', '12-dummy.netdev')
3587 start_networkd()
3588 self.wait_online(['dummy98:routable'])
b753e835 3589
4c7d13f4
YW
3590 output = check_output('tc qdisc show dev dummy98')
3591 print(output)
3592 self.assertRegex(output, 'qdisc sfq 36: root')
3593 self.assertRegex(output, 'perturb 5sec')
3594
3595 @expectedFailureIfModuleIsNotAvailable('sch_tbf')
3596 def test_qdisc_tbf(self):
3597 copy_network_unit('25-qdisc-tbf.network', '12-dummy.netdev')
1578266b
YW
3598 start_networkd()
3599 self.wait_online(['dummy98:routable'])
3600
3601 output = check_output('tc qdisc show dev dummy98')
3602 print(output)
4c7d13f4
YW
3603 self.assertRegex(output, 'qdisc tbf 35: root')
3604 self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms')
1578266b 3605
4c7d13f4
YW
3606 @expectedFailureIfModuleIsNotAvailable('sch_teql')
3607 def test_qdisc_teql(self):
3608 call_quiet('rmmod sch_teql')
3609
3610 copy_network_unit('25-qdisc-teql.network', '12-dummy.netdev')
3611 start_networkd()
3612 self.wait_links('dummy98')
3613 check_output('modprobe sch_teql max_equalizers=2')
3614 self.wait_online(['dummy98:routable'])
3615
3616 output = check_output('tc qdisc show dev dummy98')
3617 print(output)
3618 self.assertRegex(output, 'qdisc teql1 31: root')
1578266b 3619
23b38192
YW
3620class NetworkWaitOnlineTests(unittest.TestCase, Utilities):
3621
3622 def setUp(self):
3623 setup_common()
3624
3625 def tearDown(self):
3626 tear_down_common()
3627
59edcf2b 3628 @expectedFailureIfModuleIsNotAvailable('sch_netem')
70448bb1 3629 def test_wait_online_ipv4(self):
a962d857 3630 copy_network_unit('25-veth.netdev', '25-dhcp-server-with-ipv6-prefix.network', '25-dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network')
70448bb1
L
3631 start_networkd()
3632
3633 self.wait_online(['veth99:routable'], ipv4=True)
3634
3635 self.wait_address('veth99', r'192.168.5.[0-9]+', ipv='-4', timeout_sec=1)
3636
59edcf2b 3637 @expectedFailureIfModuleIsNotAvailable('sch_netem')
70448bb1 3638 def test_wait_online_ipv6(self):
a962d857 3639 copy_network_unit('25-veth.netdev', '25-ipv6-prefix-with-delay.network', '25-ipv6ra-prefix-client-with-static-ipv4-address.network')
70448bb1
L
3640 start_networkd()
3641
3642 self.wait_online(['veth99:routable'], ipv6=True)
3643
3644 self.wait_address('veth99', r'2002:da8:1:0:1034:56ff:fe78:9abc', ipv='-6', timeout_sec=1)
3645
336d18f0 3646class NetworkdStateFileTests(unittest.TestCase, Utilities):
336d18f0
YW
3647
3648 def setUp(self):
a962d857 3649 setup_common()
336d18f0
YW
3650
3651 def tearDown(self):
a962d857 3652 tear_down_common()
336d18f0
YW
3653
3654 def test_state_file(self):
a962d857 3655 copy_network_unit('12-dummy.netdev', '25-state-file-tests.network')
336d18f0
YW
3656 start_networkd()
3657 self.wait_online(['dummy98:routable'])
3658
f91b2340
YW
3659 # make link state file updated
3660 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
336d18f0 3661
94f0bd62
YW
3662 # TODO: check json string
3663 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
3664
1a8e1d78
YW
3665 output = read_link_state_file('dummy98')
3666 print(output)
3667 self.assertIn('IPV4_ADDRESS_STATE=routable', output)
3668 self.assertIn('IPV6_ADDRESS_STATE=routable', output)
3669 self.assertIn('ADMIN_STATE=configured', output)
3670 self.assertIn('OPER_STATE=routable', output)
3671 self.assertIn('REQUIRED_FOR_ONLINE=yes', output)
3672 self.assertIn('REQUIRED_OPER_STATE_FOR_ONLINE=routable', output)
3673 self.assertIn('REQUIRED_FAMILY_FOR_ONLINE=both', output)
3674 self.assertIn('ACTIVATION_POLICY=up', output)
3675 self.assertIn('NETWORK_FILE=/run/systemd/network/25-state-file-tests.network', output)
3676 self.assertIn('DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com [1111:2222::3333]:1234#ccc.com', output)
3677 self.assertIn('NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org', output)
3678 self.assertIn('DOMAINS=hogehoge', output)
3679 self.assertIn('ROUTE_DOMAINS=foofoo', output)
3680 self.assertIn('LLMNR=no', output)
3681 self.assertIn('MDNS=yes', output)
3682 self.assertIn('DNSSEC=no', output)
336d18f0 3683
66479677 3684 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12#ccc.com', '10.10.10.13', '1111:2222::3333', env=env)
336d18f0
YW
3685 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
3686 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
3687 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
3688 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
3689 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
336d18f0 3690
94f0bd62
YW
3691 # TODO: check json string
3692 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
3693
1a8e1d78
YW
3694 output = read_link_state_file('dummy98')
3695 print(output)
3696 self.assertIn('DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333', output)
3697 self.assertIn('NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org', output)
3698 self.assertIn('DOMAINS=hogehogehoge', output)
3699 self.assertIn('ROUTE_DOMAINS=foofoofoo', output)
3700 self.assertIn('LLMNR=yes', output)
3701 self.assertIn('MDNS=no', output)
3702 self.assertIn('DNSSEC=yes', output)
336d18f0
YW
3703
3704 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
336d18f0 3705
94f0bd62
YW
3706 # TODO: check json string
3707 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
3708
1a8e1d78
YW
3709 output = read_link_state_file('dummy98')
3710 print(output)
3711 self.assertIn('DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333', output)
3712 self.assertIn('NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org', output)
3713 self.assertIn('DOMAINS=hogehogehoge', output)
3714 self.assertIn('ROUTE_DOMAINS=foofoofoo', output)
3715 self.assertIn('LLMNR=yes', output)
3716 self.assertIn('MDNS=no', output)
3717 self.assertIn('DNSSEC=yes', output)
336d18f0
YW
3718
3719 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
336d18f0 3720
94f0bd62
YW
3721 # TODO: check json string
3722 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
3723
1a8e1d78
YW
3724 output = read_link_state_file('dummy98')
3725 print(output)
3726 self.assertIn('DNS=10.10.10.10#aaa.com 10.10.10.11:1111#bbb.com [1111:2222::3333]:1234#ccc.com', output)
3727 self.assertIn('NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org', output)
3728 self.assertIn('DOMAINS=hogehoge', output)
3729 self.assertIn('ROUTE_DOMAINS=foofoo', output)
3730 self.assertIn('LLMNR=no', output)
3731 self.assertIn('MDNS=yes', output)
3732 self.assertIn('DNSSEC=no', output)
336d18f0 3733
be68c2c9 3734class NetworkdBondTests(unittest.TestCase, Utilities):
c3a8853f
YW
3735
3736 def setUp(self):
a962d857 3737 setup_common()
c3a8853f
YW
3738
3739 def tearDown(self):
a962d857 3740 tear_down_common()
c3a8853f 3741
b06469a6
YW
3742 def test_bond_keep_master(self):
3743 check_output('ip link add bond199 type bond mode active-backup')
3744 check_output('ip link add dummy98 type dummy')
3745 check_output('ip link set dummy98 master bond199')
3746
a962d857 3747 copy_network_unit('23-keep-master.network')
b06469a6
YW
3748 start_networkd()
3749 self.wait_online(['dummy98:enslaved'])
3750
3751 output = check_output('ip -d link show bond199')
3752 print(output)
3753 self.assertRegex(output, 'active_slave dummy98')
3754
3755 output = check_output('ip -d link show dummy98')
3756 print(output)
3757 self.assertRegex(output, 'master bond199')
3758
c2990ec3 3759 def test_bond_active_slave(self):
a962d857 3760 copy_network_unit('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 3761 start_networkd()
e2aea43f 3762 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 3763
371810d1 3764 output = check_output('ip -d link show bond199')
c2990ec3
YW
3765 print(output)
3766 self.assertRegex(output, 'active_slave dummy98')
3767
3768 def test_bond_primary_slave(self):
a962d857 3769 copy_network_unit('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 3770 start_networkd()
e2aea43f 3771 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 3772
371810d1 3773 output = check_output('ip -d link show bond199')
c2990ec3 3774 print(output)
35a78c51 3775 self.assertRegex(output, 'primary dummy98')
c2990ec3 3776
cc3e488c 3777 def test_bond_operstate(self):
a962d857
YW
3778 copy_network_unit('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
3779 '25-bond99.network', '25-bond-slave.network')
2cf6fdff 3780 start_networkd()
e2aea43f 3781 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
c3a8853f 3782
371810d1 3783 output = check_output('ip -d link show dummy98')
c3a8853f 3784 print(output)
cc3e488c 3785 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 3786
371810d1 3787 output = check_output('ip -d link show test1')
c3a8853f
YW
3788 print(output)
3789 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
3790
371810d1 3791 output = check_output('ip -d link show bond99')
c3a8853f
YW
3792 print(output)
3793 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
3794
19cf3143
DS
3795 self.wait_operstate('dummy98', 'enslaved')
3796 self.wait_operstate('test1', 'enslaved')
3797 self.wait_operstate('bond99', 'routable')
c3a8853f 3798
cefd6b3d 3799 check_output('ip link set dummy98 down')
c3a8853f 3800
19cf3143
DS
3801 self.wait_operstate('dummy98', 'off')
3802 self.wait_operstate('test1', 'enslaved')
3803 self.wait_operstate('bond99', 'degraded-carrier')
c3a8853f 3804
cefd6b3d 3805 check_output('ip link set dummy98 up')
c3a8853f 3806
19cf3143
DS
3807 self.wait_operstate('dummy98', 'enslaved')
3808 self.wait_operstate('test1', 'enslaved')
3809 self.wait_operstate('bond99', 'routable')
c3a8853f 3810
cefd6b3d
ZJS
3811 check_output('ip link set dummy98 down')
3812 check_output('ip link set test1 down')
cc3e488c 3813
19cf3143
DS
3814 self.wait_operstate('dummy98', 'off')
3815 self.wait_operstate('test1', 'off')
2700d2c7 3816
a4632dc7 3817 if not self.wait_operstate('bond99', 'no-carrier', setup_timeout=30, fail_assert=False):
2700d2c7
YW
3818 # Huh? Kernel does not recognize that all slave interfaces are down?
3819 # Let's confirm that networkd's operstate is consistent with ip's result.
3820 self.assertNotRegex(output, 'NO-CARRIER')
cc3e488c 3821
be68c2c9 3822class NetworkdBridgeTests(unittest.TestCase, Utilities):
8d17c386 3823
1f0e3109 3824 def setUp(self):
a962d857 3825 setup_common()
1f0e3109
SS
3826
3827 def tearDown(self):
a962d857 3828 tear_down_common()
1f0e3109 3829
6f943798 3830 def test_bridge_vlan(self):
a962d857
YW
3831 copy_network_unit('11-dummy.netdev', '26-bridge-vlan-slave.network',
3832 '26-bridge.netdev', '26-bridge-vlan-master.network')
6f943798 3833 start_networkd()
e2aea43f 3834 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
6f943798
YW
3835
3836 output = check_output('bridge vlan show dev test1')
3837 print(output)
3838 self.assertNotRegex(output, '4063')
3839 for i in range(4064, 4095):
3840 self.assertRegex(output, f'{i}')
3841 self.assertNotRegex(output, '4095')
3842
3843 output = check_output('bridge vlan show dev bridge99')
3844 print(output)
3845 self.assertNotRegex(output, '4059')
3846 for i in range(4060, 4095):
3847 self.assertRegex(output, f'{i}')
3848 self.assertNotRegex(output, '4095')
3849
988b0660 3850 def test_bridge_vlan_issue_20373(self):
a962d857
YW
3851 copy_network_unit('11-dummy.netdev', '26-bridge-vlan-slave-issue-20373.network',
3852 '26-bridge-issue-20373.netdev', '26-bridge-vlan-master-issue-20373.network',
3853 '21-vlan.netdev', '21-vlan.network')
988b0660
YW
3854 start_networkd()
3855 self.wait_online(['test1:enslaved', 'bridge99:degraded', 'vlan99:routable'])
3856
3857 output = check_output('bridge vlan show dev test1')
3858 print(output)
3859 self.assertIn('100 PVID Egress Untagged', output)
3860 self.assertIn('560', output)
3861 self.assertIn('600', output)
3862
3863 output = check_output('bridge vlan show dev bridge99')
3864 print(output)
3865 self.assertIn('1 PVID Egress Untagged', output)
3866 self.assertIn('100', output)
3867 self.assertIn('600', output)
3868
cc0276cc 3869 def test_bridge_mdb(self):
a962d857
YW
3870 copy_network_unit('11-dummy.netdev', '26-bridge-mdb-slave.network',
3871 '26-bridge.netdev', '26-bridge-mdb-master.network')
cc0276cc
YW
3872 start_networkd()
3873 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
3874
3875 output = check_output('bridge mdb show dev bridge99')
3876 print(output)
3877 self.assertRegex(output, 'dev bridge99 port test1 grp ff02:aaaa:fee5::1:3 permanent *vid 4064')
3878 self.assertRegex(output, 'dev bridge99 port test1 grp 224.0.1.1 permanent *vid 4065')
3879
9f773037 3880 # Old kernel may not support bridge MDB entries on bridge master
a962d857 3881 if call_quiet('bridge mdb add dev bridge99 port bridge99 grp 224.0.1.3 temp vid 4068') == 0:
9f773037
YW
3882 self.assertRegex(output, 'dev bridge99 port bridge99 grp ff02:aaaa:fee5::1:4 temp *vid 4066')
3883 self.assertRegex(output, 'dev bridge99 port bridge99 grp 224.0.1.2 temp *vid 4067')
3884
b06469a6
YW
3885 def test_bridge_keep_master(self):
3886 check_output('ip link add bridge99 type bridge')
3887 check_output('ip link set bridge99 up')
3888 check_output('ip link add dummy98 type dummy')
3889 check_output('ip link set dummy98 master bridge99')
3890
a962d857 3891 copy_network_unit('23-keep-master.network')
b06469a6
YW
3892 start_networkd()
3893 self.wait_online(['dummy98:enslaved'])
3894
3895 output = check_output('ip -d link show dummy98')
3896 print(output)
3897 self.assertRegex(output, 'master bridge99')
3898 self.assertRegex(output, 'bridge')
3899
3900 output = check_output('bridge -d link show dummy98')
3901 print(output)
a962d857
YW
3902 self.check_bridge_port_attr('bridge99', 'dummy98', 'path_cost', '400')
3903 self.check_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode', '1')
3904 self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave', '1')
3905 self.check_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood', '1')
3906 self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood', '0')
b06469a6 3907 # CONFIG_BRIDGE_IGMP_SNOOPING=y
a962d857
YW
3908 self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast', '1', allow_enoent=True)
3909 self.check_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress', '1', allow_enoent=True)
3910 self.check_bridge_port_attr('bridge99', 'dummy98', 'learning', '0')
3911 self.check_bridge_port_attr('bridge99', 'dummy98', 'priority', '23')
3f504b89
YW
3912 self.check_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard', '0')
3913 self.check_bridge_port_attr('bridge99', 'dummy98', 'root_block', '0')
b06469a6 3914
1f0e3109 3915 def test_bridge_property(self):
a962d857
YW
3916 copy_network_unit('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
3917 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
3918 '25-bridge99.network')
2cf6fdff 3919 start_networkd()
e2aea43f 3920 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
1f0e3109 3921
21d0ed68
YW
3922 output = check_output('ip -d link show bridge99')
3923 print(output)
3924 self.assertIn('mtu 9000 ', output)
3925
371810d1 3926 output = check_output('ip -d link show test1')
1f0e3109 3927 print(output)
21d0ed68
YW
3928 self.assertIn('master bridge99 ', output)
3929 self.assertIn('bridge_slave', output)
3930 self.assertIn('mtu 9000 ', output)
1f0e3109 3931
371810d1 3932 output = check_output('ip -d link show dummy98')
1f0e3109 3933 print(output)
21d0ed68
YW
3934 self.assertIn('master bridge99 ', output)
3935 self.assertIn('bridge_slave', output)
3936 self.assertIn('mtu 9000 ', output)
1f0e3109 3937
371810d1 3938 output = check_output('ip addr show bridge99')
1f0e3109 3939 print(output)
21d0ed68 3940 self.assertIn('192.168.0.15/24', output)
1f0e3109 3941
371810d1 3942 output = check_output('bridge -d link show dummy98')
1f0e3109 3943 print(output)
a962d857
YW
3944 self.check_bridge_port_attr('bridge99', 'dummy98', 'path_cost', '400')
3945 self.check_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode', '1')
3946 self.check_bridge_port_attr('bridge99', 'dummy98', 'isolated', '1')
3947 self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave', '1')
3948 self.check_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood', '1')
3949 self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood', '0')
5424fd95 3950 # CONFIG_BRIDGE_IGMP_SNOOPING=y
a962d857
YW
3951 self.check_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast', '1', allow_enoent=True)
3952 self.check_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress', '1', allow_enoent=True)
3953 self.check_bridge_port_attr('bridge99', 'dummy98', 'learning', '0')
3954 self.check_bridge_port_attr('bridge99', 'dummy98', 'priority', '23')
3f504b89
YW
3955 self.check_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard', '0')
3956 self.check_bridge_port_attr('bridge99', 'dummy98', 'root_block', '0')
4d7ed14f 3957
5424fd95
YW
3958 output = check_output('bridge -d link show test1')
3959 print(output)
a962d857 3960 self.check_bridge_port_attr('bridge99', 'test1', 'priority', '0')
1f0e3109 3961
371810d1 3962 check_output('ip address add 192.168.0.16/24 dev bridge99')
371810d1 3963 output = check_output('ip addr show bridge99')
2be6c5d2 3964 print(output)
21d0ed68 3965 self.assertIn('192.168.0.16/24', output)
2be6c5d2 3966
e3cbaeab
YW
3967 # for issue #6088
3968 print('### ip -6 route list table all dev bridge99')
3969 output = check_output('ip -6 route list table all dev bridge99')
3970 print(output)
beb75dd3 3971 self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
e3cbaeab 3972
a962d857 3973 remove_link('test1')
19cf3143 3974 self.wait_operstate('bridge99', 'degraded-carrier')
2be6c5d2 3975
21d0ed68
YW
3976 output = check_output('ip -d link show bridge99')
3977 print(output)
3978 self.assertIn('mtu 9000 ', output)
3979
3980 output = check_output('ip -d link show dummy98')
3981 print(output)
3982 self.assertIn('master bridge99 ', output)
3983 self.assertIn('bridge_slave', output)
3984 self.assertIn('mtu 9000 ', output)
804b6cd2 3985
21d0ed68 3986 remove_link('dummy98')
19cf3143 3987 self.wait_operstate('bridge99', 'no-carrier')
2be6c5d2 3988
21d0ed68
YW
3989 output = check_output('ip -d link show bridge99')
3990 print(output)
3991 # When no carrier, the kernel may reset the MTU
3992 self.assertIn('NO-CARRIER', output)
3993
371810d1 3994 output = check_output('ip address show bridge99')
804b6cd2 3995 print(output)
21d0ed68
YW
3996 self.assertNotIn('192.168.0.15/24', output)
3997 self.assertIn('192.168.0.16/24', output) # foreign address is kept
804b6cd2 3998
e3cbaeab
YW
3999 print('### ip -6 route list table all dev bridge99')
4000 output = check_output('ip -6 route list table all dev bridge99')
4001 print(output)
beb75dd3 4002 self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
e3cbaeab 4003
21d0ed68
YW
4004 check_output('ip link add dummy98 type dummy')
4005 self.wait_online(['dummy98:enslaved', 'bridge99:routable'])
4006
4007 output = check_output('ip -d link show bridge99')
4008 print(output)
4009 self.assertIn('mtu 9000 ', output)
4010
4011 output = check_output('ip -d link show dummy98')
4012 print(output)
4013 self.assertIn('master bridge99 ', output)
4014 self.assertIn('bridge_slave', output)
4015 self.assertIn('mtu 9000 ', output)
4016
0fc0d85f 4017 def test_bridge_configure_without_carrier(self):
a962d857
YW
4018 copy_network_unit('26-bridge.netdev', '26-bridge-configure-without-carrier.network',
4019 '11-dummy.netdev')
0fc0d85f
DS
4020 start_networkd()
4021
4022 # With ConfigureWithoutCarrier=yes, the bridge should remain configured for all these situations
4023 for test in ['no-slave', 'add-slave', 'slave-up', 'slave-no-carrier', 'slave-carrier', 'slave-down']:
4024 with self.subTest(test=test):
4025 if test == 'no-slave':
4026 # bridge has no slaves; it's up but *might* not have carrier
001c07cf 4027 self.wait_operstate('bridge99', operstate=r'(no-carrier|routable)', setup_state=None, setup_timeout=30)
0fc0d85f
DS
4028 # due to a bug in the kernel, newly-created bridges are brought up
4029 # *with* carrier, unless they have had any setting changed; e.g.
4030 # their mac set, priority set, etc. Then, they will lose carrier
4031 # as soon as a (down) slave interface is added, and regain carrier
4032 # again once the slave interface is brought up.
4033 #self.check_link_attr('bridge99', 'carrier', '0')
4034 elif test == 'add-slave':
4035 # add slave to bridge, but leave it down; bridge is definitely no-carrier
4036 self.check_link_attr('test1', 'operstate', 'down')
4037 check_output('ip link set dev test1 master bridge99')
001c07cf 4038 self.wait_operstate('bridge99', operstate='no-carrier', setup_state=None)
0fc0d85f
DS
4039 self.check_link_attr('bridge99', 'carrier', '0')
4040 elif test == 'slave-up':
4041 # bring up slave, which will have carrier; bridge gains carrier
4042 check_output('ip link set dev test1 up')
4043 self.wait_online(['bridge99:routable'])
4044 self.check_link_attr('bridge99', 'carrier', '1')
4045 elif test == 'slave-no-carrier':
4046 # drop slave carrier; bridge loses carrier
4047 check_output('ip link set dev test1 carrier off')
4048 self.wait_online(['bridge99:no-carrier:no-carrier'])
4049 self.check_link_attr('bridge99', 'carrier', '0')
4050 elif test == 'slave-carrier':
4051 # restore slave carrier; bridge gains carrier
4052 check_output('ip link set dev test1 carrier on')
4053 self.wait_online(['bridge99:routable'])
4054 self.check_link_attr('bridge99', 'carrier', '1')
4055 elif test == 'slave-down':
4056 # bring down slave; bridge loses carrier
4057 check_output('ip link set dev test1 down')
4058 self.wait_online(['bridge99:no-carrier:no-carrier'])
4059 self.check_link_attr('bridge99', 'carrier', '0')
4060
4061 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
0fc0d85f
DS
4062 self.assertRegex(output, '10.1.2.3')
4063 self.assertRegex(output, '10.1.2.1')
4064
804b6cd2 4065 def test_bridge_ignore_carrier_loss(self):
a962d857
YW
4066 copy_network_unit('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
4067 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
4068 '25-bridge99-ignore-carrier-loss.network')
2cf6fdff 4069 start_networkd()
e2aea43f 4070 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
804b6cd2 4071
371810d1 4072 check_output('ip address add 192.168.0.16/24 dev bridge99')
a962d857 4073 remove_link('test1', 'dummy98')
804b6cd2
YW
4074 time.sleep(3)
4075
371810d1 4076 output = check_output('ip address show bridge99')
804b6cd2
YW
4077 print(output)
4078 self.assertRegex(output, 'NO-CARRIER')
4079 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
4080 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
4081
6609924c 4082 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
a962d857
YW
4083 copy_network_unit('26-bridge.netdev', '26-bridge-slave-interface-1.network',
4084 '25-bridge99-ignore-carrier-loss.network')
2cf6fdff 4085 start_networkd()
e2aea43f 4086 self.wait_online(['bridge99:no-carrier'])
6609924c 4087
90e3bcbd
YW
4088 for trial in range(4):
4089 check_output('ip link add dummy98 type dummy')
4090 check_output('ip link set dummy98 up')
4091 if trial < 3:
a962d857 4092 remove_link('dummy98')
6609924c 4093
e2aea43f 4094 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
6609924c 4095
371810d1 4096 output = check_output('ip address show bridge99')
6609924c
YW
4097 print(output)
4098 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
4099
371810d1 4100 output = check_output('ip rule list table 100')
6609924c 4101 print(output)
c4f7a347 4102 self.assertIn('from all to 8.8.8.8 lookup 100', output)
6609924c 4103
a03ff4c0 4104class NetworkdSRIOVTests(unittest.TestCase, Utilities):
a03ff4c0
YW
4105
4106 def setUp(self):
a962d857 4107 setup_common()
a03ff4c0
YW
4108
4109 def tearDown(self):
a962d857 4110 tear_down_common()
a03ff4c0
YW
4111
4112 @expectedFailureIfNetdevsimWithSRIOVIsNotAvailable()
4113 def test_sriov(self):
a962d857 4114 call('modprobe netdevsim')
a03ff4c0 4115
d45476ef 4116 with open('/sys/bus/netdevsim/new_device', mode='w', encoding='utf-8') as f:
a03ff4c0
YW
4117 f.write('99 1')
4118
a962d857 4119 with open('/sys/bus/netdevsim/devices/netdevsim99/sriov_numvfs', mode='w', encoding='utf-8') as f:
a03ff4c0
YW
4120 f.write('3')
4121
a962d857 4122 copy_network_unit('25-sriov.network')
a03ff4c0
YW
4123 start_networkd()
4124 self.wait_online(['eni99np1:routable'])
4125
4126 output = check_output('ip link show dev eni99np1')
4127 print(output)
4128 self.assertRegex(output,
4129 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
4130 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
4131 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
a962d857 4132 )
a03ff4c0 4133
1e8e9730
YW
4134 @expectedFailureIfNetdevsimWithSRIOVIsNotAvailable()
4135 def test_sriov_udev(self):
a962d857 4136 copy_network_unit('25-sriov.link', '25-sriov-udev.network')
1e8e9730 4137
a962d857
YW
4138 call('modprobe netdevsim')
4139
d45476ef 4140 with open('/sys/bus/netdevsim/new_device', mode='w', encoding='utf-8') as f:
1e8e9730
YW
4141 f.write('99 1')
4142
4143 start_networkd()
4144 self.wait_online(['eni99np1:routable'])
4145
4146 output = check_output('ip link show dev eni99np1')
4147 print(output)
4148 self.assertRegex(output,
4149 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
4150 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
4151 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
a962d857 4152 )
1e8e9730
YW
4153 self.assertNotIn('vf 3', output)
4154 self.assertNotIn('vf 4', output)
4155
a962d857 4156 with open(os.path.join(network_unit_dir, '25-sriov.link'), mode='a', encoding='utf-8') as f:
1e8e9730
YW
4157 f.write('[Link]\nSR-IOVVirtualFunctions=4\n')
4158
32ab27af 4159 udev_reload()
b05c4d6b 4160 call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1')
1e8e9730
YW
4161
4162 output = check_output('ip link show dev eni99np1')
4163 print(output)
4164 self.assertRegex(output,
4165 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
4166 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
4167 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off\n *'
4168 'vf 3'
a962d857 4169 )
1e8e9730
YW
4170 self.assertNotIn('vf 4', output)
4171
a962d857 4172 with open(os.path.join(network_unit_dir, '25-sriov.link'), mode='a', encoding='utf-8') as f:
1e8e9730
YW
4173 f.write('[Link]\nSR-IOVVirtualFunctions=\n')
4174
32ab27af 4175 udev_reload()
b05c4d6b 4176 call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1')
1e8e9730
YW
4177
4178 output = check_output('ip link show dev eni99np1')
4179 print(output)
4180 self.assertRegex(output,
4181 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
4182 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
4183 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off\n *'
4184 'vf 3'
a962d857 4185 )
1e8e9730
YW
4186 self.assertNotIn('vf 4', output)
4187
a962d857 4188 with open(os.path.join(network_unit_dir, '25-sriov.link'), mode='a', encoding='utf-8') as f:
1e8e9730
YW
4189 f.write('[Link]\nSR-IOVVirtualFunctions=2\n')
4190
32ab27af 4191 udev_reload()
b05c4d6b 4192 call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1')
1e8e9730
YW
4193
4194 output = check_output('ip link show dev eni99np1')
4195 print(output)
4196 self.assertRegex(output,
4197 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
4198 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off'
a962d857 4199 )
1e8e9730
YW
4200 self.assertNotIn('vf 2', output)
4201 self.assertNotIn('vf 3', output)
4202 self.assertNotIn('vf 4', output)
4203
a962d857 4204 with open(os.path.join(network_unit_dir, '25-sriov.link'), mode='a', encoding='utf-8') as f:
1e8e9730
YW
4205 f.write('[Link]\nSR-IOVVirtualFunctions=\n')
4206
32ab27af 4207 udev_reload()
b05c4d6b 4208 call(*udevadm_cmd, 'trigger', '--action=add', '--settle', '/sys/devices/netdevsim99/net/eni99np1')
1e8e9730
YW
4209
4210 output = check_output('ip link show dev eni99np1')
4211 print(output)
4212 self.assertRegex(output,
4213 'vf 0 .*00:11:22:33:44:55.*vlan 5, qos 1, vlan protocol 802.1ad, spoof checking on, link-state enable, trust on, query_rss on\n *'
4214 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
4215 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
a962d857 4216 )
1e8e9730
YW
4217 self.assertNotIn('vf 3', output)
4218 self.assertNotIn('vf 4', output)
4219
be68c2c9 4220class NetworkdLLDPTests(unittest.TestCase, Utilities):
1f0e3109
SS
4221
4222 def setUp(self):
a962d857 4223 setup_common()
1f0e3109
SS
4224
4225 def tearDown(self):
a962d857 4226 tear_down_common()
1f0e3109
SS
4227
4228 def test_lldp(self):
a962d857 4229 copy_network_unit('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2cf6fdff 4230 start_networkd()
e2aea43f 4231 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1f0e3109 4232
f0d87798
YW
4233 for trial in range(10):
4234 if trial > 0:
4235 time.sleep(1)
4236
4237 output = check_output(*networkctl_cmd, 'lldp', env=env)
4238 print(output)
4239 if re.search(r'veth99 .* veth-peer', output):
4240 break
4241 else:
4242 self.fail()
1f0e3109 4243
be68c2c9 4244class NetworkdRATests(unittest.TestCase, Utilities):
1f0e3109
SS
4245
4246 def setUp(self):
a962d857 4247 setup_common()
1f0e3109
SS
4248
4249 def tearDown(self):
a962d857 4250 tear_down_common()
1f0e3109
SS
4251
4252 def test_ipv6_prefix_delegation(self):
a962d857 4253 copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth.network')
2cf6fdff 4254 start_networkd()
e2aea43f 4255 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1f0e3109 4256
41fd8fe7
YW
4257 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4258 print(output)
4259 self.assertRegex(output, 'fe80::')
4260 self.assertRegex(output, '2002:da8:1::1')
4261
80762ccc
YW
4262 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
4263 print(output)
4264 self.assertIn('hogehoge.test', output)
4265
fc79e6ff 4266 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
4267 print(output)
4268 self.assertRegex(output, '2002:da8:1:0')
4269
e2c4070e 4270 def test_ipv6_token_static(self):
a962d857 4271 copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-static.network')
87bbebea 4272 start_networkd()
b241fa00
KF
4273 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
4274
4275 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
4276 print(output)
4277 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
68248f43
YW
4278 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe')
4279 self.assertRegex(output, '2002:da8:2:0:1a:2b:3c:4d')
4280 self.assertRegex(output, '2002:da8:2:0:fa:de:ca:fe')
b241fa00 4281
68248f43 4282 def test_ipv6_token_prefixstable(self):
a962d857 4283 copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-prefixstable.network')
c24c83dc
KF
4284 start_networkd()
4285 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
4286
4287 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
4288 print(output)
7a2e124b
YW
4289 self.assertIn('2002:da8:1:0:b47e:7975:fc7a:7d6e', output)
4290 self.assertIn('2002:da8:2:0:1034:56ff:fe78:9abc', output) # EUI64
c24c83dc 4291
68248f43 4292 def test_ipv6_token_prefixstable_without_address(self):
a962d857 4293 copy_network_unit('25-veth.netdev', '25-ipv6-prefix.network', '25-ipv6-prefix-veth-token-prefixstable-without-address.network')
87bbebea
YW
4294 start_networkd()
4295 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
4296
4297 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
4298 print(output)
7a2e124b
YW
4299 self.assertIn('2002:da8:1:0:b47e:7975:fc7a:7d6e', output)
4300 self.assertIn('2002:da8:2:0:f689:561a:8eda:7443', output)
87bbebea 4301
be68c2c9 4302class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
1f0e3109
SS
4303
4304 def setUp(self):
a962d857 4305 setup_common()
1f0e3109
SS
4306
4307 def tearDown(self):
a962d857 4308 tear_down_common()
1f0e3109
SS
4309
4310 def test_dhcp_server(self):
a962d857 4311 copy_network_unit('25-veth.netdev', '25-dhcp-client.network', '25-dhcp-server.network')
c5f7a087
YW
4312 start_networkd()
4313 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4314
4315 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
4316 print(output)
283863a1 4317 self.assertRegex(output, r'Address: 192.168.5.[0-9]* \(DHCP4 via 192.168.5.1\)')
c5f7a087
YW
4318 self.assertIn('Gateway: 192.168.5.3', output)
4319 self.assertRegex(output, 'DNS: 192.168.5.1\n *192.168.5.10')
4320 self.assertRegex(output, 'NTP: 192.168.5.1\n *192.168.5.11')
4321
4322 def test_dhcp_server_with_uplink(self):
a962d857
YW
4323 copy_network_unit('25-veth.netdev', '25-dhcp-client.network', '25-dhcp-server-downstream.network',
4324 '12-dummy.netdev', '25-dhcp-server-uplink.network')
2cf6fdff 4325 start_networkd()
e2aea43f 4326 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4327
fc79e6ff 4328 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4329 print(output)
283863a1 4330 self.assertRegex(output, r'Address: 192.168.5.[0-9]* \(DHCP4 via 192.168.5.1\)')
32d97330
YW
4331 self.assertIn('Gateway: 192.168.5.3', output)
4332 self.assertIn('DNS: 192.168.5.1', output)
4333 self.assertIn('NTP: 192.168.5.1', output)
1f0e3109 4334
1f0e3109 4335 def test_emit_router_timezone(self):
a962d857 4336 copy_network_unit('25-veth.netdev', '25-dhcp-client-timezone-router.network', '25-dhcp-server-timezone-router.network')
2cf6fdff 4337 start_networkd()
e2aea43f 4338 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4339
fc79e6ff 4340 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4341 print(output)
283863a1 4342 self.assertRegex(output, r'Address: 192.168.5.[0-9]* \(DHCP4 via 192.168.5.1\)')
32d97330
YW
4343 self.assertIn('Gateway: 192.168.5.1', output)
4344 self.assertIn('Time Zone: Europe/Berlin', output)
1f0e3109 4345
ffaece68 4346 def test_dhcp_server_static_lease(self):
a962d857 4347 copy_network_unit('25-veth.netdev', '25-dhcp-client-static-lease.network', '25-dhcp-server-static-lease.network')
ffaece68 4348 start_networkd()
4349 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4350
4351 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
4352 print(output)
32d97330 4353 self.assertIn('Address: 10.1.1.200 (DHCP4 via 10.1.1.1)', output)
ffaece68 4354
c95df587 4355class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities):
c95df587
YA
4356
4357 def setUp(self):
a962d857 4358 setup_common()
c95df587
YA
4359
4360 def tearDown(self):
a962d857 4361 tear_down_common()
c95df587
YA
4362
4363 def test_relay_agent(self):
a962d857
YW
4364 copy_network_unit('25-agent-veth-client.netdev',
4365 '25-agent-veth-server.netdev',
4366 '25-agent-client.network',
4367 '25-agent-server.network',
4368 '25-agent-client-peer.network',
4369 '25-agent-server-peer.network')
c95df587
YA
4370 start_networkd()
4371
c95df587
YA
4372 self.wait_online(['client:routable'])
4373
4374 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'client', env=env)
4375 print(output)
283863a1 4376 self.assertRegex(output, r'Address: 192.168.5.150 \(DHCP4 via 192.168.5.1\)')
c95df587 4377
be68c2c9 4378class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
1f0e3109
SS
4379
4380 def setUp(self):
a962d857 4381 setup_common()
1f0e3109
SS
4382
4383 def tearDown(self):
a962d857 4384 tear_down_common()
1f0e3109
SS
4385
4386 def test_dhcp_client_ipv6_only(self):
a962d857 4387 copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv6-only.network')
1f0e3109 4388
2cf6fdff 4389 start_networkd()
e2aea43f 4390 self.wait_online(['veth-peer:carrier'])
ec38833c 4391 start_dnsmasq()
e2aea43f 4392 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4393
18f2638f
YW
4394 # checking address
4395 output = check_output('ip address show dev veth99 scope global')
c5fcd8a7 4396 print(output)
18f2638f
YW
4397 self.assertRegex(output, r'inet6 2600::[0-9a-f:]*/128 scope global dynamic noprefixroute')
4398 self.assertNotIn('192.168.5', output)
c5fcd8a7 4399
589af70b
YW
4400 # checking semi-static route
4401 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
4402 print(output)
4403 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
4404
3a956d38 4405 # Confirm that ipv6 token is not set in the kernel
371810d1 4406 output = check_output('ip token show dev veth99')
3a956d38
YW
4407 print(output)
4408 self.assertRegex(output, 'token :: dev veth99')
4409
91a7afde
YW
4410 print('## dnsmasq log')
4411 output = read_dnsmasq_log_file()
4412 print(output)
4413 self.assertIn('DHCPSOLICIT(veth-peer)', output)
4414 self.assertNotIn('DHCPADVERTISE(veth-peer)', output)
4415 self.assertNotIn('DHCPREQUEST(veth-peer)', output)
4416 self.assertIn('DHCPREPLY(veth-peer)', output)
4417 self.assertIn('sent size: 0 option: 14 rapid-commit', output)
4418
4419 with open(os.path.join(network_unit_dir, '25-dhcp-client-ipv6-only.network'), mode='a', encoding='utf-8') as f:
4420 f.write('\n[DHCPv6]\nRapidCommit=no\n')
4421
4422 stop_dnsmasq()
4423 start_dnsmasq()
4424
4425 networkctl_reload()
4426 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4427
4428 # checking address
4429 output = check_output('ip address show dev veth99 scope global')
4430 print(output)
4431 self.assertRegex(output, r'inet6 2600::[0-9a-f:]*/128 scope global dynamic noprefixroute')
4432 self.assertNotIn('192.168.5', output)
4433
4434 # checking semi-static route
4435 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
4436 print(output)
4437 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
4438
4439 print('## dnsmasq log')
4440 output = read_dnsmasq_log_file()
4441 print(output)
4442 self.assertIn('DHCPSOLICIT(veth-peer)', output)
4443 self.assertIn('DHCPADVERTISE(veth-peer)', output)
4444 self.assertIn('DHCPREQUEST(veth-peer)', output)
4445 self.assertIn('DHCPREPLY(veth-peer)', output)
4446 self.assertNotIn('rapid-commit', output)
4447
1f0e3109 4448 def test_dhcp_client_ipv4_only(self):
a962d857 4449 copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-ipv4-only.network')
1f0e3109 4450
2cf6fdff 4451 start_networkd()
e2aea43f 4452 self.wait_online(['veth-peer:carrier'])
a962d857
YW
4453 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7',
4454 '--dhcp-option=option:domain-search,example.com',
4455 '--dhcp-alternate-port=67,5555',
4456 ipv4_range='192.168.5.110,192.168.5.119')
e2aea43f 4457 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4458
18f2638f
YW
4459 print('## ip address show dev veth99 scope global')
4460 output = check_output('ip address show dev veth99 scope global')
1f0e3109 4461 print(output)
18f2638f
YW
4462 self.assertIn('mtu 1492', output)
4463 self.assertIn('inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99', output)
4464 self.assertRegex(output, r'inet 192.168.5.11[0-9]/24 metric 24 brd 192.168.5.255 scope global secondary dynamic noprefixroute test-label')
4465 self.assertNotIn('2600::', output)
195a18c1 4466
18f2638f
YW
4467 print('## ip route show table main dev veth99')
4468 output = check_output('ip route show table main dev veth99')
195a18c1 4469 print(output)
18f2638f
YW
4470 # no DHCP routes assigned to the main table
4471 self.assertNotIn('proto dhcp', output)
4472 # static routes
4473 self.assertIn('192.168.5.0/24 proto kernel scope link src 192.168.5.250', output)
4474 self.assertIn('192.168.5.0/24 proto static scope link', output)
4475 self.assertIn('192.168.6.0/24 proto static scope link', output)
4476 self.assertIn('192.168.7.0/24 proto static scope link', output)
4477
4478 print('## ip route show table 211 dev veth99')
4479 output = check_output('ip route show table 211 dev veth99')
4480 print(output)
4481 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.11[0-9] metric 24')
4482 self.assertRegex(output, '192.168.5.0/24 proto dhcp scope link src 192.168.5.11[0-9] metric 24')
4483 self.assertRegex(output, '192.168.5.1 proto dhcp scope link src 192.168.5.11[0-9] metric 24')
4484 self.assertRegex(output, '192.168.5.6 proto dhcp scope link src 192.168.5.11[0-9] metric 24')
4485 self.assertRegex(output, '192.168.5.7 proto dhcp scope link src 192.168.5.11[0-9] metric 24')
4486 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
4487
1a8e1d78
YW
4488 print('## link state file')
4489 output = read_link_state_file('veth99')
4490 print(output)
18f2638f 4491 # checking DNS server and Domains
1a8e1d78
YW
4492 self.assertIn('DNS=192.168.5.6 192.168.5.7', output)
4493 self.assertIn('DOMAINS=example.com', output)
195a18c1 4494
18f2638f 4495 print('## dnsmasq log')
063c7e9b
YW
4496 output = read_dnsmasq_log_file()
4497 print(output)
4498 self.assertIn('vendor class: FooBarVendorTest', output)
4499 self.assertIn('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc', output)
4500 self.assertIn('client provides name: test-hostname', output)
4501 self.assertIn('26:mtu', output)
18f2638f
YW
4502
4503 # change address range, DNS servers, and Domains
888f57c1 4504 stop_dnsmasq()
a962d857
YW
4505 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8',
4506 '--dhcp-option=option:domain-search,foo.example.com',
4507 '--dhcp-alternate-port=67,5555',
4508 ipv4_range='192.168.5.120,192.168.5.129',)
195a18c1
YW
4509
4510 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
a102a52c 4511 print('Wait for the DHCP lease to be expired')
4b31fc88
YW
4512 self.wait_address_dropped('veth99', r'inet 192.168.5.11[0-9]*/24', ipv='-4', timeout_sec=120)
4513 self.wait_address('veth99', r'inet 192.168.5.12[0-9]*/24', ipv='-4')
195a18c1
YW
4514
4515 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4516
18f2638f
YW
4517 print('## ip address show dev veth99 scope global')
4518 output = check_output('ip address show dev veth99 scope global')
195a18c1 4519 print(output)
18f2638f
YW
4520 self.assertIn('mtu 1492', output)
4521 self.assertIn('inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99', output)
4522 self.assertNotIn('192.168.5.11', output)
4523 self.assertRegex(output, r'inet 192.168.5.12[0-9]/24 metric 24 brd 192.168.5.255 scope global secondary dynamic noprefixroute test-label')
4524 self.assertNotIn('2600::', output)
195a18c1 4525
18f2638f
YW
4526 print('## ip route show table main dev veth99')
4527 output = check_output('ip route show table main dev veth99')
195a18c1 4528 print(output)
18f2638f
YW
4529 # no DHCP routes assigned to the main table
4530 self.assertNotIn('proto dhcp', output)
4531 # static routes
4532 self.assertIn('192.168.5.0/24 proto kernel scope link src 192.168.5.250', output)
4533 self.assertIn('192.168.5.0/24 proto static scope link', output)
4534 self.assertIn('192.168.6.0/24 proto static scope link', output)
4535 self.assertIn('192.168.7.0/24 proto static scope link', output)
4536
4537 print('## ip route show table 211 dev veth99')
4538 output = check_output('ip route show table 211 dev veth99')
4539 print(output)
4540 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.12[0-9] metric 24')
4541 self.assertRegex(output, '192.168.5.0/24 proto dhcp scope link src 192.168.5.12[0-9] metric 24')
4542 self.assertRegex(output, '192.168.5.1 proto dhcp scope link src 192.168.5.12[0-9] metric 24')
4543 self.assertNotIn('192.168.5.6', output)
4544 self.assertRegex(output, '192.168.5.7 proto dhcp scope link src 192.168.5.12[0-9] metric 24')
4545 self.assertRegex(output, '192.168.5.8 proto dhcp scope link src 192.168.5.12[0-9] metric 24')
4546 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
4547
1a8e1d78
YW
4548 print('## link state file')
4549 output = read_link_state_file('veth99')
4550 print(output)
18f2638f 4551 # checking DNS server and Domains
1a8e1d78
YW
4552 self.assertIn('DNS=192.168.5.1 192.168.5.7 192.168.5.8', output)
4553 self.assertIn('DOMAINS=foo.example.com', output)
18f2638f
YW
4554
4555 print('## dnsmasq log')
063c7e9b
YW
4556 output = read_dnsmasq_log_file()
4557 print(output)
4558 self.assertIn('vendor class: FooBarVendorTest', output)
4559 self.assertIn('DHCPDISCOVER(veth-peer) 192.168.5.11', output)
4560 self.assertIn('client provides name: test-hostname', output)
4561 self.assertIn('26:mtu', output)
1f0e3109 4562
7c0d36ff 4563 def test_dhcp_client_ipv4_use_routes_gateway(self):
a962d857 4564 first = True
e1220a70 4565 for (routes, gateway, dns_and_ntp_routes, classless) in itertools.product([True, False], repeat=4):
a962d857
YW
4566 if first:
4567 first = False
4568 else:
4569 self.tearDown()
4570
4571 print(f'### test_dhcp_client_ipv4_use_routes_gateway(routes={routes}, gateway={gateway}, dns_and_ntp_routes={dns_and_ntp_routes}, classless={classless})')
e1220a70
YW
4572 with self.subTest(routes=routes, gateway=gateway, dns_and_ntp_routes=dns_and_ntp_routes, classless=classless):
4573 self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dns_and_ntp_routes, classless)
7c0d36ff 4574
e1220a70 4575 def _test_dhcp_client_ipv4_use_routes_gateway(self, use_routes, use_gateway, dns_and_ntp_routes, classless):
1e86c833
DDM
4576 testunit = '25-dhcp-client-ipv4-use-routes-use-gateway.network'
4577 testunits = ['25-veth.netdev', '25-dhcp-server-veth-peer.network', testunit]
6983bb0e
FS
4578 testunits.append(f'{testunit}.d/use-routes-{use_routes}.conf')
4579 testunits.append(f'{testunit}.d/use-gateway-{use_gateway}.conf')
4580 testunits.append(f'{testunit}.d/use-dns-and-ntp-routes-{dns_and_ntp_routes}.conf')
a962d857 4581 copy_network_unit(*testunits, copy_dropins=False)
4c2e1833
YW
4582
4583 start_networkd()
4584 self.wait_online(['veth-peer:carrier'])
a962d857
YW
4585 additional_options = [
4586 '--dhcp-option=option:dns-server,192.168.5.10,8.8.8.8',
4587 '--dhcp-option=option:ntp-server,192.168.5.11,9.9.9.9',
4588 '--dhcp-option=option:static-route,192.168.5.100,192.168.5.2,8.8.8.8,192.168.5.3'
4589 ]
625772c9 4590 if classless:
a962d857
YW
4591 additional_options += [
4592 '--dhcp-option=option:classless-static-route,0.0.0.0/0,192.168.5.4,8.0.0.0/8,192.168.5.5'
4593 ]
4594 start_dnsmasq(*additional_options)
4c2e1833
YW
4595 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4596
625772c9 4597 output = check_output('ip -4 route show dev veth99')
4c2e1833 4598 print(output)
4c2e1833 4599
7c0d36ff 4600 # Check UseRoutes=
625772c9
YW
4601 if use_routes:
4602 if classless:
4603 self.assertRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
4604 self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
4605 self.assertRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4606 self.assertRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4607 else:
4608 self.assertRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4609 self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024')
4610 self.assertRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4611 else:
625772c9
YW
4612 self.assertNotRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
4613 self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
4614 self.assertNotRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4615 self.assertNotRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4616 self.assertNotRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4617 self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024')
4618 self.assertNotRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
0d7bd445 4619
7c0d36ff 4620 # Check UseGateway=
625772c9
YW
4621 if use_gateway and (not classless or not use_routes):
4622 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4623 else:
625772c9 4624 self.assertNotRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
87e62d32
YW
4625
4626 # Check route to gateway
4627 if (use_gateway or dns_and_ntp_routes) and (not classless or not use_routes):
4628 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4629 else:
625772c9 4630 self.assertNotRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4631
e1220a70
YW
4632 # Check RoutesToDNS= and RoutesToNTP=
4633 if dns_and_ntp_routes:
625772c9 4634 self.assertRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
e1220a70 4635 self.assertRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
625772c9
YW
4636 if classless and use_routes:
4637 self.assertRegex(output, r'8.8.8.8 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4638 self.assertRegex(output, r'9.9.9.9 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
87e62d32 4639 else:
625772c9 4640 self.assertRegex(output, r'8.8.8.8 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4641 self.assertRegex(output, r'9.9.9.9 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4642 else:
625772c9 4643 self.assertNotRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
e1220a70 4644 self.assertNotRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
625772c9 4645 self.assertNotRegex(output, r'8.8.8.8 via 192.168.5.[0-9]* proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4646 self.assertNotRegex(output, r'9.9.9.9 via 192.168.5.[0-9]* proto dhcp src 192.168.5.[0-9]* metric 1024')
0d7bd445 4647
94f0bd62
YW
4648 # TODO: check json string
4649 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
4650
1f0e3109 4651 def test_dhcp_client_settings_anonymize(self):
a962d857 4652 copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-anonymize.network')
2cf6fdff 4653 start_networkd()
e2aea43f 4654 self.wait_online(['veth-peer:carrier'])
ec38833c 4655 start_dnsmasq()
e2aea43f 4656 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4657
063c7e9b
YW
4658 print('## dnsmasq log')
4659 output = read_dnsmasq_log_file()
4660 print(output)
4661 self.assertNotIn('VendorClassIdentifier=SusantVendorTest', output)
4662 self.assertNotIn('test-hostname', output)
4663 self.assertNotIn('26:mtu', output)
1f0e3109 4664
1e498853 4665 def test_dhcp_keep_configuration_dhcp(self):
a962d857
YW
4666 copy_network_unit('25-veth.netdev',
4667 '25-dhcp-server-veth-peer.network',
4668 '25-dhcp-client-keep-configuration-dhcp.network')
2cf6fdff 4669 start_networkd()
e2aea43f 4670 self.wait_online(['veth-peer:carrier'])
a962d857 4671 start_dnsmasq()
e2aea43f 4672 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4673
1e498853
YW
4674 output = check_output('ip address show dev veth99 scope global')
4675 print(output)
2b6a24a6
YW
4676 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global veth99\n *'
4677 'valid_lft forever preferred_lft forever')
e40a58b5 4678
5238e957 4679 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
888f57c1 4680 stop_dnsmasq()
1f0e3109
SS
4681
4682 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
a102a52c
YW
4683 print('Wait for the DHCP lease to be expired')
4684 time.sleep(120)
1f0e3109 4685
2b6a24a6 4686 # The lease address should be kept after the lease expired
1e498853
YW
4687 output = check_output('ip address show dev veth99 scope global')
4688 print(output)
2b6a24a6
YW
4689 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global veth99\n *'
4690 'valid_lft forever preferred_lft forever')
1e498853 4691
2b6a24a6 4692 stop_networkd()
1e498853 4693
2b6a24a6 4694 # The lease address should be kept after networkd stopped
1e498853
YW
4695 output = check_output('ip address show dev veth99 scope global')
4696 print(output)
2b6a24a6
YW
4697 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global veth99\n *'
4698 'valid_lft forever preferred_lft forever')
1e498853 4699
a962d857 4700 with open(os.path.join(network_unit_dir, '25-dhcp-client-keep-configuration-dhcp.network'), mode='a', encoding='utf-8') as f:
2347b6b9 4701 f.write('[Network]\nDHCP=no\n')
1e498853 4702
2347b6b9
YW
4703 start_networkd()
4704 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853 4705
2b6a24a6 4706 # Still the lease address should be kept after networkd restarted
1e498853
YW
4707 output = check_output('ip address show dev veth99 scope global')
4708 print(output)
2b6a24a6
YW
4709 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global veth99\n *'
4710 'valid_lft forever preferred_lft forever')
1e498853
YW
4711
4712 def test_dhcp_keep_configuration_dhcp_on_stop(self):
a962d857
YW
4713 copy_network_unit('25-veth.netdev',
4714 '25-dhcp-server-veth-peer.network',
4715 '25-dhcp-client-keep-configuration-dhcp-on-stop.network')
2cf6fdff 4716 start_networkd()
e2aea43f 4717 self.wait_online(['veth-peer:carrier'])
a962d857 4718 start_dnsmasq()
e2aea43f 4719 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853
YW
4720
4721 output = check_output('ip address show dev veth99 scope global')
4722 print(output)
2b6a24a6 4723 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
1e498853 4724
888f57c1 4725 stop_dnsmasq()
2b6a24a6 4726 stop_networkd()
1e498853
YW
4727
4728 output = check_output('ip address show dev veth99 scope global')
4729 print(output)
2b6a24a6 4730 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
1e498853 4731
a962d857 4732 start_networkd()
e2aea43f 4733 self.wait_online(['veth-peer:routable'])
1e498853
YW
4734
4735 output = check_output('ip address show dev veth99 scope global')
4736 print(output)
2b6a24a6 4737 self.assertNotIn('192.168.5.', output)
1f0e3109 4738
30d3b54e 4739 def test_dhcp_client_reuse_address_as_static(self):
a962d857 4740 copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client.network')
2cf6fdff 4741 start_networkd()
e2aea43f 4742 self.wait_online(['veth-peer:carrier'])
ec38833c 4743 start_dnsmasq()
e2aea43f 4744 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
4745
4746 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4747 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4748 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 4749
371810d1 4750 output = check_output('ip address show dev veth99 scope global')
15519a81
YW
4751 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output).group()
4752 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output).group()
4753 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address, 'Address=' + ipv6_address])
30d3b54e
YW
4754 print(static_network)
4755
a962d857 4756 remove_network_unit('25-dhcp-client.network')
30d3b54e 4757
a962d857 4758 with open(os.path.join(network_unit_dir, '25-static.network'), mode='w', encoding='utf-8') as f:
30d3b54e
YW
4759 f.write(static_network)
4760
15519a81
YW
4761 restart_networkd()
4762 self.wait_online(['veth99:routable'])
30d3b54e 4763
371810d1 4764 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e 4765 print(output)
15519a81
YW
4766 self.assertRegex(output, f'inet {ipv4_address} brd 192.168.5.255 scope global veth99\n *'
4767 'valid_lft forever preferred_lft forever')
30d3b54e 4768
371810d1 4769 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e 4770 print(output)
15519a81
YW
4771 self.assertRegex(output, f'inet6 {ipv6_address} scope global *\n *'
4772 'valid_lft forever preferred_lft forever')
30d3b54e 4773
18c613dc
YW
4774 @expectedFailureIfModuleIsNotAvailable('vrf')
4775 def test_dhcp_client_vrf(self):
a962d857
YW
4776 copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client-vrf.network',
4777 '25-vrf.netdev', '25-vrf.network')
2cf6fdff 4778 start_networkd()
e2aea43f 4779 self.wait_online(['veth-peer:carrier'])
ec38833c 4780 start_dnsmasq()
e2aea43f 4781 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
4782
4783 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4784 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4785 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
4786
4787 print('## ip -d link show dev vrf99')
371810d1 4788 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
4789 print(output)
4790 self.assertRegex(output, 'vrf table 42')
4791
4792 print('## ip address show vrf vrf99')
371810d1 4793 output = check_output('ip address show vrf vrf99')
d90f4f7d 4794 print(output)
3e726c15 4795 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4796 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
d90f4f7d 4797 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
4798
4799 print('## ip address show dev veth99')
371810d1 4800 output = check_output('ip address show dev veth99')
18c613dc 4801 print(output)
3e726c15 4802 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4803 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
4804 self.assertRegex(output, 'inet6 .* scope link')
4805
4806 print('## ip route show vrf vrf99')
371810d1 4807 output = check_output('ip route show vrf vrf99')
18c613dc
YW
4808 print(output)
4809 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
18c613dc 4810 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
18c613dc
YW
4811 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
4812
4813 print('## ip route show table main dev veth99')
371810d1 4814 output = check_output('ip route show table main dev veth99')
18c613dc
YW
4815 print(output)
4816 self.assertEqual(output, '')
4817
af3b1498 4818 def test_dhcp_client_gateway_onlink_implicit(self):
a962d857
YW
4819 copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network',
4820 '25-dhcp-client-gateway-onlink-implicit.network')
2cf6fdff 4821 start_networkd()
e2aea43f 4822 self.wait_online(['veth-peer:carrier'])
ec38833c 4823 start_dnsmasq()
e2aea43f 4824 self.wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 4825
fc79e6ff 4826 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
af3b1498
YW
4827 print(output)
4828 self.assertRegex(output, '192.168.5')
4829
371810d1 4830 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
4831 print(output)
4832 self.assertRegex(output, 'onlink')
371810d1 4833 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
4834 print(output)
4835 self.assertRegex(output, 'onlink')
4836
2d7a594f 4837 def test_dhcp_client_with_ipv4ll(self):
a962d857
YW
4838 copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network',
4839 '25-dhcp-client-with-ipv4ll.network')
2cf6fdff 4840 start_networkd()
2d7a594f
YW
4841 # we need to increase timeout above default, as this will need to wait for
4842 # systemd-networkd to get the dhcpv4 transient failure event
4843 self.wait_online(['veth99:degraded', 'veth-peer:routable'], timeout='60s')
63c598ed 4844
2d7a594f 4845 output = check_output('ip -4 address show dev veth99')
63c598ed 4846 print(output)
2d7a594f 4847 self.assertNotIn('192.168.5.', output)
72c747e6 4848 self.assertIn('inet 169.254.133.11/16 metric 2048 brd 169.254.255.255 scope link', output)
63c598ed 4849
a962d857 4850 start_dnsmasq()
2d7a594f
YW
4851 print('Wait for a DHCP lease to be acquired and the IPv4LL address to be dropped')
4852 self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4')
4853 self.wait_address_dropped('veth99', r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link', scope='link', ipv='-4')
4854 self.wait_online(['veth99:routable'])
63c598ed 4855
2d7a594f 4856 output = check_output('ip -4 address show dev veth99')
63c598ed 4857 print(output)
3e726c15 4858 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
2d7a594f
YW
4859 self.assertNotIn('169.254.', output)
4860 self.assertNotIn('scope link', output)
63c598ed 4861
2d7a594f
YW
4862 stop_dnsmasq()
4863 print('Wait for the DHCP lease to be expired and an IPv4LL address to be acquired')
286bf3a9 4864 self.wait_address_dropped('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4', timeout_sec=130)
72c747e6 4865 self.wait_address('veth99', r'inet 169\.254\.133\.11/16 metric 2048 brd 169\.254\.255\.255 scope link', scope='link', ipv='-4')
117a55c7 4866
2d7a594f 4867 output = check_output('ip -4 address show dev veth99')
117a55c7 4868 print(output)
2d7a594f 4869 self.assertNotIn('192.168.5.', output)
72c747e6 4870 self.assertIn('inet 169.254.133.11/16 metric 2048 brd 169.254.255.255 scope link', output)
240e4137 4871
3d8e0aa2
YW
4872 def test_dhcp_client_use_dns(self):
4873 def check(self, ipv4, ipv6):
a962d857
YW
4874 os.makedirs(os.path.join(network_unit_dir, '25-dhcp-client.network.d'), exist_ok=True)
4875 with open(os.path.join(network_unit_dir, '25-dhcp-client.network.d/override.conf'), mode='w', encoding='utf-8') as f:
3d8e0aa2
YW
4876 f.write('[DHCPv4]\nUseDNS=')
4877 f.write('yes' if ipv4 else 'no')
4878 f.write('\n[DHCPv6]\nUseDNS=')
4879 f.write('yes' if ipv6 else 'no')
4880 f.write('\n[IPv6AcceptRA]\nUseDNS=no')
4881
a962d857 4882 networkctl_reload()
3d8e0aa2 4883 self.wait_online(['veth99:routable'])
e2d5aab3 4884
3d8e0aa2
YW
4885 # link becomes 'routable' when at least one protocol provide an valid address. Hence, we need to explicitly wait for both addresses.
4886 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic', ipv='-4')
4887 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4888
3d8e0aa2
YW
4889 # make resolved re-read the link state file
4890 check_output(*resolvectl_cmd, 'revert', 'veth99', env=env)
e2d5aab3 4891
3d8e0aa2
YW
4892 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4893 print(output)
4894 if ipv4:
4895 self.assertIn('192.168.5.1', output)
4896 else:
4897 self.assertNotIn('192.168.5.1', output)
4898 if ipv6:
4899 self.assertIn('2600::1', output)
4900 else:
4901 self.assertNotIn('2600::1', output)
e2d5aab3 4902
3d8e0aa2
YW
4903 # TODO: check json string
4904 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
e2d5aab3 4905
a962d857 4906 copy_network_unit('25-veth.netdev', '25-dhcp-server-veth-peer.network', '25-dhcp-client.network', copy_dropins=False)
e2d5aab3
YW
4907
4908 start_networkd()
e2aea43f 4909 self.wait_online(['veth-peer:carrier'])
a962d857
YW
4910 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1',
4911 '--dhcp-option=option6:dns-server,[2600::1]')
e2d5aab3 4912
3d8e0aa2
YW
4913 check(self, True, True)
4914 check(self, True, False)
4915 check(self, False, True)
4916 check(self, False, False)
e2d5aab3 4917
a27588d4 4918class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
caad88a2
YW
4919
4920 def setUp(self):
a962d857 4921 setup_common()
caad88a2
YW
4922
4923 def tearDown(self):
a962d857 4924 tear_down_common()
caad88a2
YW
4925
4926 def test_dhcp6pd(self):
a962d857
YW
4927 copy_network_unit('25-veth.netdev', '25-dhcp6pd-server.network', '25-dhcp6pd-upstream.network',
4928 '25-veth-downstream-veth97.netdev', '25-dhcp-pd-downstream-veth97.network', '25-dhcp-pd-downstream-veth97-peer.network',
4929 '25-veth-downstream-veth98.netdev', '25-dhcp-pd-downstream-veth98.network', '25-dhcp-pd-downstream-veth98-peer.network',
4930 '11-dummy.netdev', '25-dhcp-pd-downstream-test1.network',
4931 '25-dhcp-pd-downstream-dummy97.network',
4932 '12-dummy.netdev', '25-dhcp-pd-downstream-dummy98.network',
4933 '13-dummy.netdev', '25-dhcp-pd-downstream-dummy99.network')
caad88a2
YW
4934
4935 start_networkd()
133f65ef 4936 self.wait_online(['veth-peer:routable'])
a962d857 4937 start_isc_dhcpd(conf_file='isc-dhcpd-dhcp6pd.conf', ipv='-6')
133f65ef 4938 self.wait_online(['veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded',
6c8d6bdd 4939 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable'])
caad88a2
YW
4940
4941 print('### ip -6 address show dev veth-peer scope global')
4942 output = check_output('ip -6 address show dev veth-peer scope global')
4943 print(output)
4944 self.assertIn('inet6 3ffe:501:ffff:100::1/64 scope global', output)
4945
f7805a6c
FS
4946 # Link Subnet IDs
4947 # test1: 0x00
4948 # dummy97: 0x01 (The link will appear later)
07b7337a
YW
4949 # dummy98: 0x00
4950 # dummy99: auto -> 0x02 (No address assignment)
f7805a6c
FS
4951 # veth97: 0x08
4952 # veth98: 0x09
38488bab 4953 # veth99: 0x10
6016f1cf 4954
caad88a2
YW
4955 print('### ip -6 address show dev veth99 scope global')
4956 output = check_output('ip -6 address show dev veth99 scope global')
4957 print(output)
4958 # IA_NA
4959 self.assertRegex(output, 'inet6 3ffe:501:ffff:100::[0-9]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
4960 # address in IA_PD (Token=static)
38488bab 4961 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]10:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic')
caad88a2 4962 # address in IA_PD (Token=eui64)
38488bab
YW
4963 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]10:1034:56ff:fe78:9abc/64 (metric 256 |)scope global dynamic')
4964 # address in IA_PD (temporary)
4965 # Note that the temporary addresses may appear after the link enters configured state
4966 self.wait_address('veth99', 'inet6 3ffe:501:ffff:[2-9a-f]10:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
caad88a2
YW
4967
4968 print('### ip -6 address show dev test1 scope global')
4969 output = check_output('ip -6 address show dev test1 scope global')
4970 print(output)
4971 # address in IA_PD (Token=static)
4972 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
4973 # address in IA_PD (temporary)
4974 self.wait_address('test1', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
4975
4976 print('### ip -6 address show dev dummy98 scope global')
4977 output = check_output('ip -6 address show dev dummy98 scope global')
4978 print(output)
4979 # address in IA_PD (Token=static)
07b7337a 4980 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
caad88a2 4981 # address in IA_PD (temporary)
07b7337a 4982 self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
6016f1cf
YW
4983
4984 print('### ip -6 address show dev dummy99 scope global')
4985 output = check_output('ip -6 address show dev dummy99 scope global')
4986 print(output)
4987 # Assign=no
07b7337a 4988 self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02')
caad88a2 4989
6c8d6bdd
YW
4990 print('### ip -6 address show dev veth97 scope global')
4991 output = check_output('ip -6 address show dev veth97 scope global')
4992 print(output)
4993 # address in IA_PD (Token=static)
4994 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
4995 # address in IA_PD (Token=eui64)
4996 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1034:56ff:fe78:9ace/64 (metric 256 |)scope global dynamic mngtmpaddr')
4997 # address in IA_PD (temporary)
4998 self.wait_address('veth97', 'inet6 3ffe:501:ffff:[2-9a-f]08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
4999
5000 print('### ip -6 address show dev veth97-peer scope global')
5001 output = check_output('ip -6 address show dev veth97-peer scope global')
5002 print(output)
5003 # NDisc address (Token=static)
5004 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
5005 # NDisc address (Token=eui64)
5006 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1034:56ff:fe78:9acf/64 (metric 256 |)scope global dynamic mngtmpaddr')
5007 # NDisc address (temporary)
5008 self.wait_address('veth97-peer', 'inet6 3ffe:501:ffff:[2-9a-f]08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
5009
caad88a2
YW
5010 print('### ip -6 address show dev veth98 scope global')
5011 output = check_output('ip -6 address show dev veth98 scope global')
5012 print(output)
5013 # address in IA_PD (Token=static)
5014 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5015 # address in IA_PD (Token=eui64)
5016 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1034:56ff:fe78:9abe/64 (metric 256 |)scope global dynamic mngtmpaddr')
5017 # address in IA_PD (temporary)
5018 self.wait_address('veth98', 'inet6 3ffe:501:ffff:[2-9a-f]09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
5019
5020 print('### ip -6 address show dev veth98-peer scope global')
5021 output = check_output('ip -6 address show dev veth98-peer scope global')
5022 print(output)
5023 # NDisc address (Token=static)
5024 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
5025 # NDisc address (Token=eui64)
5026 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1034:56ff:fe78:9abf/64 (metric 256 |)scope global dynamic mngtmpaddr')
5027 # NDisc address (temporary)
5028 self.wait_address('veth98-peer', 'inet6 3ffe:501:ffff:[2-9a-f]09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
5029
caad88a2
YW
5030 print('### ip -6 route show type unreachable')
5031 output = check_output('ip -6 route show type unreachable')
5032 print(output)
5033 self.assertRegex(output, 'unreachable 3ffe:501:ffff:[2-9a-f]00::/56 dev lo proto dhcp')
5034
5035 print('### ip -6 route show dev veth99')
5036 output = check_output('ip -6 route show dev veth99')
5037 print(output)
38488bab 5038 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]10::/64 proto kernel metric [0-9]* expires')
caad88a2
YW
5039
5040 print('### ip -6 route show dev test1')
5041 output = check_output('ip -6 route show dev test1')
5042 print(output)
5043 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/64 proto kernel metric [0-9]* expires')
5044
5045 print('### ip -6 route show dev dummy98')
5046 output = check_output('ip -6 route show dev dummy98')
5047 print(output)
07b7337a 5048 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/64 proto kernel metric [0-9]* expires')
caad88a2
YW
5049
5050 print('### ip -6 route show dev dummy99')
5051 output = check_output('ip -6 route show dev dummy99')
5052 print(output)
07b7337a 5053 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto dhcp metric [0-9]* expires')
6016f1cf
YW
5054
5055 print('### ip -6 route show dev veth97')
5056 output = check_output('ip -6 route show dev veth97')
5057 print(output)
5058 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]08::/64 proto kernel metric [0-9]* expires')
5059
5060 print('### ip -6 route show dev veth97-peer')
5061 output = check_output('ip -6 route show dev veth97-peer')
5062 print(output)
5063 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]08::/64 proto ra metric [0-9]* expires')
caad88a2
YW
5064
5065 print('### ip -6 route show dev veth98')
5066 output = check_output('ip -6 route show dev veth98')
5067 print(output)
5068 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]09::/64 proto kernel metric [0-9]* expires')
5069
5070 print('### ip -6 route show dev veth98-peer')
5071 output = check_output('ip -6 route show dev veth98-peer')
5072 print(output)
5073 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]09::/64 proto ra metric [0-9]* expires')
5074
5075 # Test case for a downstream which appears later
5076 check_output('ip link add dummy97 type dummy')
5077 self.wait_online(['dummy97:routable'])
5078
5079 print('### ip -6 address show dev dummy97 scope global')
5080 output = check_output('ip -6 address show dev dummy97 scope global')
5081 print(output)
5082 # address in IA_PD (Token=static)
6016f1cf 5083 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]01:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
caad88a2 5084 # address in IA_PD (temporary)
6016f1cf 5085 self.wait_address('dummy97', 'inet6 3ffe:501:ffff:[2-9a-f]01:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
caad88a2
YW
5086
5087 print('### ip -6 route show dev dummy97')
5088 output = check_output('ip -6 route show dev dummy97')
5089 print(output)
6016f1cf 5090 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]01::/64 proto kernel metric [0-9]* expires')
caad88a2
YW
5091
5092 # Test case for reconfigure
a962d857 5093 networkctl_reconfigure('dummy98', 'dummy99')
8d2a5502 5094 self.wait_online(['dummy98:routable', 'dummy99:degraded'])
caad88a2
YW
5095
5096 print('### ip -6 address show dev dummy98 scope global')
5097 output = check_output('ip -6 address show dev dummy98 scope global')
5098 print(output)
5099 # address in IA_PD (Token=static)
07b7337a 5100 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
caad88a2 5101 # address in IA_PD (temporary)
07b7337a 5102 self.wait_address('dummy98', 'inet6 3ffe:501:ffff:[2-9a-f]00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
6016f1cf
YW
5103
5104 print('### ip -6 address show dev dummy99 scope global')
5105 output = check_output('ip -6 address show dev dummy99 scope global')
5106 print(output)
5107 # Assign=no
07b7337a 5108 self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02')
caad88a2
YW
5109
5110 print('### ip -6 route show dev dummy98')
5111 output = check_output('ip -6 route show dev dummy98')
5112 print(output)
07b7337a 5113 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/64 proto kernel metric [0-9]* expires')
6016f1cf
YW
5114
5115 print('### ip -6 route show dev dummy99')
5116 output = check_output('ip -6 route show dev dummy99')
5117 print(output)
07b7337a 5118 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto dhcp metric [0-9]* expires')
caad88a2 5119
6a936c9c 5120 def verify_dhcp4_6rd(self, tunnel_name):
84cc85f9
YW
5121 print('### ip -4 address show dev veth-peer scope global')
5122 output = check_output('ip -4 address show dev veth-peer scope global')
5123 print(output)
5124 self.assertIn('inet 10.0.0.1/8 brd 10.255.255.255 scope global veth-peer', output)
5125
f7805a6c
FS
5126 # Link Subnet IDs
5127 # test1: 0x00
5128 # dummy97: 0x01 (The link will appear later)
07b7337a
YW
5129 # dummy98: 0x00
5130 # dummy99: auto -> 0x0[23] (No address assignment)
5131 # 6rd-XXX: auto -> 0x0[23]
f7805a6c
FS
5132 # veth97: 0x08
5133 # veth98: 0x09
5134 # veth99: 0x10
84cc85f9
YW
5135
5136 print('### ip -4 address show dev veth99 scope global')
5137 output = check_output('ip -4 address show dev veth99 scope global')
5138 print(output)
5139 self.assertRegex(output, 'inet 10.100.100.[0-9]*/8 (metric 1024 |)brd 10.255.255.255 scope global dynamic veth99')
5140
5141 print('### ip -6 address show dev veth99 scope global')
5142 output = check_output('ip -6 address show dev veth99 scope global')
5143 print(output)
5144 # address in IA_PD (Token=static)
5145 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+10:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5146 # address in IA_PD (Token=eui64)
5147 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+10:1034:56ff:fe78:9abc/64 (metric 256 |)scope global dynamic mngtmpaddr')
5148 # address in IA_PD (temporary)
5149 # Note that the temporary addresses may appear after the link enters configured state
5150 self.wait_address('veth99', 'inet6 2001:db8:6464:[0-9a-f]+10:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
5151
5152 print('### ip -6 address show dev test1 scope global')
5153 output = check_output('ip -6 address show dev test1 scope global')
5154 print(output)
5155 # address in IA_PD (Token=static)
5156 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5157 # address in IA_PD (temporary)
5158 self.wait_address('test1', 'inet6 2001:db8:6464:[0-9a-f]+00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
5159
5160 print('### ip -6 address show dev dummy98 scope global')
5161 output = check_output('ip -6 address show dev dummy98 scope global')
5162 print(output)
5163 # address in IA_PD (Token=static)
07b7337a 5164 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
84cc85f9 5165 # address in IA_PD (temporary)
07b7337a 5166 self.wait_address('dummy98', 'inet6 2001:db8:6464:[0-9a-f]+00:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
84cc85f9
YW
5167
5168 print('### ip -6 address show dev dummy99 scope global')
5169 output = check_output('ip -6 address show dev dummy99 scope global')
5170 print(output)
5171 # Assign=no
07b7337a 5172 self.assertNotRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+0[23]')
84cc85f9
YW
5173
5174 print('### ip -6 address show dev veth97 scope global')
5175 output = check_output('ip -6 address show dev veth97 scope global')
5176 print(output)
5177 # address in IA_PD (Token=static)
5178 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5179 # address in IA_PD (Token=eui64)
5180 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1034:56ff:fe78:9ace/64 (metric 256 |)scope global dynamic mngtmpaddr')
5181 # address in IA_PD (temporary)
5182 self.wait_address('veth97', 'inet6 2001:db8:6464:[0-9a-f]+08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
5183
5184 print('### ip -6 address show dev veth97-peer scope global')
5185 output = check_output('ip -6 address show dev veth97-peer scope global')
5186 print(output)
5187 # NDisc address (Token=static)
5188 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
5189 # NDisc address (Token=eui64)
5190 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1034:56ff:fe78:9acf/64 (metric 256 |)scope global dynamic mngtmpaddr')
5191 # NDisc address (temporary)
5192 self.wait_address('veth97-peer', 'inet6 2001:db8:6464:[0-9a-f]+08:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
5193
5194 print('### ip -6 address show dev veth98 scope global')
5195 output = check_output('ip -6 address show dev veth98 scope global')
5196 print(output)
5197 # address in IA_PD (Token=static)
5198 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5199 # address in IA_PD (Token=eui64)
5200 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1034:56ff:fe78:9abe/64 (metric 256 |)scope global dynamic mngtmpaddr')
5201 # address in IA_PD (temporary)
5202 self.wait_address('veth98', 'inet6 2001:db8:6464:[0-9a-f]+09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
5203
5204 print('### ip -6 address show dev veth98-peer scope global')
5205 output = check_output('ip -6 address show dev veth98-peer scope global')
5206 print(output)
5207 # NDisc address (Token=static)
5208 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
5209 # NDisc address (Token=eui64)
5210 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1034:56ff:fe78:9abf/64 (metric 256 |)scope global dynamic mngtmpaddr')
5211 # NDisc address (temporary)
5212 self.wait_address('veth98-peer', 'inet6 2001:db8:6464:[0-9a-f]+09:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
5213
5214 print('### ip -6 route show type unreachable')
5215 output = check_output('ip -6 route show type unreachable')
5216 print(output)
5217 self.assertRegex(output, 'unreachable 2001:db8:6464:[0-9a-f]+00::/56 dev lo proto dhcp')
5218
5219 print('### ip -6 route show dev veth99')
5220 output = check_output('ip -6 route show dev veth99')
5221 print(output)
5222 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+10::/64 proto kernel metric [0-9]* expires')
5223
5224 print('### ip -6 route show dev test1')
5225 output = check_output('ip -6 route show dev test1')
5226 print(output)
5227 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/64 proto kernel metric [0-9]* expires')
5228
5229 print('### ip -6 route show dev dummy98')
5230 output = check_output('ip -6 route show dev dummy98')
5231 print(output)
07b7337a 5232 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/64 proto kernel metric [0-9]* expires')
84cc85f9
YW
5233
5234 print('### ip -6 route show dev dummy99')
5235 output = check_output('ip -6 route show dev dummy99')
5236 print(output)
07b7337a 5237 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+0[23]::/64 proto dhcp metric [0-9]* expires')
84cc85f9
YW
5238
5239 print('### ip -6 route show dev veth97')
5240 output = check_output('ip -6 route show dev veth97')
5241 print(output)
5242 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+08::/64 proto kernel metric [0-9]* expires')
5243
5244 print('### ip -6 route show dev veth97-peer')
5245 output = check_output('ip -6 route show dev veth97-peer')
5246 print(output)
5247 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+08::/64 proto ra metric [0-9]* expires')
5248
5249 print('### ip -6 route show dev veth98')
5250 output = check_output('ip -6 route show dev veth98')
5251 print(output)
5252 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+09::/64 proto kernel metric [0-9]* expires')
5253
5254 print('### ip -6 route show dev veth98-peer')
5255 output = check_output('ip -6 route show dev veth98-peer')
5256 print(output)
5257 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+09::/64 proto ra metric [0-9]* expires')
5258
84cc85f9
YW
5259 print('### ip -6 address show dev dummy97 scope global')
5260 output = check_output('ip -6 address show dev dummy97 scope global')
5261 print(output)
5262 # address in IA_PD (Token=static)
5263 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+01:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5264 # address in IA_PD (temporary)
5265 self.wait_address('dummy97', 'inet6 2001:db8:6464:[0-9a-f]+01:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global temporary dynamic', ipv='-6')
5266
5267 print('### ip -6 route show dev dummy97')
5268 output = check_output('ip -6 route show dev dummy97')
5269 print(output)
5270 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+01::/64 proto kernel metric [0-9]* expires')
5271
e4295d4d
FS
5272 print(f'### ip -d link show dev {tunnel_name}')
5273 output = check_output(f'ip -d link show dev {tunnel_name}')
84cc85f9
YW
5274 print(output)
5275 self.assertIn('link/sit 10.100.100.', output)
5276 self.assertIn('local 10.100.100.', output)
84cc85f9
YW
5277 self.assertIn('ttl 64', output)
5278 self.assertIn('6rd-prefix 2001:db8::/32', output)
5279 self.assertIn('6rd-relay_prefix 10.0.0.0/8', output)
5280
e4295d4d
FS
5281 print(f'### ip -6 address show dev {tunnel_name}')
5282 output = check_output(f'ip -6 address show dev {tunnel_name}')
84cc85f9 5283 print(output)
07b7337a 5284 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+0[23]:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*:[0-9a-f]*/64 (metric 256 |)scope global dynamic')
84cc85f9
YW
5285 self.assertRegex(output, 'inet6 ::10.100.100.[0-9]+/96 scope global')
5286
e4295d4d
FS
5287 print(f'### ip -6 route show dev {tunnel_name}')
5288 output = check_output(f'ip -6 route show dev {tunnel_name}')
84cc85f9 5289 print(output)
07b7337a 5290 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+0[23]::/64 proto kernel metric [0-9]* expires')
84cc85f9
YW
5291 self.assertRegex(output, '::/96 proto kernel metric [0-9]*')
5292
5293 print('### ip -6 route show default')
5294 output = check_output('ip -6 route show default')
5295 print(output)
5296 self.assertIn('default', output)
e4295d4d 5297 self.assertIn(f'via ::10.0.0.1 dev {tunnel_name}', output)
84cc85f9 5298
6a936c9c 5299 def test_dhcp4_6rd(self):
a962d857
YW
5300 copy_network_unit('25-veth.netdev', '25-dhcp4-6rd-server.network', '25-dhcp4-6rd-upstream.network',
5301 '25-veth-downstream-veth97.netdev', '25-dhcp-pd-downstream-veth97.network', '25-dhcp-pd-downstream-veth97-peer.network',
5302 '25-veth-downstream-veth98.netdev', '25-dhcp-pd-downstream-veth98.network', '25-dhcp-pd-downstream-veth98-peer.network',
5303 '11-dummy.netdev', '25-dhcp-pd-downstream-test1.network',
5304 '25-dhcp-pd-downstream-dummy97.network',
5305 '12-dummy.netdev', '25-dhcp-pd-downstream-dummy98.network',
5306 '13-dummy.netdev', '25-dhcp-pd-downstream-dummy99.network',
5307 '80-6rd-tunnel.network')
6a936c9c
YW
5308
5309 start_networkd()
5310 self.wait_online(['veth-peer:routable'])
f7805a6c
FS
5311
5312 # ipv4masklen: 8
5313 # 6rd-prefix: 2001:db8::/32
5314 # br-addresss: 10.0.0.1
5315
a962d857
YW
5316 start_dnsmasq('--dhcp-option=212,08:20:20:01:0d:b8:00:00:00:00:00:00:00:00:00:00:00:00:0a:00:00:01',
5317 ipv4_range='10.100.100.100,10.100.100.200',
5318 ipv4_router='10.0.0.1')
6a936c9c
YW
5319 self.wait_online(['veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded',
5320 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable'])
5321
5322 # Test case for a downstream which appears later
5323 check_output('ip link add dummy97 type dummy')
5324 self.wait_online(['dummy97:routable'])
5325
5326 # Find tunnel name
5327 tunnel_name = None
5328 for name in os.listdir('/sys/class/net/'):
5329 if name.startswith('6rd-'):
5330 tunnel_name = name
5331 break
5332
e4295d4d 5333 self.wait_online([f'{tunnel_name}:routable'])
6a936c9c
YW
5334
5335 self.verify_dhcp4_6rd(tunnel_name)
5336
5337 # Test case for reconfigure
a962d857 5338 networkctl_reconfigure('dummy98', 'dummy99')
6a936c9c
YW
5339 self.wait_online(['dummy98:routable', 'dummy99:degraded'])
5340
5341 self.verify_dhcp4_6rd(tunnel_name)
5342
3af934bc 5343 print('Wait for the DHCP lease to be renewed/rebind')
a102a52c 5344 time.sleep(120)
6a936c9c 5345
6a936c9c
YW
5346 self.wait_online(['veth99:routable', 'test1:routable', 'dummy97:routable', 'dummy98:routable', 'dummy99:degraded',
5347 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable'])
5348
5349 self.verify_dhcp4_6rd(tunnel_name)
5350
9633f977 5351class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
9633f977
SS
5352
5353 def setUp(self):
a962d857 5354 setup_common()
9633f977
SS
5355
5356 def tearDown(self):
a962d857 5357 tear_down_common()
9633f977
SS
5358
5359 def test_ipv6_route_prefix(self):
a962d857
YW
5360 copy_network_unit('25-veth.netdev', '25-ipv6ra-prefix-client.network', '25-ipv6ra-prefix.network',
5361 '12-dummy.netdev', '25-ipv6ra-uplink.network')
9633f977
SS
5362
5363 start_networkd()
4a906586 5364 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
9633f977 5365
635f2a66
YW
5366 output = check_output('ip address show dev veth-peer')
5367 print(output)
5368 self.assertIn('inet6 2001:db8:0:1:', output)
5369 self.assertNotIn('inet6 2001:db8:0:2:', output)
ab47f960 5370 self.assertNotIn('inet6 2001:db8:0:3:', output)
635f2a66 5371
3c874fd7 5372 output = check_output('ip -6 route show dev veth-peer')
9633f977 5373 print(output)
635f2a66
YW
5374 self.assertIn('2001:db8:0:1::/64 proto ra', output)
5375 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
ab47f960 5376 self.assertNotIn('2001:db8:0:3::/64 proto ra', output)
635f2a66
YW
5377 self.assertIn('2001:db0:fff::/64 via ', output)
5378 self.assertNotIn('2001:db1:fff::/64 via ', output)
ab47f960 5379 self.assertNotIn('2001:db2:fff::/64 via ', output)
9633f977 5380
635f2a66
YW
5381 output = check_output('ip address show dev veth99')
5382 print(output)
5383 self.assertNotIn('inet6 2001:db8:0:1:', output)
fe2a8b3d
YW
5384 self.assertIn('inet6 2001:db8:0:2:1a:2b:3c:4d', output)
5385 self.assertIn('inet6 2001:db8:0:2:fa:de:ca:fe', output)
ab47f960 5386 self.assertNotIn('inet6 2001:db8:0:3:', output)
635f2a66 5387
4a906586
YW
5388 output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env)
5389 print(output)
5390 self.assertRegex(output, '2001:db8:1:1::2')
5391
5392 output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env)
5393 print(output)
5394 self.assertIn('example.com', output)
5395
94f0bd62
YW
5396 # TODO: check json string
5397 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
5398
635f2a66 5399 def test_ipv6_route_prefix_deny_list(self):
a962d857
YW
5400 copy_network_unit('25-veth.netdev', '25-ipv6ra-prefix-client-deny-list.network', '25-ipv6ra-prefix.network',
5401 '12-dummy.netdev', '25-ipv6ra-uplink.network')
635f2a66
YW
5402
5403 start_networkd()
4a906586 5404 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
635f2a66
YW
5405
5406 output = check_output('ip address show dev veth-peer')
5407 print(output)
5408 self.assertIn('inet6 2001:db8:0:1:', output)
5409 self.assertNotIn('inet6 2001:db8:0:2:', output)
5410
5411 output = check_output('ip -6 route show dev veth-peer')
5412 print(output)
5413 self.assertIn('2001:db8:0:1::/64 proto ra', output)
5414 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
5415 self.assertIn('2001:db0:fff::/64 via ', output)
5416 self.assertNotIn('2001:db1:fff::/64 via ', output)
5417
5418 output = check_output('ip address show dev veth99')
3c874fd7 5419 print(output)
635f2a66
YW
5420 self.assertNotIn('inet6 2001:db8:0:1:', output)
5421 self.assertIn('inet6 2001:db8:0:2:', output)
3c874fd7 5422
4a906586
YW
5423 output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env)
5424 print(output)
5425 self.assertRegex(output, '2001:db8:1:1::2')
5426
5427 output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env)
5428 print(output)
5429 self.assertIn('example.com', output)
5430
7db05447 5431class NetworkdMTUTests(unittest.TestCase, Utilities):
7db05447
DS
5432
5433 def setUp(self):
a962d857 5434 setup_common()
7db05447
DS
5435
5436 def tearDown(self):
a962d857 5437 tear_down_common()
7db05447
DS
5438
5439 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
5440 if not ipv6_mtu:
5441 ipv6_mtu = mtu
5442
5443 # test normal start
5444 start_networkd()
5445 self.wait_online(['dummy98:routable'])
a962d857
YW
5446 self.check_link_attr('dummy98', 'mtu', mtu)
5447 self.check_ipv6_sysctl_attr('dummy98', 'mtu', ipv6_mtu)
7db05447
DS
5448
5449 # test normal restart
5450 restart_networkd()
5451 self.wait_online(['dummy98:routable'])
a962d857
YW
5452 self.check_link_attr('dummy98', 'mtu', mtu)
5453 self.check_ipv6_sysctl_attr('dummy98', 'mtu', ipv6_mtu)
7db05447
DS
5454
5455 if reset:
5456 self.reset_check_mtu(mtu, ipv6_mtu)
5457
5458 def reset_check_mtu(self, mtu, ipv6_mtu=None):
5459 ''' test setting mtu/ipv6_mtu with interface already up '''
5460 stop_networkd()
5461
5462 # note - changing the device mtu resets the ipv6 mtu
a962d857
YW
5463 check_output('ip link set up mtu 1501 dev dummy98')
5464 check_output('ip link set up mtu 1500 dev dummy98')
5465 self.check_link_attr('dummy98', 'mtu', '1500')
5466 self.check_ipv6_sysctl_attr('dummy98', 'mtu', '1500')
7db05447
DS
5467
5468 self.check_mtu(mtu, ipv6_mtu, reset=False)
5469
5470 def test_mtu_network(self):
a962d857 5471 copy_network_unit('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
7db05447
DS
5472 self.check_mtu('1600')
5473
5474 def test_mtu_netdev(self):
a962d857 5475 copy_network_unit('12-dummy-mtu.netdev', '12-dummy.network', copy_dropins=False)
7db05447
DS
5476 # note - MTU set by .netdev happens ONLY at device creation!
5477 self.check_mtu('1600', reset=False)
5478
5479 def test_mtu_link(self):
a962d857 5480 copy_network_unit('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', copy_dropins=False)
7db05447
DS
5481 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
5482 self.check_mtu('1600', reset=False)
5483
5484 def test_ipv6_mtu(self):
5485 ''' set ipv6 mtu without setting device mtu '''
a962d857 5486 copy_network_unit('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
7db05447
DS
5487 self.check_mtu('1500', '1400')
5488
5489 def test_ipv6_mtu_toolarge(self):
5490 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
a962d857 5491 copy_network_unit('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
7db05447
DS
5492 self.check_mtu('1500', '1500')
5493
5494 def test_mtu_network_ipv6_mtu(self):
5495 ''' set ipv6 mtu and set device mtu via network file '''
a962d857 5496 copy_network_unit('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
7db05447
DS
5497 self.check_mtu('1600', '1550')
5498
5499 def test_mtu_netdev_ipv6_mtu(self):
5500 ''' set ipv6 mtu and set device mtu via netdev file '''
a962d857 5501 copy_network_unit('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
7db05447
DS
5502 self.check_mtu('1600', '1550', reset=False)
5503
5504 def test_mtu_link_ipv6_mtu(self):
5505 ''' set ipv6 mtu and set device mtu via link file '''
a962d857 5506 copy_network_unit('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
7db05447
DS
5507 self.check_mtu('1600', '1550', reset=False)
5508
5509
1f0e3109 5510if __name__ == '__main__':
9c1ae484
YW
5511 parser = argparse.ArgumentParser()
5512 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
5513 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
b6d587d1 5514 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
b05c4d6b 5515 parser.add_argument('--timesyncd', help='Path to systemd-timesyncd', dest='timesyncd_bin')
641aa412 5516 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
9c1ae484
YW
5517 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
5518 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
b6d587d1
YW
5519 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
5520 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
b05c4d6b 5521 parser.add_argument('--udevadm', help='Path to udevadm', dest='udevadm_bin')
9c1ae484
YW
5522 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
5523 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 5524 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 5525 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 5526 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
6c9efba6 5527 parser.add_argument('--with-coverage', help='Loosen certain sandbox restrictions to make gcov happy', dest='with_coverage', type=bool, nargs='?', const=True, default=with_coverage)
a561bcee 5528 ns, unknown_args = parser.parse_known_args(namespace=unittest)
9c1ae484
YW
5529
5530 if ns.build_dir:
b05c4d6b
YW
5531 if ns.networkd_bin or ns.resolved_bin or ns.timesyncd_bin or ns.udevd_bin or \
5532 ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin or ns.udevadm_bin:
5533 print('WARNING: --networkd, --resolved, --timesyncd, --udevd, --wait-online, --networkctl, --resolvectl, --timedatectl, or --udevadm options are ignored when --build-dir is specified.')
9c1ae484 5534 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
b6d587d1 5535 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
b05c4d6b 5536 timesyncd_bin = os.path.join(ns.build_dir, 'systemd-timesyncd')
641aa412 5537 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
9c1ae484
YW
5538 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
5539 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
b6d587d1
YW
5540 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
5541 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
b05c4d6b 5542 udevadm_bin = os.path.join(ns.build_dir, 'udevadm')
9c1ae484
YW
5543 else:
5544 if ns.networkd_bin:
5545 networkd_bin = ns.networkd_bin
b6d587d1
YW
5546 if ns.resolved_bin:
5547 resolved_bin = ns.resolved_bin
b05c4d6b
YW
5548 if ns.timesyncd_bin:
5549 timesyncd_bin = ns.timesyncd_bin
641aa412
YW
5550 if ns.udevd_bin:
5551 udevd_bin = ns.udevd_bin
9c1ae484
YW
5552 if ns.wait_online_bin:
5553 wait_online_bin = ns.wait_online_bin
5554 if ns.networkctl_bin:
5555 networkctl_bin = ns.networkctl_bin
b6d587d1
YW
5556 if ns.resolvectl_bin:
5557 resolvectl_bin = ns.resolvectl_bin
5558 if ns.timedatectl_bin:
5559 timedatectl_bin = ns.timedatectl_bin
b05c4d6b
YW
5560 if ns.udevadm_bin:
5561 udevadm_bin = ns.udevadm_bin
9c1ae484
YW
5562
5563 use_valgrind = ns.use_valgrind
5564 enable_debug = ns.enable_debug
94c03122 5565 asan_options = ns.asan_options
fa4c6095 5566 lsan_options = ns.lsan_options
94c03122 5567 ubsan_options = ns.ubsan_options
6c9efba6 5568 with_coverage = ns.with_coverage
9c1ae484
YW
5569
5570 if use_valgrind:
b05c4d6b
YW
5571 # Do not forget the trailing space.
5572 valgrind_cmd = 'valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all '
5573
5574 networkctl_cmd = valgrind_cmd.split() + [networkctl_bin]
5575 resolvectl_cmd = valgrind_cmd.split() + [resolvectl_bin]
5576 timedatectl_cmd = valgrind_cmd.split() + [timedatectl_bin]
5577 udevadm_cmd = valgrind_cmd.split() + [udevadm_bin]
5578 wait_online_cmd = valgrind_cmd.split() + [wait_online_bin]
9c1ae484 5579
94c03122 5580 if asan_options:
a962d857 5581 env.update({'ASAN_OPTIONS': asan_options})
fa4c6095 5582 if lsan_options:
a962d857 5583 env.update({'LSAN_OPTIONS': lsan_options})
94c03122 5584 if ubsan_options:
a962d857 5585 env.update({'UBSAN_OPTIONS': ubsan_options})
b05c4d6b
YW
5586 if use_valgrind:
5587 env.update({'SYSTEMD_MEMPOOL': '0'})
9c1ae484 5588
163d095f
YW
5589 wait_online_env = env.copy()
5590 if enable_debug:
a962d857 5591 wait_online_env.update({'SYSTEMD_LOG_LEVEL': 'debug'})
163d095f 5592
a561bcee 5593 sys.argv[1:] = unknown_args
0765763e 5594 unittest.main(verbosity=3)