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