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