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