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