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