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