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