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