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