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