]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
test-network: wait for the link is activated
[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:])
67 return subprocess.run(command, universal_newlines=True, **kwargs)
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
SS
87 return func
88 else:
89 return unittest.expectedFailure(func)
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
YW
98 return func
99 else:
100 return unittest.expectedFailure(func)
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
YW
109 return func
110 else:
111 return unittest.expectedFailure(func)
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
127 else:
128 return unittest.expectedFailure(func)
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
144 else:
145 return unittest.expectedFailure(func)
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
154 else:
155 return unittest.expectedFailure(func)
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
168 else:
169 return unittest.expectedFailure(func)
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
YW
185 return func
186 else:
187 return unittest.expectedFailure(func)
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')
201 except Exception as error:
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')
209 except Exception as error:
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
225 else:
226 return unittest.expectedFailure(func)
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
237 else:
238 return unittest.expectedFailure(func)
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
249 else:
250 return unittest.expectedFailure(func)
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
261 else:
262 return unittest.expectedFailure(func)
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
273 else:
274 return unittest.expectedFailure(func)
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
ZJS
488 for unit in units:
489 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
490 os.remove(os.path.join(network_unit_file_path, unit))
491 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
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:
502 if (os.path.exists(os.path.join(networkd_conf_dropin_path, dropin))):
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
1f0e3109 589
ec38833c 590class Utilities():
e39cc445 591 def check_link_exists(self, link):
ec38833c 592 self.assertTrue(link_exists(link))
2be0b6fc 593
0fc0d85f
DS
594 def check_link_attr(self, *args):
595 self.assertEqual(read_link_attr(*args[:-1]), args[-1]);
596
cfbdc438
YW
597 def wait_activated(self, link, state='down', timeout=20, fail_assert=True):
598 # wait for the interface is activated.
599 invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value')
600 needle = f'{link}: Bringing link {state}'
601 flag = state.upper()
602 for iteration in range(timeout+1):
603 output = check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id)
604 if needle in output and flag in check_output(f'ip link show {link}'):
605 return True
606 if iteration < timeout:
607 time.sleep(1)
608 if fail_assert:
609 self.fail(f'Timed out waiting for {link} activated.')
610 return False
611
a4632dc7
DS
612 def wait_operstate(self, link, operstate='degraded', setup_state='configured', setup_timeout=5, fail_assert=True):
613 """Wait for the link to reach the specified operstate and/or setup state.
614
615 Specify None or '' for either operstate or setup_state to ignore that state.
616 This will recheck until the state conditions are met or the timeout expires.
617
618 If the link successfully matches the requested state, this returns True.
619 If this times out waiting for the link to match, the behavior depends on the
620 'fail_assert' parameter; if True, this causes a test assertion failure,
621 otherwise this returns False. The default is to cause assertion failure.
622
623 Note that this function matches on *exactly* the given operstate and setup_state.
624 To wait for a link to reach *or exceed* a given operstate, use wait_online().
625 """
626 if not operstate:
627 operstate = r'\S+'
628 if not setup_state:
629 setup_state = r'\S+'
630
631 for secs in range(setup_timeout + 1):
632 output = check_output(*networkctl_cmd, '-n', '0', 'status', link, env=env)
633 print(output)
634 if re.search(rf'(?m)^\s*State:\s+{operstate}\s+\({setup_state}\)\s*$', output):
635 return True
636 # don't bother sleeping if time is up
637 if secs < setup_timeout:
638 time.sleep(1)
639 if fail_assert:
640 self.fail(f'Timed out waiting for {link} to reach state {operstate}/{setup_state}')
641 return False
2be0b6fc 642
70448bb1 643 def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, ipv4=False, ipv6=False, setup_state='configured', setup_timeout=5):
0c020321
DS
644 """Wait for the link(s) to reach the specified operstate and/or setup state.
645
646 This is similar to wait_operstate() but can be used for multiple links,
647 and it also calls systemd-networkd-wait-online to wait for the given operstate.
648 The operstate should be specified in the link name, like 'eth0:degraded'.
649 If just a link name is provided, wait-online's default operstate to wait for is degraded.
650
651 The 'timeout' parameter controls the systemd-networkd-wait-online timeout, and the
652 'setup_timeout' controls the per-link timeout waiting for the setup_state.
653
654 Set 'bool_any' to True to wait for any (instead of all) of the given links.
655 If this is set, no setup_state checks are done.
656
70448bb1
L
657 Set 'ipv4' or 'ipv6' to True to wait for IPv4 address or IPv6 address, respectively, of each of the given links.
658 This is applied only for the operational state 'degraded' or above.
659
0c020321
DS
660 Note that this function waits for the link(s) to reach *or exceed* the given operstate.
661 However, the setup_state, if specified, must be matched *exactly*.
662
663 This returns if the link(s) reached the requested operstate/setup_state; otherwise it
664 raises CalledProcessError or fails test assertion.
665 """
e2aea43f
YW
666 args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
667 if bool_any:
668 args += ['--any']
70448bb1
L
669 if ipv4:
670 args += ['--ipv4']
671 if ipv6:
672 args += ['--ipv6']
e2aea43f
YW
673 try:
674 check_output(*args, env=env)
675 except subprocess.CalledProcessError:
676 for link in links_with_operstate:
fc79e6ff 677 output = check_output(*networkctl_cmd, '-n', '0', 'status', link.split(':')[0], env=env)
e2aea43f
YW
678 print(output)
679 raise
fd372b1a 680 if not bool_any and setup_state:
0c020321
DS
681 for link in links_with_operstate:
682 self.wait_operstate(link.split(':')[0], None, setup_state, setup_timeout)
e2aea43f 683
53c32c2b 684 def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
2629df47
YW
685 for i in range(timeout_sec):
686 if i > 0:
687 time.sleep(1)
371810d1 688 output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
571f9539 689 if re.search(address_regex, output) and 'tentative' not in output:
2629df47 690 break
240e4137
YW
691
692 self.assertRegex(output, address_regex)
693
694 def wait_address_dropped(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
695 for i in range(timeout_sec):
696 if i > 0:
697 time.sleep(1)
698 output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
699 if not re.search(address_regex, output):
700 break
701
702 self.assertNotRegex(output, address_regex)
2629df47 703
1ca44d7d
YW
704class NetworkctlTests(unittest.TestCase, Utilities):
705
706 links = [
dcd9f07c 707 'dummy98',
1ca44d7d
YW
708 'test1',
709 'veth99',
710 ]
711
712 units = [
713 '11-dummy.netdev',
6d5b4efe 714 '11-dummy-mtu.netdev',
1ca44d7d 715 '11-dummy.network',
dcd9f07c 716 '12-dummy.netdev',
6934ace0 717 '12-dummy.link',
dcd9f07c 718 '25-address-static.network',
1ca44d7d
YW
719 '25-veth.netdev',
720 'netdev-link-local-addressing-yes.network',
721 ]
722
723 def setUp(self):
ec38833c 724 remove_links(self.links)
aaae5713 725 stop_networkd(show_logs=False)
1ca44d7d
YW
726
727 def tearDown(self):
ec38833c
ZJS
728 remove_links(self.links)
729 remove_unit_from_networkd_path(self.units)
aaae5713 730 stop_networkd(show_logs=True)
1ca44d7d 731
6934ace0
YW
732 @expectedFailureIfAlternativeNameIsNotAvailable()
733 def test_altname(self):
734 copy_unit_to_networkd_unit_path('netdev-link-local-addressing-yes.network', '12-dummy.netdev', '12-dummy.link')
735 check_output('udevadm control --reload')
736 start_networkd()
737 self.wait_online(['dummy98:degraded'])
738
fc79e6ff 739 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
6934ace0
YW
740 self.assertRegex(output, 'hogehogehogehogehogehoge')
741
dcd9f07c
YW
742 def test_reconfigure(self):
743 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
744 start_networkd()
745 self.wait_online(['dummy98:routable'])
746
747 output = check_output('ip -4 address show dev dummy98')
748 print(output)
3bad5487
YW
749 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
750 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
751 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
dcd9f07c
YW
752
753 check_output('ip address del 10.1.2.3/16 dev dummy98')
754 check_output('ip address del 10.1.2.4/16 dev dummy98')
755 check_output('ip address del 10.2.2.4/16 dev dummy98')
756
757 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
758 self.wait_online(['dummy98:routable'])
759
760 output = check_output('ip -4 address show dev dummy98')
761 print(output)
3bad5487
YW
762 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
763 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
764 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
765
766 remove_unit_from_networkd_path(['25-address-static.network'])
767
768 check_output(*networkctl_cmd, 'reload', env=env)
769 self.wait_operstate('dummy98', 'degraded', setup_state='unmanaged')
770
771 output = check_output('ip -4 address show dev dummy98')
772 print(output)
773 self.assertNotIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
774 self.assertNotIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
775 self.assertNotIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
776
777 copy_unit_to_networkd_unit_path('25-address-static.network')
778 check_output(*networkctl_cmd, 'reload', env=env)
779 self.wait_online(['dummy98:routable'])
780
781 output = check_output('ip -4 address show dev dummy98')
782 print(output)
783 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
784 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
785 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
dcd9f07c 786
66de8671
YW
787 def test_reload(self):
788 start_networkd(3)
789
790 copy_unit_to_networkd_unit_path('11-dummy.netdev')
791 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 792 self.wait_operstate('test1', 'off', setup_state='unmanaged')
66de8671
YW
793
794 copy_unit_to_networkd_unit_path('11-dummy.network')
795 check_output(*networkctl_cmd, 'reload', env=env)
796 self.wait_online(['test1:degraded'])
797
798 remove_unit_from_networkd_path(['11-dummy.network'])
799 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 800 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
66de8671
YW
801
802 remove_unit_from_networkd_path(['11-dummy.netdev'])
803 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 804 self.wait_operstate('test1', 'degraded', setup_state='unmanaged')
66de8671
YW
805
806 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
807 check_output(*networkctl_cmd, 'reload', env=env)
19cf3143 808 self.wait_operstate('test1', 'degraded')
66de8671 809
1ca44d7d 810 def test_glob(self):
ec38833c 811 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
2cf6fdff 812 start_networkd()
1ca44d7d 813
e2aea43f 814 self.wait_online(['test1:degraded'])
1ca44d7d 815
371810d1 816 output = check_output(*networkctl_cmd, 'list', env=env)
1ca44d7d
YW
817 self.assertRegex(output, '1 lo ')
818 self.assertRegex(output, 'test1')
819
371810d1 820 output = check_output(*networkctl_cmd, 'list', 'test1', env=env)
1ca44d7d
YW
821 self.assertNotRegex(output, '1 lo ')
822 self.assertRegex(output, 'test1')
823
371810d1 824 output = check_output(*networkctl_cmd, 'list', 'te*', env=env)
1ca44d7d
YW
825 self.assertNotRegex(output, '1 lo ')
826 self.assertRegex(output, 'test1')
827
fc79e6ff 828 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'te*', env=env)
1ca44d7d
YW
829 self.assertNotRegex(output, '1: lo ')
830 self.assertRegex(output, 'test1')
831
fc79e6ff 832 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'tes[a-z][0-9]', env=env)
1ca44d7d
YW
833 self.assertNotRegex(output, '1: lo ')
834 self.assertRegex(output, 'test1')
835
6d5b4efe 836 def test_mtu(self):
ec38833c 837 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
2cf6fdff 838 start_networkd()
6d5b4efe 839
e2aea43f 840 self.wait_online(['test1:degraded'])
6d5b4efe 841
fc79e6ff 842 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
6d5b4efe
YW
843 self.assertRegex(output, 'MTU: 1600')
844
e28fd95f
YW
845 def test_type(self):
846 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
847 start_networkd()
e2aea43f 848 self.wait_online(['test1:degraded'])
e28fd95f 849
fc79e6ff 850 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
e28fd95f
YW
851 print(output)
852 self.assertRegex(output, 'Type: ether')
853
fc79e6ff 854 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
e28fd95f
YW
855 print(output)
856 self.assertRegex(output, 'Type: loopback')
857
858 @expectedFailureIfLinkFileFieldIsNotSet()
859 def test_udev_link_file(self):
860 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
861 start_networkd()
e2aea43f 862 self.wait_online(['test1:degraded'])
e28fd95f 863
fc79e6ff 864 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
e28fd95f 865 print(output)
426654d7 866 self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
e28fd95f
YW
867 self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network')
868
fc79e6ff 869 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'lo', env=env)
e28fd95f 870 print(output)
70f32a26 871 self.assertRegex(output, r'Link File: n/a')
e28fd95f
YW
872 self.assertRegex(output, r'Network File: n/a')
873
bee692fd 874 def test_delete_links(self):
ec38833c
ZJS
875 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
876 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 877 start_networkd()
bee692fd 878
e2aea43f 879 self.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
bee692fd 880
7a2f6fb6 881 check_output(*networkctl_cmd, 'delete', 'test1', 'veth99', env=env)
ec38833c
ZJS
882 self.assertFalse(link_exists('test1'))
883 self.assertFalse(link_exists('veth99'))
884 self.assertFalse(link_exists('veth-peer'))
bee692fd 885
1f0e3109
SS
886class NetworkdNetDevTests(unittest.TestCase, Utilities):
887
e64dc406
YW
888 links_remove_earlier = [
889 'xfrm99',
890 ]
891
892 links = [
09ea6724 893 '6rdtun99',
13060471 894 'bareudp99',
c0267a59 895 'batadv99',
713bfdaa 896 'bond98',
09ea6724
YW
897 'bond99',
898 'bridge99',
899 'dropin-test',
900 'dummy98',
6a97a864
YW
901 'erspan98',
902 'erspan99',
09ea6724 903 'geneve99',
4b6a6d1e 904 'gretap96',
6a97a864 905 'gretap98',
09ea6724 906 'gretap99',
4b6a6d1e 907 'gretun96',
6a97a864
YW
908 'gretun97',
909 'gretun98',
09ea6724 910 'gretun99',
b076d5d7 911 'ifb99',
6a97a864 912 'ip6gretap98',
09ea6724 913 'ip6gretap99',
42a29fcb 914 'ip6gretun96',
6a97a864
YW
915 'ip6gretun97',
916 'ip6gretun98',
917 'ip6gretun99',
da7d6848 918 'ip6tnl-slaac',
6a97a864
YW
919 'ip6tnl97',
920 'ip6tnl98',
09ea6724 921 'ip6tnl99',
4b6a6d1e 922 'ipiptun96',
6a97a864
YW
923 'ipiptun97',
924 'ipiptun98',
09ea6724
YW
925 'ipiptun99',
926 'ipvlan99',
956c8fec 927 'ipvtap99',
09ea6724
YW
928 'isataptun99',
929 'macvlan99',
930 'macvtap99',
811f33d0 931 'nlmon99',
4b6a6d1e 932 'sittun96',
6a97a864
YW
933 'sittun97',
934 'sittun98',
09ea6724
YW
935 'sittun99',
936 'tap99',
937 'test1',
938 'tun99',
939 'vcan99',
0874be35 940 'veth-mtu',
09ea6724
YW
941 'veth99',
942 'vlan99',
943 'vrf99',
6a97a864
YW
944 'vti6tun97',
945 'vti6tun98',
09ea6724 946 'vti6tun99',
42a29fcb 947 'vtitun96',
6a97a864
YW
948 'vtitun97',
949 'vtitun98',
09ea6724 950 'vtitun99',
f63b14d3 951 'vxcan99',
49ad8da7 952 'vxlan-slaac',
cca07d91 953 'vxlan97',
039971ea 954 'vxlan98',
09ea6724 955 'vxlan99',
da3509f0 956 'wg97',
da44fb8a 957 'wg98',
e64dc406
YW
958 'wg99',
959 ]
09ea6724
YW
960
961 units = [
962 '10-dropin-test.netdev',
963 '11-dummy.netdev',
03db80b2 964 '11-dummy.network',
09ea6724 965 '12-dummy.netdev',
6b9518a0
YW
966 '13-not-match-udev-property.network',
967 '14-match-udev-property.network',
753e0a24 968 '15-name-conflict-test.netdev',
09ea6724
YW
969 '21-macvlan.netdev',
970 '21-macvtap.netdev',
7f45d738 971 '21-vlan-test1.network',
09ea6724
YW
972 '21-vlan.netdev',
973 '21-vlan.network',
974 '25-6rd-tunnel.netdev',
13060471 975 '25-bareudp.netdev',
c0267a59 976 '25-batadv.netdev',
09ea6724 977 '25-bond.netdev',
fde60a42 978 '25-bond-balanced-tlb.netdev',
09ea6724 979 '25-bridge.netdev',
1285edf3 980 '25-bridge-configure-without-carrier.network',
03db80b2 981 '25-bridge.network',
6a97a864 982 '25-erspan-tunnel-local-any.netdev',
09ea6724 983 '25-erspan-tunnel.netdev',
4b6a6d1e
YW
984 '25-fou-gretap.netdev',
985 '25-fou-gre.netdev',
986 '25-fou-ipip.netdev',
987 '25-fou-ipproto-gre.netdev',
988 '25-fou-ipproto-ipip.netdev',
989 '25-fou-sit.netdev',
09ea6724 990 '25-geneve.netdev',
6a97a864 991 '25-gretap-tunnel-local-any.netdev',
09ea6724 992 '25-gretap-tunnel.netdev',
42a29fcb 993 '25-gre-tunnel-any-any.netdev',
6a97a864
YW
994 '25-gre-tunnel-local-any.netdev',
995 '25-gre-tunnel-remote-any.netdev',
09ea6724 996 '25-gre-tunnel.netdev',
b076d5d7 997 '25-ifb.netdev',
6a97a864
YW
998 '25-ip6gretap-tunnel-local-any.netdev',
999 '25-ip6gretap-tunnel.netdev',
42a29fcb 1000 '25-ip6gre-tunnel-any-any.netdev',
6a97a864
YW
1001 '25-ip6gre-tunnel-local-any.netdev',
1002 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 1003 '25-ip6gre-tunnel.netdev',
42a29fcb 1004 '25-ip6tnl-tunnel-any-any.netdev',
6a97a864 1005 '25-ip6tnl-tunnel-local-any.netdev',
da7d6848
YW
1006 '25-ip6tnl-tunnel-local-slaac.netdev',
1007 '25-ip6tnl-tunnel-local-slaac.network',
42a29fcb 1008 '25-ip6tnl-tunnel-remote-any.netdev',
09ea6724 1009 '25-ip6tnl-tunnel.netdev',
42a29fcb 1010 '25-ipip-tunnel-any-any.netdev',
09ea6724 1011 '25-ipip-tunnel-independent.netdev',
95082dbe 1012 '25-ipip-tunnel-independent-loopback.netdev',
6a97a864
YW
1013 '25-ipip-tunnel-local-any.netdev',
1014 '25-ipip-tunnel-remote-any.netdev',
09ea6724
YW
1015 '25-ipip-tunnel.netdev',
1016 '25-ipvlan.netdev',
956c8fec 1017 '25-ipvtap.netdev',
09ea6724 1018 '25-isatap-tunnel.netdev',
02849d8b
YW
1019 '25-macsec.key',
1020 '25-macsec.netdev',
1021 '25-macsec.network',
811f33d0 1022 '25-nlmon.netdev',
42a29fcb 1023 '25-sit-tunnel-any-any.netdev',
6a97a864
YW
1024 '25-sit-tunnel-local-any.netdev',
1025 '25-sit-tunnel-remote-any.netdev',
09ea6724
YW
1026 '25-sit-tunnel.netdev',
1027 '25-tap.netdev',
1028 '25-tun.netdev',
5cf52d90 1029 '25-tunnel-any-any.network',
11309591
YW
1030 '25-tunnel-local-any.network',
1031 '25-tunnel-remote-any.network',
1032 '25-tunnel.network',
09ea6724 1033 '25-vcan.netdev',
0874be35 1034 '25-veth-mtu.netdev',
09ea6724
YW
1035 '25-veth.netdev',
1036 '25-vrf.netdev',
42a29fcb 1037 '25-vti6-tunnel-any-any.netdev',
6a97a864
YW
1038 '25-vti6-tunnel-local-any.netdev',
1039 '25-vti6-tunnel-remote-any.netdev',
09ea6724 1040 '25-vti6-tunnel.netdev',
42a29fcb 1041 '25-vti-tunnel-any-any.netdev',
6a97a864
YW
1042 '25-vti-tunnel-local-any.netdev',
1043 '25-vti-tunnel-remote-any.netdev',
09ea6724 1044 '25-vti-tunnel.netdev',
f63b14d3 1045 '25-vxcan.netdev',
039971ea 1046 '25-vxlan-independent.netdev',
cca07d91 1047 '25-vxlan-ipv6.netdev',
49ad8da7
YW
1048 '25-vxlan-local-slaac.netdev',
1049 '25-vxlan-local-slaac.network',
1050 '25-vxlan-veth99.network',
09ea6724 1051 '25-vxlan.netdev',
da44fb8a
YW
1052 '25-wireguard-23-peers.netdev',
1053 '25-wireguard-23-peers.network',
da3509f0
YW
1054 '25-wireguard-no-peer.netdev',
1055 '25-wireguard-no-peer.network',
9e5d79e7 1056 '25-wireguard-preshared-key.txt',
39bcff3b 1057 '25-wireguard-private-key.txt',
09ea6724 1058 '25-wireguard.netdev',
5a0bd90b 1059 '25-wireguard.network',
e64dc406
YW
1060 '25-xfrm.netdev',
1061 '25-xfrm-independent.netdev',
09ea6724 1062 '6rd.network',
6730a1f3 1063 'erspan.network',
09ea6724
YW
1064 'gre.network',
1065 'gretap.network',
1066 'gretun.network',
1067 'ip6gretap.network',
6a97a864 1068 'ip6gretun.network',
da7d6848 1069 'ip6tnl-slaac.network',
09ea6724
YW
1070 'ip6tnl.network',
1071 'ipip.network',
da7d6848 1072 'ipv6-prefix.network',
09ea6724 1073 'ipvlan.network',
956c8fec 1074 'ipvtap.network',
09ea6724 1075 'isatap.network',
02849d8b 1076 'macsec.network',
09ea6724
YW
1077 'macvlan.network',
1078 'macvtap.network',
077f9abc 1079 'netdev-link-local-addressing-yes.network',
09ea6724
YW
1080 'sit.network',
1081 'vti6.network',
1082 'vti.network',
cca07d91 1083 'vxlan-ipv6.network',
1c862fe0 1084 'vxlan-test1.network',
e64dc406
YW
1085 'vxlan.network',
1086 'xfrm.network',
1087 ]
1f0e3109 1088
def9fc0d
YW
1089 fou_ports = [
1090 '55555',
1091 '55556']
1092
1f0e3109 1093 def setUp(self):
ec38833c 1094 remove_fou_ports(self.fou_ports)
e64dc406 1095 remove_links(self.links_remove_earlier)
ec38833c 1096 remove_links(self.links)
aaae5713 1097 stop_networkd(show_logs=False)
1f0e3109
SS
1098
1099 def tearDown(self):
ec38833c 1100 remove_fou_ports(self.fou_ports)
e64dc406 1101 remove_links(self.links_remove_earlier)
ec38833c
ZJS
1102 remove_links(self.links)
1103 remove_unit_from_networkd_path(self.units)
aaae5713 1104 stop_networkd(show_logs=True)
1f0e3109 1105
1ca44d7d 1106 def test_dropin_and_name_conflict(self):
ec38833c 1107 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
2cf6fdff 1108 start_networkd()
d80734f7 1109
e2aea43f 1110 self.wait_online(['dropin-test:off'], setup_state='unmanaged')
d80734f7 1111
371810d1 1112 output = check_output('ip link show dropin-test')
d80734f7 1113 print(output)
45aa0e84 1114 self.assertRegex(output, '00:50:56:c0:00:28')
d80734f7 1115
6b9518a0
YW
1116 def test_match_udev_property(self):
1117 copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network')
1118 start_networkd()
e2aea43f 1119 self.wait_online(['dummy98:routable'])
6b9518a0 1120
fc79e6ff 1121 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
6b9518a0
YW
1122 print(output)
1123 self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property')
1124
03db80b2 1125 def test_wait_online_any(self):
ec38833c 1126 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
2cf6fdff 1127 start_networkd()
03db80b2 1128
e2aea43f 1129 self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
03db80b2 1130
19cf3143
DS
1131 self.wait_operstate('bridge99', '(off|no-carrier)', setup_state='configuring')
1132 self.wait_operstate('test1', 'degraded')
03db80b2 1133
13060471
YW
1134 @expectedFailureIfModuleIsNotAvailable('bareudp')
1135 def test_bareudp(self):
1136 copy_unit_to_networkd_unit_path('25-bareudp.netdev', 'netdev-link-local-addressing-yes.network')
1137 start_networkd()
1138
1139 self.wait_online(['bareudp99:degraded'])
1140
1141 output = check_output('ip -d link show bareudp99')
1142 print(output)
1143 self.assertRegex(output, 'dstport 1000 ')
1144 self.assertRegex(output, 'ethertype ip ')
1145
c0267a59
AW
1146 @expectedFailureIfModuleIsNotAvailable('batman-adv')
1147 def test_batadv(self):
1148 copy_unit_to_networkd_unit_path('25-batadv.netdev', 'netdev-link-local-addressing-yes.network')
1149 start_networkd()
1150
1151 self.wait_online(['batadv99:degraded'])
1152
1153 output = check_output('ip -d link show batadv99')
1154 print(output)
1155 self.assertRegex(output, 'batadv')
1156
1f0e3109 1157 def test_bridge(self):
1285edf3 1158 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network')
2cf6fdff 1159 start_networkd()
1f0e3109 1160
e2aea43f 1161 self.wait_online(['bridge99:no-carrier'])
1f0e3109 1162
3d165124 1163 tick = os.sysconf('SC_CLK_TCK')
ec38833c
ZJS
1164 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick))
1165 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick))
c9047092
YW
1166 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick))
1167 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick))
1168 self.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority')))
1169 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier')))
1170 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping')))
1171 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
1172 self.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
1f0e3109 1173
fc79e6ff 1174 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
36bc2ffb
YW
1175 print(output)
1176 self.assertRegex(output, 'Priority: 9')
1177 self.assertRegex(output, 'STP: yes')
1178 self.assertRegex(output, 'Multicast IGMP Version: 3')
1179
1f0e3109 1180 def test_bond(self):
ec38833c 1181 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
2cf6fdff 1182 start_networkd()
ec38833c 1183
e2aea43f 1184 self.wait_online(['bond99:off', 'bond98:off'], setup_state='unmanaged')
ec38833c
ZJS
1185
1186 self.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
1187 self.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
1188 self.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
1189 self.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
1190 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
1191 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
1192 self.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
1193 self.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
1194 self.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
1195 self.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
1196 self.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
1197
1198 self.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
1199 self.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
fde60a42 1200
1f0e3109 1201 def test_vlan(self):
ec38833c
ZJS
1202 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
1203 '21-vlan.network', '21-vlan-test1.network')
2cf6fdff 1204 start_networkd()
1f0e3109 1205
e2aea43f 1206 self.wait_online(['test1:degraded', 'vlan99:routable'])
1f0e3109 1207
371810d1 1208 output = check_output('ip -d link show test1')
72b7f1b9 1209 print(output)
7d7be1b9 1210 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 1211
371810d1 1212 output = check_output('ip -d link show vlan99')
14ecd604 1213 print(output)
06895a1d
YW
1214 self.assertRegex(output, ' mtu 2000 ')
1215 self.assertRegex(output, 'REORDER_HDR')
1216 self.assertRegex(output, 'LOOSE_BINDING')
1217 self.assertRegex(output, 'GVRP')
1218 self.assertRegex(output, 'MVRP')
1219 self.assertRegex(output, ' id 99 ')
1f0e3109 1220
371810d1 1221 output = check_output('ip -4 address show dev test1')
7f45d738
YW
1222 print(output)
1223 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
1224 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
1225
371810d1 1226 output = check_output('ip -4 address show dev vlan99')
7f45d738
YW
1227 print(output)
1228 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
1229
1f0e3109 1230 def test_macvtap(self):
460feb61
YW
1231 for mode in ['private', 'vepa', 'bridge', 'passthru']:
1232 with self.subTest(mode=mode):
1233 if mode != 'private':
1234 self.tearDown()
ec38833c
ZJS
1235 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
1236 '11-dummy.netdev', 'macvtap.network')
460feb61
YW
1237 with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f:
1238 f.write('[MACVTAP]\nMode=' + mode)
2cf6fdff 1239 start_networkd()
1f0e3109 1240
c918b70a
TY
1241 self.wait_online(['macvtap99:degraded',
1242 'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
460feb61 1243
371810d1 1244 output = check_output('ip -d link show macvtap99')
460feb61
YW
1245 print(output)
1246 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
1f0e3109
SS
1247
1248 def test_macvlan(self):
dff9792b
YW
1249 for mode in ['private', 'vepa', 'bridge', 'passthru']:
1250 with self.subTest(mode=mode):
1251 if mode != 'private':
1252 self.tearDown()
ec38833c
ZJS
1253 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
1254 '11-dummy.netdev', 'macvlan.network')
dff9792b
YW
1255 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
1256 f.write('[MACVLAN]\nMode=' + mode)
2cf6fdff 1257 start_networkd()
dff9792b 1258
c918b70a
TY
1259 self.wait_online(['macvlan99:degraded',
1260 'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
dff9792b 1261
371810d1 1262 output = check_output('ip -d link show test1')
dff9792b
YW
1263 print(output)
1264 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 1265
371810d1 1266 output = check_output('ip -d link show macvlan99')
dff9792b
YW
1267 print(output)
1268 self.assertRegex(output, ' mtu 2000 ')
1269 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
72b7f1b9 1270
1d0c9bd7
YW
1271 rc = call("ip link del test1")
1272 self.assertEqual(rc, 0)
1273 time.sleep(1)
1274
1275 rc = call("ip link add test1 type dummy")
1276 self.assertEqual(rc, 0)
1277 time.sleep(1)
1278
c918b70a
TY
1279 self.wait_online(['macvlan99:degraded',
1280 'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
1d0c9bd7
YW
1281
1282 output = check_output('ip -d link show test1')
1283 print(output)
1284 self.assertRegex(output, ' mtu 2000 ')
1285
1286 output = check_output('ip -d link show macvlan99')
1287 print(output)
1288 self.assertRegex(output, ' mtu 2000 ')
1289 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
1290
7a0a37b2 1291 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109 1292 def test_ipvlan(self):
bc6dff6e
YW
1293 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
1294 with self.subTest(mode=mode, flag=flag):
1295 if mode != 'L2':
1296 self.tearDown()
ec38833c
ZJS
1297 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
1298 '11-dummy.netdev', 'ipvlan.network')
bc6dff6e
YW
1299 with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f:
1300 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
1f0e3109 1301
2cf6fdff 1302 start_networkd()
e2aea43f 1303 self.wait_online(['ipvlan99:degraded', 'test1:degraded'])
bc6dff6e 1304
371810d1 1305 output = check_output('ip -d link show ipvlan99')
bc6dff6e
YW
1306 print(output)
1307 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
1f0e3109 1308
956c8fec
YW
1309 @expectedFailureIfModuleIsNotAvailable('ipvtap')
1310 def test_ipvtap(self):
40921f08
YW
1311 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
1312 with self.subTest(mode=mode, flag=flag):
1313 if mode != 'L2':
1314 self.tearDown()
ec38833c
ZJS
1315 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
1316 '11-dummy.netdev', 'ipvtap.network')
40921f08
YW
1317 with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f:
1318 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
1319
2cf6fdff 1320 start_networkd()
e2aea43f 1321 self.wait_online(['ipvtap99:degraded', 'test1:degraded'])
956c8fec 1322
371810d1 1323 output = check_output('ip -d link show ipvtap99')
40921f08
YW
1324 print(output)
1325 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
956c8fec 1326
1f0e3109 1327 def test_veth(self):
0874be35
YW
1328 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network',
1329 '25-veth-mtu.netdev')
2cf6fdff 1330 start_networkd()
1f0e3109 1331
0874be35 1332 self.wait_online(['veth99:degraded', 'veth-peer:degraded', 'veth-mtu:degraded', 'veth-mtu-peer:degraded'])
671dacdf 1333
371810d1 1334 output = check_output('ip -d link show veth99')
671dacdf
YW
1335 print(output)
1336 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
371810d1 1337 output = check_output('ip -d link show veth-peer')
671dacdf
YW
1338 print(output)
1339 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
1f0e3109 1340
0874be35
YW
1341 output = check_output('ip -d link show veth-mtu')
1342 print(output)
1343 self.assertRegex(output, 'link/ether 12:34:56:78:9a:be')
1344 self.assertRegex(output, 'mtu 1800')
1345 output = check_output('ip -d link show veth-mtu-peer')
1346 print(output)
1347 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bf')
1348 self.assertRegex(output, 'mtu 1800')
1349
1f0e3109 1350 def test_tun(self):
ec38833c 1351 copy_unit_to_networkd_unit_path('25-tun.netdev')
2cf6fdff 1352 start_networkd()
1f0e3109 1353
e2aea43f 1354 self.wait_online(['tun99:off'], setup_state='unmanaged')
1f0e3109 1355
371810d1 1356 output = check_output('ip -d link show tun99')
2746d307
YW
1357 print(output)
1358 # Old ip command does not support IFF_ flags
426654d7 1359 self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
2746d307 1360
1f0e3109 1361 def test_tap(self):
ec38833c 1362 copy_unit_to_networkd_unit_path('25-tap.netdev')
2cf6fdff 1363 start_networkd()
1f0e3109 1364
e2aea43f 1365 self.wait_online(['tap99:off'], setup_state='unmanaged')
1f0e3109 1366
371810d1 1367 output = check_output('ip -d link show tap99')
2746d307
YW
1368 print(output)
1369 # Old ip command does not support IFF_ flags
426654d7 1370 self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
2746d307 1371
7a0a37b2 1372 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109 1373 def test_vrf(self):
ec38833c 1374 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1375 start_networkd()
1f0e3109 1376
e2aea43f 1377 self.wait_online(['vrf99:carrier'])
1f0e3109 1378
7a0a37b2 1379 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109 1380 def test_vcan(self):
ec38833c 1381 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1382 start_networkd()
1f0e3109 1383
e2aea43f 1384 self.wait_online(['vcan99:carrier'])
1f0e3109 1385
f63b14d3
YW
1386 @expectedFailureIfModuleIsNotAvailable('vxcan')
1387 def test_vxcan(self):
ec38833c 1388 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1389 start_networkd()
f63b14d3 1390
e2aea43f 1391 self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
f63b14d3 1392
7a3bc5a8
EV
1393 @expectedFailureIfModuleIsNotAvailable('wireguard')
1394 def test_wireguard(self):
ec38833c
ZJS
1395 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
1396 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
da3509f0
YW
1397 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt',
1398 '25-wireguard-no-peer.netdev', '25-wireguard-no-peer.network')
2cf6fdff 1399 start_networkd()
84d32bf5
YW
1400 self.wait_online(['wg99:routable', 'wg98:routable', 'wg97:carrier'])
1401
1402 output = check_output('ip -4 address show dev wg99')
1403 print(output)
1404 self.assertIn('inet 192.168.124.1/24 scope global wg99', output)
5a0bd90b 1405
045db4fa
YW
1406 output = check_output('ip -4 address show dev wg98')
1407 print(output)
1408 self.assertIn('inet 192.168.123.123/24 scope global wg98', output)
1409
1410 output = check_output('ip -6 address show dev wg98')
1411 print(output)
1412 self.assertIn('inet6 fd8d:4d6d:3ccb:500::1/64 scope global', output)
1413
6387cac3
YW
1414 output = check_output('ip -4 route show dev wg99 table 1234')
1415 print(output)
1416 self.assertIn('192.168.26.0/24 proto static metric 123', output)
1417
1418 output = check_output('ip -6 route show dev wg99 table 1234')
1419 print(output)
1420 self.assertIn('fd31:bf08:57cb::/48 proto static metric 123 pref medium', output)
1421
1422 output = check_output('ip -6 route show dev wg98 table 1234')
1423 print(output)
1424 self.assertIn('fd8d:4d6d:3ccb:500:c79:2339:edce:ece1 proto static metric 123 pref medium', output)
1425 self.assertIn('fd8d:4d6d:3ccb:500:1dbf:ca8a:32d3:dd81 proto static metric 123 pref medium', output)
1426 self.assertIn('fd8d:4d6d:3ccb:500:1e54:1415:35d0:a47c proto static metric 123 pref medium', output)
1427 self.assertIn('fd8d:4d6d:3ccb:500:270d:b5dd:4a3f:8909 proto static metric 123 pref medium', output)
1428 self.assertIn('fd8d:4d6d:3ccb:500:5660:679d:3532:94d8 proto static metric 123 pref medium', output)
1429 self.assertIn('fd8d:4d6d:3ccb:500:6825:573f:30f3:9472 proto static metric 123 pref medium', output)
1430 self.assertIn('fd8d:4d6d:3ccb:500:6f2e:6888:c6fd:dfb9 proto static metric 123 pref medium', output)
1431 self.assertIn('fd8d:4d6d:3ccb:500:8d4d:bab:7280:a09a proto static metric 123 pref medium', output)
1432 self.assertIn('fd8d:4d6d:3ccb:500:900c:d437:ec27:8822 proto static metric 123 pref medium', output)
1433 self.assertIn('fd8d:4d6d:3ccb:500:9742:9931:5217:18d5 proto static metric 123 pref medium', output)
1434 self.assertIn('fd8d:4d6d:3ccb:500:9c11:d820:2e96:9be0 proto static metric 123 pref medium', output)
1435 self.assertIn('fd8d:4d6d:3ccb:500:a072:80da:de4f:add1 proto static metric 123 pref medium', output)
1436 self.assertIn('fd8d:4d6d:3ccb:500:a3f3:df38:19b0:721 proto static metric 123 pref medium', output)
1437 self.assertIn('fd8d:4d6d:3ccb:500:a94b:cd6a:a32d:90e6 proto static metric 123 pref medium', output)
1438 self.assertIn('fd8d:4d6d:3ccb:500:b39c:9cdc:755a:ead3 proto static metric 123 pref medium', output)
1439 self.assertIn('fd8d:4d6d:3ccb:500:b684:4f81:2e3e:132e proto static metric 123 pref medium', output)
1440 self.assertIn('fd8d:4d6d:3ccb:500:bad5:495d:8e9c:3427 proto static metric 123 pref medium', output)
1441 self.assertIn('fd8d:4d6d:3ccb:500:bfe5:c3c3:5d77:fcb proto static metric 123 pref medium', output)
1442 self.assertIn('fd8d:4d6d:3ccb:500:c624:6bf7:4c09:3b59 proto static metric 123 pref medium', output)
1443 self.assertIn('fd8d:4d6d:3ccb:500:d4f9:5dc:9296:a1a proto static metric 123 pref medium', output)
1444 self.assertIn('fd8d:4d6d:3ccb:500:dcdd:d33b:90c9:6088 proto static metric 123 pref medium', output)
1445 self.assertIn('fd8d:4d6d:3ccb:500:e2e1:ae15:103f:f376 proto static metric 123 pref medium', output)
1446 self.assertIn('fd8d:4d6d:3ccb:500:f349:c4f0:10c1:6b4 proto static metric 123 pref medium', output)
1447 self.assertIn('fd8d:4d6d:3ccb:c79:2339:edce::/96 proto static metric 123 pref medium', output)
1448 self.assertIn('fd8d:4d6d:3ccb:1dbf:ca8a:32d3::/96 proto static metric 123 pref medium', output)
1449 self.assertIn('fd8d:4d6d:3ccb:1e54:1415:35d0::/96 proto static metric 123 pref medium', output)
1450 self.assertIn('fd8d:4d6d:3ccb:270d:b5dd:4a3f::/96 proto static metric 123 pref medium', output)
1451 self.assertIn('fd8d:4d6d:3ccb:5660:679d:3532::/96 proto static metric 123 pref medium', output)
1452 self.assertIn('fd8d:4d6d:3ccb:6825:573f:30f3::/96 proto static metric 123 pref medium', output)
1453 self.assertIn('fd8d:4d6d:3ccb:6f2e:6888:c6fd::/96 proto static metric 123 pref medium', output)
1454 self.assertIn('fd8d:4d6d:3ccb:8d4d:bab:7280::/96 proto static metric 123 pref medium', output)
1455 self.assertIn('fd8d:4d6d:3ccb:900c:d437:ec27::/96 proto static metric 123 pref medium', output)
1456 self.assertIn('fd8d:4d6d:3ccb:9742:9931:5217::/96 proto static metric 123 pref medium', output)
1457 self.assertIn('fd8d:4d6d:3ccb:9c11:d820:2e96::/96 proto static metric 123 pref medium', output)
1458 self.assertIn('fd8d:4d6d:3ccb:a072:80da:de4f::/96 proto static metric 123 pref medium', output)
1459 self.assertIn('fd8d:4d6d:3ccb:a3f3:df38:19b0::/96 proto static metric 123 pref medium', output)
1460 self.assertIn('fd8d:4d6d:3ccb:a94b:cd6a:a32d::/96 proto static metric 123 pref medium', output)
1461 self.assertIn('fd8d:4d6d:3ccb:b39c:9cdc:755a::/96 proto static metric 123 pref medium', output)
1462 self.assertIn('fd8d:4d6d:3ccb:b684:4f81:2e3e::/96 proto static metric 123 pref medium', output)
1463 self.assertIn('fd8d:4d6d:3ccb:bad5:495d:8e9c::/96 proto static metric 123 pref medium', output)
1464 self.assertIn('fd8d:4d6d:3ccb:bfe5:c3c3:5d77::/96 proto static metric 123 pref medium', output)
1465 self.assertIn('fd8d:4d6d:3ccb:c624:6bf7:4c09::/96 proto static metric 123 pref medium', output)
1466 self.assertIn('fd8d:4d6d:3ccb:d4f9:5dc:9296::/96 proto static metric 123 pref medium', output)
1467 self.assertIn('fd8d:4d6d:3ccb:dcdd:d33b:90c9::/96 proto static metric 123 pref medium', output)
1468 self.assertIn('fd8d:4d6d:3ccb:e2e1:ae15:103f::/96 proto static metric 123 pref medium', output)
1469 self.assertIn('fd8d:4d6d:3ccb:f349:c4f0:10c1::/96 proto static metric 123 pref medium', output)
1470
7a3bc5a8 1471 if shutil.which('wg'):
371810d1 1472 call('wg')
5a0bd90b 1473
371810d1 1474 output = check_output('wg show wg99 listen-port')
84d32bf5 1475 self.assertEqual(output, '51820')
371810d1 1476 output = check_output('wg show wg99 fwmark')
84d32bf5
YW
1477 self.assertEqual(output, '0x4d2')
1478 output = check_output('wg show wg99 private-key')
1479 self.assertEqual(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong=')
371810d1 1480 output = check_output('wg show wg99 allowed-ips')
84d32bf5
YW
1481 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t192.168.124.3/32', output)
1482 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\t192.168.124.2/32', output)
1483 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128', output)
1484 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48', output)
371810d1 1485 output = check_output('wg show wg99 persistent-keepalive')
84d32bf5
YW
1486 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\toff', output)
1487 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\toff', output)
1488 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\toff', output)
1489 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20', output)
371810d1 1490 output = check_output('wg show wg99 endpoints')
84d32bf5
YW
1491 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t(none)', output)
1492 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\t(none)', output)
1493 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\t(none)', output)
1494 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820', output)
371810d1 1495 output = check_output('wg show wg99 preshared-keys')
84d32bf5
YW
1496 self.assertIn('9uioxkGzjvGjkse3V35I9AhorWfIjBcrf3UPMS0bw2c=\t6Fsg8XN0DE6aPQgAX4r2oazEYJOGqyHUz3QRH/jCB+I=', output)
1497 self.assertIn('TTiCUpCxS7zDn/ax4p5W6Evg41r8hOrnWQw2Sq6Nh10=\tit7nd33chCT/tKT2ZZWfYyp43Zs+6oif72hexnSNMqA=', output)
1498 self.assertIn('lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tcPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=', output)
1499 self.assertIn('RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\tIIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=', output)
7a3bc5a8 1500
371810d1 1501 output = check_output('wg show wg98 private-key')
84d32bf5 1502 self.assertEqual(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr+WHtZLZ90FU=')
da44fb8a 1503
da3509f0 1504 output = check_output('wg show wg97 listen-port')
84d32bf5 1505 self.assertEqual(output, '51821')
da3509f0 1506 output = check_output('wg show wg97 fwmark')
84d32bf5 1507 self.assertEqual(output, '0x4d3')
da3509f0 1508
1f0e3109 1509 def test_geneve(self):
ec38833c 1510 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1511 start_networkd()
1f0e3109 1512
e2aea43f 1513 self.wait_online(['geneve99:degraded'])
1f0e3109 1514
371810d1 1515 output = check_output('ip -d link show geneve99')
14ecd604 1516 print(output)
06895a1d
YW
1517 self.assertRegex(output, '192.168.22.1')
1518 self.assertRegex(output, '6082')
1519 self.assertRegex(output, 'udpcsum')
1520 self.assertRegex(output, 'udp6zerocsumrx')
1f0e3109
SS
1521
1522 def test_ipip_tunnel(self):
ec38833c
ZJS
1523 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
1524 '25-ipip-tunnel.netdev', '25-tunnel.network',
1525 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1526 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1527 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1528 start_networkd()
e2aea43f 1529 self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
6a97a864 1530
371810d1 1531 output = check_output('ip -d link show ipiptun99')
6a97a864 1532 print(output)
426654d7 1533 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98')
371810d1 1534 output = check_output('ip -d link show ipiptun98')
6a97a864 1535 print(output)
426654d7 1536 self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98')
371810d1 1537 output = check_output('ip -d link show ipiptun97')
6a97a864 1538 print(output)
426654d7 1539 self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98')
42a29fcb
YW
1540 output = check_output('ip -d link show ipiptun96')
1541 print(output)
426654d7 1542 self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98')
1f0e3109
SS
1543
1544 def test_gre_tunnel(self):
ec38833c
ZJS
1545 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
1546 '25-gre-tunnel.netdev', '25-tunnel.network',
1547 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1548 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1549 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1550 start_networkd()
e2aea43f 1551 self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
6a97a864 1552
371810d1 1553 output = check_output('ip -d link show gretun99')
6a97a864
YW
1554 print(output)
1555 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
1556 self.assertRegex(output, 'ikey 1.2.3.103')
1557 self.assertRegex(output, 'okey 1.2.4.103')
1558 self.assertRegex(output, 'iseq')
1559 self.assertRegex(output, 'oseq')
371810d1 1560 output = check_output('ip -d link show gretun98')
6a97a864
YW
1561 print(output)
1562 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
1563 self.assertRegex(output, 'ikey 0.0.0.104')
1564 self.assertRegex(output, 'okey 0.0.0.104')
1565 self.assertNotRegex(output, 'iseq')
1566 self.assertNotRegex(output, 'oseq')
371810d1 1567 output = check_output('ip -d link show gretun97')
6a97a864
YW
1568 print(output)
1569 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
38f4bb44
YW
1570 self.assertRegex(output, 'ikey 0.0.0.105')
1571 self.assertRegex(output, 'okey 0.0.0.105')
1572 self.assertNotRegex(output, 'iseq')
1573 self.assertNotRegex(output, 'oseq')
42a29fcb
YW
1574 output = check_output('ip -d link show gretun96')
1575 print(output)
1576 self.assertRegex(output, 'gre remote any local any dev dummy98')
1577 self.assertRegex(output, 'ikey 0.0.0.106')
1578 self.assertRegex(output, 'okey 0.0.0.106')
1579 self.assertNotRegex(output, 'iseq')
1580 self.assertNotRegex(output, 'oseq')
6a97a864
YW
1581
1582 def test_ip6gre_tunnel(self):
ec38833c
ZJS
1583 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
1584 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
1585 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1586 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1587 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
01943d43 1588 start_networkd(5)
6a97a864 1589
17bcf0a0
YW
1590 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1591
e39cc445
YW
1592 self.check_link_exists('dummy98')
1593 self.check_link_exists('ip6gretun99')
1594 self.check_link_exists('ip6gretun98')
1595 self.check_link_exists('ip6gretun97')
42a29fcb 1596 self.check_link_exists('ip6gretun96')
6a97a864 1597
371810d1 1598 output = check_output('ip -d link show ip6gretun99')
6a97a864
YW
1599 print(output)
1600 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1601 output = check_output('ip -d link show ip6gretun98')
6a97a864
YW
1602 print(output)
1603 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
371810d1 1604 output = check_output('ip -d link show ip6gretun97')
6a97a864
YW
1605 print(output)
1606 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
42a29fcb
YW
1607 output = check_output('ip -d link show ip6gretun96')
1608 print(output)
1609 self.assertRegex(output, 'ip6gre remote any local any dev dummy98')
1f0e3109 1610
11309591 1611 def test_gretap_tunnel(self):
ec38833c
ZJS
1612 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1613 '25-gretap-tunnel.netdev', '25-tunnel.network',
1614 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1615 start_networkd()
e2aea43f 1616 self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
6a97a864 1617
371810d1 1618 output = check_output('ip -d link show gretap99')
6a97a864
YW
1619 print(output)
1620 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
1621 self.assertRegex(output, 'ikey 0.0.0.106')
1622 self.assertRegex(output, 'okey 0.0.0.106')
1623 self.assertRegex(output, 'iseq')
1624 self.assertRegex(output, 'oseq')
371810d1 1625 output = check_output('ip -d link show gretap98')
6a97a864
YW
1626 print(output)
1627 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
1628 self.assertRegex(output, 'ikey 0.0.0.107')
1629 self.assertRegex(output, 'okey 0.0.0.107')
1630 self.assertRegex(output, 'iseq')
1631 self.assertRegex(output, 'oseq')
1f0e3109
SS
1632
1633 def test_ip6gretap_tunnel(self):
ec38833c
ZJS
1634 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1635 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1636 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1637 start_networkd()
e2aea43f 1638 self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
6a97a864 1639
371810d1 1640 output = check_output('ip -d link show ip6gretap99')
6a97a864
YW
1641 print(output)
1642 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1643 output = check_output('ip -d link show ip6gretap98')
6a97a864
YW
1644 print(output)
1645 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1f0e3109
SS
1646
1647 def test_vti_tunnel(self):
ec38833c
ZJS
1648 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1649 '25-vti-tunnel.netdev', '25-tunnel.network',
1650 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1651 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1652 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1653 start_networkd()
e2aea43f 1654 self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
6a97a864 1655
371810d1 1656 output = check_output('ip -d link show vtitun99')
6a97a864
YW
1657 print(output)
1658 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
371810d1 1659 output = check_output('ip -d link show vtitun98')
6a97a864
YW
1660 print(output)
1661 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
371810d1 1662 output = check_output('ip -d link show vtitun97')
6a97a864
YW
1663 print(output)
1664 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
42a29fcb
YW
1665 output = check_output('ip -d link show vtitun96')
1666 print(output)
1667 self.assertRegex(output, 'vti remote any local any dev dummy98')
1f0e3109
SS
1668
1669 def test_vti6_tunnel(self):
ec38833c
ZJS
1670 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1671 '25-vti6-tunnel.netdev', '25-tunnel.network',
1672 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1673 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
2cf6fdff 1674 start_networkd()
e2aea43f 1675 self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
6a97a864 1676
371810d1 1677 output = check_output('ip -d link show vti6tun99')
6a97a864
YW
1678 print(output)
1679 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 1680 output = check_output('ip -d link show vti6tun98')
6a97a864 1681 print(output)
426654d7 1682 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1683 output = check_output('ip -d link show vti6tun97')
6a97a864 1684 print(output)
426654d7 1685 self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
1686
1687 def test_ip6tnl_tunnel(self):
ec38833c
ZJS
1688 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1689 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1690 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
da7d6848
YW
1691 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1692 '25-veth.netdev', 'ip6tnl-slaac.network', 'ipv6-prefix.network',
1693 '25-ip6tnl-tunnel-local-slaac.netdev', '25-ip6tnl-tunnel-local-slaac.network')
2cf6fdff 1694 start_networkd()
da7d6848
YW
1695 self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'ip6tnl-slaac:degraded',
1696 'dummy98:degraded', 'veth99:routable', 'veth-peer:degraded'])
6a97a864 1697
371810d1 1698 output = check_output('ip -d link show ip6tnl99')
6a97a864 1699 print(output)
da7d6848 1700 self.assertIn('ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98', output)
371810d1 1701 output = check_output('ip -d link show ip6tnl98')
6a97a864 1702 print(output)
426654d7 1703 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98')
371810d1 1704 output = check_output('ip -d link show ip6tnl97')
6a97a864 1705 print(output)
426654d7 1706 self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
da7d6848
YW
1707 output = check_output('ip -d link show ip6tnl-slaac')
1708 print(output)
1709 self.assertIn('ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2002:da8:1:0:1034:56ff:fe78:9abc dev veth99', output)
1710
1711 output = check_output('ip -6 address show veth99')
1712 print(output)
1713 self.assertIn('inet6 2002:da8:1:0:1034:56ff:fe78:9abc/64 scope global dynamic', output)
1714
1715 output = check_output('ip -4 route show default')
1716 print(output)
1717 self.assertIn('default dev ip6tnl-slaac proto static', output)
1f0e3109
SS
1718
1719 def test_sit_tunnel(self):
ec38833c
ZJS
1720 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1721 '25-sit-tunnel.netdev', '25-tunnel.network',
1722 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
42a29fcb
YW
1723 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1724 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
2cf6fdff 1725 start_networkd()
e2aea43f 1726 self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
6a97a864 1727
371810d1 1728 output = check_output('ip -d link show sittun99')
6a97a864 1729 print(output)
426654d7 1730 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98")
371810d1 1731 output = check_output('ip -d link show sittun98')
6a97a864 1732 print(output)
426654d7 1733 self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98")
371810d1 1734 output = check_output('ip -d link show sittun97')
6a97a864 1735 print(output)
426654d7 1736 self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98")
42a29fcb
YW
1737 output = check_output('ip -d link show sittun96')
1738 print(output)
426654d7 1739 self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98")
1f0e3109 1740
d0e728b6 1741 def test_isatap_tunnel(self):
ec38833c
ZJS
1742 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1743 '25-isatap-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1744 start_networkd()
e2aea43f 1745 self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
d0e728b6 1746
371810d1 1747 output = check_output('ip -d link show isataptun99')
14ecd604 1748 print(output)
d0e728b6
SS
1749 self.assertRegex(output, "isatap ")
1750
d29dc4f1 1751 def test_6rd_tunnel(self):
ec38833c
ZJS
1752 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1753 '25-6rd-tunnel.netdev', '25-tunnel.network')
2cf6fdff 1754 start_networkd()
e2aea43f 1755 self.wait_online(['sittun99:routable', 'dummy98:degraded'])
d29dc4f1 1756
371810d1 1757 output = check_output('ip -d link show sittun99')
6a97a864
YW
1758 print(output)
1759 self.assertRegex(output, '6rd-prefix 2602::/24')
1760
7bea7f9b 1761 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b 1762 def test_erspan_tunnel(self):
ec38833c
ZJS
1763 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1764 '25-erspan-tunnel.netdev', '25-tunnel.network',
1765 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
2cf6fdff 1766 start_networkd()
e2aea43f 1767 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
2266864b 1768
371810d1 1769 output = check_output('ip -d link show erspan99')
6a97a864
YW
1770 print(output)
1771 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
38f4bb44
YW
1772 self.assertRegex(output, 'ikey 0.0.0.101')
1773 self.assertRegex(output, 'okey 0.0.0.101')
1774 self.assertRegex(output, 'iseq')
1775 self.assertRegex(output, 'oseq')
371810d1 1776 output = check_output('ip -d link show erspan98')
2266864b 1777 print(output)
6a97a864
YW
1778 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
1779 self.assertRegex(output, '102')
38f4bb44
YW
1780 self.assertRegex(output, 'ikey 0.0.0.102')
1781 self.assertRegex(output, 'okey 0.0.0.102')
1782 self.assertRegex(output, 'iseq')
1783 self.assertRegex(output, 'oseq')
2266864b 1784
1f0e3109 1785 def test_tunnel_independent(self):
ec38833c 1786 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1787 start_networkd()
e40a58b5 1788
e2aea43f 1789 self.wait_online(['ipiptun99:carrier'])
1f0e3109 1790
95082dbe
YW
1791 def test_tunnel_independent_loopback(self):
1792 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1793 start_networkd()
1794
e2aea43f 1795 self.wait_online(['ipiptun99:carrier'])
95082dbe 1796
e64dc406
YW
1797 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1798 def test_xfrm(self):
1799 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1800 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1801 start_networkd()
1802
e2aea43f 1803 self.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
e64dc406
YW
1804
1805 output = check_output('ip link show dev xfrm99')
1806 print(output)
1807
1808 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1809 def test_xfrm_independent(self):
1810 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1811 start_networkd()
1812
e2aea43f 1813 self.wait_online(['xfrm99:degraded'])
e64dc406 1814
4b6a6d1e
YW
1815 @expectedFailureIfModuleIsNotAvailable('fou')
1816 def test_fou(self):
1817 # The following redundant check is necessary for CentOS CI.
1818 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1819 self.assertTrue(is_module_available('fou'))
1820
ec38833c
ZJS
1821 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1822 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1823 '25-fou-gre.netdev', '25-fou-gretap.netdev')
2cf6fdff 1824 start_networkd()
4b6a6d1e 1825
e2aea43f 1826 self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged')
4b6a6d1e 1827
371810d1 1828 output = check_output('ip fou show')
4b6a6d1e
YW
1829 print(output)
1830 self.assertRegex(output, 'port 55555 ipproto 4')
1831 self.assertRegex(output, 'port 55556 ipproto 47')
1832
371810d1 1833 output = check_output('ip -d link show ipiptun96')
4b6a6d1e
YW
1834 print(output)
1835 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1836 output = check_output('ip -d link show sittun96')
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 gretun96')
4b6a6d1e
YW
1840 print(output)
1841 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
371810d1 1842 output = check_output('ip -d link show gretap96')
4b6a6d1e
YW
1843 print(output)
1844 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1845
1f0e3109 1846 def test_vxlan(self):
49ad8da7
YW
1847 copy_unit_to_networkd_unit_path('11-dummy.netdev', 'vxlan-test1.network',
1848 '25-vxlan.netdev', 'vxlan.network',
cca07d91 1849 '25-vxlan-ipv6.netdev', 'vxlan-ipv6.network',
039971ea 1850 '25-vxlan-independent.netdev', 'netdev-link-local-addressing-yes.network',
49ad8da7
YW
1851 '25-veth.netdev', '25-vxlan-veth99.network', 'ipv6-prefix.network',
1852 '25-vxlan-local-slaac.netdev', '25-vxlan-local-slaac.network')
2cf6fdff 1853 start_networkd()
1f0e3109 1854
49ad8da7
YW
1855 self.wait_online(['test1:degraded', 'veth99:routable', 'veth-peer:degraded',
1856 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded', 'vxlan-slaac:degraded'])
1f0e3109 1857
371810d1 1858 output = check_output('ip -d link show vxlan99')
14ecd604 1859 print(output)
cca07d91
YW
1860 self.assertIn('999', output)
1861 self.assertIn('5555', output)
1862 self.assertIn('l2miss', output)
1863 self.assertIn('l3miss', output)
1864 self.assertIn('udpcsum', output)
1865 self.assertIn('udp6zerocsumtx', output)
1866 self.assertIn('udp6zerocsumrx', output)
1867 self.assertIn('remcsumtx', output)
1868 self.assertIn('remcsumrx', output)
1869 self.assertIn('gbp', output)
1f0e3109 1870
371810d1 1871 output = check_output('bridge fdb show dev vxlan99')
1c862fe0 1872 print(output)
cca07d91
YW
1873 self.assertIn('00:11:22:33:44:55 dst 10.0.0.5 self permanent', output)
1874 self.assertIn('00:11:22:33:44:66 dst 10.0.0.6 self permanent', output)
1875 self.assertIn('00:11:22:33:44:77 dst 10.0.0.7 via test1 self permanent', output)
1c862fe0 1876
fc79e6ff 1877 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'vxlan99', env=env)
36bc2ffb 1878 print(output)
cca07d91
YW
1879 self.assertIn('VNI: 999', output)
1880 self.assertIn('Destination Port: 5555', output)
1881 self.assertIn('Underlying Device: test1', output)
1882
1883 output = check_output('bridge fdb show dev vxlan97')
1884 print(output)
1885 self.assertIn('00:00:00:00:00:00 dst fe80::23b:d2ff:fe95:967f via test1 self permanent', output)
1886 self.assertIn('00:00:00:00:00:00 dst fe80::27c:16ff:fec0:6c74 via test1 self permanent', output)
1887 self.assertIn('00:00:00:00:00:00 dst fe80::2a2:e4ff:fef9:2269 via test1 self permanent', output)
36bc2ffb 1888
49ad8da7
YW
1889 output = check_output('ip -d link show vxlan-slaac')
1890 print(output)
1891 self.assertIn('vxlan id 4831584 local 2002:da8:1:0:1034:56ff:fe78:9abc dev veth99', output)
1892
1893 output = check_output('ip -6 address show veth99')
1894 print(output)
1895 self.assertIn('inet6 2002:da8:1:0:1034:56ff:fe78:9abc/64 scope global dynamic', output)
1896
02849d8b 1897 def test_macsec(self):
ec38833c
ZJS
1898 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1899 'macsec.network', '12-dummy.netdev')
2cf6fdff 1900 start_networkd()
02849d8b 1901
e2aea43f 1902 self.wait_online(['dummy98:degraded', 'macsec99:routable'])
02849d8b 1903
371810d1 1904 output = check_output('ip -d link show macsec99')
02849d8b
YW
1905 print(output)
1906 self.assertRegex(output, 'macsec99@dummy98')
1907 self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
1908 self.assertRegex(output, 'encrypt on')
1909
371810d1 1910 output = check_output('ip macsec show macsec99')
02849d8b
YW
1911 print(output)
1912 self.assertRegex(output, 'encrypt on')
1913 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
1914 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1915 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1916 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on')
1917 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1918 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1919 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1920 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1921 self.assertNotRegex(output, 'key 02030405067080900000000000000000')
1922 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
1923 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1924
811f33d0 1925 def test_nlmon(self):
ec38833c 1926 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
2cf6fdff 1927 start_networkd()
811f33d0 1928
e2aea43f 1929 self.wait_online(['nlmon99:carrier'])
02849d8b 1930
b076d5d7
YW
1931 @expectedFailureIfModuleIsNotAvailable('ifb')
1932 def test_ifb(self):
1933 copy_unit_to_networkd_unit_path('25-ifb.netdev', 'netdev-link-local-addressing-yes.network')
1934 start_networkd()
1935
1936 self.wait_online(['ifb99:degraded'])
1937
cff83db9
YW
1938class NetworkdL2TPTests(unittest.TestCase, Utilities):
1939
1940 links =[
1941 'l2tp-ses1',
1942 'l2tp-ses2',
1943 'l2tp-ses3',
1944 'l2tp-ses4',
1945 'test1']
1946
1947 units = [
1948 '11-dummy.netdev',
1949 '25-l2tp-dummy.network',
e2aea43f 1950 '25-l2tp.network',
cff83db9
YW
1951 '25-l2tp-ip.netdev',
1952 '25-l2tp-udp.netdev']
1953
1954 l2tp_tunnel_ids = [ '10' ]
1955
1956 def setUp(self):
ad78d7b0 1957 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c 1958 remove_links(self.links)
aaae5713 1959 stop_networkd(show_logs=False)
cff83db9
YW
1960
1961 def tearDown(self):
ad78d7b0 1962 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
ec38833c
ZJS
1963 remove_links(self.links)
1964 remove_unit_from_networkd_path(self.units)
aaae5713 1965 stop_networkd(show_logs=True)
cff83db9
YW
1966
1967 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1968 def test_l2tp_udp(self):
e2aea43f
YW
1969 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1970 '25-l2tp-udp.netdev', '25-l2tp.network')
2cf6fdff 1971 start_networkd()
cff83db9 1972
e2aea43f 1973 self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
cff83db9 1974
371810d1 1975 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1976 print(output)
1977 self.assertRegex(output, "Tunnel 10, encap UDP")
1978 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1979 self.assertRegex(output, "Peer tunnel 11")
1980 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
1981 self.assertRegex(output, "UDP checksum: enabled")
1982
371810d1 1983 output = check_output('ip l2tp show session tid 10 session_id 15')
cff83db9
YW
1984 print(output)
1985 self.assertRegex(output, "Session 15 in tunnel 10")
1986 self.assertRegex(output, "Peer session 16, tunnel 11")
1987 self.assertRegex(output, "interface name: l2tp-ses1")
1988
371810d1 1989 output = check_output('ip l2tp show session tid 10 session_id 17')
cff83db9
YW
1990 print(output)
1991 self.assertRegex(output, "Session 17 in tunnel 10")
1992 self.assertRegex(output, "Peer session 18, tunnel 11")
1993 self.assertRegex(output, "interface name: l2tp-ses2")
1994
1995 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1996 def test_l2tp_ip(self):
e2aea43f
YW
1997 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1998 '25-l2tp-ip.netdev', '25-l2tp.network')
2cf6fdff 1999 start_networkd()
cff83db9 2000
e2aea43f 2001 self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
cff83db9 2002
371810d1 2003 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
2004 print(output)
2005 self.assertRegex(output, "Tunnel 10, encap IP")
2006 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
2007 self.assertRegex(output, "Peer tunnel 12")
2008
371810d1 2009 output = check_output('ip l2tp show session tid 10 session_id 25')
cff83db9
YW
2010 print(output)
2011 self.assertRegex(output, "Session 25 in tunnel 10")
2012 self.assertRegex(output, "Peer session 26, tunnel 12")
2013 self.assertRegex(output, "interface name: l2tp-ses3")
2014
371810d1 2015 output = check_output('ip l2tp show session tid 10 session_id 27')
cff83db9
YW
2016 print(output)
2017 self.assertRegex(output, "Session 27 in tunnel 10")
2018 self.assertRegex(output, "Peer session 28, tunnel 12")
2019 self.assertRegex(output, "interface name: l2tp-ses4")
2020
be68c2c9 2021class NetworkdNetworkTests(unittest.TestCase, Utilities):
09ea6724
YW
2022 links = [
2023 'bond199',
2024 'dummy98',
cd65d067 2025 'dummy99',
74761cf3 2026 'gretun97',
fb2ba330 2027 'ip6gretun97',
086bcf5d 2028 'test1',
70448bb1 2029 'veth-peer',
086bcf5d 2030 'veth99',
40afe491 2031 'vrf99',
74761cf3 2032 ]
09ea6724
YW
2033
2034 units = [
2035 '11-dummy.netdev',
2036 '12-dummy.netdev',
61764fe4 2037 '12-dummy.network',
09ea6724 2038 '23-active-slave.network',
1e498853 2039 '24-keep-configuration-static.network',
fdcd1ec5 2040 '24-search-domain.network',
44924431 2041 '25-address-ipv4acd-veth99.network',
09ea6724 2042 '25-address-link-section.network',
21266e60 2043 '25-address-peer-ipv4.network',
b8102725 2044 '25-address-static.network',
2236d75d 2045 '25-activation-policy.network',
cd65d067 2046 '25-bind-carrier.network',
09ea6724
YW
2047 '25-bond-active-backup-slave.netdev',
2048 '25-fibrule-invert.network',
2049 '25-fibrule-port-range.network',
6be8e78e 2050 '25-fibrule-uidrange.network',
74761cf3 2051 '25-gre-tunnel-remote-any.netdev',
fb2ba330 2052 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 2053 '25-ipv6-address-label-section.network',
cff0cadc 2054 '25-ipv6-proxy-ndp.network',
ef3c8a92
YW
2055 '25-link-local-addressing-no.network',
2056 '25-link-local-addressing-yes.network',
2057 '25-link-section-unmanaged.network',
e4a71bf3 2058 '25-neighbor-section.network',
d1bdafd2 2059 '25-neighbor-next.network',
fb2ba330 2060 '25-neighbor-ipv6.network',
74761cf3
YW
2061 '25-neighbor-ip-dummy.network',
2062 '25-neighbor-ip.network',
9c8f90d0 2063 '25-nexthop-dummy.network',
9947c7ba 2064 '25-nexthop-nothing.network',
086bcf5d 2065 '25-nexthop.network',
f6c6af38 2066 '25-qdisc-cake.network',
f1de1eb3 2067 '25-qdisc-clsact-and-htb.network',
557fa421 2068 '25-qdisc-drr.network',
b753e835 2069 '25-qdisc-ets.network',
1578266b 2070 '25-qdisc-fq_pie.network',
970ab1fc 2071 '25-qdisc-hhf.network',
ab9dc1db 2072 '25-qdisc-ingress-netem-compat.network',
be94e591 2073 '25-qdisc-pie.network',
891ff963 2074 '25-qdisc-qfq.network',
c9d223e8
YW
2075 '25-prefix-route-with-vrf.network',
2076 '25-prefix-route-without-vrf.network',
20ca06a6 2077 '25-route-ipv6-src.network',
0ef830cf 2078 '25-route-static.network',
297f9d86 2079 '25-route-via-ipv6.network',
40afe491 2080 '25-route-vrf.network',
0b1cd3e2
WKI
2081 '25-gateway-static.network',
2082 '25-gateway-next-static.network',
4da33154 2083 '25-sysctl-disable-ipv6.network',
09ea6724 2084 '25-sysctl.network',
9bacf431 2085 '25-test1.network',
086bcf5d
YW
2086 '25-veth-peer.network',
2087 '25-veth.netdev',
40afe491 2088 '25-vrf.netdev',
c9d223e8 2089 '25-vrf.network',
7b3770a7 2090 '26-link-local-addressing-ipv6.network',
70448bb1
L
2091 'dhcp-client-ipv4-ipv6ra-prefix-client-with-delay.network',
2092 'dhcp-server-with-ipv6-prefix.network',
2093 'ipv6ra-prefix-client-with-static-ipv4-address.network',
2094 'ipv6-prefix-with-delay.network',
b677774d 2095 'routing-policy-rule-dummy98.network',
87adeabf 2096 'routing-policy-rule-test1.network',
49ff3f34
YW
2097 'routing-policy-rule-reconfigure1.network',
2098 'routing-policy-rule-reconfigure2.network',
87adeabf 2099 ]
1f0e3109 2100
1d26d4cd
YW
2101 networkd_conf_dropins = [
2102 'networkd-manage-foreign-routes-no.conf',
2103 ]
2104
2e8a32af 2105 routing_policy_rule_tables = ['7', '8', '9', '10', '1011']
5f68a6a4 2106 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
95c74b0a 2107
1f0e3109 2108 def setUp(self):
69a91c70 2109 remove_blackhole_nexthops()
ec38833c
ZJS
2110 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
2111 remove_routes(self.routes)
2112 remove_links(self.links)
aaae5713 2113 stop_networkd(show_logs=False)
44924431 2114 call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
1f0e3109
SS
2115
2116 def tearDown(self):
69a91c70 2117 remove_blackhole_nexthops()
ec38833c
ZJS
2118 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
2119 remove_routes(self.routes)
2120 remove_links(self.links)
2121 remove_unit_from_networkd_path(self.units)
1d26d4cd 2122 remove_networkd_conf_dropin(self.networkd_conf_dropins)
aaae5713 2123 stop_networkd(show_logs=True)
44924431 2124 call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
1f0e3109 2125
b8102725 2126 def test_address_static(self):
ec38833c 2127 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
2cf6fdff 2128 start_networkd()
b8102725 2129
e2aea43f 2130 self.wait_online(['dummy98:routable'])
b8102725 2131
371810d1 2132 output = check_output('ip -4 address show dev dummy98')
b8102725 2133 print(output)
4a704501
YW
2134 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
2135 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
2136 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
2137 self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output)
045db4fa 2138 self.assertIn('inet 10.8.8.1/16 scope global dummy98', output)
1ac845ff
YW
2139 self.assertIn('inet 10.8.8.2/16 brd 10.8.8.128 scope global secondary dummy98', output)
2140 self.assertRegex(output, 'inet 10.9.0.1/16 (metric 128 |)brd 10.9.255.255 scope global dummy98')
b8102725 2141
766f8f38
YW
2142 # test for ENOBUFS issue #17012
2143 for i in range(1,254):
4a704501 2144 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
766f8f38 2145
b8102725 2146 # invalid sections
4a704501
YW
2147 self.assertNotIn('10.10.0.1/16', output)
2148 self.assertNotIn('10.10.0.2/16', output)
b8102725 2149
371810d1 2150 output = check_output('ip -4 address show dev dummy98 label 32')
4a704501 2151 self.assertIn('inet 10.3.2.3/16 brd 10.3.255.255 scope global 32', output)
b8102725 2152
371810d1 2153 output = check_output('ip -4 address show dev dummy98 label 33')
4a704501 2154 self.assertIn('inet 10.4.2.3 peer 10.4.2.4/16 scope global 33', output)
b8102725 2155
371810d1 2156 output = check_output('ip -4 address show dev dummy98 label 34')
4a704501 2157 self.assertRegex(output, r'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
b8102725 2158
371810d1 2159 output = check_output('ip -4 address show dev dummy98 label 35')
4a704501 2160 self.assertRegex(output, r'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
b8102725 2161
1ac845ff
YW
2162 output = check_output('ip -4 route show dev dummy98')
2163 print(output)
2164 self.assertIn('10.9.0.0/16 proto kernel scope link src 10.9.0.1 metric 128', output)
2165
371810d1 2166 output = check_output('ip -6 address show dev dummy98')
b8102725 2167 print(output)
4a704501
YW
2168 self.assertIn('inet6 2001:db8:0:f101::15/64 scope global', output)
2169 self.assertIn('inet6 2001:db8:0:f101::16/64 scope global', output)
2170 self.assertIn('inet6 2001:db8:0:f102::15/64 scope global', output)
2171 self.assertIn('inet6 2001:db8:0:f102::16/64 scope global', output)
2172 self.assertIn('inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global', output)
2173 self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output)
2174 self.assertRegex(output, r'inet6 fd[0-9a-f:]*1/64 scope global')
b8102725 2175
40971657
YW
2176 # Tests for #20891.
2177 # 1. set preferred lifetime forever to drop the deprecated flag for testing #20891.
2178 self.assertEqual(call('ip address change 10.7.8.9/16 dev dummy98 preferred_lft forever'), 0)
2179 self.assertEqual(call('ip address change 2001:db8:1:f101::1/64 dev dummy98 preferred_lft forever'), 0)
2180 output = check_output('ip -4 address show dev dummy98')
2181 print(output)
2182 self.assertNotIn('deprecated', output)
2183 output = check_output('ip -6 address show dev dummy98')
2184 print(output)
2185 self.assertNotIn('deprecated', output)
2186
5b47f35d
YW
2187 # 2. reconfigure the interface.
2188 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
766f8f38
YW
2189 self.wait_online(['dummy98:routable'])
2190
40971657
YW
2191 # 3. check the deprecated flag is set for the address configured with PreferredLifetime=0
2192 output = check_output('ip -4 address show dev dummy98')
2193 print(output)
2194 self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output)
2195 output = check_output('ip -6 address show dev dummy98')
2196 print(output)
2197 self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output)
2198
766f8f38
YW
2199 # test for ENOBUFS issue #17012
2200 output = check_output('ip -4 address show dev dummy98')
2201 for i in range(1,254):
4a704501 2202 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
e4783b54 2203
146726b2
YW
2204 # TODO: check json string
2205 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
2206
44924431
YW
2207 def test_address_ipv4acd(self):
2208 check_output('ip netns add ns99')
2209 check_output('ip link add veth99 type veth peer veth-peer')
2210 check_output('ip link set veth-peer netns ns99')
2211 check_output('ip link set veth99 up')
2212 check_output('ip netns exec ns99 ip link set veth-peer up')
2213 check_output('ip netns exec ns99 ip address add 192.168.100.10/24 dev veth-peer')
2214
2215 copy_unit_to_networkd_unit_path('25-address-ipv4acd-veth99.network', dropins=False)
dc7d3c5f 2216 start_networkd()
44924431 2217 self.wait_online(['veth99:routable'])
dc7d3c5f
YW
2218
2219 output = check_output('ip -4 address show dev veth99')
2220 print(output)
44924431
YW
2221 self.assertNotIn('192.168.100.10/24', output)
2222 self.assertIn('192.168.100.11/24', output)
dc7d3c5f 2223
44924431
YW
2224 copy_unit_to_networkd_unit_path('25-address-ipv4acd-veth99.network.d/conflict-address.conf')
2225 run(*networkctl_cmd, 'reload', env=env)
2226 time.sleep(1)
2227 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env)
2228 self.assertTrue(rc == 1)
2229
2230 output = check_output('ip -4 address show dev veth99')
dc7d3c5f 2231 print(output)
44924431
YW
2232 self.assertNotIn('192.168.100.10/24', output)
2233 self.assertIn('192.168.100.11/24', output)
dc7d3c5f 2234
21266e60
YW
2235 def test_address_peer_ipv4(self):
2236 # test for issue #17304
2237 copy_unit_to_networkd_unit_path('25-address-peer-ipv4.network', '12-dummy.netdev')
2238
2239 for trial in range(2):
2240 if trial == 0:
2241 start_networkd()
2242 else:
2243 restart_networkd()
2244
2245 self.wait_online(['dummy98:routable'])
2246
2247 output = check_output('ip -4 address show dev dummy98')
2248 self.assertIn('inet 100.64.0.1 peer 100.64.0.2/32 scope global', output)
2249
c9d223e8
YW
2250 @expectedFailureIfModuleIsNotAvailable('vrf')
2251 def test_prefix_route(self):
2252 copy_unit_to_networkd_unit_path('25-prefix-route-with-vrf.network', '12-dummy.netdev',
2253 '25-prefix-route-without-vrf.network', '11-dummy.netdev',
2254 '25-vrf.netdev', '25-vrf.network')
2255 for trial in range(2):
2256 if trial == 0:
2257 start_networkd()
2258 else:
2259 restart_networkd(3)
2260
2261 self.wait_online(['dummy98:routable', 'test1:routable', 'vrf99:carrier'])
2262
2263 output = check_output('ip route show table 42 dev dummy98')
2264 print('### ip route show table 42 dev dummy98')
2265 print(output)
2266 self.assertRegex(output, 'local 10.20.22.1 proto kernel scope host src 10.20.22.1')
c9d223e8
YW
2267 self.assertRegex(output, '10.20.33.0/24 proto kernel scope link src 10.20.33.1')
2268 self.assertRegex(output, 'local 10.20.33.1 proto kernel scope host src 10.20.33.1')
2269 self.assertRegex(output, 'broadcast 10.20.33.255 proto kernel scope link src 10.20.33.1')
2270 self.assertRegex(output, 'local 10.20.44.1 proto kernel scope host src 10.20.44.1')
c9d223e8
YW
2271 self.assertRegex(output, 'local 10.20.55.1 proto kernel scope host src 10.20.55.1')
2272 self.assertRegex(output, 'broadcast 10.20.55.255 proto kernel scope link src 10.20.55.1')
2273 output = check_output('ip -6 route show table 42 dev dummy98')
2274 print('### ip -6 route show table 42 dev dummy98')
2275 print(output)
2276 if trial == 0:
2277 # Kernel's bug?
2278 self.assertRegex(output, 'local fdde:11:22::1 proto kernel metric 0 pref medium')
2279 #self.assertRegex(output, 'fdde:11:22::1 proto kernel metric 256 pref medium')
2280 self.assertRegex(output, 'local fdde:11:33::1 proto kernel metric 0 pref medium')
2281 self.assertRegex(output, 'fdde:11:33::/64 proto kernel metric 256 pref medium')
2282 self.assertRegex(output, 'local fdde:11:44::1 proto kernel metric 0 pref medium')
2283 self.assertRegex(output, 'local fdde:11:55::1 proto kernel metric 0 pref medium')
2284 self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
beb75dd3 2285 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
c9d223e8
YW
2286
2287 print()
2288
2289 output = check_output('ip route show dev test1')
2290 print('### ip route show dev test1')
2291 print(output)
2292 self.assertRegex(output, '10.21.33.0/24 proto kernel scope link src 10.21.33.1')
2293 output = check_output('ip route show table local dev test1')
2294 print('### ip route show table local dev test1')
2295 print(output)
2296 self.assertRegex(output, 'local 10.21.22.1 proto kernel scope host src 10.21.22.1')
c9d223e8
YW
2297 self.assertRegex(output, 'local 10.21.33.1 proto kernel scope host src 10.21.33.1')
2298 self.assertRegex(output, 'broadcast 10.21.33.255 proto kernel scope link src 10.21.33.1')
2299 self.assertRegex(output, 'local 10.21.44.1 proto kernel scope host src 10.21.44.1')
c9d223e8
YW
2300 self.assertRegex(output, 'local 10.21.55.1 proto kernel scope host src 10.21.55.1')
2301 self.assertRegex(output, 'broadcast 10.21.55.255 proto kernel scope link src 10.21.55.1')
2302 output = check_output('ip -6 route show dev test1')
2303 print('### ip -6 route show dev test1')
2304 print(output)
2305 self.assertRegex(output, 'fdde:12:22::1 proto kernel metric 256 pref medium')
2306 self.assertRegex(output, 'fdde:12:33::/64 proto kernel metric 256 pref medium')
2307 self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
2308 output = check_output('ip -6 route show table local dev test1')
2309 print('### ip -6 route show table local dev test1')
2310 print(output)
2311 self.assertRegex(output, 'local fdde:12:22::1 proto kernel metric 0 pref medium')
2312 self.assertRegex(output, 'local fdde:12:33::1 proto kernel metric 0 pref medium')
2313 self.assertRegex(output, 'local fdde:12:44::1 proto kernel metric 0 pref medium')
2314 self.assertRegex(output, 'local fdde:12:55::1 proto kernel metric 0 pref medium')
beb75dd3 2315 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
c9d223e8 2316
1f0e3109 2317 def test_configure_without_carrier(self):
9bacf431 2318 copy_unit_to_networkd_unit_path('11-dummy.netdev')
2cf6fdff 2319 start_networkd()
9bacf431
DS
2320 self.wait_operstate('test1', 'off', '')
2321 check_output('ip link set dev test1 up carrier off')
2322
2323 copy_unit_to_networkd_unit_path('25-test1.network.d/configure-without-carrier.conf', dropins=False)
2324 restart_networkd()
2325 self.wait_online(['test1:no-carrier'])
2326
2327 carrier_map = {'on': '1', 'off': '0'}
2328 routable_map = {'on': 'routable', 'off': 'no-carrier'}
2329 for carrier in ['off', 'on', 'off']:
2330 with self.subTest(carrier=carrier):
2331 if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
2332 check_output(f'ip link set dev test1 carrier {carrier}')
705c7b18 2333 self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}'])
9bacf431
DS
2334
2335 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
2336 print(output)
2337 self.assertRegex(output, '192.168.0.15')
2338 self.assertRegex(output, '192.168.0.1')
2339 self.assertRegex(output, routable_map[carrier])
e40a58b5 2340
9bacf431
DS
2341 def test_configure_without_carrier_yes_ignore_carrier_loss_no(self):
2342 copy_unit_to_networkd_unit_path('11-dummy.netdev')
2343 start_networkd()
2344 self.wait_operstate('test1', 'off', '')
2345 check_output('ip link set dev test1 up carrier off')
2346
2347 copy_unit_to_networkd_unit_path('25-test1.network')
2348 restart_networkd()
2349 self.wait_online(['test1:no-carrier'])
2350
2351 carrier_map = {'on': '1', 'off': '0'}
2352 routable_map = {'on': 'routable', 'off': 'no-carrier'}
2353 for (carrier, have_config) in [('off', True), ('on', True), ('off', False)]:
2354 with self.subTest(carrier=carrier, have_config=have_config):
2355 if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
2356 check_output(f'ip link set dev test1 carrier {carrier}')
705c7b18 2357 self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}'])
9bacf431
DS
2358
2359 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
2360 print(output)
2361 if have_config:
2362 self.assertRegex(output, '192.168.0.15')
2363 self.assertRegex(output, '192.168.0.1')
2364 else:
2365 self.assertNotRegex(output, '192.168.0.15')
2366 self.assertNotRegex(output, '192.168.0.1')
2367 self.assertRegex(output, routable_map[carrier])
1f0e3109 2368
1f0e3109 2369 def test_routing_policy_rule(self):
ec38833c 2370 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
2cf6fdff 2371 start_networkd()
e2aea43f 2372 self.wait_online(['test1:degraded'])
e40a58b5 2373
65c24cd0 2374 output = check_output('ip rule list iif test1 priority 111')
1f0e3109 2375 print(output)
65c24cd0 2376 self.assertRegex(output, '111:')
1f0e3109 2377 self.assertRegex(output, 'from 192.168.100.18')
426654d7 2378 self.assertRegex(output, r'tos (0x08|throughput)\s')
1f0e3109
SS
2379 self.assertRegex(output, 'iif test1')
2380 self.assertRegex(output, 'oif test1')
2381 self.assertRegex(output, 'lookup 7')
2382
65c24cd0
YW
2383 output = check_output('ip rule list iif test1 priority 101')
2384 print(output)
2385 self.assertRegex(output, '101:')
2386 self.assertRegex(output, 'from all')
2387 self.assertRegex(output, 'iif test1')
2388 self.assertRegex(output, 'lookup 9')
2389
2390 output = check_output('ip -6 rule list iif test1 priority 100')
2391 print(output)
2392 self.assertRegex(output, '100:')
2393 self.assertRegex(output, 'from all')
2394 self.assertRegex(output, 'iif test1')
2395 self.assertRegex(output, 'lookup 8')
2396
2e8a32af
HV
2397 output = check_output('ip rule list iif test1 priority 102')
2398 print(output)
2399 self.assertRegex(output, '102:')
2400 self.assertRegex(output, 'from 0.0.0.0/8')
2401 self.assertRegex(output, 'iif test1')
2402 self.assertRegex(output, 'lookup 10')
2403
146726b2
YW
2404 # TODO: check json string
2405 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
2406
b677774d 2407 def test_routing_policy_rule_issue_11280(self):
ec38833c
ZJS
2408 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
2409 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
b677774d 2410
b677774d
YW
2411 for trial in range(3):
2412 # Remove state files only first time
e2aea43f
YW
2413 start_networkd(3)
2414 self.wait_online(['test1:degraded', 'dummy98:degraded'])
df7f9afa 2415 time.sleep(1)
b677774d 2416
371810d1 2417 output = check_output('ip rule list table 7')
b677774d 2418 print(output)
426654d7 2419 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
b677774d 2420
371810d1 2421 output = check_output('ip rule list table 8')
b677774d 2422 print(output)
426654d7 2423 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
b677774d 2424
aaae5713
YW
2425 stop_networkd(remove_state_files=False)
2426
87adeabf 2427 def test_routing_policy_rule_reconfigure(self):
49ff3f34 2428 copy_unit_to_networkd_unit_path('routing-policy-rule-reconfigure2.network', '11-dummy.netdev')
87adeabf
YW
2429 start_networkd()
2430 self.wait_online(['test1:degraded'])
2431
2432 output = check_output('ip rule list table 1011')
2433 print(output)
49ff3f34
YW
2434 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2435 self.assertIn('10112: from all oif test1 lookup 1011', output)
2436 self.assertIn('10113: from all iif test1 lookup 1011', output)
2437 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2438
2439 output = check_output('ip -6 rule list table 1011')
2440 print(output)
2441 self.assertIn('10112: from all oif test1 lookup 1011', output)
2442
2443 copy_unit_to_networkd_unit_path('routing-policy-rule-reconfigure1.network', '11-dummy.netdev')
2444 run(*networkctl_cmd, 'reload', env=env)
2445 time.sleep(1)
2446 self.wait_online(['test1:degraded'])
2447
2448 output = check_output('ip rule list table 1011')
2449 print(output)
2450 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2451 self.assertIn('10112: from all oif test1 lookup 1011', output)
2452 self.assertIn('10113: from all iif test1 lookup 1011', output)
2453 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2454
2455 output = check_output('ip -6 rule list table 1011')
2456 print(output)
2457 self.assertNotIn('10112: from all oif test1 lookup 1011', output)
2458 self.assertIn('10113: from all iif test1 lookup 1011', output)
87adeabf
YW
2459
2460 run('ip rule delete priority 10111')
2461 run('ip rule delete priority 10112')
2462 run('ip rule delete priority 10113')
2463 run('ip rule delete priority 10114')
49ff3f34 2464 run('ip -6 rule delete priority 10113')
87adeabf
YW
2465
2466 output = check_output('ip rule list table 1011')
2467 print(output)
2468 self.assertEqual(output, '')
2469
49ff3f34
YW
2470 output = check_output('ip -6 rule list table 1011')
2471 print(output)
2472 self.assertEqual(output, '')
87adeabf 2473
49ff3f34 2474 run(*networkctl_cmd, 'reconfigure', 'test1', env=env)
87adeabf
YW
2475 self.wait_online(['test1:degraded'])
2476
2477 output = check_output('ip rule list table 1011')
2478 print(output)
49ff3f34
YW
2479 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2480 self.assertIn('10112: from all oif test1 lookup 1011', output)
2481 self.assertIn('10113: from all iif test1 lookup 1011', output)
2482 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2483
2484 output = check_output('ip -6 rule list table 1011')
2485 print(output)
2486 self.assertIn('10113: from all iif test1 lookup 1011', output)
87adeabf 2487
d586a2c3 2488 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0 2489 def test_routing_policy_rule_port_range(self):
ec38833c 2490 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
2cf6fdff 2491 start_networkd()
e2aea43f 2492 self.wait_online(['test1:degraded'])
e40a58b5 2493
371810d1 2494 output = check_output('ip rule')
926062f0
SS
2495 print(output)
2496 self.assertRegex(output, '111')
2497 self.assertRegex(output, 'from 192.168.100.18')
2498 self.assertRegex(output, '1123-1150')
2499 self.assertRegex(output, '3224-3290')
2500 self.assertRegex(output, 'tcp')
2501 self.assertRegex(output, 'lookup 7')
1f0e3109 2502
d586a2c3 2503 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd 2504 def test_routing_policy_rule_invert(self):
ec38833c 2505 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
2cf6fdff 2506 start_networkd()
e2aea43f 2507 self.wait_online(['test1:degraded'])
e40a58b5 2508
371810d1 2509 output = check_output('ip rule')
efecf9cd 2510 print(output)
efecf9cd
SS
2511 self.assertRegex(output, '111')
2512 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
2513 self.assertRegex(output, 'tcp')
2514 self.assertRegex(output, 'lookup 7')
2515
6be8e78e
YW
2516 @expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
2517 def test_routing_policy_rule_uidrange(self):
2518 copy_unit_to_networkd_unit_path('25-fibrule-uidrange.network', '11-dummy.netdev')
2519 start_networkd()
2520 self.wait_online(['test1:degraded'])
2521
2522 output = check_output('ip rule')
2523 print(output)
2524 self.assertRegex(output, '111')
2525 self.assertRegex(output, 'from 192.168.100.18')
2526 self.assertRegex(output, 'lookup 7')
2527 self.assertRegex(output, 'uidrange 100-200')
2528
1d26d4cd
YW
2529 def _test_route_static(self, manage_foreign_routes):
2530 if not manage_foreign_routes:
2531 copy_networkd_conf_dropin('networkd-manage-foreign-routes-no.conf')
2532
ec38833c 2533 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
2cf6fdff 2534 start_networkd()
e2aea43f
YW
2535 self.wait_online(['dummy98:routable'])
2536
fc79e6ff 2537 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
e2aea43f 2538 print(output)
0d34228f 2539
6d60f9db 2540 print('### ip -6 route show dev dummy98')
371810d1 2541 output = check_output('ip -6 route show dev dummy98')
0d34228f 2542 print(output)
0b5dc249
YW
2543 self.assertIn('2001:1234:5:8fff:ff:ff:ff:ff proto static', output)
2544 self.assertIn('2001:1234:5:8f63::1 proto kernel', output)
180c5116 2545 self.assertIn('2001:1234:5:afff:ff:ff:ff:ff via fe80:0:222:4dff:ff:ff:ff:ff proto static', output)
1f0e3109 2546
d9005dec
YW
2547 print('### ip -6 route show default')
2548 output = check_output('ip -6 route show default')
6d60f9db 2549 print(output)
0b5dc249
YW
2550 self.assertIn('default', output)
2551 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff', output)
1f0e3109 2552
6d60f9db 2553 print('### ip -4 route show dev dummy98')
371810d1 2554 output = check_output('ip -4 route show dev dummy98')
1f0e3109 2555 print(output)
0b5dc249
YW
2556 self.assertIn('149.10.124.48/28 proto kernel scope link src 149.10.124.58', output)
2557 self.assertIn('149.10.124.64 proto static scope link', output)
2558 self.assertIn('169.254.0.0/16 proto static scope link metric 2048', output)
902bbdc4
YW
2559 self.assertIn('192.168.1.1 proto static scope link initcwnd 20', output)
2560 self.assertIn('192.168.1.2 proto static scope link initrwnd 30', output)
2561 self.assertIn('192.168.1.3 proto static scope link advmss 30', output)
0b5dc249 2562 self.assertIn('multicast 149.10.123.4 proto static', output)
1f0e3109 2563
6d60f9db 2564 print('### ip -4 route show dev dummy98 default')
371810d1 2565 output = check_output('ip -4 route show dev dummy98 default')
6d60f9db 2566 print(output)
0b5dc249
YW
2567 self.assertIn('default via 149.10.125.65 proto static onlink', output)
2568 self.assertIn('default via 149.10.124.64 proto static', output)
2569 self.assertIn('default proto static', output)
1f0e3109 2570
6d60f9db
YW
2571 print('### ip -4 route show table local dev dummy98')
2572 output = check_output('ip -4 route show table local dev dummy98')
2573 print(output)
0b5dc249
YW
2574 self.assertIn('local 149.10.123.1 proto static scope host', output)
2575 self.assertIn('anycast 149.10.123.2 proto static scope link', output)
2576 self.assertIn('broadcast 149.10.123.3 proto static scope link', output)
6d60f9db
YW
2577
2578 print('### ip route show type blackhole')
371810d1 2579 output = check_output('ip route show type blackhole')
1f0e3109 2580 print(output)
0b5dc249 2581 self.assertIn('blackhole 202.54.1.2 proto static', output)
f5050e48 2582
6d60f9db 2583 print('### ip route show type unreachable')
371810d1 2584 output = check_output('ip route show type unreachable')
f5050e48 2585 print(output)
0b5dc249 2586 self.assertIn('unreachable 202.54.1.3 proto static', output)
f5050e48 2587
6d60f9db 2588 print('### ip route show type prohibit')
371810d1 2589 output = check_output('ip route show type prohibit')
f5050e48 2590 print(output)
0b5dc249 2591 self.assertIn('prohibit 202.54.1.4 proto static', output)
f5050e48 2592
452d86a5
YW
2593 print('### ip -6 route show type blackhole')
2594 output = check_output('ip -6 route show type blackhole')
2595 print(output)
2596 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output)
2597
2598 print('### ip -6 route show type unreachable')
2599 output = check_output('ip -6 route show type unreachable')
2600 print(output)
2601 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output)
2602
2603 print('### ip -6 route show type prohibit')
2604 output = check_output('ip -6 route show type prohibit')
2605 print(output)
2606 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
2607
a0ce990e
YW
2608 print('### ip route show 192.168.10.1')
2609 output = check_output('ip route show 192.168.10.1')
2610 print(output)
0b5dc249
YW
2611 self.assertIn('192.168.10.1 proto static', output)
2612 self.assertIn('nexthop via 149.10.124.59 dev dummy98 weight 10', output)
2613 self.assertIn('nexthop via 149.10.124.60 dev dummy98 weight 5', output)
a0ce990e
YW
2614
2615 print('### ip route show 192.168.10.2')
2616 output = check_output('ip route show 192.168.10.2')
2617 print(output)
2618 # old ip command does not show IPv6 gateways...
0b5dc249
YW
2619 self.assertIn('192.168.10.2 proto static', output)
2620 self.assertIn('nexthop', output)
2621 self.assertIn('dev dummy98 weight 10', output)
2622 self.assertIn('dev dummy98 weight 5', output)
a0ce990e
YW
2623
2624 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2625 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2626 print(output)
2627 # old ip command does not show 'nexthop' keyword and weight...
0b5dc249
YW
2628 self.assertIn('2001:1234:5:7fff:ff:ff:ff:ff', output)
2629 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98', output)
2630 self.assertIn('via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98', output)
a0ce990e 2631
146726b2
YW
2632 # TODO: check json string
2633 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
2634
43d4bc9f
YW
2635 copy_unit_to_networkd_unit_path('25-address-static.network')
2636 check_output(*networkctl_cmd, 'reload', env=env)
37b9c79e 2637 time.sleep(1)
43d4bc9f
YW
2638 self.wait_online(['dummy98:routable'])
2639
2640 # check all routes managed by Manager are removed
2641 print('### ip route show type blackhole')
2642 output = check_output('ip route show type blackhole')
2643 print(output)
2644 self.assertEqual(output, '')
2645
2646 print('### ip route show type unreachable')
2647 output = check_output('ip route show type unreachable')
2648 print(output)
2649 self.assertEqual(output, '')
2650
2651 print('### ip route show type prohibit')
2652 output = check_output('ip route show type prohibit')
2653 print(output)
2654 self.assertEqual(output, '')
2655
452d86a5
YW
2656 print('### ip -6 route show type blackhole')
2657 output = check_output('ip -6 route show type blackhole')
2658 print(output)
2659 self.assertEqual(output, '')
2660
2661 print('### ip -6 route show type unreachable')
2662 output = check_output('ip -6 route show type unreachable')
2663 print(output)
2664 self.assertEqual(output, '')
2665
2666 print('### ip -6 route show type prohibit')
2667 output = check_output('ip -6 route show type prohibit')
2668 print(output)
2669 self.assertEqual(output, '')
2670
43d4bc9f
YW
2671 remove_unit_from_networkd_path(['25-address-static.network'])
2672 check_output(*networkctl_cmd, 'reload', env=env)
37b9c79e 2673 time.sleep(1)
43d4bc9f
YW
2674 self.wait_online(['dummy98:routable'])
2675
2676 # check all routes managed by Manager are reconfigured
2677 print('### ip route show type blackhole')
2678 output = check_output('ip route show type blackhole')
2679 print(output)
0b5dc249 2680 self.assertIn('blackhole 202.54.1.2 proto static', output)
43d4bc9f
YW
2681
2682 print('### ip route show type unreachable')
2683 output = check_output('ip route show type unreachable')
2684 print(output)
0b5dc249 2685 self.assertIn('unreachable 202.54.1.3 proto static', output)
43d4bc9f
YW
2686
2687 print('### ip route show type prohibit')
2688 output = check_output('ip route show type prohibit')
2689 print(output)
0b5dc249 2690 self.assertIn('prohibit 202.54.1.4 proto static', output)
43d4bc9f 2691
452d86a5
YW
2692 print('### ip -6 route show type blackhole')
2693 output = check_output('ip -6 route show type blackhole')
2694 print(output)
2695 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output)
2696
2697 print('### ip -6 route show type unreachable')
2698 output = check_output('ip -6 route show type unreachable')
2699 print(output)
2700 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output)
2701
2702 print('### ip -6 route show type prohibit')
2703 output = check_output('ip -6 route show type prohibit')
2704 print(output)
2705 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
2706
43d4bc9f
YW
2707 rc = call("ip link del dummy98")
2708 self.assertEqual(rc, 0)
2709 time.sleep(2)
2710
2711 # check all routes managed by Manager are removed
2712 print('### ip route show type blackhole')
2713 output = check_output('ip route show type blackhole')
2714 print(output)
2715 self.assertEqual(output, '')
2716
2717 print('### ip route show type unreachable')
2718 output = check_output('ip route show type unreachable')
2719 print(output)
2720 self.assertEqual(output, '')
2721
2722 print('### ip route show type prohibit')
2723 output = check_output('ip route show type prohibit')
2724 print(output)
2725 self.assertEqual(output, '')
2726
452d86a5
YW
2727 print('### ip -6 route show type blackhole')
2728 output = check_output('ip -6 route show type blackhole')
2729 print(output)
2730 self.assertEqual(output, '')
2731
2732 print('### ip -6 route show type unreachable')
2733 output = check_output('ip -6 route show type unreachable')
2734 print(output)
2735 self.assertEqual(output, '')
2736
2737 print('### ip -6 route show type prohibit')
2738 output = check_output('ip -6 route show type prohibit')
2739 print(output)
2740 self.assertEqual(output, '')
2741
1d26d4cd
YW
2742 self.tearDown()
2743
2744 def test_route_static(self):
2745 for manage_foreign_routes in [True, False]:
2746 with self.subTest(manage_foreign_routes=manage_foreign_routes):
2747 self._test_route_static(manage_foreign_routes)
2748
297f9d86
YW
2749 @expectedFailureIfRTA_VIAIsNotSupported()
2750 def test_route_via_ipv6(self):
2751 copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev')
2752 start_networkd()
2753 self.wait_online(['dummy98:routable'])
2754
2755 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
2756 print(output)
2757
2758 print('### ip -6 route show dev dummy98')
2759 output = check_output('ip -6 route show dev dummy98')
2760 print(output)
2761 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
2762 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
2763
2764 print('### ip -4 route show dev dummy98')
2765 output = check_output('ip -4 route show dev dummy98')
2766 print(output)
2767 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
2768 self.assertRegex(output, '149.10.124.66 via inet6 2001:1234:5:8fff:ff:ff:ff:ff proto static')
2769
40afe491
YW
2770 @expectedFailureIfModuleIsNotAvailable('vrf')
2771 def test_route_vrf(self):
2772 copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
2773 '25-vrf.netdev', '25-vrf.network')
2774 start_networkd()
2775 self.wait_online(['dummy98:routable', 'vrf99:carrier'])
2776
2777 output = check_output('ip route show vrf vrf99')
2778 print(output)
2779 self.assertRegex(output, 'default via 192.168.100.1')
2780
2781 output = check_output('ip route show')
2782 print(output)
2783 self.assertNotRegex(output, 'default via 192.168.100.1')
2784
0b1cd3e2
WKI
2785 def test_gateway_reconfigure(self):
2786 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
2787 start_networkd()
2788 self.wait_online(['dummy98:routable'])
2789 print('### ip -4 route show dev dummy98 default')
2790 output = check_output('ip -4 route show dev dummy98 default')
2791 print(output)
2792 self.assertRegex(output, 'default via 149.10.124.59 proto static')
2793 self.assertNotRegex(output, '149.10.124.60')
2794
2795 remove_unit_from_networkd_path(['25-gateway-static.network'])
2796 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
2797 restart_networkd(3)
2798 self.wait_online(['dummy98:routable'])
2799 print('### ip -4 route show dev dummy98 default')
2800 output = check_output('ip -4 route show dev dummy98 default')
2801 print(output)
2802 self.assertNotRegex(output, '149.10.124.59')
2803 self.assertRegex(output, 'default via 149.10.124.60 proto static')
2804
20ca06a6
DA
2805 def test_ip_route_ipv6_src_route(self):
2806 # a dummy device does not make the addresses go through tentative state, so we
2807 # reuse a bond from an earlier test, which does make the addresses go through
2808 # tentative state, and do our test on that
ec38833c 2809 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 2810 start_networkd()
e2aea43f 2811 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
20ca06a6 2812
371810d1 2813 output = check_output('ip -6 route list dev bond199')
20ca06a6
DA
2814 print(output)
2815 self.assertRegex(output, 'abcd::/16')
2816 self.assertRegex(output, 'src')
2817 self.assertRegex(output, '2001:1234:56:8f63::2')
2818
1f0e3109 2819 def test_ip_link_mac_address(self):
ec38833c 2820 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
2cf6fdff 2821 start_networkd()
e2aea43f 2822 self.wait_online(['dummy98:degraded'])
1f0e3109 2823
371810d1 2824 output = check_output('ip link show dummy98')
1f0e3109 2825 print(output)
45aa0e84 2826 self.assertRegex(output, '00:01:02:aa:bb:cc')
1f0e3109
SS
2827
2828 def test_ip_link_unmanaged(self):
ec38833c 2829 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
df7f9afa 2830 start_networkd(5)
1f0e3109 2831
e39cc445 2832 self.check_link_exists('dummy98')
1f0e3109 2833
19cf3143 2834 self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
1f0e3109
SS
2835
2836 def test_ipv6_address_label(self):
ec38833c 2837 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
2cf6fdff 2838 start_networkd()
e2aea43f 2839 self.wait_online(['dummy98:degraded'])
1f0e3109 2840
371810d1 2841 output = check_output('ip addrlabel list')
1f0e3109
SS
2842 print(output)
2843 self.assertRegex(output, '2004:da8:1::/64')
2844
cff0cadc
YW
2845 def test_ipv6_proxy_ndp(self):
2846 copy_unit_to_networkd_unit_path('25-ipv6-proxy-ndp.network', '12-dummy.netdev')
2847 start_networkd()
2848
2849 self.wait_online(['dummy98:routable'])
2850
2851 output = check_output('ip neighbor show proxy dev dummy98')
2852 print(output)
2853 for i in range(1,5):
2854 self.assertRegex(output, f'2607:5300:203:5215:{i}::1 *proxy')
2855
d86f5c19 2856 def test_neighbor_section(self):
ec38833c 2857 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2cf6fdff 2858 start_networkd()
e2aea43f 2859 self.wait_online(['dummy98:degraded'], timeout='40s')
e4a71bf3 2860
d1bdafd2 2861 print('### ip neigh list dev dummy98')
df7f9afa 2862 output = check_output('ip neigh list dev dummy98')
e4a71bf3
WKI
2863 print(output)
2864 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 2865 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 2866
146726b2
YW
2867 # TODO: check json string
2868 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
2869
d1bdafd2
WKI
2870 def test_neighbor_reconfigure(self):
2871 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2872 start_networkd()
2873 self.wait_online(['dummy98:degraded'], timeout='40s')
2874
2875 print('### ip neigh list dev dummy98')
2876 output = check_output('ip neigh list dev dummy98')
2877 print(output)
2878 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2879 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2880
2881 remove_unit_from_networkd_path(['25-neighbor-section.network'])
2882 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
2883 restart_networkd(3)
2884 self.wait_online(['dummy98:degraded'], timeout='40s')
2885 print('### ip neigh list dev dummy98')
2886 output = check_output('ip neigh list dev dummy98')
2887 print(output)
2888 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2889 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
2890 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
2891
74761cf3 2892 def test_neighbor_gre(self):
fb2ba330
YW
2893 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
2894 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
74761cf3 2895 start_networkd()
fb2ba330 2896 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
74761cf3
YW
2897
2898 output = check_output('ip neigh list dev gretun97')
2899 print(output)
2900 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
fb2ba330
YW
2901
2902 output = check_output('ip neigh list dev ip6gretun97')
2903 print(output)
2904 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
74761cf3 2905
146726b2
YW
2906 # TODO: check json string
2907 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
2908
05514ae1 2909 def test_link_local_addressing(self):
ec38833c
ZJS
2910 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
2911 '25-link-local-addressing-no.network', '12-dummy.netdev')
2cf6fdff 2912 start_networkd()
e2aea43f 2913 self.wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1 2914
371810d1 2915 output = check_output('ip address show dev test1')
05514ae1
YW
2916 print(output)
2917 self.assertRegex(output, 'inet .* scope link')
2918 self.assertRegex(output, 'inet6 .* scope link')
2919
371810d1 2920 output = check_output('ip address show dev dummy98')
05514ae1
YW
2921 print(output)
2922 self.assertNotRegex(output, 'inet6* .* scope link')
2923
05514ae1
YW
2924 '''
2925 Documentation/networking/ip-sysctl.txt
2926
2927 addr_gen_mode - INTEGER
2928 Defines how link-local and autoconf addresses are generated.
2929
2930 0: generate address based on EUI64 (default)
2931 1: do no generate a link-local address, use EUI64 for addresses generated
2932 from autoconf
2933 2: generate stable privacy addresses, using the secret from
2934 stable_secret (RFC7217)
2935 3: generate stable privacy addresses, using a random secret if unset
2936 '''
2937
4681ab55
YW
2938 self.assertEqual(read_ipv6_sysctl_attr('test1', 'stable_secret'), '0123:4567:89ab:cdef:0123:4567:89ab:cdef')
2939 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '2')
2940 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
05514ae1 2941
7b3770a7
YW
2942 def test_link_local_addressing_remove_ipv6ll(self):
2943 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
2944 start_networkd()
2945 self.wait_online(['dummy98:degraded'])
2946
2947 output = check_output('ip address show dev dummy98')
2948 print(output)
2949 self.assertRegex(output, 'inet6 .* scope link')
2950
2951 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
2952 restart_networkd(1)
2953 self.wait_online(['dummy98:carrier'])
2954
2955 output = check_output('ip address show dev dummy98')
2956 print(output)
2957 self.assertNotRegex(output, 'inet6* .* scope link')
2958
1f0e3109 2959 def test_sysctl(self):
ec38833c 2960 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
2cf6fdff 2961 start_networkd()
e2aea43f 2962 self.wait_online(['dummy98:degraded'])
ec38833c
ZJS
2963
2964 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
2965 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
2966 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
2967 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
2968 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
2969 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
2970 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
29f69c57 2971 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'accept_local'), '1')
1f0e3109 2972
4da33154 2973 def test_sysctl_disable_ipv6(self):
ec38833c 2974 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
4da33154
YW
2975
2976 print('## Disable ipv6')
cefd6b3d
ZJS
2977 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
2978 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
4da33154 2979
2cf6fdff 2980 start_networkd()
e2aea43f 2981 self.wait_online(['dummy98:routable'])
4da33154 2982
371810d1 2983 output = check_output('ip -4 address show dummy98')
4da33154
YW
2984 print(output)
2985 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2986 output = check_output('ip -6 address show dummy98')
4da33154 2987 print(output)
57ad7607
ZJS
2988 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2989 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2990 output = check_output('ip -4 route show dev dummy98')
2991 print(output)
3d2c2692 2992 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
d9005dec 2993 output = check_output('ip -6 route show default')
4933b97d 2994 print(output)
d9005dec
YW
2995 self.assertRegex(output, 'default')
2996 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
4da33154 2997
cefd6b3d 2998 check_output('ip link del dummy98')
4da33154
YW
2999
3000 print('## Enable ipv6')
cefd6b3d
ZJS
3001 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
3002 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
4da33154 3003
e2aea43f
YW
3004 restart_networkd(3)
3005 self.wait_online(['dummy98:routable'])
4da33154 3006
371810d1 3007 output = check_output('ip -4 address show dummy98')
4da33154
YW
3008 print(output)
3009 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 3010 output = check_output('ip -6 address show dummy98')
4da33154 3011 print(output)
4933b97d 3012 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
4da33154 3013 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
3014 output = check_output('ip -4 route show dev dummy98')
3015 print(output)
3d2c2692 3016 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
d9005dec 3017 output = check_output('ip -6 route show default')
4933b97d 3018 print(output)
d9005dec 3019 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
4da33154 3020
cd65d067 3021 def test_bind_carrier(self):
bc942f69
YW
3022 check_output('ip link add dummy98 type dummy')
3023 check_output('ip link set dummy98 up')
3024 time.sleep(2)
3025
ec38833c 3026 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
2cf6fdff 3027 start_networkd()
e2aea43f 3028 self.wait_online(['test1:routable'])
cd65d067 3029
371810d1 3030 output = check_output('ip address show test1')
cd65d067
YW
3031 print(output)
3032 self.assertRegex(output, 'UP,LOWER_UP')
3033 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 3034 self.wait_operstate('test1', 'routable')
cd65d067 3035
cefd6b3d
ZJS
3036 check_output('ip link add dummy99 type dummy')
3037 check_output('ip link set dummy99 up')
b117044c 3038 time.sleep(2)
371810d1 3039 output = check_output('ip address show test1')
cd65d067
YW
3040 print(output)
3041 self.assertRegex(output, 'UP,LOWER_UP')
3042 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 3043 self.wait_operstate('test1', 'routable')
cd65d067 3044
cefd6b3d 3045 check_output('ip link del dummy98')
b117044c 3046 time.sleep(2)
371810d1 3047 output = check_output('ip address show test1')
cd65d067
YW
3048 print(output)
3049 self.assertRegex(output, 'UP,LOWER_UP')
3050 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 3051 self.wait_operstate('test1', 'routable')
cd65d067 3052
bc942f69 3053 check_output('ip link set dummy99 down')
b117044c 3054 time.sleep(2)
371810d1 3055 output = check_output('ip address show test1')
cd65d067
YW
3056 print(output)
3057 self.assertNotRegex(output, 'UP,LOWER_UP')
3058 self.assertRegex(output, 'DOWN')
3059 self.assertNotRegex(output, '192.168.10')
19cf3143 3060 self.wait_operstate('test1', 'off')
cd65d067 3061
bc942f69 3062 check_output('ip link set dummy99 up')
b117044c 3063 time.sleep(2)
371810d1 3064 output = check_output('ip address show test1')
cd65d067
YW
3065 print(output)
3066 self.assertRegex(output, 'UP,LOWER_UP')
3067 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 3068 self.wait_operstate('test1', 'routable')
cd65d067 3069
2236d75d 3070 def _test_activation_policy(self, test):
2236d75d
DS
3071 conffile = '25-activation-policy.network'
3072 if test:
3073 conffile = f'{conffile}.d/{test}.conf'
3074 copy_unit_to_networkd_unit_path('11-dummy.netdev', conffile, dropins=False)
3075 start_networkd()
3076
3077 always = test.startswith('always')
3078 if test == 'manual':
3079 initial_up = 'UP' in check_output('ip link show test1')
3080 else:
3081 initial_up = not test.endswith('down') # note: default is up
3082 expect_up = initial_up
3083 next_up = not expect_up
3084
cfbdc438
YW
3085 if test.endswith('down'):
3086 self.wait_activated('test1')
3087
2236d75d
DS
3088 for iteration in range(4):
3089 with self.subTest(iteration=iteration, expect_up=expect_up):
3090 operstate = 'routable' if expect_up else 'off'
618da3e7 3091 setup_state = 'configured' if expect_up else ('configuring' if iteration == 0 else None)
2236d75d 3092 self.wait_operstate('test1', operstate, setup_state=setup_state, setup_timeout=20)
2236d75d
DS
3093
3094 if expect_up:
3095 self.assertIn('UP', check_output('ip link show test1'))
3096 self.assertIn('192.168.10.30/24', check_output('ip address show test1'))
1ef2eedc 3097 self.assertIn('default via 192.168.10.1', check_output('ip route show dev test1'))
2236d75d
DS
3098 else:
3099 self.assertIn('DOWN', check_output('ip link show test1'))
3100
3101 if next_up:
3102 check_output('ip link set dev test1 up')
3103 else:
3104 check_output('ip link set dev test1 down')
3105 expect_up = initial_up if always else next_up
3106 next_up = not next_up
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
3821 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
3822 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
3823 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
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
YW
3858 # CONFIG_BRIDGE_IGMP_SNOOPING=y
3859 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
3860 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
7f15b714 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')
3897 self.assertNotRegex(output, '192.168.0.16/24')
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',
ffaece68 4237 'dhcp-server-static-lease.network',
4e0006cc
YW
4238 'dhcp-server-timezone-router.network',
4239 'dhcp-server-uplink.network',
4240 ]
1f0e3109
SS
4241
4242 def setUp(self):
ec38833c 4243 remove_links(self.links)
aaae5713 4244 stop_networkd(show_logs=False)
1f0e3109
SS
4245
4246 def tearDown(self):
ec38833c
ZJS
4247 remove_links(self.links)
4248 remove_unit_from_networkd_path(self.units)
aaae5713 4249 stop_networkd(show_logs=True)
1f0e3109
SS
4250
4251 def test_dhcp_server(self):
4e0006cc
YW
4252 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network',
4253 '12-dummy.netdev', 'dhcp-server-uplink.network')
2cf6fdff 4254 start_networkd()
e2aea43f 4255 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4256
fc79e6ff 4257 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4258 print(output)
32d97330
YW
4259 self.assertRegex(output, 'Address: 192.168.5.[0-9]* \(DHCP4 via 192.168.5.1\)')
4260 self.assertIn('Gateway: 192.168.5.3', output)
4261 self.assertIn('DNS: 192.168.5.1', output)
4262 self.assertIn('NTP: 192.168.5.1', output)
1f0e3109 4263
1f0e3109 4264 def test_emit_router_timezone(self):
ec38833c 4265 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2cf6fdff 4266 start_networkd()
e2aea43f 4267 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4268
fc79e6ff 4269 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4270 print(output)
32d97330
YW
4271 self.assertRegex(output, 'Address: 192.168.5.[0-9]* \(DHCP4 via 192.168.5.1\)')
4272 self.assertIn('Gateway: 192.168.5.1', output)
4273 self.assertIn('Time Zone: Europe/Berlin', output)
1f0e3109 4274
ffaece68 4275 def test_dhcp_server_static_lease(self):
4276 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-static-lease.network', 'dhcp-server-static-lease.network')
4277 start_networkd()
4278 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4279
4280 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
4281 print(output)
32d97330 4282 self.assertIn('Address: 10.1.1.200 (DHCP4 via 10.1.1.1)', output)
ffaece68 4283
c95df587
YA
4284class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities):
4285 links = [
4286 'client',
4287 'server',
4288 'client-peer',
4289 'server-peer',
4290 ]
4291
4292 units = [
4293 'agent-veth-client.netdev',
4294 'agent-veth-server.netdev',
4295 'agent-client.network',
4296 'agent-server.network',
4297 'agent-client-peer.network',
4298 'agent-server-peer.network',
4299 ]
4300
4301 def setUp(self):
4302 remove_links(self.links)
4303 stop_networkd(show_logs=False)
4304
4305 def tearDown(self):
4306 remove_links(self.links)
4307 remove_unit_from_networkd_path(self.units)
4308 stop_networkd(show_logs=True)
4309
4310 def test_relay_agent(self):
4311 copy_unit_to_networkd_unit_path(*self.units)
4312 start_networkd()
4313
c95df587
YA
4314 self.wait_online(['client:routable'])
4315
4316 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'client', env=env)
4317 print(output)
4318 self.assertRegex(output, 'Address: 192.168.5.150 \(DHCP4 via 192.168.5.1\)')
4319
be68c2c9 4320class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
09ea6724 4321 links = [
18c613dc
YW
4322 'veth99',
4323 'vrf99']
09ea6724
YW
4324
4325 units = [
4326 '25-veth.netdev',
18c613dc
YW
4327 '25-vrf.netdev',
4328 '25-vrf.network',
ab47f960 4329 'dhcp-client-allow-list.network',
09ea6724 4330 'dhcp-client-anonymize.network',
0fd8b718 4331 'dhcp-client-decline.network',
214c5bae
YW
4332 'dhcp-client-gateway-ipv4.network',
4333 'dhcp-client-gateway-ipv6.network',
af3b1498 4334 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
4335 'dhcp-client-ipv4-dhcp-settings.network',
4336 'dhcp-client-ipv4-only-ipv6-disabled.network',
4337 'dhcp-client-ipv4-only.network',
7c0d36ff 4338 'dhcp-client-ipv4-use-routes-use-gateway.network',
09ea6724 4339 'dhcp-client-ipv6-only.network',
1e498853
YW
4340 'dhcp-client-keep-configuration-dhcp-on-stop.network',
4341 'dhcp-client-keep-configuration-dhcp.network',
09ea6724 4342 'dhcp-client-listen-port.network',
c1b01a62
YW
4343 'dhcp-client-reassign-static-routes-ipv4.network',
4344 'dhcp-client-reassign-static-routes-ipv6.network',
09ea6724
YW
4345 'dhcp-client-route-metric.network',
4346 'dhcp-client-route-table.network',
e2d5aab3
YW
4347 'dhcp-client-use-dns-ipv4-and-ra.network',
4348 'dhcp-client-use-dns-ipv4.network',
4349 'dhcp-client-use-dns-no.network',
4350 'dhcp-client-use-dns-yes.network',
e0c1341d 4351 'dhcp-client-use-domains.network',
18c613dc 4352 'dhcp-client-vrf.network',
240e4137 4353 'dhcp-client-with-ipv4ll.network',
4c882c16 4354 'dhcp-client-with-static-address.network',
3e9d5552 4355 'dhcp-client.network',
0fd8b718 4356 'dhcp-server-decline.network',
09ea6724 4357 'dhcp-server-veth-peer.network',
30d3b54e
YW
4358 'dhcp-v4-server-veth-peer.network',
4359 'static.network']
1f0e3109
SS
4360
4361 def setUp(self):
888f57c1 4362 stop_dnsmasq()
a4a1385e
YW
4363 remove_dnsmasq_lease_file()
4364 remove_dnsmasq_log_file()
ec38833c 4365 remove_links(self.links)
aaae5713 4366 stop_networkd(show_logs=False)
1f0e3109
SS
4367
4368 def tearDown(self):
888f57c1 4369 stop_dnsmasq()
ed08ed4a
YW
4370 remove_dnsmasq_lease_file()
4371 remove_dnsmasq_log_file()
ec38833c
ZJS
4372 remove_links(self.links)
4373 remove_unit_from_networkd_path(self.units)
aaae5713 4374 stop_networkd(show_logs=True)
1f0e3109
SS
4375
4376 def test_dhcp_client_ipv6_only(self):
ec38833c 4377 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109 4378
2cf6fdff 4379 start_networkd()
e2aea43f 4380 self.wait_online(['veth-peer:carrier'])
ec38833c 4381 start_dnsmasq()
e2aea43f 4382 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4383
fc79e6ff 4384 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
4385 print(output)
4386 self.assertRegex(output, '2600::')
4387 self.assertNotRegex(output, '192.168.5')
4388
c5fcd8a7
YW
4389 output = check_output('ip addr show dev veth99')
4390 print(output)
4391 self.assertRegex(output, '2600::')
4392 self.assertNotRegex(output, '192.168.5')
4393 self.assertNotRegex(output, 'tentative')
4394
3a956d38 4395 # Confirm that ipv6 token is not set in the kernel
371810d1 4396 output = check_output('ip token show dev veth99')
3a956d38
YW
4397 print(output)
4398 self.assertRegex(output, 'token :: dev veth99')
4399
1f0e3109 4400 def test_dhcp_client_ipv4_only(self):
ec38833c 4401 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109 4402
2cf6fdff 4403 start_networkd()
e2aea43f 4404 self.wait_online(['veth-peer:carrier'])
195a18c1 4405 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
e2aea43f 4406 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4407
fc79e6ff 4408 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
4409 print(output)
4410 self.assertNotRegex(output, '2600::')
4411 self.assertRegex(output, '192.168.5')
195a18c1
YW
4412 self.assertRegex(output, '192.168.5.6')
4413 self.assertRegex(output, '192.168.5.7')
4414
4415 # checking routes to DNS servers
4416 output = check_output('ip route show dev veth99')
4417 print(output)
4418 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
4419 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
4420 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
4421
888f57c1 4422 stop_dnsmasq()
195a18c1
YW
4423 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
4424
4425 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4426 print('Wait for the dynamic address to be renewed')
4427 time.sleep(125)
4428
4429 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4430
fc79e6ff 4431 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
195a18c1
YW
4432 print(output)
4433 self.assertNotRegex(output, '2600::')
4434 self.assertRegex(output, '192.168.5')
4435 self.assertNotRegex(output, '192.168.5.6')
4436 self.assertRegex(output, '192.168.5.7')
4437 self.assertRegex(output, '192.168.5.8')
4438
4439 # checking routes to DNS servers
4440 output = check_output('ip route show dev veth99')
4441 print(output)
4442 self.assertNotRegex(output, r'192.168.5.6')
4443 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
4444 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
4445 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
1f0e3109 4446
7c0d36ff 4447 def test_dhcp_client_ipv4_use_routes_gateway(self):
e1220a70 4448 for (routes, gateway, dns_and_ntp_routes, classless) in itertools.product([True, False], repeat=4):
7c0d36ff 4449 self.setUp()
e1220a70
YW
4450 with self.subTest(routes=routes, gateway=gateway, dns_and_ntp_routes=dns_and_ntp_routes, classless=classless):
4451 self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dns_and_ntp_routes, classless)
7c0d36ff
DS
4452 self.tearDown()
4453
e1220a70 4454 def _test_dhcp_client_ipv4_use_routes_gateway(self, use_routes, use_gateway, dns_and_ntp_routes, classless):
7c0d36ff
DS
4455 testunit = 'dhcp-client-ipv4-use-routes-use-gateway.network'
4456 testunits = ['25-veth.netdev', 'dhcp-server-veth-peer.network', testunit]
625772c9
YW
4457 testunits.append(f'{testunit}.d/use-routes-{use_routes}.conf');
4458 testunits.append(f'{testunit}.d/use-gateway-{use_gateway}.conf');
e1220a70 4459 testunits.append(f'{testunit}.d/use-dns-and-ntp-routes-{dns_and_ntp_routes}.conf');
7c0d36ff 4460 copy_unit_to_networkd_unit_path(*testunits, dropins=False)
4c2e1833
YW
4461
4462 start_networkd()
4463 self.wait_online(['veth-peer:carrier'])
e1220a70 4464 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
4465 if classless:
4466 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'
4467 start_dnsmasq(additional_options=additional_options, lease_time='2m')
4c2e1833
YW
4468 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4469
625772c9 4470 output = check_output('ip -4 route show dev veth99')
4c2e1833 4471 print(output)
4c2e1833 4472
7c0d36ff 4473 # Check UseRoutes=
625772c9
YW
4474 if use_routes:
4475 if classless:
4476 self.assertRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
4477 self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
4478 self.assertRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4479 self.assertRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4480 else:
4481 self.assertRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4482 self.assertRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024')
4483 self.assertRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4484 else:
625772c9
YW
4485 self.assertNotRegex(output, r'default via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
4486 self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
4487 self.assertNotRegex(output, r'192.168.5.4 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4488 self.assertNotRegex(output, r'192.168.5.5 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4489 self.assertNotRegex(output, r'192.168.5.0/24 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4490 self.assertNotRegex(output, r'8.0.0.0/8 via 192.168.5.3 proto dhcp src 192.168.5.[0-9]* metric 1024')
4491 self.assertNotRegex(output, r'192.168.5.3 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
0d7bd445 4492
7c0d36ff 4493 # Check UseGateway=
625772c9
YW
4494 if use_gateway and (not classless or not use_routes):
4495 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4496 else:
625772c9 4497 self.assertNotRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
87e62d32
YW
4498
4499 # Check route to gateway
4500 if (use_gateway or dns_and_ntp_routes) and (not classless or not use_routes):
4501 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4502 else:
625772c9 4503 self.assertNotRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4504
e1220a70
YW
4505 # Check RoutesToDNS= and RoutesToNTP=
4506 if dns_and_ntp_routes:
625772c9 4507 self.assertRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
e1220a70 4508 self.assertRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
625772c9
YW
4509 if classless and use_routes:
4510 self.assertRegex(output, r'8.8.8.8 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4511 self.assertRegex(output, r'9.9.9.9 via 192.168.5.4 proto dhcp src 192.168.5.[0-9]* metric 1024')
87e62d32 4512 else:
625772c9 4513 self.assertRegex(output, r'8.8.8.8 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
e1220a70 4514 self.assertRegex(output, r'9.9.9.9 via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
7c0d36ff 4515 else:
625772c9 4516 self.assertNotRegex(output, r'192.168.5.10 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
e1220a70 4517 self.assertNotRegex(output, r'192.168.5.11 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
625772c9 4518 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 4519 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 4520
94f0bd62
YW
4521 # TODO: check json string
4522 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
4523
1f0e3109 4524 def test_dhcp_client_ipv4_ipv6(self):
308d01f3 4525 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only.network')
2cf6fdff 4526 start_networkd()
e2aea43f 4527 self.wait_online(['veth-peer:carrier'])
ec38833c 4528 start_dnsmasq()
e2aea43f 4529 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
4530
4531 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4532 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 4533 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 4534
fc79e6ff 4535 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
4536 print(output)
4537 self.assertRegex(output, '2600::')
4538 self.assertRegex(output, '192.168.5')
4539
4540 def test_dhcp_client_settings(self):
ec38833c 4541 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 4542
2cf6fdff 4543 start_networkd()
e2aea43f 4544 self.wait_online(['veth-peer:carrier'])
ec38833c 4545 start_dnsmasq()
e2aea43f 4546 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 4547
0ae7a66d 4548 print('## ip address show dev veth99')
371810d1 4549 output = check_output('ip address show dev veth99')
1f0e3109
SS
4550 print(output)
4551 self.assertRegex(output, '12:34:56:78:9a:bc')
4552 self.assertRegex(output, '192.168.5')
4553 self.assertRegex(output, '1492')
d419ef02 4554 self.assertRegex(output, 'test-label')
1f0e3109 4555
0ae7a66d 4556 print('## ip route show table main dev veth99')
371810d1 4557 output = check_output('ip route show table main dev veth99')
1f0e3109 4558 print(output)
156ddf8d 4559 # See issue #8726
dd9b10c8
YW
4560 main_table_is_empty = output == ''
4561 if not main_table_is_empty:
4562 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 4563
0ae7a66d 4564 print('## ip route show table 211 dev veth99')
371810d1 4565 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
4566 print(output)
4567 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
dd9b10c8
YW
4568 if main_table_is_empty:
4569 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
0ae7a66d
YW
4570 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
4571
4572 print('## dnsmasq log')
ec38833c
ZJS
4573 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
4574 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
4575 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
4576 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109 4577
1f0e3109 4578 def test_dhcp_client_settings_anonymize(self):
ec38833c 4579 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2cf6fdff 4580 start_networkd()
e2aea43f 4581 self.wait_online(['veth-peer:carrier'])
ec38833c 4582 start_dnsmasq()
e2aea43f 4583 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4584
ec38833c
ZJS
4585 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
4586 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
4587 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
4588
4589 def test_dhcp_client_listen_port(self):
ec38833c 4590 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2cf6fdff 4591 start_networkd()
e2aea43f 4592 self.wait_online(['veth-peer:carrier'])
ec38833c 4593 start_dnsmasq('--dhcp-alternate-port=67,5555')
e2aea43f 4594 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47 4595
371810d1 4596 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
4597 print(output)
4598 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109 4599
4c882c16
YW
4600 def test_dhcp_client_with_static_address(self):
4601 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
4602 'dhcp-client-with-static-address.network')
4603 start_networkd()
e2aea43f 4604 self.wait_online(['veth-peer:carrier'])
4c882c16 4605 start_dnsmasq()
e2aea43f 4606 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4c882c16
YW
4607
4608 output = check_output('ip address show dev veth99 scope global')
4609 print(output)
4610 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3e726c15 4611 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
4612
4613 output = check_output('ip route show dev veth99')
4614 print(output)
4615 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
4616 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
4c882c16
YW
4617 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
4618
1f0e3109 4619 def test_dhcp_route_table_id(self):
ec38833c 4620 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2cf6fdff 4621 start_networkd()
e2aea43f 4622 self.wait_online(['veth-peer:carrier'])
ec38833c 4623 start_dnsmasq()
e2aea43f 4624 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4625
371810d1 4626 output = check_output('ip route show table 12')
1f0e3109 4627 print(output)
1f0e3109
SS
4628 self.assertRegex(output, 'veth99 proto dhcp')
4629 self.assertRegex(output, '192.168.5.1')
4630
4631 def test_dhcp_route_metric(self):
ec38833c 4632 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2cf6fdff 4633 start_networkd()
e2aea43f 4634 self.wait_online(['veth-peer:carrier'])
ec38833c 4635 start_dnsmasq()
e2aea43f 4636 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4637
371810d1 4638 output = check_output('ip route show dev veth99')
1f0e3109 4639 print(output)
3e726c15
YW
4640 self.assertIn('default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 24', output)
4641 self.assertIn('192.168.5.0/24 proto kernel scope link src 192.168.5.181 metric 24', output)
4642 self.assertIn('192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 24', output)
1f0e3109 4643
c1b01a62 4644 def test_dhcp_client_reassign_static_routes_ipv4(self):
c38d2d4d 4645 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
c1b01a62 4646 'dhcp-client-reassign-static-routes-ipv4.network')
c38d2d4d 4647 start_networkd()
e2aea43f 4648 self.wait_online(['veth-peer:carrier'])
c38d2d4d 4649 start_dnsmasq(lease_time='2m')
e2aea43f 4650 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c38d2d4d
YW
4651
4652 output = check_output('ip address show dev veth99 scope global')
4653 print(output)
3e726c15 4654 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
c38d2d4d
YW
4655
4656 output = check_output('ip route show dev veth99')
4657 print(output)
4658 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
4659 self.assertRegex(output, r'192.168.5.0/24 proto static')
4660 self.assertRegex(output, r'192.168.6.0/24 proto static')
4661 self.assertRegex(output, r'192.168.7.0/24 proto static')
4662
888f57c1 4663 stop_dnsmasq()
c1b01a62
YW
4664 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
4665
c38d2d4d
YW
4666 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4667 print('Wait for the dynamic address to be renewed')
4668 time.sleep(125)
4669
e2aea43f 4670 self.wait_online(['veth99:routable'])
c38d2d4d
YW
4671
4672 output = check_output('ip route show dev veth99')
4673 print(output)
4674 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
4675 self.assertRegex(output, r'192.168.5.0/24 proto static')
4676 self.assertRegex(output, r'192.168.6.0/24 proto static')
4677 self.assertRegex(output, r'192.168.7.0/24 proto static')
4678
c1b01a62
YW
4679 def test_dhcp_client_reassign_static_routes_ipv6(self):
4680 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4681 'dhcp-client-reassign-static-routes-ipv6.network')
4682 start_networkd()
e2aea43f 4683 self.wait_online(['veth-peer:carrier'])
c1b01a62 4684 start_dnsmasq(lease_time='2m')
e2aea43f 4685 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c1b01a62
YW
4686
4687 output = check_output('ip address show dev veth99 scope global')
4688 print(output)
426654d7 4689 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
c1b01a62
YW
4690
4691 output = check_output('ip -6 route show dev veth99')
4692 print(output)
4693 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
4694 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
4695
888f57c1 4696 stop_dnsmasq()
c1b01a62
YW
4697 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
4698
4699 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
4700 print('Wait for the dynamic address to be renewed')
4701 time.sleep(125)
4702
e2aea43f 4703 self.wait_online(['veth99:routable'])
c1b01a62
YW
4704
4705 output = check_output('ip -6 route show dev veth99')
4706 print(output)
4707 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
4708 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
4709
1e498853
YW
4710 def test_dhcp_keep_configuration_dhcp(self):
4711 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2cf6fdff 4712 start_networkd()
e2aea43f 4713 self.wait_online(['veth-peer:carrier'])
1e498853 4714 start_dnsmasq(lease_time='2m')
e2aea43f 4715 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 4716
1e498853
YW
4717 output = check_output('ip address show dev veth99 scope global')
4718 print(output)
4719 self.assertRegex(output, r'192.168.5.*')
4720
fc79e6ff 4721 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4722 print(output)
1e498853 4723 self.assertRegex(output, r'192.168.5.*')
e40a58b5 4724
5238e957 4725 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
888f57c1 4726 stop_dnsmasq()
1f0e3109
SS
4727
4728 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 4729 print('Wait for the dynamic address to be expired')
1f0e3109
SS
4730 time.sleep(125)
4731
1e498853
YW
4732 print('The lease address should be kept after lease expired')
4733 output = check_output('ip address show dev veth99 scope global')
4734 print(output)
4735 self.assertRegex(output, r'192.168.5.*')
4736
fc79e6ff 4737 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 4738 print(output)
1e498853
YW
4739 self.assertRegex(output, r'192.168.5.*')
4740
3aa645f0
MB
4741 check_output('systemctl stop systemd-networkd.socket')
4742 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
4743
4744 print('The lease address should be kept after networkd stopped')
4745 output = check_output('ip address show dev veth99 scope global')
4746 print(output)
4747 self.assertRegex(output, r'192.168.5.*')
4748
2347b6b9
YW
4749 with open(os.path.join(network_unit_file_path, 'dhcp-client-keep-configuration-dhcp.network'), mode='a') as f:
4750 f.write('[Network]\nDHCP=no\n')
1e498853 4751
2347b6b9
YW
4752 start_networkd()
4753 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853
YW
4754
4755 print('Still the lease address should be kept after networkd restarted')
4756 output = check_output('ip address show dev veth99 scope global')
4757 print(output)
4758 self.assertRegex(output, r'192.168.5.*')
4759
fc79e6ff 4760 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
4761 print(output)
4762 self.assertRegex(output, r'192.168.5.*')
4763
4764 def test_dhcp_keep_configuration_dhcp_on_stop(self):
4765 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2cf6fdff 4766 start_networkd()
e2aea43f 4767 self.wait_online(['veth-peer:carrier'])
1e498853 4768 start_dnsmasq(lease_time='2m')
e2aea43f 4769 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1e498853
YW
4770
4771 output = check_output('ip address show dev veth99 scope global')
4772 print(output)
4773 self.assertRegex(output, r'192.168.5.*')
4774
888f57c1 4775 stop_dnsmasq()
3aa645f0
MB
4776 check_output('systemctl stop systemd-networkd.socket')
4777 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
4778
4779 output = check_output('ip address show dev veth99 scope global')
4780 print(output)
4781 self.assertRegex(output, r'192.168.5.*')
4782
e2aea43f
YW
4783 restart_networkd(3)
4784 self.wait_online(['veth-peer:routable'])
1e498853
YW
4785
4786 output = check_output('ip address show dev veth99 scope global')
4787 print(output)
4788 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 4789
30d3b54e 4790 def test_dhcp_client_reuse_address_as_static(self):
ec38833c 4791 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2cf6fdff 4792 start_networkd()
e2aea43f 4793 self.wait_online(['veth-peer:carrier'])
ec38833c 4794 start_dnsmasq()
e2aea43f 4795 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
4796
4797 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4798 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 4799 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 4800
371810d1 4801 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
4802 print(output)
4803 self.assertRegex(output, '192.168.5')
4804 self.assertRegex(output, '2600::')
4805
2629df47
YW
4806 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
4807 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
4808 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
4809 print(static_network)
4810
ec38833c 4811 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
4812
4813 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
4814 f.write(static_network)
4815
2629df47
YW
4816 # When networkd started, the links are already configured, so let's wait for 5 seconds
4817 # the links to be re-configured.
aaae5713 4818 restart_networkd(5)
e2aea43f 4819 self.wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 4820
371810d1 4821 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
4822 print(output)
4823 self.assertRegex(output, '192.168.5')
4824 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
4825
371810d1 4826 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
4827 print(output)
4828 self.assertRegex(output, '2600::')
4829 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
4830
18c613dc
YW
4831 @expectedFailureIfModuleIsNotAvailable('vrf')
4832 def test_dhcp_client_vrf(self):
ec38833c
ZJS
4833 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
4834 '25-vrf.netdev', '25-vrf.network')
2cf6fdff 4835 start_networkd()
e2aea43f 4836 self.wait_online(['veth-peer:carrier'])
ec38833c 4837 start_dnsmasq()
e2aea43f 4838 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
4839
4840 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 4841 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 4842 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
4843
4844 print('## ip -d link show dev vrf99')
371810d1 4845 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
4846 print(output)
4847 self.assertRegex(output, 'vrf table 42')
4848
4849 print('## ip address show vrf vrf99')
371810d1 4850 output = check_output('ip address show vrf vrf99')
d90f4f7d 4851 print(output)
3e726c15 4852 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4853 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
d90f4f7d 4854 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
4855
4856 print('## ip address show dev veth99')
371810d1 4857 output = check_output('ip address show dev veth99')
18c613dc 4858 print(output)
3e726c15 4859 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4860 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
4861 self.assertRegex(output, 'inet6 .* scope link')
4862
4863 print('## ip route show vrf vrf99')
371810d1 4864 output = check_output('ip route show vrf vrf99')
18c613dc
YW
4865 print(output)
4866 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
18c613dc 4867 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
18c613dc
YW
4868 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
4869
4870 print('## ip route show table main dev veth99')
371810d1 4871 output = check_output('ip route show table main dev veth99')
18c613dc
YW
4872 print(output)
4873 self.assertEqual(output, '')
4874
214c5bae
YW
4875 def test_dhcp_client_gateway_ipv4(self):
4876 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4877 'dhcp-client-gateway-ipv4.network')
4878 start_networkd()
4879 self.wait_online(['veth-peer:carrier'])
4880 start_dnsmasq()
4881 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4882
4df8a8e8 4883 output = check_output('ip route list dev veth99')
214c5bae 4884 print(output)
4df8a8e8
YW
4885 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]*')
4886 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
4887
4888 with open(os.path.join(network_unit_file_path, 'dhcp-client-gateway-ipv4.network'), mode='a') as f:
4889 f.write('[DHCPv4]\nUseGateway=no\n')
4890
4891 rc = call(*networkctl_cmd, 'reload', env=env)
4892 self.assertEqual(rc, 0)
4893
4894 time.sleep(2)
4895 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4896
4897 output = check_output('ip route list dev veth99')
4898 print(output)
4899 self.assertNotRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]*')
4900 self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
214c5bae
YW
4901
4902 def test_dhcp_client_gateway_ipv6(self):
4903 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4904 'dhcp-client-gateway-ipv6.network')
4905 start_networkd()
4906 self.wait_online(['veth-peer:carrier'])
4907 start_dnsmasq()
4908 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4909
4910 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
4911 print(output)
4912 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
4913
af3b1498 4914 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
4915 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4916 'dhcp-client-gateway-onlink-implicit.network')
2cf6fdff 4917 start_networkd()
e2aea43f 4918 self.wait_online(['veth-peer:carrier'])
ec38833c 4919 start_dnsmasq()
e2aea43f 4920 self.wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 4921
fc79e6ff 4922 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
af3b1498
YW
4923 print(output)
4924 self.assertRegex(output, '192.168.5')
4925
371810d1 4926 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
4927 print(output)
4928 self.assertRegex(output, 'onlink')
371810d1 4929 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
4930 print(output)
4931 self.assertRegex(output, 'onlink')
4932
3ca1fab7 4933 def test_dhcp_client_with_ipv4ll_with_dhcp_server(self):
ec38833c 4934 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
240e4137 4935 'dhcp-client-with-ipv4ll.network')
2cf6fdff 4936 start_networkd()
e2aea43f 4937 self.wait_online(['veth-peer:carrier'])
ec38833c 4938 start_dnsmasq(lease_time='2m')
e2aea43f 4939 self.wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 4940
371810d1 4941 output = check_output('ip address show dev veth99')
63c598ed
YW
4942 print(output)
4943
371810d1 4944 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4945 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4946 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4947 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4948 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4949 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4950 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4951 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
63c598ed
YW
4952
4953 print('Wait for the dynamic address to be expired')
4954 time.sleep(130)
4955
371810d1 4956 output = check_output('ip address show dev veth99')
63c598ed
YW
4957 print(output)
4958
371810d1 4959 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4960 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4961 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4962 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4963 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4964 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4965 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4966 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
63c598ed 4967
ec38833c 4968 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 4969
3ca1fab7 4970 def test_dhcp_client_with_ipv4ll_without_dhcp_server(self):
ec38833c 4971 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
240e4137 4972 'dhcp-client-with-ipv4ll.network')
2cf6fdff 4973 start_networkd()
b226c15c
DS
4974 # we need to increase timeout above default, as this will need to wait for
4975 # systemd-networkd to get the dhcpv4 transient failure event
4976 self.wait_online(['veth99:degraded', 'veth-peer:routable'], timeout='60s')
117a55c7 4977
371810d1 4978 output = check_output('ip address show dev veth99')
117a55c7
YW
4979 print(output)
4980
371810d1 4981 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4982 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4983 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4984 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4985 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3e726c15 4986 self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4987 output = check_output('ip -4 address show dev veth99 scope link')
3e726c15 4988 self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 metric 2048 brd 169\.254\.255\.255 scope link')
240e4137
YW
4989
4990 start_dnsmasq(lease_time='2m')
3e726c15
YW
4991 self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 metric 1024 brd 192\.168\.5\.255 scope global dynamic', ipv='-4')
4992 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 4993
b6efd661 4994 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
4995 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4996 'dhcp-client-ipv4-only-ipv6-disabled.network')
2cf6fdff 4997 start_networkd()
e2aea43f 4998 self.wait_online(['veth-peer:carrier'])
ec38833c 4999 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
e2aea43f 5000 self.wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
5001
5002 # test for issue #12490
5003
371810d1 5004 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661 5005 print(output)
3e726c15 5006 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
b6efd661
YW
5007 address1=None
5008 for line in output.splitlines():
5009 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
5010 address1 = line.split()[1].split('/')[0]
5011 break
5012
371810d1 5013 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
5014 print(output)
5015 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
5016 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
5017
888f57c1 5018 stop_dnsmasq()
ec38833c 5019 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
5020
5021 print('Wait for the dynamic address to be expired')
5022 time.sleep(130)
5023
371810d1 5024 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661 5025 print(output)
3e726c15 5026 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
b6efd661
YW
5027 address2=None
5028 for line in output.splitlines():
3e726c15 5029 if 'metric 1024 brd 192.168.5.255 scope global dynamic veth99' in line:
b6efd661
YW
5030 address2 = line.split()[1].split('/')[0]
5031 break
5032
5033 self.assertNotEqual(address1, address2)
5034
371810d1 5035 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
5036 print(output)
5037 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
5038 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
5039 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
5040 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
5041
e2d5aab3
YW
5042 def test_dhcp_client_use_dns_yes(self):
5043 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
5044
5045 start_networkd()
e2aea43f 5046 self.wait_online(['veth-peer:carrier'])
e2d5aab3 5047 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 5048 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
5049
5050 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 5051 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 5052 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 5053
693283cd 5054 time.sleep(3)
e2d5aab3
YW
5055 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
5056 print(output)
5057 self.assertRegex(output, '192.168.5.1')
5058 self.assertRegex(output, '2600::1')
5059
94f0bd62
YW
5060 # TODO: check json string
5061 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
5062
e2d5aab3
YW
5063 def test_dhcp_client_use_dns_no(self):
5064 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
5065
5066 start_networkd()
e2aea43f 5067 self.wait_online(['veth-peer:carrier'])
e2d5aab3 5068 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 5069 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
5070
5071 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 5072 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 5073 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 5074
693283cd 5075 time.sleep(3)
e2d5aab3
YW
5076 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
5077 print(output)
5078 self.assertNotRegex(output, '192.168.5.1')
5079 self.assertNotRegex(output, '2600::1')
5080
5081 def test_dhcp_client_use_dns_ipv4(self):
5082 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
5083
5084 start_networkd()
e2aea43f 5085 self.wait_online(['veth-peer:carrier'])
e2d5aab3 5086 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 5087 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
5088
5089 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 5090 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 5091 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 5092
693283cd 5093 time.sleep(3)
e2d5aab3
YW
5094 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
5095 print(output)
5096 self.assertRegex(output, '192.168.5.1')
5097 self.assertNotRegex(output, '2600::1')
5098
5099 def test_dhcp_client_use_dns_ipv4_and_ra(self):
5100 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
5101
5102 start_networkd()
e2aea43f 5103 self.wait_online(['veth-peer:carrier'])
e2d5aab3 5104 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 5105 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
5106
5107 # link become 'routable' when at least one protocol provide an valid address.
3e726c15 5108 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 5109 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 5110
693283cd 5111 time.sleep(3)
e2d5aab3
YW
5112 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
5113 print(output)
5114 self.assertRegex(output, '192.168.5.1')
5115 self.assertRegex(output, '2600::1')
5116
e0c1341d
YW
5117 def test_dhcp_client_use_domains(self):
5118 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
5119
5120 start_networkd()
e2aea43f 5121 self.wait_online(['veth-peer:carrier'])
e0c1341d 5122 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
e2aea43f 5123 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e0c1341d 5124
fc79e6ff 5125 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
e0c1341d
YW
5126 print(output)
5127 self.assertRegex(output, 'Search Domains: example.com')
5128
5129 time.sleep(3)
5130 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
5131 print(output)
5132 self.assertRegex(output, 'example.com')
5133
0fd8b718
YW
5134 def test_dhcp_client_decline(self):
5135 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
5136
5137 start_networkd()
44924431
YW
5138 self.wait_online(['veth99:routable', 'veth-peer:routable'])
5139
5140 output = check_output('ip -4 address show dev veth99 scope global dynamic')
5141 print(output)
5142 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
0fd8b718 5143
ab47f960
YW
5144 def test_dhcp_client_allow_list(self):
5145 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-allow-list.network')
5146
5147 start_networkd()
5148 self.wait_online(['veth99:routable', 'veth-peer:routable'])
5149
5150 output = check_output('ip -4 address show dev veth99 scope global dynamic')
5151 print(output)
5152 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 metric 1024 brd 192.168.5.255 scope global dynamic veth99')
5153
a27588d4 5154class NetworkdDHCPPDTests(unittest.TestCase, Utilities):
caad88a2
YW
5155 links = [
5156 'dummy97',
5157 'dummy98',
5158 'dummy99',
5159 'test1',
6c8d6bdd 5160 'veth97',
caad88a2
YW
5161 'veth98',
5162 'veth99',
5163 ]
5164
5165 units = [
5166 '11-dummy.netdev',
5167 '12-dummy.netdev',
5168 '13-dummy.netdev',
5169 '25-veth.netdev',
6c8d6bdd
YW
5170 '25-veth-downstream-veth97.netdev',
5171 '25-veth-downstream-veth98.netdev',
42592d0a 5172 '80-6rd-tunnel.network',
a27588d4
YW
5173 'dhcp-pd-downstream-dummy97.network',
5174 'dhcp-pd-downstream-dummy98.network',
5175 'dhcp-pd-downstream-dummy99.network',
5176 'dhcp-pd-downstream-test1.network',
5177 'dhcp-pd-downstream-veth97.network',
5178 'dhcp-pd-downstream-veth97-peer.network',
5179 'dhcp-pd-downstream-veth98.network',
5180 'dhcp-pd-downstream-veth98-peer.network',
84cc85f9
YW
5181 'dhcp4-6rd-server.network',
5182 'dhcp4-6rd-upstream.network',
caad88a2
YW
5183 'dhcp6pd-server.network',
5184 'dhcp6pd-upstream.network',
5185 ]
5186
5187 def setUp(self):
5188 stop_isc_dhcpd()
4862fb69 5189 stop_dnsmasq()
caad88a2
YW
5190 remove_links(self.links)
5191 stop_networkd(show_logs=False)
5192
5193 def tearDown(self):
5194 stop_isc_dhcpd()
4862fb69 5195 stop_dnsmasq()
caad88a2
YW
5196 remove_links(self.links)
5197 remove_unit_from_networkd_path(self.units)
5198 stop_networkd(show_logs=True)
5199
5200 def test_dhcp6pd(self):
5201 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp6pd-server.network', 'dhcp6pd-upstream.network',
a27588d4
YW
5202 '25-veth-downstream-veth97.netdev', 'dhcp-pd-downstream-veth97.network', 'dhcp-pd-downstream-veth97-peer.network',
5203 '25-veth-downstream-veth98.netdev', 'dhcp-pd-downstream-veth98.network', 'dhcp-pd-downstream-veth98-peer.network',
5204 '11-dummy.netdev', 'dhcp-pd-downstream-test1.network',
5205 'dhcp-pd-downstream-dummy97.network',
5206 '12-dummy.netdev', 'dhcp-pd-downstream-dummy98.network',
5207 '13-dummy.netdev', 'dhcp-pd-downstream-dummy99.network')
caad88a2
YW
5208
5209 start_networkd()
133f65ef 5210 self.wait_online(['veth-peer:routable'])
5f7f1f82 5211 start_isc_dhcpd('veth-peer', 'isc-dhcpd-dhcp6pd.conf', ip='-6')
133f65ef 5212 self.wait_online(['veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded',
6c8d6bdd 5213 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable'])
caad88a2
YW
5214
5215 print('### ip -6 address show dev veth-peer scope global')
5216 output = check_output('ip -6 address show dev veth-peer scope global')
5217 print(output)
5218 self.assertIn('inet6 3ffe:501:ffff:100::1/64 scope global', output)
5219
6016f1cf
YW
5220 '''
5221 Link Subnet IDs
5222 test1: 0x00
5223 dummy97: 0x01 (The link will appear later)
5224 dummy98: 0x02
5225 dummy99: auto -> 0x03 (No address assignment)
5226 veth97: 0x08
5227 veth98: 0x09
ab0c82d9 5228 veth99: 0x10 (ignored, as it is upstream)
6016f1cf
YW
5229 '''
5230
caad88a2
YW
5231 print('### ip -6 address show dev veth99 scope global')
5232 output = check_output('ip -6 address show dev veth99 scope global')
5233 print(output)
5234 # IA_NA
5235 self.assertRegex(output, 'inet6 3ffe:501:ffff:100::[0-9]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
5236 # address in IA_PD (Token=static)
ab0c82d9 5237 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/56 (metric 256 |)scope global dynamic')
caad88a2 5238 # address in IA_PD (Token=eui64)
ab0c82d9 5239 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1034:56ff:fe78:9abc/56 (metric 256 |)scope global dynamic')
caad88a2
YW
5240
5241 print('### ip -6 address show dev test1 scope global')
5242 output = check_output('ip -6 address show dev test1 scope global')
5243 print(output)
5244 # address in IA_PD (Token=static)
5245 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5246 # address in IA_PD (temporary)
ab0c82d9 5247 # Note that the temporary addresses may appear after the link enters configured state
caad88a2
YW
5248 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')
5249
5250 print('### ip -6 address show dev dummy98 scope global')
5251 output = check_output('ip -6 address show dev dummy98 scope global')
5252 print(output)
5253 # address in IA_PD (Token=static)
6016f1cf 5254 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
caad88a2 5255 # address in IA_PD (temporary)
6016f1cf
YW
5256 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')
5257
5258 print('### ip -6 address show dev dummy99 scope global')
5259 output = check_output('ip -6 address show dev dummy99 scope global')
5260 print(output)
5261 # Assign=no
5262 self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03')
caad88a2 5263
6c8d6bdd
YW
5264 print('### ip -6 address show dev veth97 scope global')
5265 output = check_output('ip -6 address show dev veth97 scope global')
5266 print(output)
5267 # address in IA_PD (Token=static)
5268 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5269 # address in IA_PD (Token=eui64)
5270 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1034:56ff:fe78:9ace/64 (metric 256 |)scope global dynamic mngtmpaddr')
5271 # address in IA_PD (temporary)
5272 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')
5273
5274 print('### ip -6 address show dev veth97-peer scope global')
5275 output = check_output('ip -6 address show dev veth97-peer scope global')
5276 print(output)
5277 # NDisc address (Token=static)
5278 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
5279 # NDisc address (Token=eui64)
5280 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]08:1034:56ff:fe78:9acf/64 (metric 256 |)scope global dynamic mngtmpaddr')
5281 # NDisc address (temporary)
5282 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')
5283
caad88a2
YW
5284 print('### ip -6 address show dev veth98 scope global')
5285 output = check_output('ip -6 address show dev veth98 scope global')
5286 print(output)
5287 # address in IA_PD (Token=static)
5288 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5289 # address in IA_PD (Token=eui64)
5290 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1034:56ff:fe78:9abe/64 (metric 256 |)scope global dynamic mngtmpaddr')
5291 # address in IA_PD (temporary)
5292 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')
5293
5294 print('### ip -6 address show dev veth98-peer scope global')
5295 output = check_output('ip -6 address show dev veth98-peer scope global')
5296 print(output)
5297 # NDisc address (Token=static)
5298 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
5299 # NDisc address (Token=eui64)
5300 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]09:1034:56ff:fe78:9abf/64 (metric 256 |)scope global dynamic mngtmpaddr')
5301 # NDisc address (temporary)
5302 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')
5303
caad88a2
YW
5304 print('### ip -6 route show type unreachable')
5305 output = check_output('ip -6 route show type unreachable')
5306 print(output)
5307 self.assertRegex(output, 'unreachable 3ffe:501:ffff:[2-9a-f]00::/56 dev lo proto dhcp')
5308
5309 print('### ip -6 route show dev veth99')
5310 output = check_output('ip -6 route show dev veth99')
5311 print(output)
ab0c82d9 5312 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/56 proto kernel metric [0-9]* expires')
caad88a2
YW
5313
5314 print('### ip -6 route show dev test1')
5315 output = check_output('ip -6 route show dev test1')
5316 print(output)
5317 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]00::/64 proto kernel metric [0-9]* expires')
5318
5319 print('### ip -6 route show dev dummy98')
5320 output = check_output('ip -6 route show dev dummy98')
5321 print(output)
6016f1cf 5322 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto kernel metric [0-9]* expires')
caad88a2
YW
5323
5324 print('### ip -6 route show dev dummy99')
5325 output = check_output('ip -6 route show dev dummy99')
5326 print(output)
6016f1cf
YW
5327 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto dhcp metric [0-9]* expires')
5328
5329 print('### ip -6 route show dev veth97')
5330 output = check_output('ip -6 route show dev veth97')
5331 print(output)
5332 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]08::/64 proto kernel metric [0-9]* expires')
5333
5334 print('### ip -6 route show dev veth97-peer')
5335 output = check_output('ip -6 route show dev veth97-peer')
5336 print(output)
5337 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]08::/64 proto ra metric [0-9]* expires')
caad88a2
YW
5338
5339 print('### ip -6 route show dev veth98')
5340 output = check_output('ip -6 route show dev veth98')
5341 print(output)
5342 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]09::/64 proto kernel metric [0-9]* expires')
5343
5344 print('### ip -6 route show dev veth98-peer')
5345 output = check_output('ip -6 route show dev veth98-peer')
5346 print(output)
5347 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]09::/64 proto ra metric [0-9]* expires')
5348
5349 # Test case for a downstream which appears later
5350 check_output('ip link add dummy97 type dummy')
5351 self.wait_online(['dummy97:routable'])
5352
5353 print('### ip -6 address show dev dummy97 scope global')
5354 output = check_output('ip -6 address show dev dummy97 scope global')
5355 print(output)
5356 # address in IA_PD (Token=static)
6016f1cf 5357 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]01:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
caad88a2 5358 # address in IA_PD (temporary)
6016f1cf 5359 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
5360
5361 print('### ip -6 route show dev dummy97')
5362 output = check_output('ip -6 route show dev dummy97')
5363 print(output)
6016f1cf 5364 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]01::/64 proto kernel metric [0-9]* expires')
caad88a2
YW
5365
5366 # Test case for reconfigure
6016f1cf 5367 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', 'dummy99', env=env)
caad88a2
YW
5368 self.wait_online(['dummy98:routable'])
5369
5370 print('### ip -6 address show dev dummy98 scope global')
5371 output = check_output('ip -6 address show dev dummy98 scope global')
5372 print(output)
5373 # address in IA_PD (Token=static)
6016f1cf 5374 self.assertRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
caad88a2 5375 # address in IA_PD (temporary)
6016f1cf
YW
5376 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')
5377
5378 print('### ip -6 address show dev dummy99 scope global')
5379 output = check_output('ip -6 address show dev dummy99 scope global')
5380 print(output)
5381 # Assign=no
5382 self.assertNotRegex(output, 'inet6 3ffe:501:ffff:[2-9a-f]03')
caad88a2
YW
5383
5384 print('### ip -6 route show dev dummy98')
5385 output = check_output('ip -6 route show dev dummy98')
5386 print(output)
6016f1cf
YW
5387 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]02::/64 proto kernel metric [0-9]* expires')
5388
5389 print('### ip -6 route show dev dummy99')
5390 output = check_output('ip -6 route show dev dummy99')
5391 print(output)
5392 self.assertRegex(output, '3ffe:501:ffff:[2-9a-f]03::/64 proto dhcp metric [0-9]* expires')
caad88a2 5393
6a936c9c 5394 def verify_dhcp4_6rd(self, tunnel_name):
84cc85f9
YW
5395 print('### ip -4 address show dev veth-peer scope global')
5396 output = check_output('ip -4 address show dev veth-peer scope global')
5397 print(output)
5398 self.assertIn('inet 10.0.0.1/8 brd 10.255.255.255 scope global veth-peer', output)
5399
5400 '''
5401 Link Subnet IDs
5402 test1: 0x00
5403 dummy97: 0x01 (The link will appear later)
5404 dummy98: 0x02
5405 dummy99: auto -> 0x03 (No address assignment)
5406 veth97: 0x08
5407 veth98: 0x09
5408 veth99: 0x10
5409 '''
5410
5411 print('### ip -4 address show dev veth99 scope global')
5412 output = check_output('ip -4 address show dev veth99 scope global')
5413 print(output)
5414 self.assertRegex(output, 'inet 10.100.100.[0-9]*/8 (metric 1024 |)brd 10.255.255.255 scope global dynamic veth99')
5415
5416 print('### ip -6 address show dev veth99 scope global')
5417 output = check_output('ip -6 address show dev veth99 scope global')
5418 print(output)
5419 # address in IA_PD (Token=static)
5420 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+10:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5421 # address in IA_PD (Token=eui64)
5422 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+10:1034:56ff:fe78:9abc/64 (metric 256 |)scope global dynamic mngtmpaddr')
5423 # address in IA_PD (temporary)
5424 # Note that the temporary addresses may appear after the link enters configured state
5425 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')
5426
5427 print('### ip -6 address show dev test1 scope global')
5428 output = check_output('ip -6 address show dev test1 scope global')
5429 print(output)
5430 # address in IA_PD (Token=static)
5431 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+00:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5432 # address in IA_PD (temporary)
5433 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')
5434
5435 print('### ip -6 address show dev dummy98 scope global')
5436 output = check_output('ip -6 address show dev dummy98 scope global')
5437 print(output)
5438 # address in IA_PD (Token=static)
5439 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+02:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5440 # address in IA_PD (temporary)
5441 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')
5442
5443 print('### ip -6 address show dev dummy99 scope global')
5444 output = check_output('ip -6 address show dev dummy99 scope global')
5445 print(output)
5446 # Assign=no
5447 self.assertNotRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+03')
5448
5449 print('### ip -6 address show dev veth97 scope global')
5450 output = check_output('ip -6 address show dev veth97 scope global')
5451 print(output)
5452 # address in IA_PD (Token=static)
5453 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5454 # address in IA_PD (Token=eui64)
5455 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1034:56ff:fe78:9ace/64 (metric 256 |)scope global dynamic mngtmpaddr')
5456 # address in IA_PD (temporary)
5457 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')
5458
5459 print('### ip -6 address show dev veth97-peer scope global')
5460 output = check_output('ip -6 address show dev veth97-peer scope global')
5461 print(output)
5462 # NDisc address (Token=static)
5463 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
5464 # NDisc address (Token=eui64)
5465 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+08:1034:56ff:fe78:9acf/64 (metric 256 |)scope global dynamic mngtmpaddr')
5466 # NDisc address (temporary)
5467 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')
5468
5469 print('### ip -6 address show dev veth98 scope global')
5470 output = check_output('ip -6 address show dev veth98 scope global')
5471 print(output)
5472 # address in IA_PD (Token=static)
5473 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5474 # address in IA_PD (Token=eui64)
5475 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1034:56ff:fe78:9abe/64 (metric 256 |)scope global dynamic mngtmpaddr')
5476 # address in IA_PD (temporary)
5477 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')
5478
5479 print('### ip -6 address show dev veth98-peer scope global')
5480 output = check_output('ip -6 address show dev veth98-peer scope global')
5481 print(output)
5482 # NDisc address (Token=static)
5483 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1a:2b:3c:4e/64 (metric 256 |)scope global dynamic mngtmpaddr')
5484 # NDisc address (Token=eui64)
5485 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+09:1034:56ff:fe78:9abf/64 (metric 256 |)scope global dynamic mngtmpaddr')
5486 # NDisc address (temporary)
5487 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')
5488
5489 print('### ip -6 route show type unreachable')
5490 output = check_output('ip -6 route show type unreachable')
5491 print(output)
5492 self.assertRegex(output, 'unreachable 2001:db8:6464:[0-9a-f]+00::/56 dev lo proto dhcp')
5493
5494 print('### ip -6 route show dev veth99')
5495 output = check_output('ip -6 route show dev veth99')
5496 print(output)
5497 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+10::/64 proto kernel metric [0-9]* expires')
5498
5499 print('### ip -6 route show dev test1')
5500 output = check_output('ip -6 route show dev test1')
5501 print(output)
5502 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/64 proto kernel metric [0-9]* expires')
5503
5504 print('### ip -6 route show dev dummy98')
5505 output = check_output('ip -6 route show dev dummy98')
5506 print(output)
5507 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+02::/64 proto kernel metric [0-9]* expires')
5508
5509 print('### ip -6 route show dev dummy99')
5510 output = check_output('ip -6 route show dev dummy99')
5511 print(output)
5512 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+03::/64 proto dhcp metric [0-9]* expires')
5513
5514 print('### ip -6 route show dev veth97')
5515 output = check_output('ip -6 route show dev veth97')
5516 print(output)
5517 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+08::/64 proto kernel metric [0-9]* expires')
5518
5519 print('### ip -6 route show dev veth97-peer')
5520 output = check_output('ip -6 route show dev veth97-peer')
5521 print(output)
5522 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+08::/64 proto ra metric [0-9]* expires')
5523
5524 print('### ip -6 route show dev veth98')
5525 output = check_output('ip -6 route show dev veth98')
5526 print(output)
5527 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+09::/64 proto kernel metric [0-9]* expires')
5528
5529 print('### ip -6 route show dev veth98-peer')
5530 output = check_output('ip -6 route show dev veth98-peer')
5531 print(output)
5532 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+09::/64 proto ra metric [0-9]* expires')
5533
84cc85f9
YW
5534 print('### ip -6 address show dev dummy97 scope global')
5535 output = check_output('ip -6 address show dev dummy97 scope global')
5536 print(output)
5537 # address in IA_PD (Token=static)
5538 self.assertRegex(output, 'inet6 2001:db8:6464:[0-9a-f]+01:1a:2b:3c:4d/64 (metric 256 |)scope global dynamic mngtmpaddr')
5539 # address in IA_PD (temporary)
5540 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')
5541
5542 print('### ip -6 route show dev dummy97')
5543 output = check_output('ip -6 route show dev dummy97')
5544 print(output)
5545 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+01::/64 proto kernel metric [0-9]* expires')
5546
84cc85f9
YW
5547 print('### ip -d link show dev {}'.format(tunnel_name))
5548 output = check_output('ip -d link show dev {}'.format(tunnel_name))
5549 print(output)
5550 self.assertIn('link/sit 10.100.100.', output)
5551 self.assertIn('local 10.100.100.', output)
84cc85f9
YW
5552 self.assertIn('ttl 64', output)
5553 self.assertIn('6rd-prefix 2001:db8::/32', output)
5554 self.assertIn('6rd-relay_prefix 10.0.0.0/8', output)
5555
5556 print('### ip -6 address show dev {}'.format(tunnel_name))
5557 output = check_output('ip -6 address show dev {}'.format(tunnel_name))
5558 print(output)
5559 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')
5560 self.assertRegex(output, 'inet6 ::10.100.100.[0-9]+/96 scope global')
5561
5562 print('### ip -6 route show dev {}'.format(tunnel_name))
5563 output = check_output('ip -6 route show dev {}'.format(tunnel_name))
5564 print(output)
5565 self.assertRegex(output, '2001:db8:6464:[0-9a-f]+00::/56 proto kernel metric [0-9]* expires')
5566 self.assertRegex(output, '::/96 proto kernel metric [0-9]*')
5567
5568 print('### ip -6 route show default')
5569 output = check_output('ip -6 route show default')
5570 print(output)
5571 self.assertIn('default', output)
5572 self.assertIn('via ::10.0.0.1 dev {}'.format(tunnel_name), output)
5573
6a936c9c
YW
5574 def test_dhcp4_6rd(self):
5575 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp4-6rd-server.network', 'dhcp4-6rd-upstream.network',
5576 '25-veth-downstream-veth97.netdev', 'dhcp-pd-downstream-veth97.network', 'dhcp-pd-downstream-veth97-peer.network',
5577 '25-veth-downstream-veth98.netdev', 'dhcp-pd-downstream-veth98.network', 'dhcp-pd-downstream-veth98-peer.network',
5578 '11-dummy.netdev', 'dhcp-pd-downstream-test1.network',
5579 'dhcp-pd-downstream-dummy97.network',
5580 '12-dummy.netdev', 'dhcp-pd-downstream-dummy98.network',
5581 '13-dummy.netdev', 'dhcp-pd-downstream-dummy99.network',
5582 '80-6rd-tunnel.network')
5583
5584 start_networkd()
5585 self.wait_online(['veth-peer:routable'])
5586 '''
5587 ipv4masklen: 8
5588 6rd-prefix: 2001:db8::/32
5589 br-addresss: 10.0.0.1
5590 '''
5591 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')
5592 self.wait_online(['veth99:routable', 'test1:routable', 'dummy98:routable', 'dummy99:degraded',
5593 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable'])
5594
5595 # Test case for a downstream which appears later
5596 check_output('ip link add dummy97 type dummy')
5597 self.wait_online(['dummy97:routable'])
5598
5599 # Find tunnel name
5600 tunnel_name = None
5601 for name in os.listdir('/sys/class/net/'):
5602 if name.startswith('6rd-'):
5603 tunnel_name = name
5604 break
5605
5606 self.wait_online(['{}:routable'.format(tunnel_name)])
5607
5608 self.verify_dhcp4_6rd(tunnel_name)
5609
5610 # Test case for reconfigure
5611 check_output(*networkctl_cmd, 'reconfigure', 'dummy98', 'dummy99', env=env)
5612 self.wait_online(['dummy98:routable', 'dummy99:degraded'])
5613
5614 self.verify_dhcp4_6rd(tunnel_name)
5615
5616 # Test for renewing/rebinding lease
5617 print('wait for 120 sec')
5618 time.sleep(30)
5619 print('wait for 90 sec')
5620 time.sleep(30)
5621 print('wait for 60 sec')
5622 time.sleep(30)
5623 print('wait for 30 sec')
5624 time.sleep(30)
5625
5626 dump_dnsmasq_log_file()
5627
5628 self.wait_online(['veth99:routable', 'test1:routable', 'dummy97:routable', 'dummy98:routable', 'dummy99:degraded',
5629 'veth97:routable', 'veth97-peer:routable', 'veth98:routable', 'veth98-peer:routable'])
5630
5631 self.verify_dhcp4_6rd(tunnel_name)
5632
9633f977 5633class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
4a906586
YW
5634 links = [
5635 'dummy98',
5636 'veth99',
5637 ]
9633f977
SS
5638
5639 units = [
4a906586 5640 '12-dummy.netdev',
9633f977 5641 '25-veth.netdev',
635f2a66 5642 'ipv6ra-prefix-client-deny-list.network',
9633f977 5643 'ipv6ra-prefix-client.network',
4a906586
YW
5644 'ipv6ra-prefix.network',
5645 'ipv6ra-uplink.network',
5646 ]
9633f977
SS
5647
5648 def setUp(self):
5649 remove_links(self.links)
5650 stop_networkd(show_logs=False)
5651
5652 def tearDown(self):
9633f977
SS
5653 remove_links(self.links)
5654 remove_unit_from_networkd_path(self.units)
5655 stop_networkd(show_logs=True)
5656
5657 def test_ipv6_route_prefix(self):
4a906586
YW
5658 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network',
5659 '12-dummy.netdev', 'ipv6ra-uplink.network')
9633f977
SS
5660
5661 start_networkd()
4a906586 5662 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
9633f977 5663
635f2a66
YW
5664 output = check_output('ip address show dev veth-peer')
5665 print(output)
5666 self.assertIn('inet6 2001:db8:0:1:', output)
5667 self.assertNotIn('inet6 2001:db8:0:2:', output)
ab47f960 5668 self.assertNotIn('inet6 2001:db8:0:3:', output)
635f2a66 5669
3c874fd7 5670 output = check_output('ip -6 route show dev veth-peer')
9633f977 5671 print(output)
635f2a66
YW
5672 self.assertIn('2001:db8:0:1::/64 proto ra', output)
5673 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
ab47f960 5674 self.assertNotIn('2001:db8:0:3::/64 proto ra', output)
635f2a66
YW
5675 self.assertIn('2001:db0:fff::/64 via ', output)
5676 self.assertNotIn('2001:db1:fff::/64 via ', output)
ab47f960 5677 self.assertNotIn('2001:db2:fff::/64 via ', output)
9633f977 5678
635f2a66
YW
5679 output = check_output('ip address show dev veth99')
5680 print(output)
5681 self.assertNotIn('inet6 2001:db8:0:1:', output)
fe2a8b3d
YW
5682 self.assertIn('inet6 2001:db8:0:2:1a:2b:3c:4d', output)
5683 self.assertIn('inet6 2001:db8:0:2:fa:de:ca:fe', output)
ab47f960 5684 self.assertNotIn('inet6 2001:db8:0:3:', output)
635f2a66 5685
4a906586
YW
5686 output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env)
5687 print(output)
5688 self.assertRegex(output, '2001:db8:1:1::2')
5689
5690 output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env)
5691 print(output)
5692 self.assertIn('example.com', output)
5693
94f0bd62
YW
5694 # TODO: check json string
5695 check_output(*networkctl_cmd, '--json=short', 'status', env=env)
5696
635f2a66 5697 def test_ipv6_route_prefix_deny_list(self):
4a906586
YW
5698 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client-deny-list.network', 'ipv6ra-prefix.network',
5699 '12-dummy.netdev', 'ipv6ra-uplink.network')
635f2a66
YW
5700
5701 start_networkd()
4a906586 5702 self.wait_online(['veth99:routable', 'veth-peer:routable', 'dummy98:routable'])
635f2a66
YW
5703
5704 output = check_output('ip address show dev veth-peer')
5705 print(output)
5706 self.assertIn('inet6 2001:db8:0:1:', output)
5707 self.assertNotIn('inet6 2001:db8:0:2:', output)
5708
5709 output = check_output('ip -6 route show dev veth-peer')
5710 print(output)
5711 self.assertIn('2001:db8:0:1::/64 proto ra', output)
5712 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
5713 self.assertIn('2001:db0:fff::/64 via ', output)
5714 self.assertNotIn('2001:db1:fff::/64 via ', output)
5715
5716 output = check_output('ip address show dev veth99')
3c874fd7 5717 print(output)
635f2a66
YW
5718 self.assertNotIn('inet6 2001:db8:0:1:', output)
5719 self.assertIn('inet6 2001:db8:0:2:', output)
3c874fd7 5720
4a906586
YW
5721 output = check_output(*resolvectl_cmd, 'dns', 'veth-peer', env=env)
5722 print(output)
5723 self.assertRegex(output, '2001:db8:1:1::2')
5724
5725 output = check_output(*resolvectl_cmd, 'domain', 'veth-peer', env=env)
5726 print(output)
5727 self.assertIn('example.com', output)
5728
7db05447
DS
5729class NetworkdMTUTests(unittest.TestCase, Utilities):
5730 links = ['dummy98']
5731
5732 units = [
5733 '12-dummy.netdev',
5734 '12-dummy-mtu.netdev',
5735 '12-dummy-mtu.link',
5736 '12-dummy.network',
5737 ]
5738
5739 def setUp(self):
5740 remove_links(self.links)
5741 stop_networkd(show_logs=False)
5742
5743 def tearDown(self):
7db05447
DS
5744 remove_links(self.links)
5745 remove_unit_from_networkd_path(self.units)
5746 stop_networkd(show_logs=True)
5747
5748 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
5749 if not ipv6_mtu:
5750 ipv6_mtu = mtu
5751
5752 # test normal start
5753 start_networkd()
5754 self.wait_online(['dummy98:routable'])
5755 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
5756 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
5757
5758 # test normal restart
5759 restart_networkd()
5760 self.wait_online(['dummy98:routable'])
5761 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
5762 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
5763
5764 if reset:
5765 self.reset_check_mtu(mtu, ipv6_mtu)
5766
5767 def reset_check_mtu(self, mtu, ipv6_mtu=None):
5768 ''' test setting mtu/ipv6_mtu with interface already up '''
5769 stop_networkd()
5770
5771 # note - changing the device mtu resets the ipv6 mtu
5772 run('ip link set up mtu 1501 dev dummy98')
5773 run('ip link set up mtu 1500 dev dummy98')
5774 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
5775 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
5776
5777 self.check_mtu(mtu, ipv6_mtu, reset=False)
5778
5779 def test_mtu_network(self):
5780 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
5781 self.check_mtu('1600')
5782
5783 def test_mtu_netdev(self):
5784 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
5785 # note - MTU set by .netdev happens ONLY at device creation!
5786 self.check_mtu('1600', reset=False)
5787
5788 def test_mtu_link(self):
5789 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
5790 # must reload udev because it only picks up new files after 3 second delay
5791 call('udevadm control --reload')
5792 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
5793 self.check_mtu('1600', reset=False)
5794
5795 def test_ipv6_mtu(self):
5796 ''' set ipv6 mtu without setting device mtu '''
5797 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
5798 self.check_mtu('1500', '1400')
5799
5800 def test_ipv6_mtu_toolarge(self):
5801 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
5802 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
5803 self.check_mtu('1500', '1500')
5804
5805 def test_mtu_network_ipv6_mtu(self):
5806 ''' set ipv6 mtu and set device mtu via network file '''
5807 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
5808 self.check_mtu('1600', '1550')
5809
5810 def test_mtu_netdev_ipv6_mtu(self):
5811 ''' set ipv6 mtu and set device mtu via netdev file '''
5812 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
5813 self.check_mtu('1600', '1550', reset=False)
5814
5815 def test_mtu_link_ipv6_mtu(self):
5816 ''' set ipv6 mtu and set device mtu via link file '''
5817 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
5818 # must reload udev because it only picks up new files after 3 second delay
5819 call('udevadm control --reload')
5820 self.check_mtu('1600', '1550', reset=False)
5821
5822
1f0e3109 5823if __name__ == '__main__':
9c1ae484
YW
5824 parser = argparse.ArgumentParser()
5825 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
5826 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
b6d587d1 5827 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
641aa412 5828 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
9c1ae484
YW
5829 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
5830 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
b6d587d1
YW
5831 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
5832 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
9c1ae484
YW
5833 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
5834 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 5835 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 5836 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 5837 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
6c9efba6 5838 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
5839 ns, args = parser.parse_known_args(namespace=unittest)
5840
5841 if ns.build_dir:
641aa412 5842 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 5843 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
9c1ae484 5844 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
b6d587d1 5845 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
641aa412 5846 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
9c1ae484
YW
5847 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
5848 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
b6d587d1
YW
5849 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
5850 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
9c1ae484
YW
5851 else:
5852 if ns.networkd_bin:
5853 networkd_bin = ns.networkd_bin
b6d587d1
YW
5854 if ns.resolved_bin:
5855 resolved_bin = ns.resolved_bin
641aa412
YW
5856 if ns.udevd_bin:
5857 udevd_bin = ns.udevd_bin
9c1ae484
YW
5858 if ns.wait_online_bin:
5859 wait_online_bin = ns.wait_online_bin
5860 if ns.networkctl_bin:
5861 networkctl_bin = ns.networkctl_bin
b6d587d1
YW
5862 if ns.resolvectl_bin:
5863 resolvectl_bin = ns.resolvectl_bin
5864 if ns.timedatectl_bin:
5865 timedatectl_bin = ns.timedatectl_bin
9c1ae484
YW
5866
5867 use_valgrind = ns.use_valgrind
5868 enable_debug = ns.enable_debug
94c03122 5869 asan_options = ns.asan_options
fa4c6095 5870 lsan_options = ns.lsan_options
94c03122 5871 ubsan_options = ns.ubsan_options
6c9efba6 5872 with_coverage = ns.with_coverage
9c1ae484
YW
5873
5874 if use_valgrind:
5875 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
b6d587d1
YW
5876 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
5877 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
9c1ae484
YW
5878 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
5879 else:
5880 networkctl_cmd = [networkctl_bin]
b6d587d1
YW
5881 resolvectl_cmd = [resolvectl_bin]
5882 timedatectl_cmd = [timedatectl_bin]
9c1ae484
YW
5883 wait_online_cmd = [wait_online_bin]
5884
5885 if enable_debug:
5886 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
5887 if asan_options:
5888 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
5889 if lsan_options:
5890 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
5891 if ubsan_options:
5892 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
5893
5894 sys.argv[1:] = args
1f0e3109
SS
5895 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
5896 verbosity=3))