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