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