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