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