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