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