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