]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
network: add nexthop ID in debugging logs
[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',
b8102725 1756 '25-address-static.network',
2236d75d 1757 '25-activation-policy.network',
cd65d067 1758 '25-bind-carrier.network',
09ea6724
YW
1759 '25-bond-active-backup-slave.netdev',
1760 '25-fibrule-invert.network',
1761 '25-fibrule-port-range.network',
6be8e78e 1762 '25-fibrule-uidrange.network',
74761cf3 1763 '25-gre-tunnel-remote-any.netdev',
fb2ba330 1764 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 1765 '25-ipv6-address-label-section.network',
cff0cadc 1766 '25-ipv6-proxy-ndp.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 1831 print(output)
4a704501
YW
1832 self.assertIn('inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98', output)
1833 self.assertIn('inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98', output)
1834 self.assertIn('inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98', output)
1835 self.assertIn('inet 10.7.8.9/16 brd 10.7.255.255 scope link deprecated dummy98', output)
b8102725 1836
766f8f38
YW
1837 # test for ENOBUFS issue #17012
1838 for i in range(1,254):
4a704501 1839 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
766f8f38 1840
b8102725 1841 # invalid sections
4a704501
YW
1842 self.assertNotIn('10.10.0.1/16', output)
1843 self.assertNotIn('10.10.0.2/16', output)
b8102725 1844
371810d1 1845 output = check_output('ip -4 address show dev dummy98 label 32')
4a704501 1846 self.assertIn('inet 10.3.2.3/16 brd 10.3.255.255 scope global 32', output)
b8102725 1847
371810d1 1848 output = check_output('ip -4 address show dev dummy98 label 33')
4a704501 1849 self.assertIn('inet 10.4.2.3 peer 10.4.2.4/16 scope global 33', output)
b8102725 1850
371810d1 1851 output = check_output('ip -4 address show dev dummy98 label 34')
4a704501 1852 self.assertRegex(output, r'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
b8102725 1853
371810d1 1854 output = check_output('ip -4 address show dev dummy98 label 35')
4a704501 1855 self.assertRegex(output, r'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
b8102725 1856
371810d1 1857 output = check_output('ip -6 address show dev dummy98')
b8102725 1858 print(output)
4a704501
YW
1859 self.assertIn('inet6 2001:db8:0:f101::15/64 scope global', output)
1860 self.assertIn('inet6 2001:db8:0:f101::16/64 scope global', output)
1861 self.assertIn('inet6 2001:db8:0:f102::15/64 scope global', output)
1862 self.assertIn('inet6 2001:db8:0:f102::16/64 scope global', output)
1863 self.assertIn('inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global', output)
1864 self.assertIn('inet6 2001:db8:1:f101::1/64 scope global deprecated', output)
1865 self.assertRegex(output, r'inet6 fd[0-9a-f:]*1/64 scope global')
b8102725 1866
766f8f38
YW
1867 restart_networkd()
1868 self.wait_online(['dummy98:routable'])
1869
1870 # test for ENOBUFS issue #17012
1871 output = check_output('ip -4 address show dev dummy98')
1872 for i in range(1,254):
4a704501 1873 self.assertIn(f'inet 10.3.3.{i}/16 brd 10.3.255.255', output)
e4783b54 1874
dc7d3c5f
YW
1875 def test_address_dad(self):
1876 copy_unit_to_networkd_unit_path('25-address-dad-veth99.network', '25-address-dad-veth-peer.network',
1877 '25-veth.netdev')
1878 start_networkd()
1879 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1880
1881 output = check_output('ip -4 address show dev veth99')
1882 print(output)
1883 self.assertRegex(output, '192.168.100.10/24')
1884
1885 output = check_output('ip -4 address show dev veth-peer')
1886 print(output)
1887 self.assertNotRegex(output, '192.168.100.10/24')
1888
21266e60
YW
1889 def test_address_peer_ipv4(self):
1890 # test for issue #17304
1891 copy_unit_to_networkd_unit_path('25-address-peer-ipv4.network', '12-dummy.netdev')
1892
1893 for trial in range(2):
1894 if trial == 0:
1895 start_networkd()
1896 else:
1897 restart_networkd()
1898
1899 self.wait_online(['dummy98:routable'])
1900
1901 output = check_output('ip -4 address show dev dummy98')
1902 self.assertIn('inet 100.64.0.1 peer 100.64.0.2/32 scope global', output)
1903
c9d223e8
YW
1904 @expectedFailureIfModuleIsNotAvailable('vrf')
1905 def test_prefix_route(self):
1906 copy_unit_to_networkd_unit_path('25-prefix-route-with-vrf.network', '12-dummy.netdev',
1907 '25-prefix-route-without-vrf.network', '11-dummy.netdev',
1908 '25-vrf.netdev', '25-vrf.network')
1909 for trial in range(2):
1910 if trial == 0:
1911 start_networkd()
1912 else:
1913 restart_networkd(3)
1914
1915 self.wait_online(['dummy98:routable', 'test1:routable', 'vrf99:carrier'])
1916
1917 output = check_output('ip route show table 42 dev dummy98')
1918 print('### ip route show table 42 dev dummy98')
1919 print(output)
1920 self.assertRegex(output, 'local 10.20.22.1 proto kernel scope host src 10.20.22.1')
1921 self.assertRegex(output, 'broadcast 10.20.33.0 proto kernel scope link src 10.20.33.1')
1922 self.assertRegex(output, '10.20.33.0/24 proto kernel scope link src 10.20.33.1')
1923 self.assertRegex(output, 'local 10.20.33.1 proto kernel scope host src 10.20.33.1')
1924 self.assertRegex(output, 'broadcast 10.20.33.255 proto kernel scope link src 10.20.33.1')
1925 self.assertRegex(output, 'local 10.20.44.1 proto kernel scope host src 10.20.44.1')
1926 self.assertRegex(output, 'broadcast 10.20.55.0 proto kernel scope link src 10.20.55.1')
1927 self.assertRegex(output, 'local 10.20.55.1 proto kernel scope host src 10.20.55.1')
1928 self.assertRegex(output, 'broadcast 10.20.55.255 proto kernel scope link src 10.20.55.1')
1929 output = check_output('ip -6 route show table 42 dev dummy98')
1930 print('### ip -6 route show table 42 dev dummy98')
1931 print(output)
1932 if trial == 0:
1933 # Kernel's bug?
1934 self.assertRegex(output, 'local fdde:11:22::1 proto kernel metric 0 pref medium')
1935 #self.assertRegex(output, 'fdde:11:22::1 proto kernel metric 256 pref medium')
1936 self.assertRegex(output, 'local fdde:11:33::1 proto kernel metric 0 pref medium')
1937 self.assertRegex(output, 'fdde:11:33::/64 proto kernel metric 256 pref medium')
1938 self.assertRegex(output, 'local fdde:11:44::1 proto kernel metric 0 pref medium')
1939 self.assertRegex(output, 'local fdde:11:55::1 proto kernel metric 0 pref medium')
1940 self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
beb75dd3 1941 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
c9d223e8
YW
1942
1943 print()
1944
1945 output = check_output('ip route show dev test1')
1946 print('### ip route show dev test1')
1947 print(output)
1948 self.assertRegex(output, '10.21.33.0/24 proto kernel scope link src 10.21.33.1')
1949 output = check_output('ip route show table local dev test1')
1950 print('### ip route show table local dev test1')
1951 print(output)
1952 self.assertRegex(output, 'local 10.21.22.1 proto kernel scope host src 10.21.22.1')
1953 self.assertRegex(output, 'broadcast 10.21.33.0 proto kernel scope link src 10.21.33.1')
1954 self.assertRegex(output, 'local 10.21.33.1 proto kernel scope host src 10.21.33.1')
1955 self.assertRegex(output, 'broadcast 10.21.33.255 proto kernel scope link src 10.21.33.1')
1956 self.assertRegex(output, 'local 10.21.44.1 proto kernel scope host src 10.21.44.1')
1957 self.assertRegex(output, 'broadcast 10.21.55.0 proto kernel scope link src 10.21.55.1')
1958 self.assertRegex(output, 'local 10.21.55.1 proto kernel scope host src 10.21.55.1')
1959 self.assertRegex(output, 'broadcast 10.21.55.255 proto kernel scope link src 10.21.55.1')
1960 output = check_output('ip -6 route show dev test1')
1961 print('### ip -6 route show dev test1')
1962 print(output)
1963 self.assertRegex(output, 'fdde:12:22::1 proto kernel metric 256 pref medium')
1964 self.assertRegex(output, 'fdde:12:33::/64 proto kernel metric 256 pref medium')
1965 self.assertRegex(output, 'fe80::/64 proto kernel metric 256 pref medium')
1966 output = check_output('ip -6 route show table local dev test1')
1967 print('### ip -6 route show table local dev test1')
1968 print(output)
1969 self.assertRegex(output, 'local fdde:12:22::1 proto kernel metric 0 pref medium')
1970 self.assertRegex(output, 'local fdde:12:33::1 proto kernel metric 0 pref medium')
1971 self.assertRegex(output, 'local fdde:12:44::1 proto kernel metric 0 pref medium')
1972 self.assertRegex(output, 'local fdde:12:55::1 proto kernel metric 0 pref medium')
beb75dd3 1973 self.assertRegex(output, 'ff00::/8 (proto kernel )?metric 256 (linkdown )?pref medium')
c9d223e8 1974
1f0e3109 1975 def test_configure_without_carrier(self):
9bacf431 1976 copy_unit_to_networkd_unit_path('11-dummy.netdev')
2cf6fdff 1977 start_networkd()
9bacf431
DS
1978 self.wait_operstate('test1', 'off', '')
1979 check_output('ip link set dev test1 up carrier off')
1980
1981 copy_unit_to_networkd_unit_path('25-test1.network.d/configure-without-carrier.conf', dropins=False)
1982 restart_networkd()
1983 self.wait_online(['test1:no-carrier'])
1984
1985 carrier_map = {'on': '1', 'off': '0'}
1986 routable_map = {'on': 'routable', 'off': 'no-carrier'}
1987 for carrier in ['off', 'on', 'off']:
1988 with self.subTest(carrier=carrier):
1989 if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
1990 check_output(f'ip link set dev test1 carrier {carrier}')
1991 self.wait_online([f'test1:{routable_map[carrier]}'])
1992
1993 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
1994 print(output)
1995 self.assertRegex(output, '192.168.0.15')
1996 self.assertRegex(output, '192.168.0.1')
1997 self.assertRegex(output, routable_map[carrier])
e40a58b5 1998
9bacf431
DS
1999 def test_configure_without_carrier_yes_ignore_carrier_loss_no(self):
2000 copy_unit_to_networkd_unit_path('11-dummy.netdev')
2001 start_networkd()
2002 self.wait_operstate('test1', 'off', '')
2003 check_output('ip link set dev test1 up carrier off')
2004
2005 copy_unit_to_networkd_unit_path('25-test1.network')
2006 restart_networkd()
2007 self.wait_online(['test1:no-carrier'])
2008
2009 carrier_map = {'on': '1', 'off': '0'}
2010 routable_map = {'on': 'routable', 'off': 'no-carrier'}
2011 for (carrier, have_config) in [('off', True), ('on', True), ('off', False)]:
2012 with self.subTest(carrier=carrier, have_config=have_config):
2013 if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
2014 check_output(f'ip link set dev test1 carrier {carrier}')
2015 self.wait_online([f'test1:{routable_map[carrier]}'])
2016
2017 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
2018 print(output)
2019 if have_config:
2020 self.assertRegex(output, '192.168.0.15')
2021 self.assertRegex(output, '192.168.0.1')
2022 else:
2023 self.assertNotRegex(output, '192.168.0.15')
2024 self.assertNotRegex(output, '192.168.0.1')
2025 self.assertRegex(output, routable_map[carrier])
1f0e3109 2026
1f0e3109 2027 def test_routing_policy_rule(self):
ec38833c 2028 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
2cf6fdff 2029 start_networkd()
e2aea43f 2030 self.wait_online(['test1:degraded'])
e40a58b5 2031
65c24cd0 2032 output = check_output('ip rule list iif test1 priority 111')
1f0e3109 2033 print(output)
65c24cd0 2034 self.assertRegex(output, '111:')
1f0e3109 2035 self.assertRegex(output, 'from 192.168.100.18')
426654d7 2036 self.assertRegex(output, r'tos (0x08|throughput)\s')
1f0e3109
SS
2037 self.assertRegex(output, 'iif test1')
2038 self.assertRegex(output, 'oif test1')
2039 self.assertRegex(output, 'lookup 7')
2040
65c24cd0
YW
2041 output = check_output('ip rule list iif test1 priority 101')
2042 print(output)
2043 self.assertRegex(output, '101:')
2044 self.assertRegex(output, 'from all')
2045 self.assertRegex(output, 'iif test1')
2046 self.assertRegex(output, 'lookup 9')
2047
2048 output = check_output('ip -6 rule list iif test1 priority 100')
2049 print(output)
2050 self.assertRegex(output, '100:')
2051 self.assertRegex(output, 'from all')
2052 self.assertRegex(output, 'iif test1')
2053 self.assertRegex(output, 'lookup 8')
2054
b677774d 2055 def test_routing_policy_rule_issue_11280(self):
ec38833c
ZJS
2056 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
2057 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
b677774d 2058
b677774d
YW
2059 for trial in range(3):
2060 # Remove state files only first time
e2aea43f
YW
2061 start_networkd(3)
2062 self.wait_online(['test1:degraded', 'dummy98:degraded'])
df7f9afa 2063 time.sleep(1)
b677774d 2064
371810d1 2065 output = check_output('ip rule list table 7')
b677774d 2066 print(output)
426654d7 2067 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
b677774d 2068
371810d1 2069 output = check_output('ip rule list table 8')
b677774d 2070 print(output)
426654d7 2071 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
b677774d 2072
aaae5713
YW
2073 stop_networkd(remove_state_files=False)
2074
87adeabf 2075 def test_routing_policy_rule_reconfigure(self):
49ff3f34 2076 copy_unit_to_networkd_unit_path('routing-policy-rule-reconfigure2.network', '11-dummy.netdev')
87adeabf
YW
2077 start_networkd()
2078 self.wait_online(['test1:degraded'])
2079
2080 output = check_output('ip rule list table 1011')
2081 print(output)
49ff3f34
YW
2082 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2083 self.assertIn('10112: from all oif test1 lookup 1011', output)
2084 self.assertIn('10113: from all iif test1 lookup 1011', output)
2085 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2086
2087 output = check_output('ip -6 rule list table 1011')
2088 print(output)
2089 self.assertIn('10112: from all oif test1 lookup 1011', output)
2090
2091 copy_unit_to_networkd_unit_path('routing-policy-rule-reconfigure1.network', '11-dummy.netdev')
2092 run(*networkctl_cmd, 'reload', env=env)
2093 time.sleep(1)
2094 self.wait_online(['test1:degraded'])
2095
2096 output = check_output('ip rule list table 1011')
2097 print(output)
2098 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2099 self.assertIn('10112: from all oif test1 lookup 1011', output)
2100 self.assertIn('10113: from all iif test1 lookup 1011', output)
2101 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2102
2103 output = check_output('ip -6 rule list table 1011')
2104 print(output)
2105 self.assertNotIn('10112: from all oif test1 lookup 1011', output)
2106 self.assertIn('10113: from all iif test1 lookup 1011', output)
87adeabf
YW
2107
2108 run('ip rule delete priority 10111')
2109 run('ip rule delete priority 10112')
2110 run('ip rule delete priority 10113')
2111 run('ip rule delete priority 10114')
49ff3f34 2112 run('ip -6 rule delete priority 10113')
87adeabf
YW
2113
2114 output = check_output('ip rule list table 1011')
2115 print(output)
2116 self.assertEqual(output, '')
2117
49ff3f34
YW
2118 output = check_output('ip -6 rule list table 1011')
2119 print(output)
2120 self.assertEqual(output, '')
87adeabf 2121
49ff3f34 2122 run(*networkctl_cmd, 'reconfigure', 'test1', env=env)
87adeabf
YW
2123 self.wait_online(['test1:degraded'])
2124
2125 output = check_output('ip rule list table 1011')
2126 print(output)
49ff3f34
YW
2127 self.assertIn('10111: from all fwmark 0x3f3 lookup 1011', output)
2128 self.assertIn('10112: from all oif test1 lookup 1011', output)
2129 self.assertIn('10113: from all iif test1 lookup 1011', output)
2130 self.assertIn('10114: from 192.168.8.254 lookup 1011', output)
2131
2132 output = check_output('ip -6 rule list table 1011')
2133 print(output)
2134 self.assertIn('10113: from all iif test1 lookup 1011', output)
87adeabf 2135
d586a2c3 2136 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0 2137 def test_routing_policy_rule_port_range(self):
ec38833c 2138 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
2cf6fdff 2139 start_networkd()
e2aea43f 2140 self.wait_online(['test1:degraded'])
e40a58b5 2141
371810d1 2142 output = check_output('ip rule')
926062f0
SS
2143 print(output)
2144 self.assertRegex(output, '111')
2145 self.assertRegex(output, 'from 192.168.100.18')
2146 self.assertRegex(output, '1123-1150')
2147 self.assertRegex(output, '3224-3290')
2148 self.assertRegex(output, 'tcp')
2149 self.assertRegex(output, 'lookup 7')
1f0e3109 2150
d586a2c3 2151 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd 2152 def test_routing_policy_rule_invert(self):
ec38833c 2153 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
2cf6fdff 2154 start_networkd()
e2aea43f 2155 self.wait_online(['test1:degraded'])
e40a58b5 2156
371810d1 2157 output = check_output('ip rule')
efecf9cd 2158 print(output)
efecf9cd
SS
2159 self.assertRegex(output, '111')
2160 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
2161 self.assertRegex(output, 'tcp')
2162 self.assertRegex(output, 'lookup 7')
2163
6be8e78e
YW
2164 @expectedFailureIfRoutingPolicyUIDRangeIsNotAvailable()
2165 def test_routing_policy_rule_uidrange(self):
2166 copy_unit_to_networkd_unit_path('25-fibrule-uidrange.network', '11-dummy.netdev')
2167 start_networkd()
2168 self.wait_online(['test1:degraded'])
2169
2170 output = check_output('ip rule')
2171 print(output)
2172 self.assertRegex(output, '111')
2173 self.assertRegex(output, 'from 192.168.100.18')
2174 self.assertRegex(output, 'lookup 7')
2175 self.assertRegex(output, 'uidrange 100-200')
2176
0ef830cf 2177 def test_route_static(self):
ec38833c 2178 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
2cf6fdff 2179 start_networkd()
e2aea43f
YW
2180 self.wait_online(['dummy98:routable'])
2181
fc79e6ff 2182 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
e2aea43f 2183 print(output)
0d34228f 2184
6d60f9db 2185 print('### ip -6 route show dev dummy98')
371810d1 2186 output = check_output('ip -6 route show dev dummy98')
0d34228f 2187 print(output)
0b5dc249
YW
2188 self.assertIn('2001:1234:5:8fff:ff:ff:ff:ff proto static', output)
2189 self.assertIn('2001:1234:5:8f63::1 proto kernel', output)
1f0e3109 2190
d9005dec
YW
2191 print('### ip -6 route show default')
2192 output = check_output('ip -6 route show default')
6d60f9db 2193 print(output)
0b5dc249
YW
2194 self.assertIn('default', output)
2195 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff', output)
1f0e3109 2196
6d60f9db 2197 print('### ip -4 route show dev dummy98')
371810d1 2198 output = check_output('ip -4 route show dev dummy98')
1f0e3109 2199 print(output)
0b5dc249
YW
2200 self.assertIn('149.10.124.48/28 proto kernel scope link src 149.10.124.58', output)
2201 self.assertIn('149.10.124.64 proto static scope link', output)
2202 self.assertIn('169.254.0.0/16 proto static scope link metric 2048', output)
2203 self.assertIn('192.168.1.1 proto static initcwnd 20', output)
2204 self.assertIn('192.168.1.2 proto static initrwnd 30', output)
2205 self.assertIn('192.168.1.3 proto static advmss 30', output)
2206 self.assertIn('multicast 149.10.123.4 proto static', output)
1f0e3109 2207
6d60f9db 2208 print('### ip -4 route show dev dummy98 default')
371810d1 2209 output = check_output('ip -4 route show dev dummy98 default')
6d60f9db 2210 print(output)
0b5dc249
YW
2211 self.assertIn('default via 149.10.125.65 proto static onlink', output)
2212 self.assertIn('default via 149.10.124.64 proto static', output)
2213 self.assertIn('default proto static', output)
1f0e3109 2214
6d60f9db
YW
2215 print('### ip -4 route show table local dev dummy98')
2216 output = check_output('ip -4 route show table local dev dummy98')
2217 print(output)
0b5dc249
YW
2218 self.assertIn('local 149.10.123.1 proto static scope host', output)
2219 self.assertIn('anycast 149.10.123.2 proto static scope link', output)
2220 self.assertIn('broadcast 149.10.123.3 proto static scope link', output)
6d60f9db
YW
2221
2222 print('### ip route show type blackhole')
371810d1 2223 output = check_output('ip route show type blackhole')
1f0e3109 2224 print(output)
0b5dc249 2225 self.assertIn('blackhole 202.54.1.2 proto static', output)
f5050e48 2226
6d60f9db 2227 print('### ip route show type unreachable')
371810d1 2228 output = check_output('ip route show type unreachable')
f5050e48 2229 print(output)
0b5dc249 2230 self.assertIn('unreachable 202.54.1.3 proto static', output)
f5050e48 2231
6d60f9db 2232 print('### ip route show type prohibit')
371810d1 2233 output = check_output('ip route show type prohibit')
f5050e48 2234 print(output)
0b5dc249 2235 self.assertIn('prohibit 202.54.1.4 proto static', output)
f5050e48 2236
452d86a5
YW
2237 print('### ip -6 route show type blackhole')
2238 output = check_output('ip -6 route show type blackhole')
2239 print(output)
2240 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output)
2241
2242 print('### ip -6 route show type unreachable')
2243 output = check_output('ip -6 route show type unreachable')
2244 print(output)
2245 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output)
2246
2247 print('### ip -6 route show type prohibit')
2248 output = check_output('ip -6 route show type prohibit')
2249 print(output)
2250 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
2251
a0ce990e
YW
2252 print('### ip route show 192.168.10.1')
2253 output = check_output('ip route show 192.168.10.1')
2254 print(output)
0b5dc249
YW
2255 self.assertIn('192.168.10.1 proto static', output)
2256 self.assertIn('nexthop via 149.10.124.59 dev dummy98 weight 10', output)
2257 self.assertIn('nexthop via 149.10.124.60 dev dummy98 weight 5', output)
a0ce990e
YW
2258
2259 print('### ip route show 192.168.10.2')
2260 output = check_output('ip route show 192.168.10.2')
2261 print(output)
2262 # old ip command does not show IPv6 gateways...
0b5dc249
YW
2263 self.assertIn('192.168.10.2 proto static', output)
2264 self.assertIn('nexthop', output)
2265 self.assertIn('dev dummy98 weight 10', output)
2266 self.assertIn('dev dummy98 weight 5', output)
a0ce990e
YW
2267
2268 print('### ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2269 output = check_output('ip -6 route show 2001:1234:5:7fff:ff:ff:ff:ff')
2270 print(output)
2271 # old ip command does not show 'nexthop' keyword and weight...
0b5dc249
YW
2272 self.assertIn('2001:1234:5:7fff:ff:ff:ff:ff', output)
2273 self.assertIn('via 2001:1234:5:8fff:ff:ff:ff:ff dev dummy98', output)
2274 self.assertIn('via 2001:1234:5:9fff:ff:ff:ff:ff dev dummy98', output)
a0ce990e 2275
43d4bc9f
YW
2276 copy_unit_to_networkd_unit_path('25-address-static.network')
2277 check_output(*networkctl_cmd, 'reload', env=env)
37b9c79e 2278 time.sleep(1)
43d4bc9f
YW
2279 self.wait_online(['dummy98:routable'])
2280
2281 # check all routes managed by Manager are removed
2282 print('### ip route show type blackhole')
2283 output = check_output('ip route show type blackhole')
2284 print(output)
2285 self.assertEqual(output, '')
2286
2287 print('### ip route show type unreachable')
2288 output = check_output('ip route show type unreachable')
2289 print(output)
2290 self.assertEqual(output, '')
2291
2292 print('### ip route show type prohibit')
2293 output = check_output('ip route show type prohibit')
2294 print(output)
2295 self.assertEqual(output, '')
2296
452d86a5
YW
2297 print('### ip -6 route show type blackhole')
2298 output = check_output('ip -6 route show type blackhole')
2299 print(output)
2300 self.assertEqual(output, '')
2301
2302 print('### ip -6 route show type unreachable')
2303 output = check_output('ip -6 route show type unreachable')
2304 print(output)
2305 self.assertEqual(output, '')
2306
2307 print('### ip -6 route show type prohibit')
2308 output = check_output('ip -6 route show type prohibit')
2309 print(output)
2310 self.assertEqual(output, '')
2311
43d4bc9f
YW
2312 remove_unit_from_networkd_path(['25-address-static.network'])
2313 check_output(*networkctl_cmd, 'reload', env=env)
37b9c79e 2314 time.sleep(1)
43d4bc9f
YW
2315 self.wait_online(['dummy98:routable'])
2316
2317 # check all routes managed by Manager are reconfigured
2318 print('### ip route show type blackhole')
2319 output = check_output('ip route show type blackhole')
2320 print(output)
0b5dc249 2321 self.assertIn('blackhole 202.54.1.2 proto static', output)
43d4bc9f
YW
2322
2323 print('### ip route show type unreachable')
2324 output = check_output('ip route show type unreachable')
2325 print(output)
0b5dc249 2326 self.assertIn('unreachable 202.54.1.3 proto static', output)
43d4bc9f
YW
2327
2328 print('### ip route show type prohibit')
2329 output = check_output('ip route show type prohibit')
2330 print(output)
0b5dc249 2331 self.assertIn('prohibit 202.54.1.4 proto static', output)
43d4bc9f 2332
452d86a5
YW
2333 print('### ip -6 route show type blackhole')
2334 output = check_output('ip -6 route show type blackhole')
2335 print(output)
2336 self.assertIn('blackhole 2001:1234:5678::2 dev lo proto static', output)
2337
2338 print('### ip -6 route show type unreachable')
2339 output = check_output('ip -6 route show type unreachable')
2340 print(output)
2341 self.assertIn('unreachable 2001:1234:5678::3 dev lo proto static', output)
2342
2343 print('### ip -6 route show type prohibit')
2344 output = check_output('ip -6 route show type prohibit')
2345 print(output)
2346 self.assertIn('prohibit 2001:1234:5678::4 dev lo proto static', output)
2347
43d4bc9f
YW
2348 rc = call("ip link del dummy98")
2349 self.assertEqual(rc, 0)
2350 time.sleep(2)
2351
2352 # check all routes managed by Manager are removed
2353 print('### ip route show type blackhole')
2354 output = check_output('ip route show type blackhole')
2355 print(output)
2356 self.assertEqual(output, '')
2357
2358 print('### ip route show type unreachable')
2359 output = check_output('ip route show type unreachable')
2360 print(output)
2361 self.assertEqual(output, '')
2362
2363 print('### ip route show type prohibit')
2364 output = check_output('ip route show type prohibit')
2365 print(output)
2366 self.assertEqual(output, '')
2367
452d86a5
YW
2368 print('### ip -6 route show type blackhole')
2369 output = check_output('ip -6 route show type blackhole')
2370 print(output)
2371 self.assertEqual(output, '')
2372
2373 print('### ip -6 route show type unreachable')
2374 output = check_output('ip -6 route show type unreachable')
2375 print(output)
2376 self.assertEqual(output, '')
2377
2378 print('### ip -6 route show type prohibit')
2379 output = check_output('ip -6 route show type prohibit')
2380 print(output)
2381 self.assertEqual(output, '')
2382
297f9d86
YW
2383 @expectedFailureIfRTA_VIAIsNotSupported()
2384 def test_route_via_ipv6(self):
2385 copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev')
2386 start_networkd()
2387 self.wait_online(['dummy98:routable'])
2388
2389 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
2390 print(output)
2391
2392 print('### ip -6 route show dev dummy98')
2393 output = check_output('ip -6 route show dev dummy98')
2394 print(output)
2395 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
2396 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
2397
2398 print('### ip -4 route show dev dummy98')
2399 output = check_output('ip -4 route show dev dummy98')
2400 print(output)
2401 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
2402 self.assertRegex(output, '149.10.124.66 via inet6 2001:1234:5:8fff:ff:ff:ff:ff proto static')
2403
40afe491
YW
2404 @expectedFailureIfModuleIsNotAvailable('vrf')
2405 def test_route_vrf(self):
2406 copy_unit_to_networkd_unit_path('25-route-vrf.network', '12-dummy.netdev',
2407 '25-vrf.netdev', '25-vrf.network')
2408 start_networkd()
2409 self.wait_online(['dummy98:routable', 'vrf99:carrier'])
2410
2411 output = check_output('ip route show vrf vrf99')
2412 print(output)
2413 self.assertRegex(output, 'default via 192.168.100.1')
2414
2415 output = check_output('ip route show')
2416 print(output)
2417 self.assertNotRegex(output, 'default via 192.168.100.1')
2418
0b1cd3e2
WKI
2419 def test_gateway_reconfigure(self):
2420 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
2421 start_networkd()
2422 self.wait_online(['dummy98:routable'])
2423 print('### ip -4 route show dev dummy98 default')
2424 output = check_output('ip -4 route show dev dummy98 default')
2425 print(output)
2426 self.assertRegex(output, 'default via 149.10.124.59 proto static')
2427 self.assertNotRegex(output, '149.10.124.60')
2428
2429 remove_unit_from_networkd_path(['25-gateway-static.network'])
2430 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
2431 restart_networkd(3)
2432 self.wait_online(['dummy98:routable'])
2433 print('### ip -4 route show dev dummy98 default')
2434 output = check_output('ip -4 route show dev dummy98 default')
2435 print(output)
2436 self.assertNotRegex(output, '149.10.124.59')
2437 self.assertRegex(output, 'default via 149.10.124.60 proto static')
2438
20ca06a6
DA
2439 def test_ip_route_ipv6_src_route(self):
2440 # a dummy device does not make the addresses go through tentative state, so we
2441 # reuse a bond from an earlier test, which does make the addresses go through
2442 # tentative state, and do our test on that
ec38833c 2443 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 2444 start_networkd()
e2aea43f 2445 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
20ca06a6 2446
371810d1 2447 output = check_output('ip -6 route list dev bond199')
20ca06a6
DA
2448 print(output)
2449 self.assertRegex(output, 'abcd::/16')
2450 self.assertRegex(output, 'src')
2451 self.assertRegex(output, '2001:1234:56:8f63::2')
2452
1f0e3109 2453 def test_ip_link_mac_address(self):
ec38833c 2454 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
2cf6fdff 2455 start_networkd()
e2aea43f 2456 self.wait_online(['dummy98:degraded'])
1f0e3109 2457
371810d1 2458 output = check_output('ip link show dummy98')
1f0e3109
SS
2459 print(output)
2460 self.assertRegex(output, '00:01:02:aa:bb:cc')
2461
2462 def test_ip_link_unmanaged(self):
ec38833c 2463 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
df7f9afa 2464 start_networkd(5)
1f0e3109 2465
e39cc445 2466 self.check_link_exists('dummy98')
1f0e3109 2467
19cf3143 2468 self.wait_operstate('dummy98', 'off', setup_state='unmanaged')
1f0e3109
SS
2469
2470 def test_ipv6_address_label(self):
ec38833c 2471 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
2cf6fdff 2472 start_networkd()
e2aea43f 2473 self.wait_online(['dummy98:degraded'])
1f0e3109 2474
371810d1 2475 output = check_output('ip addrlabel list')
1f0e3109
SS
2476 print(output)
2477 self.assertRegex(output, '2004:da8:1::/64')
2478
cff0cadc
YW
2479 def test_ipv6_proxy_ndp(self):
2480 copy_unit_to_networkd_unit_path('25-ipv6-proxy-ndp.network', '12-dummy.netdev')
2481 start_networkd()
2482
2483 self.wait_online(['dummy98:routable'])
2484
2485 output = check_output('ip neighbor show proxy dev dummy98')
2486 print(output)
2487 for i in range(1,5):
2488 self.assertRegex(output, f'2607:5300:203:5215:{i}::1 *proxy')
2489
d86f5c19 2490 def test_neighbor_section(self):
ec38833c 2491 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2cf6fdff 2492 start_networkd()
e2aea43f 2493 self.wait_online(['dummy98:degraded'], timeout='40s')
e4a71bf3 2494
d1bdafd2 2495 print('### ip neigh list dev dummy98')
df7f9afa 2496 output = check_output('ip neigh list dev dummy98')
e4a71bf3
WKI
2497 print(output)
2498 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 2499 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 2500
d1bdafd2
WKI
2501 def test_neighbor_reconfigure(self):
2502 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
2503 start_networkd()
2504 self.wait_online(['dummy98:degraded'], timeout='40s')
2505
2506 print('### ip neigh list dev dummy98')
2507 output = check_output('ip neigh list dev dummy98')
2508 print(output)
2509 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2510 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
2511
2512 remove_unit_from_networkd_path(['25-neighbor-section.network'])
2513 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
2514 restart_networkd(3)
2515 self.wait_online(['dummy98:degraded'], timeout='40s')
2516 print('### ip neigh list dev dummy98')
2517 output = check_output('ip neigh list dev dummy98')
2518 print(output)
2519 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
2520 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
2521 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
2522
74761cf3 2523 def test_neighbor_gre(self):
fb2ba330
YW
2524 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
2525 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
74761cf3 2526 start_networkd()
fb2ba330 2527 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
74761cf3
YW
2528
2529 output = check_output('ip neigh list dev gretun97')
2530 print(output)
2531 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
fb2ba330
YW
2532
2533 output = check_output('ip neigh list dev ip6gretun97')
2534 print(output)
2535 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
74761cf3 2536
05514ae1 2537 def test_link_local_addressing(self):
ec38833c
ZJS
2538 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
2539 '25-link-local-addressing-no.network', '12-dummy.netdev')
2cf6fdff 2540 start_networkd()
e2aea43f 2541 self.wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1 2542
371810d1 2543 output = check_output('ip address show dev test1')
05514ae1
YW
2544 print(output)
2545 self.assertRegex(output, 'inet .* scope link')
2546 self.assertRegex(output, 'inet6 .* scope link')
2547
371810d1 2548 output = check_output('ip address show dev dummy98')
05514ae1
YW
2549 print(output)
2550 self.assertNotRegex(output, 'inet6* .* scope link')
2551
05514ae1
YW
2552 '''
2553 Documentation/networking/ip-sysctl.txt
2554
2555 addr_gen_mode - INTEGER
2556 Defines how link-local and autoconf addresses are generated.
2557
2558 0: generate address based on EUI64 (default)
2559 1: do no generate a link-local address, use EUI64 for addresses generated
2560 from autoconf
2561 2: generate stable privacy addresses, using the secret from
2562 stable_secret (RFC7217)
2563 3: generate stable privacy addresses, using a random secret if unset
2564 '''
2565
2566 test1_addr_gen_mode = ''
2567 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
2568 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
2569 try:
2570 f.readline()
2571 except IOError:
2572 # if stable_secret is unset, then EIO is returned
2573 test1_addr_gen_mode = '0'
2574 else:
2575 test1_addr_gen_mode = '2'
2576 else:
2577 test1_addr_gen_mode = '0'
2578
2579 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
ec38833c 2580 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
05514ae1
YW
2581
2582 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
ec38833c 2583 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
05514ae1 2584
7b3770a7
YW
2585 def test_link_local_addressing_remove_ipv6ll(self):
2586 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
2587 start_networkd()
2588 self.wait_online(['dummy98:degraded'])
2589
2590 output = check_output('ip address show dev dummy98')
2591 print(output)
2592 self.assertRegex(output, 'inet6 .* scope link')
2593
2594 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
2595 restart_networkd(1)
2596 self.wait_online(['dummy98:carrier'])
2597
2598 output = check_output('ip address show dev dummy98')
2599 print(output)
2600 self.assertNotRegex(output, 'inet6* .* scope link')
2601
1f0e3109 2602 def test_sysctl(self):
ec38833c 2603 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
2cf6fdff 2604 start_networkd()
e2aea43f 2605 self.wait_online(['dummy98:degraded'])
ec38833c
ZJS
2606
2607 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
2608 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
2609 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
2610 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
2611 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
2612 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
2613 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
29f69c57 2614 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'accept_local'), '1')
1f0e3109 2615
4da33154 2616 def test_sysctl_disable_ipv6(self):
ec38833c 2617 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
4da33154
YW
2618
2619 print('## Disable ipv6')
cefd6b3d
ZJS
2620 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
2621 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
4da33154 2622
2cf6fdff 2623 start_networkd()
e2aea43f 2624 self.wait_online(['dummy98:routable'])
4da33154 2625
371810d1 2626 output = check_output('ip -4 address show dummy98')
4da33154
YW
2627 print(output)
2628 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2629 output = check_output('ip -6 address show dummy98')
4da33154 2630 print(output)
57ad7607
ZJS
2631 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
2632 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2633 output = check_output('ip -4 route show dev dummy98')
2634 print(output)
3d2c2692 2635 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
d9005dec 2636 output = check_output('ip -6 route show default')
4933b97d 2637 print(output)
d9005dec
YW
2638 self.assertRegex(output, 'default')
2639 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
4da33154 2640
cefd6b3d 2641 check_output('ip link del dummy98')
4da33154
YW
2642
2643 print('## Enable ipv6')
cefd6b3d
ZJS
2644 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
2645 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
4da33154 2646
e2aea43f
YW
2647 restart_networkd(3)
2648 self.wait_online(['dummy98:routable'])
4da33154 2649
371810d1 2650 output = check_output('ip -4 address show dummy98')
4da33154
YW
2651 print(output)
2652 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 2653 output = check_output('ip -6 address show dummy98')
4da33154 2654 print(output)
4933b97d 2655 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
4da33154 2656 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
2657 output = check_output('ip -4 route show dev dummy98')
2658 print(output)
3d2c2692 2659 self.assertRegex(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
d9005dec 2660 output = check_output('ip -6 route show default')
4933b97d 2661 print(output)
d9005dec 2662 self.assertRegex(output, 'via 2607:5300:203:39ff:ff:ff:ff:ff')
4da33154 2663
cd65d067 2664 def test_bind_carrier(self):
bc942f69
YW
2665 check_output('ip link add dummy98 type dummy')
2666 check_output('ip link set dummy98 up')
2667 time.sleep(2)
2668
ec38833c 2669 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
2cf6fdff 2670 start_networkd()
e2aea43f 2671 self.wait_online(['test1:routable'])
cd65d067 2672
371810d1 2673 output = check_output('ip address show test1')
cd65d067
YW
2674 print(output)
2675 self.assertRegex(output, 'UP,LOWER_UP')
2676 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2677 self.wait_operstate('test1', 'routable')
cd65d067 2678
cefd6b3d
ZJS
2679 check_output('ip link add dummy99 type dummy')
2680 check_output('ip link set dummy99 up')
b117044c 2681 time.sleep(2)
371810d1 2682 output = check_output('ip address show test1')
cd65d067
YW
2683 print(output)
2684 self.assertRegex(output, 'UP,LOWER_UP')
2685 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2686 self.wait_operstate('test1', 'routable')
cd65d067 2687
cefd6b3d 2688 check_output('ip link del dummy98')
b117044c 2689 time.sleep(2)
371810d1 2690 output = check_output('ip address show test1')
cd65d067
YW
2691 print(output)
2692 self.assertRegex(output, 'UP,LOWER_UP')
2693 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2694 self.wait_operstate('test1', 'routable')
cd65d067 2695
bc942f69 2696 check_output('ip link set dummy99 down')
b117044c 2697 time.sleep(2)
371810d1 2698 output = check_output('ip address show test1')
cd65d067
YW
2699 print(output)
2700 self.assertNotRegex(output, 'UP,LOWER_UP')
2701 self.assertRegex(output, 'DOWN')
2702 self.assertNotRegex(output, '192.168.10')
19cf3143 2703 self.wait_operstate('test1', 'off')
cd65d067 2704
bc942f69 2705 check_output('ip link set dummy99 up')
b117044c 2706 time.sleep(2)
371810d1 2707 output = check_output('ip address show test1')
cd65d067
YW
2708 print(output)
2709 self.assertRegex(output, 'UP,LOWER_UP')
2710 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
19cf3143 2711 self.wait_operstate('test1', 'routable')
cd65d067 2712
2236d75d
DS
2713 def _test_activation_policy(self, test):
2714 self.setUp()
2715 conffile = '25-activation-policy.network'
2716 if test:
2717 conffile = f'{conffile}.d/{test}.conf'
2718 copy_unit_to_networkd_unit_path('11-dummy.netdev', conffile, dropins=False)
2719 start_networkd()
2720
2721 always = test.startswith('always')
2722 if test == 'manual':
2723 initial_up = 'UP' in check_output('ip link show test1')
2724 else:
2725 initial_up = not test.endswith('down') # note: default is up
2726 expect_up = initial_up
2727 next_up = not expect_up
2728
2729 # if initial expected state is down, must wait for setup_state to reach configuring
2730 # so systemd-networkd considers it 'activated'
2731 setup_state = None if initial_up else 'configuring'
2732
2733 for iteration in range(4):
2734 with self.subTest(iteration=iteration, expect_up=expect_up):
2735 operstate = 'routable' if expect_up else 'off'
2736 self.wait_operstate('test1', operstate, setup_state=setup_state, setup_timeout=20)
2737 setup_state = None
2738
2739 if expect_up:
2740 self.assertIn('UP', check_output('ip link show test1'))
2741 self.assertIn('192.168.10.30/24', check_output('ip address show test1'))
2742 self.assertIn('default via 192.168.10.1', check_output('ip route show'))
2743 else:
2744 self.assertIn('DOWN', check_output('ip link show test1'))
2745
2746 if next_up:
2747 check_output('ip link set dev test1 up')
2748 else:
2749 check_output('ip link set dev test1 down')
2750 expect_up = initial_up if always else next_up
2751 next_up = not next_up
2752
2753 self.tearDown()
2754
2755 def test_activation_policy(self):
2756 for test in ['up', 'always-up', 'manual', 'always-down', 'down', '']:
2757 with self.subTest(test=test):
2758 self._test_activation_policy(test)
2759
fdcd1ec5 2760 def test_domain(self):
ec38833c 2761 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2cf6fdff 2762 start_networkd()
e2aea43f 2763 self.wait_online(['dummy98:routable'])
fdcd1ec5 2764
fc79e6ff 2765 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'dummy98', env=env)
fdcd1ec5
YW
2766 print(output)
2767 self.assertRegex(output, 'Address: 192.168.42.100')
2768 self.assertRegex(output, 'DNS: 192.168.42.1')
2769 self.assertRegex(output, 'Search Domains: one')
2770
1e498853 2771 def test_keep_configuration_static(self):
3aa645f0
MB
2772 check_output('systemctl stop systemd-networkd.socket')
2773 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
2774
2775 check_output('ip link add name dummy98 type dummy')
2776 check_output('ip address add 10.1.2.3/16 dev dummy98')
2777 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2778 output = check_output('ip address show dummy98')
2779 print(output)
2780 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2781 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2782 output = check_output('ip route show dev dummy98')
2783 print(output)
2784
2785 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2cf6fdff 2786 start_networkd()
e2aea43f 2787 self.wait_online(['dummy98:routable'])
1e498853
YW
2788
2789 output = check_output('ip address show dummy98')
2790 print(output)
2791 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2792 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2793
086bcf5d
YW
2794 @expectedFailureIfNexthopIsNotAvailable()
2795 def test_nexthop(self):
2796 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2797 start_networkd()
2798 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2799
2800 output = check_output('ip nexthop list dev veth99')
2801 print(output)
6cd8f9b5
YW
2802 self.assertIn('id 1 via 192.168.5.1 dev veth99', output)
2803 self.assertIn('id 2 via 2001:1234:5:8f63::2 dev veth99', output)
2804 self.assertIn('id 3 dev veth99', output)
2805 self.assertIn('id 4 dev veth99', output)
2806 self.assertRegex(output, r'id [0-9]* via 192.168.5.2 dev veth99')
086bcf5d 2807
ef3c8a92 2808 def test_qdisc(self):
f1de1eb3
YW
2809 copy_unit_to_networkd_unit_path('25-qdisc-clsact-and-htb.network', '12-dummy.netdev',
2810 '25-qdisc-ingress-netem-compat.network', '11-dummy.netdev')
2811 check_output('modprobe sch_teql max_equalizers=2')
ef3c8a92
YW
2812 start_networkd()
2813
1b628c4f 2814 self.wait_online(['dummy98:routable', 'test1:routable'])
ef3c8a92 2815
f1de1eb3
YW
2816 output = check_output('tc qdisc show dev test1')
2817 print(output)
2818 self.assertRegex(output, 'qdisc netem')
7887e580 2819 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
f1de1eb3
YW
2820 self.assertRegex(output, 'qdisc ingress')
2821
ef3c8a92
YW
2822 output = check_output('tc qdisc show dev dummy98')
2823 print(output)
f1de1eb3
YW
2824 self.assertRegex(output, 'qdisc clsact')
2825
2826 self.assertRegex(output, 'qdisc htb 2: root')
2827 self.assertRegex(output, r'default (0x30|30)')
2828
2829 self.assertRegex(output, 'qdisc netem 30: parent 2:30')
7887e580 2830 self.assertRegex(output, 'limit 100 delay 50(.0)?ms 10(.0)?ms loss 20%')
40821c2a 2831 self.assertRegex(output, 'qdisc fq_codel')
7887e580 2832 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 2833
f1de1eb3 2834 self.assertRegex(output, 'qdisc teql1 31: parent 2:31')
0baddbd5 2835
f1de1eb3 2836 self.assertRegex(output, 'qdisc fq 32: parent 2:32')
a05a6e8b
YW
2837 self.assertRegex(output, 'limit 1000p flow_limit 200p buckets 512 orphan_mask 511')
2838 self.assertRegex(output, 'quantum 1500')
2839 self.assertRegex(output, 'initial_quantum 13000')
2840 self.assertRegex(output, 'maxrate 1Mbit')
ab9dc1db 2841
f1de1eb3 2842 self.assertRegex(output, 'qdisc codel 33: parent 2:33')
7887e580 2843 self.assertRegex(output, 'limit 2000p target 10(.0)?ms ce_threshold 100(.0)?ms interval 50(.0)?ms ecn')
ab9dc1db 2844
f1de1eb3 2845 self.assertRegex(output, 'qdisc fq_codel 34: parent 2:34')
7887e580 2846 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 2847
f1de1eb3 2848 self.assertRegex(output, 'qdisc tbf 35: parent 2:35')
7887e580 2849 self.assertRegex(output, 'rate 1Gbit burst 5000b peakrate 100Gbit minburst 987500b lat 70(.0)?ms')
ab9dc1db 2850
f1de1eb3
YW
2851 self.assertRegex(output, 'qdisc sfq 36: parent 2:36')
2852 self.assertRegex(output, 'perturb 5sec')
3d55b5a9 2853
bc0769c9
YW
2854 self.assertRegex(output, 'qdisc pfifo 37: parent 2:37')
2855 self.assertRegex(output, 'limit 100000p')
2856
95edcf3f
YW
2857 self.assertRegex(output, 'qdisc gred 38: parent 2:38')
2858 self.assertRegex(output, 'vqs 12 default 10 grio')
2859
f2c5c129
YW
2860 self.assertRegex(output, 'qdisc sfb 39: parent 2:39')
2861 self.assertRegex(output, 'limit 200000')
2862
7b1a31a3
YW
2863 self.assertRegex(output, 'qdisc bfifo 3a: parent 2:3a')
2864 self.assertRegex(output, 'limit 1000000')
2865
73136507
YW
2866 self.assertRegex(output, 'qdisc pfifo_head_drop 3b: parent 2:3b')
2867 self.assertRegex(output, 'limit 1023p')
2868
41bb371b
YW
2869 self.assertRegex(output, 'qdisc pfifo_fast 3c: parent 2:3c')
2870
2ee7e54b 2871 output = check_output('tc -d class show dev dummy98')
ab9dc1db 2872 print(output)
f1de1eb3
YW
2873 self.assertRegex(output, 'class htb 2:30 root leaf 30:')
2874 self.assertRegex(output, 'class htb 2:31 root leaf 31:')
2875 self.assertRegex(output, 'class htb 2:32 root leaf 32:')
2876 self.assertRegex(output, 'class htb 2:33 root leaf 33:')
2877 self.assertRegex(output, 'class htb 2:34 root leaf 34:')
2878 self.assertRegex(output, 'class htb 2:35 root leaf 35:')
2879 self.assertRegex(output, 'class htb 2:36 root leaf 36:')
bc0769c9 2880 self.assertRegex(output, 'class htb 2:37 root leaf 37:')
95edcf3f 2881 self.assertRegex(output, 'class htb 2:38 root leaf 38:')
f2c5c129 2882 self.assertRegex(output, 'class htb 2:39 root leaf 39:')
7b1a31a3 2883 self.assertRegex(output, 'class htb 2:3a root leaf 3a:')
73136507 2884 self.assertRegex(output, 'class htb 2:3b root leaf 3b:')
41bb371b 2885 self.assertRegex(output, 'class htb 2:3c root leaf 3c:')
2ee7e54b
YW
2886 self.assertRegex(output, 'prio 1 quantum 4000 rate 1Mbit overhead 100 ceil 500Kbit')
2887 self.assertRegex(output, 'burst 123456')
2888 self.assertRegex(output, 'cburst 123457')
0baddbd5 2889
557fa421 2890 def test_qdisc2(self):
891ff963
YW
2891 copy_unit_to_networkd_unit_path('25-qdisc-drr.network', '12-dummy.netdev',
2892 '25-qdisc-qfq.network', '11-dummy.netdev')
557fa421
YW
2893 start_networkd()
2894
891ff963 2895 self.wait_online(['dummy98:routable', 'test1:routable'])
557fa421
YW
2896
2897 output = check_output('tc qdisc show dev dummy98')
2898 print(output)
2899 self.assertRegex(output, 'qdisc drr 2: root')
2900 output = check_output('tc class show dev dummy98')
2901 print(output)
2902 self.assertRegex(output, 'class drr 2:30 root quantum 2000b')
2903
891ff963
YW
2904 output = check_output('tc qdisc show dev test1')
2905 print(output)
2906 self.assertRegex(output, 'qdisc qfq 2: root')
2907 output = check_output('tc class show dev test1')
2908 print(output)
2909 self.assertRegex(output, 'class qfq 2:30 root weight 2 maxpkt 16000')
2910 self.assertRegex(output, 'class qfq 2:31 root weight 10 maxpkt 8000')
2911
f6c6af38
YW
2912 @expectedFailureIfCAKEIsNotAvailable()
2913 def test_qdisc_cake(self):
2914 copy_unit_to_networkd_unit_path('25-qdisc-cake.network', '12-dummy.netdev')
3d55b5a9 2915 start_networkd()
3d55b5a9
YW
2916 self.wait_online(['dummy98:routable'])
2917
2918 output = check_output('tc qdisc show dev dummy98')
2919 print(output)
f6c6af38
YW
2920 self.assertRegex(output, 'qdisc cake 3a: root')
2921 self.assertRegex(output, 'bandwidth 500Mbit')
2922 self.assertRegex(output, 'overhead 128')
3d55b5a9 2923
be94e591
YW
2924 @expectedFailureIfPIEIsNotAvailable()
2925 def test_qdisc_pie(self):
2926 copy_unit_to_networkd_unit_path('25-qdisc-pie.network', '12-dummy.netdev')
2927 start_networkd()
2928 self.wait_online(['dummy98:routable'])
2929
2930 output = check_output('tc qdisc show dev dummy98')
2931 print(output)
2932 self.assertRegex(output, 'qdisc pie 3a: root')
2933 self.assertRegex(output, 'limit 200000')
2934
970ab1fc
YW
2935 @expectedFailureIfHHFIsNotAvailable()
2936 def test_qdisc_hhf(self):
2937 copy_unit_to_networkd_unit_path('25-qdisc-hhf.network', '12-dummy.netdev')
2938 start_networkd()
2939 self.wait_online(['dummy98:routable'])
2940
2941 output = check_output('tc qdisc show dev dummy98')
2942 print(output)
2943 self.assertRegex(output, 'qdisc hhf 3a: root')
2944 self.assertRegex(output, 'limit 1022p')
2945
b753e835
YW
2946 @expectedFailureIfETSIsNotAvailable()
2947 def test_qdisc_ets(self):
2948 copy_unit_to_networkd_unit_path('25-qdisc-ets.network', '12-dummy.netdev')
2949 start_networkd()
2950 self.wait_online(['dummy98:routable'])
2951
2952 output = check_output('tc qdisc show dev dummy98')
2953 print(output)
1578266b 2954
b753e835
YW
2955 self.assertRegex(output, 'qdisc ets 3a: root')
2956 self.assertRegex(output, 'bands 10 strict 3')
2957 self.assertRegex(output, 'quanta 1 2 3 4 5')
2958 self.assertRegex(output, 'priomap 3 4 5 6 7')
2959
1578266b
YW
2960 @expectedFailureIfFQPIEIsNotAvailable()
2961 def test_qdisc_fq_pie(self):
2962 copy_unit_to_networkd_unit_path('25-qdisc-fq_pie.network', '12-dummy.netdev')
2963 start_networkd()
2964 self.wait_online(['dummy98:routable'])
2965
2966 output = check_output('tc qdisc show dev dummy98')
2967 print(output)
2968
2969 self.assertRegex(output, 'qdisc fq_pie 3a: root')
2970 self.assertRegex(output, 'limit 200000p')
2971
3d2c2692
YW
2972 @expectedFailureIfNetdevsimWithSRIOVIsNotAvailable()
2973 def test_sriov(self):
2974 call('rmmod netdevsim', stderr=subprocess.DEVNULL)
2975 call('modprobe netdevsim', stderr=subprocess.DEVNULL)
2976 with open('/sys/bus/netdevsim/new_device', mode='w') as f:
2977 f.write('99 1')
2978
2979 call('udevadm settle')
2980 call('udevadm info -w10s /sys/devices/netdevsim99/net/eni99np1', stderr=subprocess.DEVNULL)
2981 with open('/sys/class/net/eni99np1/device/sriov_numvfs', mode='w') as f:
2982 f.write('3')
2983
2984 copy_unit_to_networkd_unit_path('25-sriov.network')
2985 start_networkd()
2986 self.wait_online(['eni99np1:routable'])
2987
2988 output = check_output('ip link show dev eni99np1')
2989 print(output)
2990 self.assertRegex(output,
2991 '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 *'
2992 'vf 1 .*00:11:22:33:44:56.*vlan 6, qos 2, spoof checking off, link-state disable, trust off, query_rss off\n *'
2993 'vf 2 .*00:11:22:33:44:57.*vlan 7, qos 3, spoof checking off, link-state auto, trust off, query_rss off'
2994 )
2995
2996 call('rmmod netdevsim', stderr=subprocess.DEVNULL)
2997
336d18f0
YW
2998class NetworkdStateFileTests(unittest.TestCase, Utilities):
2999 links = [
3000 'dummy98',
3001 ]
3002
3003 units = [
3004 '12-dummy.netdev',
3005 'state-file-tests.network',
3006 ]
3007
3008 def setUp(self):
3009 remove_links(self.links)
3010 stop_networkd(show_logs=False)
3011
3012 def tearDown(self):
3013 remove_links(self.links)
3014 remove_unit_from_networkd_path(self.units)
3015 stop_networkd(show_logs=True)
3016
3017 def test_state_file(self):
3018 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
3019 start_networkd()
3020 self.wait_online(['dummy98:routable'])
3021
3022 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
3023 print(output)
3024 ifindex = output.split()[0]
3025
3026 path = os.path.join('/run/systemd/netif/links/', ifindex)
3027 self.assertTrue(os.path.exists(path))
f91b2340
YW
3028
3029 # make link state file updated
3030 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
336d18f0
YW
3031
3032 with open(path) as f:
3033 data = f.read()
3034 self.assertRegex(data, r'ADMIN_STATE=configured')
3035 self.assertRegex(data, r'OPER_STATE=routable')
3036 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
3037 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
a853652a 3038 self.assertRegex(data, r'ACTIVATION_POLICY=up')
336d18f0 3039 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
66479677 3040 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
3041 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
3042 self.assertRegex(data, r'DOMAINS=hogehoge')
3043 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
3044 self.assertRegex(data, r'LLMNR=no')
3045 self.assertRegex(data, r'MDNS=yes')
3046 self.assertRegex(data, r'DNSSEC=no')
336d18f0 3047
66479677 3048 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12#ccc.com', '10.10.10.13', '1111:2222::3333', env=env)
336d18f0
YW
3049 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
3050 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
3051 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
3052 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
3053 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
336d18f0
YW
3054
3055 with open(path) as f:
3056 data = f.read()
66479677 3057 self.assertRegex(data, r'DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333')
336d18f0
YW
3058 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
3059 self.assertRegex(data, r'DOMAINS=hogehogehoge')
3060 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
3061 self.assertRegex(data, r'LLMNR=yes')
3062 self.assertRegex(data, r'MDNS=no')
3063 self.assertRegex(data, r'DNSSEC=yes')
3064
3065 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
336d18f0
YW
3066
3067 with open(path) as f:
3068 data = f.read()
66479677 3069 self.assertRegex(data, r'DNS=10.10.10.12#ccc.com 10.10.10.13 1111:2222::3333')
336d18f0
YW
3070 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
3071 self.assertRegex(data, r'DOMAINS=hogehogehoge')
3072 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
3073 self.assertRegex(data, r'LLMNR=yes')
3074 self.assertRegex(data, r'MDNS=no')
3075 self.assertRegex(data, r'DNSSEC=yes')
3076
3077 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
336d18f0
YW
3078
3079 with open(path) as f:
3080 data = f.read()
66479677 3081 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
3082 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
3083 self.assertRegex(data, r'DOMAINS=hogehoge')
3084 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
3085 self.assertRegex(data, r'LLMNR=no')
3086 self.assertRegex(data, r'MDNS=yes')
3087 self.assertRegex(data, r'DNSSEC=no')
3088
be68c2c9 3089class NetworkdBondTests(unittest.TestCase, Utilities):
c3a8853f 3090 links = [
c2990ec3 3091 'bond199',
c3a8853f 3092 'bond99',
cc3e488c
YW
3093 'dummy98',
3094 'test1']
c3a8853f
YW
3095
3096 units = [
cc3e488c
YW
3097 '11-dummy.netdev',
3098 '12-dummy.netdev',
c2990ec3
YW
3099 '23-active-slave.network',
3100 '23-bond199.network',
3101 '23-primary-slave.network',
c2990ec3 3102 '25-bond-active-backup-slave.netdev',
c3a8853f 3103 '25-bond.netdev',
c3a8853f 3104 'bond99.network',
cc3e488c 3105 'bond-slave.network']
c3a8853f
YW
3106
3107 def setUp(self):
ec38833c 3108 remove_links(self.links)
aaae5713 3109 stop_networkd(show_logs=False)
c3a8853f
YW
3110
3111 def tearDown(self):
ec38833c
ZJS
3112 remove_links(self.links)
3113 remove_unit_from_networkd_path(self.units)
aaae5713 3114 stop_networkd(show_logs=True)
c3a8853f 3115
c2990ec3 3116 def test_bond_active_slave(self):
ec38833c 3117 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 3118 start_networkd()
e2aea43f 3119 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 3120
371810d1 3121 output = check_output('ip -d link show bond199')
c2990ec3
YW
3122 print(output)
3123 self.assertRegex(output, 'active_slave dummy98')
3124
3125 def test_bond_primary_slave(self):
35a78c51 3126 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2cf6fdff 3127 start_networkd()
e2aea43f 3128 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
c2990ec3 3129
371810d1 3130 output = check_output('ip -d link show bond199')
c2990ec3 3131 print(output)
35a78c51 3132 self.assertRegex(output, 'primary dummy98')
c2990ec3 3133
cc3e488c 3134 def test_bond_operstate(self):
ec38833c
ZJS
3135 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
3136 'bond99.network','bond-slave.network')
2cf6fdff 3137 start_networkd()
e2aea43f 3138 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
c3a8853f 3139
371810d1 3140 output = check_output('ip -d link show dummy98')
c3a8853f 3141 print(output)
cc3e488c 3142 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 3143
371810d1 3144 output = check_output('ip -d link show test1')
c3a8853f
YW
3145 print(output)
3146 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
3147
371810d1 3148 output = check_output('ip -d link show bond99')
c3a8853f
YW
3149 print(output)
3150 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
3151
19cf3143
DS
3152 self.wait_operstate('dummy98', 'enslaved')
3153 self.wait_operstate('test1', 'enslaved')
3154 self.wait_operstate('bond99', 'routable')
c3a8853f 3155
cefd6b3d 3156 check_output('ip link set dummy98 down')
c3a8853f 3157
19cf3143
DS
3158 self.wait_operstate('dummy98', 'off')
3159 self.wait_operstate('test1', 'enslaved')
3160 self.wait_operstate('bond99', 'degraded-carrier')
c3a8853f 3161
cefd6b3d 3162 check_output('ip link set dummy98 up')
c3a8853f 3163
19cf3143
DS
3164 self.wait_operstate('dummy98', 'enslaved')
3165 self.wait_operstate('test1', 'enslaved')
3166 self.wait_operstate('bond99', 'routable')
c3a8853f 3167
cefd6b3d
ZJS
3168 check_output('ip link set dummy98 down')
3169 check_output('ip link set test1 down')
cc3e488c 3170
19cf3143
DS
3171 self.wait_operstate('dummy98', 'off')
3172 self.wait_operstate('test1', 'off')
2700d2c7 3173
a4632dc7 3174 if not self.wait_operstate('bond99', 'no-carrier', setup_timeout=30, fail_assert=False):
2700d2c7
YW
3175 # Huh? Kernel does not recognize that all slave interfaces are down?
3176 # Let's confirm that networkd's operstate is consistent with ip's result.
3177 self.assertNotRegex(output, 'NO-CARRIER')
cc3e488c 3178
be68c2c9 3179class NetworkdBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
3180 links = [
3181 'bridge99',
3182 'dummy98',
3183 'test1']
3184
3185 units = [
3186 '11-dummy.netdev',
3187 '12-dummy.netdev',
3188 '26-bridge.netdev',
0fc0d85f 3189 '26-bridge-configure-without-carrier.network',
cc0276cc
YW
3190 '26-bridge-mdb-master.network',
3191 '26-bridge-mdb-slave.network',
09ea6724
YW
3192 '26-bridge-slave-interface-1.network',
3193 '26-bridge-slave-interface-2.network',
6f943798
YW
3194 '26-bridge-vlan-master.network',
3195 '26-bridge-vlan-slave.network',
804b6cd2 3196 'bridge99-ignore-carrier-loss.network',
09ea6724 3197 'bridge99.network']
1f0e3109 3198
8d17c386
YW
3199 routing_policy_rule_tables = ['100']
3200
1f0e3109 3201 def setUp(self):
8d17c386 3202 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c 3203 remove_links(self.links)
aaae5713 3204 stop_networkd(show_logs=False)
1f0e3109
SS
3205
3206 def tearDown(self):
8d17c386 3207 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
ec38833c
ZJS
3208 remove_links(self.links)
3209 remove_unit_from_networkd_path(self.units)
aaae5713 3210 stop_networkd(show_logs=True)
1f0e3109 3211
6f943798
YW
3212 def test_bridge_vlan(self):
3213 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
3214 '26-bridge.netdev', '26-bridge-vlan-master.network')
3215 start_networkd()
e2aea43f 3216 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
6f943798
YW
3217
3218 output = check_output('bridge vlan show dev test1')
3219 print(output)
3220 self.assertNotRegex(output, '4063')
3221 for i in range(4064, 4095):
3222 self.assertRegex(output, f'{i}')
3223 self.assertNotRegex(output, '4095')
3224
3225 output = check_output('bridge vlan show dev bridge99')
3226 print(output)
3227 self.assertNotRegex(output, '4059')
3228 for i in range(4060, 4095):
3229 self.assertRegex(output, f'{i}')
3230 self.assertNotRegex(output, '4095')
3231
cc0276cc
YW
3232 def test_bridge_mdb(self):
3233 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-mdb-slave.network',
3234 '26-bridge.netdev', '26-bridge-mdb-master.network')
3235 start_networkd()
3236 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
3237
3238 output = check_output('bridge mdb show dev bridge99')
3239 print(output)
3240 self.assertRegex(output, 'dev bridge99 port test1 grp ff02:aaaa:fee5::1:3 permanent *vid 4064')
3241 self.assertRegex(output, 'dev bridge99 port test1 grp 224.0.1.1 permanent *vid 4065')
3242
9f773037
YW
3243 # Old kernel may not support bridge MDB entries on bridge master
3244 if call('bridge mdb add dev bridge99 port bridge99 grp 224.0.1.3 temp vid 4068', stderr=subprocess.DEVNULL) == 0:
3245 self.assertRegex(output, 'dev bridge99 port bridge99 grp ff02:aaaa:fee5::1:4 temp *vid 4066')
3246 self.assertRegex(output, 'dev bridge99 port bridge99 grp 224.0.1.2 temp *vid 4067')
3247
1f0e3109 3248 def test_bridge_property(self):
ec38833c
ZJS
3249 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
3250 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
3251 'bridge99.network')
2cf6fdff 3252 start_networkd()
e2aea43f 3253 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
1f0e3109 3254
371810d1 3255 output = check_output('ip -d link show test1')
1f0e3109
SS
3256 print(output)
3257 self.assertRegex(output, 'master')
3258 self.assertRegex(output, 'bridge')
3259
371810d1 3260 output = check_output('ip -d link show dummy98')
1f0e3109
SS
3261 print(output)
3262 self.assertRegex(output, 'master')
3263 self.assertRegex(output, 'bridge')
3264
371810d1 3265 output = check_output('ip addr show bridge99')
1f0e3109 3266 print(output)
2be6c5d2 3267 self.assertRegex(output, '192.168.0.15/24')
1f0e3109 3268
371810d1 3269 output = check_output('bridge -d link show dummy98')
1f0e3109 3270 print(output)
ec38833c 3271 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
5424fd95
YW
3272 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
3273 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
ec38833c
ZJS
3274 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
3275 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
5424fd95
YW
3276 # CONFIG_BRIDGE_IGMP_SNOOPING=y
3277 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
3278 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
7f15b714 3279 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
ec38833c
ZJS
3280 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
3281 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
5424fd95
YW
3282 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
3283 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
3284 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
4d7ed14f 3285
5424fd95
YW
3286 output = check_output('bridge -d link show test1')
3287 print(output)
3288 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
1f0e3109 3289
371810d1 3290 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
3291 time.sleep(1)
3292
371810d1 3293 output = check_output('ip addr show bridge99')
2be6c5d2
YW
3294 print(output)
3295 self.assertRegex(output, '192.168.0.16/24')
3296
e3cbaeab
YW
3297 # for issue #6088
3298 print('### ip -6 route list table all dev bridge99')
3299 output = check_output('ip -6 route list table all dev bridge99')
3300 print(output)
beb75dd3 3301 self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
e3cbaeab 3302
371810d1 3303 self.assertEqual(call('ip link del test1'), 0)
2be6c5d2 3304
19cf3143 3305 self.wait_operstate('bridge99', 'degraded-carrier')
2be6c5d2 3306
cefd6b3d 3307 check_output('ip link del dummy98')
804b6cd2 3308
19cf3143 3309 self.wait_operstate('bridge99', 'no-carrier')
2be6c5d2 3310
371810d1 3311 output = check_output('ip address show bridge99')
804b6cd2
YW
3312 print(output)
3313 self.assertRegex(output, 'NO-CARRIER')
3314 self.assertNotRegex(output, '192.168.0.15/24')
3315 self.assertNotRegex(output, '192.168.0.16/24')
3316
e3cbaeab
YW
3317 print('### ip -6 route list table all dev bridge99')
3318 output = check_output('ip -6 route list table all dev bridge99')
3319 print(output)
beb75dd3 3320 self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium')
e3cbaeab 3321
0fc0d85f
DS
3322 def test_bridge_configure_without_carrier(self):
3323 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-configure-without-carrier.network',
3324 '11-dummy.netdev')
3325 start_networkd()
3326
3327 # With ConfigureWithoutCarrier=yes, the bridge should remain configured for all these situations
3328 for test in ['no-slave', 'add-slave', 'slave-up', 'slave-no-carrier', 'slave-carrier', 'slave-down']:
3329 with self.subTest(test=test):
3330 if test == 'no-slave':
3331 # bridge has no slaves; it's up but *might* not have carrier
001c07cf 3332 self.wait_operstate('bridge99', operstate=r'(no-carrier|routable)', setup_state=None, setup_timeout=30)
0fc0d85f
DS
3333 # due to a bug in the kernel, newly-created bridges are brought up
3334 # *with* carrier, unless they have had any setting changed; e.g.
3335 # their mac set, priority set, etc. Then, they will lose carrier
3336 # as soon as a (down) slave interface is added, and regain carrier
3337 # again once the slave interface is brought up.
3338 #self.check_link_attr('bridge99', 'carrier', '0')
3339 elif test == 'add-slave':
3340 # add slave to bridge, but leave it down; bridge is definitely no-carrier
3341 self.check_link_attr('test1', 'operstate', 'down')
3342 check_output('ip link set dev test1 master bridge99')
001c07cf 3343 self.wait_operstate('bridge99', operstate='no-carrier', setup_state=None)
0fc0d85f
DS
3344 self.check_link_attr('bridge99', 'carrier', '0')
3345 elif test == 'slave-up':
3346 # bring up slave, which will have carrier; bridge gains carrier
3347 check_output('ip link set dev test1 up')
3348 self.wait_online(['bridge99:routable'])
3349 self.check_link_attr('bridge99', 'carrier', '1')
3350 elif test == 'slave-no-carrier':
3351 # drop slave carrier; bridge loses carrier
3352 check_output('ip link set dev test1 carrier off')
3353 self.wait_online(['bridge99:no-carrier:no-carrier'])
3354 self.check_link_attr('bridge99', 'carrier', '0')
3355 elif test == 'slave-carrier':
3356 # restore slave carrier; bridge gains carrier
3357 check_output('ip link set dev test1 carrier on')
3358 self.wait_online(['bridge99:routable'])
3359 self.check_link_attr('bridge99', 'carrier', '1')
3360 elif test == 'slave-down':
3361 # bring down slave; bridge loses carrier
3362 check_output('ip link set dev test1 down')
3363 self.wait_online(['bridge99:no-carrier:no-carrier'])
3364 self.check_link_attr('bridge99', 'carrier', '0')
3365
3366 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
0fc0d85f
DS
3367 self.assertRegex(output, '10.1.2.3')
3368 self.assertRegex(output, '10.1.2.1')
3369
804b6cd2 3370 def test_bridge_ignore_carrier_loss(self):
ec38833c
ZJS
3371 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
3372 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
3373 'bridge99-ignore-carrier-loss.network')
2cf6fdff 3374 start_networkd()
e2aea43f 3375 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
804b6cd2 3376
371810d1 3377 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
3378 time.sleep(1)
3379
371810d1
ZJS
3380 check_output('ip link del test1')
3381 check_output('ip link del dummy98')
804b6cd2
YW
3382 time.sleep(3)
3383
371810d1 3384 output = check_output('ip address show bridge99')
804b6cd2
YW
3385 print(output)
3386 self.assertRegex(output, 'NO-CARRIER')
3387 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
3388 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
3389
6609924c 3390 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
ec38833c
ZJS
3391 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
3392 'bridge99-ignore-carrier-loss.network')
2cf6fdff 3393 start_networkd()
e2aea43f 3394 self.wait_online(['bridge99:no-carrier'])
6609924c 3395
90e3bcbd
YW
3396 for trial in range(4):
3397 check_output('ip link add dummy98 type dummy')
3398 check_output('ip link set dummy98 up')
3399 if trial < 3:
3400 check_output('ip link del dummy98')
6609924c 3401
e2aea43f 3402 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
6609924c 3403
371810d1 3404 output = check_output('ip address show bridge99')
6609924c
YW
3405 print(output)
3406 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
3407
371810d1 3408 output = check_output('ip rule list table 100')
6609924c 3409 print(output)
1e5fd321 3410 self.assertIn('0: from all to 8.8.8.8 lookup 100', output)
6609924c 3411
be68c2c9 3412class NetworkdLLDPTests(unittest.TestCase, Utilities):
1f0e3109
SS
3413 links = ['veth99']
3414
09ea6724
YW
3415 units = [
3416 '23-emit-lldp.network',
3417 '24-lldp.network',
3418 '25-veth.netdev']
1f0e3109
SS
3419
3420 def setUp(self):
ec38833c 3421 remove_links(self.links)
aaae5713 3422 stop_networkd(show_logs=False)
1f0e3109
SS
3423
3424 def tearDown(self):
ec38833c
ZJS
3425 remove_links(self.links)
3426 remove_unit_from_networkd_path(self.units)
aaae5713 3427 stop_networkd(show_logs=True)
1f0e3109
SS
3428
3429 def test_lldp(self):
ec38833c 3430 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2cf6fdff 3431 start_networkd()
e2aea43f 3432 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1f0e3109 3433
f0d87798
YW
3434 for trial in range(10):
3435 if trial > 0:
3436 time.sleep(1)
3437
3438 output = check_output(*networkctl_cmd, 'lldp', env=env)
3439 print(output)
3440 if re.search(r'veth99 .* veth-peer', output):
3441 break
3442 else:
3443 self.fail()
1f0e3109 3444
be68c2c9 3445class NetworkdRATests(unittest.TestCase, Utilities):
1f0e3109
SS
3446 links = ['veth99']
3447
09ea6724
YW
3448 units = [
3449 '25-veth.netdev',
3450 'ipv6-prefix.network',
87bbebea 3451 'ipv6-prefix-veth.network',
e2c4070e 3452 'ipv6-prefix-veth-token-static.network',
68248f43
YW
3453 'ipv6-prefix-veth-token-prefixstable.network',
3454 'ipv6-prefix-veth-token-prefixstable-without-address.network']
1f0e3109
SS
3455
3456 def setUp(self):
ec38833c 3457 remove_links(self.links)
aaae5713 3458 stop_networkd(show_logs=False)
1f0e3109
SS
3459
3460 def tearDown(self):
ec38833c
ZJS
3461 remove_links(self.links)
3462 remove_unit_from_networkd_path(self.units)
aaae5713 3463 stop_networkd(show_logs=True)
1f0e3109
SS
3464
3465 def test_ipv6_prefix_delegation(self):
ec38833c 3466 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2cf6fdff 3467 start_networkd()
e2aea43f 3468 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1f0e3109 3469
41fd8fe7
YW
3470 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3471 print(output)
3472 self.assertRegex(output, 'fe80::')
3473 self.assertRegex(output, '2002:da8:1::1')
3474
80762ccc
YW
3475 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3476 print(output)
3477 self.assertIn('hogehoge.test', output)
3478
fc79e6ff 3479 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3480 print(output)
3481 self.assertRegex(output, '2002:da8:1:0')
3482
e2c4070e
YW
3483 def test_ipv6_token_static(self):
3484 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static.network')
87bbebea 3485 start_networkd()
b241fa00
KF
3486 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3487
3488 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3489 print(output)
3490 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
68248f43
YW
3491 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe')
3492 self.assertRegex(output, '2002:da8:2:0:1a:2b:3c:4d')
3493 self.assertRegex(output, '2002:da8:2:0:fa:de:ca:fe')
b241fa00 3494
68248f43
YW
3495 def test_ipv6_token_prefixstable(self):
3496 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network')
c24c83dc
KF
3497 start_networkd()
3498 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3499
3500 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3501 print(output)
68248f43
YW
3502 self.assertRegex(output, '2002:da8:1:0')
3503 self.assertRegex(output, '2002:da8:2:0.*78:9abc') # EUI
c24c83dc 3504
68248f43
YW
3505 def test_ipv6_token_prefixstable_without_address(self):
3506 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable-without-address.network')
87bbebea
YW
3507 start_networkd()
3508 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3509
3510 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3511 print(output)
3512 self.assertRegex(output, '2002:da8:1:0')
68248f43 3513 self.assertRegex(output, '2002:da8:2:0')
87bbebea 3514
be68c2c9 3515class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
fdcd1ec5 3516 links = ['veth99']
09ea6724
YW
3517
3518 units = [
09ea6724
YW
3519 '25-veth.netdev',
3520 'dhcp-client.network',
3521 'dhcp-client-timezone-router.network',
3522 'dhcp-server.network',
3523 'dhcp-server-timezone-router.network']
1f0e3109
SS
3524
3525 def setUp(self):
ec38833c 3526 remove_links(self.links)
aaae5713 3527 stop_networkd(show_logs=False)
1f0e3109
SS
3528
3529 def tearDown(self):
ec38833c
ZJS
3530 remove_links(self.links)
3531 remove_unit_from_networkd_path(self.units)
aaae5713 3532 stop_networkd(show_logs=True)
1f0e3109
SS
3533
3534 def test_dhcp_server(self):
ec38833c 3535 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2cf6fdff 3536 start_networkd()
e2aea43f 3537 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3538
fc79e6ff 3539 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3540 print(output)
3541 self.assertRegex(output, '192.168.5.*')
3542 self.assertRegex(output, 'Gateway: 192.168.5.1')
3543 self.assertRegex(output, 'DNS: 192.168.5.1')
3544 self.assertRegex(output, 'NTP: 192.168.5.1')
3545
1f0e3109 3546 def test_emit_router_timezone(self):
ec38833c 3547 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2cf6fdff 3548 start_networkd()
e2aea43f 3549 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3550
fc79e6ff 3551 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3552 print(output)
3553 self.assertRegex(output, 'Gateway: 192.168.5.*')
3554 self.assertRegex(output, '192.168.5.*')
3555 self.assertRegex(output, 'Europe/Berlin')
3556
be68c2c9 3557class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
09ea6724 3558 links = [
18c613dc
YW
3559 'veth99',
3560 'vrf99']
09ea6724
YW
3561
3562 units = [
3563 '25-veth.netdev',
18c613dc
YW
3564 '25-vrf.netdev',
3565 '25-vrf.network',
09ea6724 3566 'dhcp-client-anonymize.network',
0fd8b718 3567 'dhcp-client-decline.network',
214c5bae
YW
3568 'dhcp-client-gateway-ipv4.network',
3569 'dhcp-client-gateway-ipv6.network',
af3b1498 3570 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
3571 'dhcp-client-ipv4-dhcp-settings.network',
3572 'dhcp-client-ipv4-only-ipv6-disabled.network',
3573 'dhcp-client-ipv4-only.network',
7c0d36ff 3574 'dhcp-client-ipv4-use-routes-use-gateway.network',
09ea6724
YW
3575 'dhcp-client-ipv6-only.network',
3576 'dhcp-client-ipv6-rapid-commit.network',
1e498853
YW
3577 'dhcp-client-keep-configuration-dhcp-on-stop.network',
3578 'dhcp-client-keep-configuration-dhcp.network',
09ea6724 3579 'dhcp-client-listen-port.network',
c1b01a62
YW
3580 'dhcp-client-reassign-static-routes-ipv4.network',
3581 'dhcp-client-reassign-static-routes-ipv6.network',
09ea6724
YW
3582 'dhcp-client-route-metric.network',
3583 'dhcp-client-route-table.network',
e2d5aab3
YW
3584 'dhcp-client-use-dns-ipv4-and-ra.network',
3585 'dhcp-client-use-dns-ipv4.network',
3586 'dhcp-client-use-dns-no.network',
3587 'dhcp-client-use-dns-yes.network',
e0c1341d 3588 'dhcp-client-use-domains.network',
18c613dc 3589 'dhcp-client-vrf.network',
240e4137 3590 'dhcp-client-with-ipv4ll.network',
4c882c16 3591 'dhcp-client-with-static-address.network',
3e9d5552 3592 'dhcp-client.network',
0fd8b718 3593 'dhcp-server-decline.network',
09ea6724 3594 'dhcp-server-veth-peer.network',
30d3b54e
YW
3595 'dhcp-v4-server-veth-peer.network',
3596 'static.network']
1f0e3109
SS
3597
3598 def setUp(self):
ec38833c
ZJS
3599 stop_dnsmasq(dnsmasq_pid_file)
3600 remove_links(self.links)
aaae5713 3601 stop_networkd(show_logs=False)
1f0e3109
SS
3602
3603 def tearDown(self):
ec38833c
ZJS
3604 stop_dnsmasq(dnsmasq_pid_file)
3605 remove_lease_file()
3606 remove_log_file()
3607 remove_links(self.links)
3608 remove_unit_from_networkd_path(self.units)
aaae5713 3609 stop_networkd(show_logs=True)
1f0e3109
SS
3610
3611 def test_dhcp_client_ipv6_only(self):
ec38833c 3612 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109 3613
2cf6fdff 3614 start_networkd()
e2aea43f 3615 self.wait_online(['veth-peer:carrier'])
ec38833c 3616 start_dnsmasq()
e2aea43f 3617 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3618
fc79e6ff 3619 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3620 print(output)
3621 self.assertRegex(output, '2600::')
3622 self.assertNotRegex(output, '192.168.5')
3623
c5fcd8a7
YW
3624 output = check_output('ip addr show dev veth99')
3625 print(output)
3626 self.assertRegex(output, '2600::')
3627 self.assertNotRegex(output, '192.168.5')
3628 self.assertNotRegex(output, 'tentative')
3629
3a956d38 3630 # Confirm that ipv6 token is not set in the kernel
371810d1 3631 output = check_output('ip token show dev veth99')
3a956d38
YW
3632 print(output)
3633 self.assertRegex(output, 'token :: dev veth99')
3634
1f0e3109 3635 def test_dhcp_client_ipv4_only(self):
ec38833c 3636 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109 3637
2cf6fdff 3638 start_networkd()
e2aea43f 3639 self.wait_online(['veth-peer:carrier'])
195a18c1 3640 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
e2aea43f 3641 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3642
fc79e6ff 3643 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3644 print(output)
3645 self.assertNotRegex(output, '2600::')
3646 self.assertRegex(output, '192.168.5')
195a18c1
YW
3647 self.assertRegex(output, '192.168.5.6')
3648 self.assertRegex(output, '192.168.5.7')
3649
3650 # checking routes to DNS servers
3651 output = check_output('ip route show dev veth99')
3652 print(output)
3653 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
3654 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
3655 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
3656
3657 stop_dnsmasq(dnsmasq_pid_file)
3658 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
3659
3660 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3661 print('Wait for the dynamic address to be renewed')
3662 time.sleep(125)
3663
3664 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3665
fc79e6ff 3666 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
195a18c1
YW
3667 print(output)
3668 self.assertNotRegex(output, '2600::')
3669 self.assertRegex(output, '192.168.5')
3670 self.assertNotRegex(output, '192.168.5.6')
3671 self.assertRegex(output, '192.168.5.7')
3672 self.assertRegex(output, '192.168.5.8')
3673
3674 # checking routes to DNS servers
3675 output = check_output('ip route show dev veth99')
3676 print(output)
3677 self.assertNotRegex(output, r'192.168.5.6')
3678 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
3679 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
3680 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
1f0e3109 3681
7c0d36ff 3682 def test_dhcp_client_ipv4_use_routes_gateway(self):
06c2b0c7 3683 for (routes, gateway, dnsroutes) in itertools.product([True, False, None], repeat=3):
7c0d36ff 3684 self.setUp()
06c2b0c7
DS
3685 with self.subTest(routes=routes, gateway=gateway, dnsroutes=dnsroutes):
3686 self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dnsroutes)
7c0d36ff
DS
3687 self.tearDown()
3688
06c2b0c7 3689 def _test_dhcp_client_ipv4_use_routes_gateway(self, routes, gateway, dnsroutes):
7c0d36ff
DS
3690 testunit = 'dhcp-client-ipv4-use-routes-use-gateway.network'
3691 testunits = ['25-veth.netdev', 'dhcp-server-veth-peer.network', testunit]
3692 if routes != None:
3693 testunits.append(f'{testunit}.d/use-routes-{routes}.conf');
3694 if gateway != None:
3695 testunits.append(f'{testunit}.d/use-gateway-{gateway}.conf');
06c2b0c7
DS
3696 if dnsroutes != None:
3697 testunits.append(f'{testunit}.d/use-dns-routes-{dnsroutes}.conf');
7c0d36ff 3698 copy_unit_to_networkd_unit_path(*testunits, dropins=False)
4c2e1833
YW
3699
3700 start_networkd()
3701 self.wait_online(['veth-peer:carrier'])
3702 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
3703 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3704
3705 output = check_output('ip route show dev veth99')
3706 print(output)
4c2e1833 3707
7c0d36ff
DS
3708 # UseRoutes= defaults to true
3709 useroutes = routes in [True, None]
3710 # UseGateway= defaults to useroutes
3711 usegateway = useroutes if gateway == None else gateway
0d7bd445 3712
7c0d36ff
DS
3713 # Check UseRoutes=
3714 if useroutes:
3715 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.181 metric 1024')
3716 else:
3717 self.assertNotRegex(output, r'192.168.5.5')
0d7bd445 3718
7c0d36ff
DS
3719 # Check UseGateway=
3720 if usegateway:
3721 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
3722 else:
3723 self.assertNotRegex(output, r'default via 192.168.5.1')
3724
06c2b0c7
DS
3725 # Check RoutesToDNS=, which defaults to false
3726 if dnsroutes:
7c0d36ff
DS
3727 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
3728 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
3729 else:
3730 self.assertNotRegex(output, r'192.168.5.6')
3731 self.assertNotRegex(output, r'192.168.5.7')
0d7bd445 3732
1f0e3109 3733 def test_dhcp_client_ipv4_ipv6(self):
ec38833c
ZJS
3734 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
3735 'dhcp-client-ipv4-only.network')
2cf6fdff 3736 start_networkd()
e2aea43f 3737 self.wait_online(['veth-peer:carrier'])
ec38833c 3738 start_dnsmasq()
e2aea43f 3739 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
3740
3741 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 3742 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 3743 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 3744
fc79e6ff 3745 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109
SS
3746 print(output)
3747 self.assertRegex(output, '2600::')
3748 self.assertRegex(output, '192.168.5')
3749
3750 def test_dhcp_client_settings(self):
ec38833c 3751 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 3752
2cf6fdff 3753 start_networkd()
e2aea43f 3754 self.wait_online(['veth-peer:carrier'])
ec38833c 3755 start_dnsmasq()
e2aea43f 3756 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3757
0ae7a66d 3758 print('## ip address show dev veth99')
371810d1 3759 output = check_output('ip address show dev veth99')
1f0e3109
SS
3760 print(output)
3761 self.assertRegex(output, '12:34:56:78:9a:bc')
3762 self.assertRegex(output, '192.168.5')
3763 self.assertRegex(output, '1492')
3764
0ae7a66d 3765 print('## ip route show table main dev veth99')
371810d1 3766 output = check_output('ip route show table main dev veth99')
1f0e3109 3767 print(output)
156ddf8d 3768 # See issue #8726
dd9b10c8
YW
3769 main_table_is_empty = output == ''
3770 if not main_table_is_empty:
3771 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 3772
0ae7a66d 3773 print('## ip route show table 211 dev veth99')
371810d1 3774 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
3775 print(output)
3776 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
dd9b10c8
YW
3777 if main_table_is_empty:
3778 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
0ae7a66d
YW
3779 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
3780 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
3781
3782 print('## dnsmasq log')
ec38833c
ZJS
3783 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
3784 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
3785 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
3786 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
3787
3788 def test_dhcp6_client_settings_rapidcommit_true(self):
ec38833c 3789 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2cf6fdff 3790 start_networkd()
e2aea43f 3791 self.wait_online(['veth-peer:carrier'])
ec38833c 3792 start_dnsmasq()
e2aea43f 3793 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3794
371810d1 3795 output = check_output('ip address show dev veth99')
1f0e3109
SS
3796 print(output)
3797 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 3798 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
3799
3800 def test_dhcp6_client_settings_rapidcommit_false(self):
ec38833c 3801 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2cf6fdff 3802 start_networkd()
e2aea43f 3803 self.wait_online(['veth-peer:carrier'])
ec38833c 3804 start_dnsmasq()
e2aea43f 3805 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 3806
371810d1 3807 output = check_output('ip address show dev veth99')
1f0e3109
SS
3808 print(output)
3809 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 3810 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
3811
3812 def test_dhcp_client_settings_anonymize(self):
ec38833c 3813 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2cf6fdff 3814 start_networkd()
e2aea43f 3815 self.wait_online(['veth-peer:carrier'])
ec38833c 3816 start_dnsmasq()
e2aea43f 3817 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3818
ec38833c
ZJS
3819 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
3820 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
3821 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
3822
3823 def test_dhcp_client_listen_port(self):
ec38833c 3824 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2cf6fdff 3825 start_networkd()
e2aea43f 3826 self.wait_online(['veth-peer:carrier'])
ec38833c 3827 start_dnsmasq('--dhcp-alternate-port=67,5555')
e2aea43f 3828 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47 3829
371810d1 3830 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
3831 print(output)
3832 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109 3833
4c882c16
YW
3834 def test_dhcp_client_with_static_address(self):
3835 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
3836 'dhcp-client-with-static-address.network')
3837 start_networkd()
e2aea43f 3838 self.wait_online(['veth-peer:carrier'])
4c882c16 3839 start_dnsmasq()
e2aea43f 3840 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4c882c16
YW
3841
3842 output = check_output('ip address show dev veth99 scope global')
3843 print(output)
3844 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3845 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
3846
3847 output = check_output('ip route show dev veth99')
3848 print(output)
3849 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
3850 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
3851 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
3852 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
3853
1f0e3109 3854 def test_dhcp_route_table_id(self):
ec38833c 3855 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2cf6fdff 3856 start_networkd()
e2aea43f 3857 self.wait_online(['veth-peer:carrier'])
ec38833c 3858 start_dnsmasq()
e2aea43f 3859 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3860
371810d1 3861 output = check_output('ip route show table 12')
1f0e3109 3862 print(output)
1f0e3109
SS
3863 self.assertRegex(output, 'veth99 proto dhcp')
3864 self.assertRegex(output, '192.168.5.1')
3865
3866 def test_dhcp_route_metric(self):
ec38833c 3867 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2cf6fdff 3868 start_networkd()
e2aea43f 3869 self.wait_online(['veth-peer:carrier'])
ec38833c 3870 start_dnsmasq()
e2aea43f 3871 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3872
371810d1 3873 output = check_output('ip route show dev veth99')
1f0e3109 3874 print(output)
1f0e3109
SS
3875 self.assertRegex(output, 'metric 24')
3876
c1b01a62 3877 def test_dhcp_client_reassign_static_routes_ipv4(self):
c38d2d4d 3878 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
c1b01a62 3879 'dhcp-client-reassign-static-routes-ipv4.network')
c38d2d4d 3880 start_networkd()
e2aea43f 3881 self.wait_online(['veth-peer:carrier'])
c38d2d4d 3882 start_dnsmasq(lease_time='2m')
e2aea43f 3883 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c38d2d4d
YW
3884
3885 output = check_output('ip address show dev veth99 scope global')
3886 print(output)
3887 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3888
3889 output = check_output('ip route show dev veth99')
3890 print(output)
3891 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3892 self.assertRegex(output, r'192.168.5.0/24 proto static')
3893 self.assertRegex(output, r'192.168.6.0/24 proto static')
3894 self.assertRegex(output, r'192.168.7.0/24 proto static')
3895
c1b01a62
YW
3896 stop_dnsmasq(dnsmasq_pid_file)
3897 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
3898
c38d2d4d
YW
3899 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3900 print('Wait for the dynamic address to be renewed')
3901 time.sleep(125)
3902
e2aea43f 3903 self.wait_online(['veth99:routable'])
c38d2d4d
YW
3904
3905 output = check_output('ip route show dev veth99')
3906 print(output)
3907 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3908 self.assertRegex(output, r'192.168.5.0/24 proto static')
3909 self.assertRegex(output, r'192.168.6.0/24 proto static')
3910 self.assertRegex(output, r'192.168.7.0/24 proto static')
3911
c1b01a62
YW
3912 def test_dhcp_client_reassign_static_routes_ipv6(self):
3913 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3914 'dhcp-client-reassign-static-routes-ipv6.network')
3915 start_networkd()
e2aea43f 3916 self.wait_online(['veth-peer:carrier'])
c1b01a62 3917 start_dnsmasq(lease_time='2m')
e2aea43f 3918 self.wait_online(['veth99:routable', 'veth-peer:routable'])
c1b01a62
YW
3919
3920 output = check_output('ip address show dev veth99 scope global')
3921 print(output)
426654d7 3922 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
c1b01a62
YW
3923
3924 output = check_output('ip -6 route show dev veth99')
3925 print(output)
3926 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3927 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3928
3929 stop_dnsmasq(dnsmasq_pid_file)
3930 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
3931
3932 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3933 print('Wait for the dynamic address to be renewed')
3934 time.sleep(125)
3935
e2aea43f 3936 self.wait_online(['veth99:routable'])
c1b01a62
YW
3937
3938 output = check_output('ip -6 route show dev veth99')
3939 print(output)
3940 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3941 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3942
1e498853
YW
3943 def test_dhcp_keep_configuration_dhcp(self):
3944 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2cf6fdff 3945 start_networkd()
e2aea43f 3946 self.wait_online(['veth-peer:carrier'])
1e498853 3947 start_dnsmasq(lease_time='2m')
e2aea43f 3948 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 3949
1e498853
YW
3950 output = check_output('ip address show dev veth99 scope global')
3951 print(output)
3952 self.assertRegex(output, r'192.168.5.*')
3953
fc79e6ff 3954 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 3955 print(output)
1e498853 3956 self.assertRegex(output, r'192.168.5.*')
e40a58b5 3957
5238e957 3958 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
ec38833c 3959 stop_dnsmasq(dnsmasq_pid_file)
1f0e3109
SS
3960
3961 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 3962 print('Wait for the dynamic address to be expired')
1f0e3109
SS
3963 time.sleep(125)
3964
1e498853
YW
3965 print('The lease address should be kept after lease expired')
3966 output = check_output('ip address show dev veth99 scope global')
3967 print(output)
3968 self.assertRegex(output, r'192.168.5.*')
3969
fc79e6ff 3970 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1f0e3109 3971 print(output)
1e498853
YW
3972 self.assertRegex(output, r'192.168.5.*')
3973
3aa645f0
MB
3974 check_output('systemctl stop systemd-networkd.socket')
3975 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
3976
3977 print('The lease address should be kept after networkd stopped')
3978 output = check_output('ip address show dev veth99 scope global')
3979 print(output)
3980 self.assertRegex(output, r'192.168.5.*')
3981
fc79e6ff 3982 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
3983 print(output)
3984 self.assertRegex(output, r'192.168.5.*')
3985
e2aea43f
YW
3986 start_networkd(3)
3987 self.wait_online(['veth-peer:routable'])
1e498853
YW
3988
3989 print('Still the lease address should be kept after networkd restarted')
3990 output = check_output('ip address show dev veth99 scope global')
3991 print(output)
3992 self.assertRegex(output, r'192.168.5.*')
3993
fc79e6ff 3994 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
1e498853
YW
3995 print(output)
3996 self.assertRegex(output, r'192.168.5.*')
3997
3998 def test_dhcp_keep_configuration_dhcp_on_stop(self):
3999 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2cf6fdff 4000 start_networkd()
e2aea43f 4001 self.wait_online(['veth-peer:carrier'])
1e498853 4002 start_dnsmasq(lease_time='2m')
e2aea43f 4003 self.wait_online(['veth99:routable', 'veth-peer:routable'])
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
4009 stop_dnsmasq(dnsmasq_pid_file)
3aa645f0
MB
4010 check_output('systemctl stop systemd-networkd.socket')
4011 check_output('systemctl stop systemd-networkd.service')
1e498853
YW
4012
4013 output = check_output('ip address show dev veth99 scope global')
4014 print(output)
4015 self.assertRegex(output, r'192.168.5.*')
4016
e2aea43f
YW
4017 restart_networkd(3)
4018 self.wait_online(['veth-peer:routable'])
1e498853
YW
4019
4020 output = check_output('ip address show dev veth99 scope global')
4021 print(output)
4022 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 4023
30d3b54e 4024 def test_dhcp_client_reuse_address_as_static(self):
ec38833c 4025 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2cf6fdff 4026 start_networkd()
e2aea43f 4027 self.wait_online(['veth-peer:carrier'])
ec38833c 4028 start_dnsmasq()
e2aea43f 4029 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
4030
4031 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 4032 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4033 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 4034
371810d1 4035 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
4036 print(output)
4037 self.assertRegex(output, '192.168.5')
4038 self.assertRegex(output, '2600::')
4039
2629df47
YW
4040 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
4041 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
4042 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
4043 print(static_network)
4044
ec38833c 4045 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
4046
4047 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
4048 f.write(static_network)
4049
2629df47
YW
4050 # When networkd started, the links are already configured, so let's wait for 5 seconds
4051 # the links to be re-configured.
aaae5713 4052 restart_networkd(5)
e2aea43f 4053 self.wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 4054
371810d1 4055 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
4056 print(output)
4057 self.assertRegex(output, '192.168.5')
4058 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
4059
371810d1 4060 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
4061 print(output)
4062 self.assertRegex(output, '2600::')
4063 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
4064
18c613dc
YW
4065 @expectedFailureIfModuleIsNotAvailable('vrf')
4066 def test_dhcp_client_vrf(self):
ec38833c
ZJS
4067 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
4068 '25-vrf.netdev', '25-vrf.network')
2cf6fdff 4069 start_networkd()
e2aea43f 4070 self.wait_online(['veth-peer:carrier'])
ec38833c 4071 start_dnsmasq()
e2aea43f 4072 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
4073
4074 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79 4075 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4076 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
4077
4078 print('## ip -d link show dev vrf99')
371810d1 4079 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
4080 print(output)
4081 self.assertRegex(output, 'vrf table 42')
4082
4083 print('## ip address show vrf vrf99')
371810d1 4084 output = check_output('ip address show vrf vrf99')
d90f4f7d 4085 print(output)
d90f4f7d 4086 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4087 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
d90f4f7d 4088 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
4089
4090 print('## ip address show dev veth99')
371810d1 4091 output = check_output('ip address show dev veth99')
18c613dc 4092 print(output)
18c613dc 4093 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
426654d7 4094 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
4095 self.assertRegex(output, 'inet6 .* scope link')
4096
4097 print('## ip route show vrf vrf99')
371810d1 4098 output = check_output('ip route show vrf vrf99')
18c613dc
YW
4099 print(output)
4100 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
18c613dc
YW
4101 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
4102 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
4103 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
4104
4105 print('## ip route show table main dev veth99')
371810d1 4106 output = check_output('ip route show table main dev veth99')
18c613dc
YW
4107 print(output)
4108 self.assertEqual(output, '')
4109
214c5bae
YW
4110 def test_dhcp_client_gateway_ipv4(self):
4111 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4112 'dhcp-client-gateway-ipv4.network')
4113 start_networkd()
4114 self.wait_online(['veth-peer:carrier'])
4115 start_dnsmasq()
4116 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4117
4118 output = check_output('ip route list dev veth99 10.0.0.0/8')
4119 print(output)
c27abcf4 4120 self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto dhcp')
214c5bae
YW
4121
4122 def test_dhcp_client_gateway_ipv6(self):
4123 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4124 'dhcp-client-gateway-ipv6.network')
4125 start_networkd()
4126 self.wait_online(['veth-peer:carrier'])
4127 start_dnsmasq()
4128 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4129
4130 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
4131 print(output)
4132 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
4133
af3b1498 4134 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
4135 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4136 'dhcp-client-gateway-onlink-implicit.network')
2cf6fdff 4137 start_networkd()
e2aea43f 4138 self.wait_online(['veth-peer:carrier'])
ec38833c 4139 start_dnsmasq()
e2aea43f 4140 self.wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 4141
fc79e6ff 4142 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
af3b1498
YW
4143 print(output)
4144 self.assertRegex(output, '192.168.5')
4145
371810d1 4146 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
4147 print(output)
4148 self.assertRegex(output, 'onlink')
371810d1 4149 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
4150 print(output)
4151 self.assertRegex(output, 'onlink')
4152
3ca1fab7 4153 def test_dhcp_client_with_ipv4ll_with_dhcp_server(self):
ec38833c 4154 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
240e4137 4155 'dhcp-client-with-ipv4ll.network')
2cf6fdff 4156 start_networkd()
e2aea43f 4157 self.wait_online(['veth-peer:carrier'])
ec38833c 4158 start_dnsmasq(lease_time='2m')
e2aea43f 4159 self.wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 4160
371810d1 4161 output = check_output('ip address show dev veth99')
63c598ed
YW
4162 print(output)
4163
371810d1 4164 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4165 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4166 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4167 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4168 output = check_output('ip -4 address show dev veth99 scope global dynamic')
240e4137 4169 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4170 output = check_output('ip -4 address show dev veth99 scope link')
240e4137 4171 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link')
63c598ed
YW
4172
4173 print('Wait for the dynamic address to be expired')
4174 time.sleep(130)
4175
371810d1 4176 output = check_output('ip address show dev veth99')
63c598ed
YW
4177 print(output)
4178
371810d1 4179 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4180 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4181 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4182 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4183 output = check_output('ip -4 address show dev veth99 scope global dynamic')
240e4137 4184 self.assertRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4185 output = check_output('ip -4 address show dev veth99 scope link')
240e4137 4186 self.assertNotRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link')
63c598ed 4187
ec38833c 4188 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 4189
3ca1fab7 4190 def test_dhcp_client_with_ipv4ll_without_dhcp_server(self):
ec38833c 4191 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
240e4137 4192 'dhcp-client-with-ipv4ll.network')
2cf6fdff 4193 start_networkd()
b226c15c
DS
4194 # we need to increase timeout above default, as this will need to wait for
4195 # systemd-networkd to get the dhcpv4 transient failure event
4196 self.wait_online(['veth99:degraded', 'veth-peer:routable'], timeout='60s')
117a55c7 4197
371810d1 4198 output = check_output('ip address show dev veth99')
117a55c7
YW
4199 print(output)
4200
371810d1 4201 output = check_output('ip -6 address show dev veth99 scope global dynamic')
240e4137 4202 self.assertNotRegex(output, r'inet6 2600::[0-9a-f]+/128 scope global dynamic')
371810d1 4203 output = check_output('ip -6 address show dev veth99 scope link')
240e4137 4204 self.assertRegex(output, r'inet6 .* scope link')
371810d1 4205 output = check_output('ip -4 address show dev veth99 scope global dynamic')
240e4137 4206 self.assertNotRegex(output, r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic veth99')
371810d1 4207 output = check_output('ip -4 address show dev veth99 scope link')
240e4137
YW
4208 self.assertRegex(output, r'inet 169\.254\.\d+\.\d+/16 brd 169\.254\.255\.255 scope link')
4209
4210 start_dnsmasq(lease_time='2m')
4211 self.wait_address('veth99', r'inet 192\.168\.5\.\d+/24 brd 192\.168\.5\.255 scope global dynamic', ipv='-4')
4212 self.wait_address_dropped('veth99', r'inet 169\.254\.\d+\.\d+/16 brd 169\.255\.255\.255 scope link', scope='link', ipv='-4')
117a55c7 4213
b6efd661 4214 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
4215 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
4216 'dhcp-client-ipv4-only-ipv6-disabled.network')
2cf6fdff 4217 start_networkd()
e2aea43f 4218 self.wait_online(['veth-peer:carrier'])
ec38833c 4219 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
e2aea43f 4220 self.wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
4221
4222 # test for issue #12490
4223
371810d1 4224 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
4225 print(output)
4226 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
4227 address1=None
4228 for line in output.splitlines():
4229 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
4230 address1 = line.split()[1].split('/')[0]
4231 break
4232
371810d1 4233 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
4234 print(output)
4235 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
4236 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
4237
ec38833c
ZJS
4238 stop_dnsmasq(dnsmasq_pid_file)
4239 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
4240
4241 print('Wait for the dynamic address to be expired')
4242 time.sleep(130)
4243
371810d1 4244 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
4245 print(output)
4246 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
4247 address2=None
4248 for line in output.splitlines():
4249 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
4250 address2 = line.split()[1].split('/')[0]
4251 break
4252
4253 self.assertNotEqual(address1, address2)
4254
371810d1 4255 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
4256 print(output)
4257 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
4258 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
4259 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
4260 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
4261
e2d5aab3
YW
4262 def test_dhcp_client_use_dns_yes(self):
4263 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
4264
4265 start_networkd()
e2aea43f 4266 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4267 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4268 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4269
4270 # link become 'routable' when at least one protocol provide an valid address.
4271 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4272 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4273
693283cd 4274 time.sleep(3)
e2d5aab3
YW
4275 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4276 print(output)
4277 self.assertRegex(output, '192.168.5.1')
4278 self.assertRegex(output, '2600::1')
4279
4280 def test_dhcp_client_use_dns_no(self):
4281 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
4282
4283 start_networkd()
e2aea43f 4284 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4285 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4286 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4287
4288 # link become 'routable' when at least one protocol provide an valid address.
4289 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4290 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4291
693283cd 4292 time.sleep(3)
e2d5aab3
YW
4293 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4294 print(output)
4295 self.assertNotRegex(output, '192.168.5.1')
4296 self.assertNotRegex(output, '2600::1')
4297
4298 def test_dhcp_client_use_dns_ipv4(self):
4299 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
4300
4301 start_networkd()
e2aea43f 4302 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4303 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4304 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4305
4306 # link become 'routable' when at least one protocol provide an valid address.
4307 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4308 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4309
693283cd 4310 time.sleep(3)
e2d5aab3
YW
4311 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4312 print(output)
4313 self.assertRegex(output, '192.168.5.1')
4314 self.assertNotRegex(output, '2600::1')
4315
4316 def test_dhcp_client_use_dns_ipv4_and_ra(self):
4317 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
4318
4319 start_networkd()
e2aea43f 4320 self.wait_online(['veth-peer:carrier'])
e2d5aab3 4321 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
e2aea43f 4322 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e2d5aab3
YW
4323
4324 # link become 'routable' when at least one protocol provide an valid address.
4325 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
426654d7 4326 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
e2d5aab3 4327
693283cd 4328 time.sleep(3)
e2d5aab3
YW
4329 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
4330 print(output)
4331 self.assertRegex(output, '192.168.5.1')
4332 self.assertRegex(output, '2600::1')
4333
e0c1341d
YW
4334 def test_dhcp_client_use_domains(self):
4335 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
4336
4337 start_networkd()
e2aea43f 4338 self.wait_online(['veth-peer:carrier'])
e0c1341d 4339 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
e2aea43f 4340 self.wait_online(['veth99:routable', 'veth-peer:routable'])
e0c1341d 4341
fc79e6ff 4342 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
e0c1341d
YW
4343 print(output)
4344 self.assertRegex(output, 'Search Domains: example.com')
4345
4346 time.sleep(3)
4347 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
4348 print(output)
4349 self.assertRegex(output, 'example.com')
4350
0fd8b718
YW
4351 def test_dhcp_client_decline(self):
4352 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
4353
4354 start_networkd()
4355 self.wait_online(['veth-peer:carrier'])
4356 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env)
4357 self.assertTrue(rc == 1)
4358
9633f977
SS
4359class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
4360 links = ['veth99']
4361
4362 units = [
4363 '25-veth.netdev',
635f2a66 4364 'ipv6ra-prefix-client-deny-list.network',
9633f977
SS
4365 'ipv6ra-prefix-client.network',
4366 'ipv6ra-prefix.network'
4367 ]
4368
4369 def setUp(self):
4370 remove_links(self.links)
4371 stop_networkd(show_logs=False)
4372
4373 def tearDown(self):
4374 remove_log_file()
4375 remove_links(self.links)
4376 remove_unit_from_networkd_path(self.units)
4377 stop_networkd(show_logs=True)
4378
4379 def test_ipv6_route_prefix(self):
4380 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
4381
4382 start_networkd()
9633f977
SS
4383 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4384
635f2a66
YW
4385 output = check_output('ip address show dev veth-peer')
4386 print(output)
4387 self.assertIn('inet6 2001:db8:0:1:', output)
4388 self.assertNotIn('inet6 2001:db8:0:2:', output)
4389
3c874fd7 4390 output = check_output('ip -6 route show dev veth-peer')
9633f977 4391 print(output)
635f2a66
YW
4392 self.assertIn('2001:db8:0:1::/64 proto ra', output)
4393 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
4394 self.assertIn('2001:db0:fff::/64 via ', output)
4395 self.assertNotIn('2001:db1:fff::/64 via ', output)
9633f977 4396
635f2a66
YW
4397 output = check_output('ip address show dev veth99')
4398 print(output)
4399 self.assertNotIn('inet6 2001:db8:0:1:', output)
4400 self.assertIn('inet6 2001:db8:0:2:', output)
4401
4402 def test_ipv6_route_prefix_deny_list(self):
4403 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client-deny-list.network', 'ipv6ra-prefix.network')
4404
4405 start_networkd()
4406 self.wait_online(['veth99:routable', 'veth-peer:routable'])
4407
4408 output = check_output('ip address show dev veth-peer')
4409 print(output)
4410 self.assertIn('inet6 2001:db8:0:1:', output)
4411 self.assertNotIn('inet6 2001:db8:0:2:', output)
4412
4413 output = check_output('ip -6 route show dev veth-peer')
4414 print(output)
4415 self.assertIn('2001:db8:0:1::/64 proto ra', output)
4416 self.assertNotIn('2001:db8:0:2::/64 proto ra', output)
4417 self.assertIn('2001:db0:fff::/64 via ', output)
4418 self.assertNotIn('2001:db1:fff::/64 via ', output)
4419
4420 output = check_output('ip address show dev veth99')
3c874fd7 4421 print(output)
635f2a66
YW
4422 self.assertNotIn('inet6 2001:db8:0:1:', output)
4423 self.assertIn('inet6 2001:db8:0:2:', output)
3c874fd7 4424
7db05447
DS
4425class NetworkdMTUTests(unittest.TestCase, Utilities):
4426 links = ['dummy98']
4427
4428 units = [
4429 '12-dummy.netdev',
4430 '12-dummy-mtu.netdev',
4431 '12-dummy-mtu.link',
4432 '12-dummy.network',
4433 ]
4434
4435 def setUp(self):
4436 remove_links(self.links)
4437 stop_networkd(show_logs=False)
4438
4439 def tearDown(self):
4440 remove_log_file()
4441 remove_links(self.links)
4442 remove_unit_from_networkd_path(self.units)
4443 stop_networkd(show_logs=True)
4444
4445 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
4446 if not ipv6_mtu:
4447 ipv6_mtu = mtu
4448
4449 # test normal start
4450 start_networkd()
4451 self.wait_online(['dummy98:routable'])
4452 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
4453 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
4454
4455 # test normal restart
4456 restart_networkd()
4457 self.wait_online(['dummy98:routable'])
4458 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
4459 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
4460
4461 if reset:
4462 self.reset_check_mtu(mtu, ipv6_mtu)
4463
4464 def reset_check_mtu(self, mtu, ipv6_mtu=None):
4465 ''' test setting mtu/ipv6_mtu with interface already up '''
4466 stop_networkd()
4467
4468 # note - changing the device mtu resets the ipv6 mtu
4469 run('ip link set up mtu 1501 dev dummy98')
4470 run('ip link set up mtu 1500 dev dummy98')
4471 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
4472 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
4473
4474 self.check_mtu(mtu, ipv6_mtu, reset=False)
4475
4476 def test_mtu_network(self):
4477 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
4478 self.check_mtu('1600')
4479
4480 def test_mtu_netdev(self):
4481 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
4482 # note - MTU set by .netdev happens ONLY at device creation!
4483 self.check_mtu('1600', reset=False)
4484
4485 def test_mtu_link(self):
4486 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
4487 # must reload udev because it only picks up new files after 3 second delay
4488 call('udevadm control --reload')
4489 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
4490 self.check_mtu('1600', reset=False)
4491
4492 def test_ipv6_mtu(self):
4493 ''' set ipv6 mtu without setting device mtu '''
4494 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
4495 self.check_mtu('1500', '1400')
4496
4497 def test_ipv6_mtu_toolarge(self):
4498 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
4499 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
4500 self.check_mtu('1500', '1500')
4501
4502 def test_mtu_network_ipv6_mtu(self):
4503 ''' set ipv6 mtu and set device mtu via network file '''
4504 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
4505 self.check_mtu('1600', '1550')
4506
4507 def test_mtu_netdev_ipv6_mtu(self):
4508 ''' set ipv6 mtu and set device mtu via netdev file '''
4509 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
4510 self.check_mtu('1600', '1550', reset=False)
4511
4512 def test_mtu_link_ipv6_mtu(self):
4513 ''' set ipv6 mtu and set device mtu via link file '''
4514 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
4515 # must reload udev because it only picks up new files after 3 second delay
4516 call('udevadm control --reload')
4517 self.check_mtu('1600', '1550', reset=False)
4518
4519
1f0e3109 4520if __name__ == '__main__':
9c1ae484
YW
4521 parser = argparse.ArgumentParser()
4522 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
4523 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
b6d587d1 4524 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
641aa412 4525 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
9c1ae484
YW
4526 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
4527 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
b6d587d1
YW
4528 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
4529 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
9c1ae484
YW
4530 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
4531 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 4532 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 4533 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 4534 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
9c1ae484
YW
4535 ns, args = parser.parse_known_args(namespace=unittest)
4536
4537 if ns.build_dir:
641aa412 4538 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 4539 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
9c1ae484 4540 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
b6d587d1 4541 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
641aa412 4542 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
9c1ae484
YW
4543 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
4544 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
b6d587d1
YW
4545 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
4546 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
9c1ae484
YW
4547 else:
4548 if ns.networkd_bin:
4549 networkd_bin = ns.networkd_bin
b6d587d1
YW
4550 if ns.resolved_bin:
4551 resolved_bin = ns.resolved_bin
641aa412
YW
4552 if ns.udevd_bin:
4553 udevd_bin = ns.udevd_bin
9c1ae484
YW
4554 if ns.wait_online_bin:
4555 wait_online_bin = ns.wait_online_bin
4556 if ns.networkctl_bin:
4557 networkctl_bin = ns.networkctl_bin
b6d587d1
YW
4558 if ns.resolvectl_bin:
4559 resolvectl_bin = ns.resolvectl_bin
4560 if ns.timedatectl_bin:
4561 timedatectl_bin = ns.timedatectl_bin
9c1ae484
YW
4562
4563 use_valgrind = ns.use_valgrind
4564 enable_debug = ns.enable_debug
94c03122 4565 asan_options = ns.asan_options
fa4c6095 4566 lsan_options = ns.lsan_options
94c03122 4567 ubsan_options = ns.ubsan_options
9c1ae484
YW
4568
4569 if use_valgrind:
4570 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
b6d587d1
YW
4571 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
4572 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
9c1ae484
YW
4573 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
4574 else:
4575 networkctl_cmd = [networkctl_bin]
b6d587d1
YW
4576 resolvectl_cmd = [resolvectl_bin]
4577 timedatectl_cmd = [timedatectl_bin]
9c1ae484
YW
4578 wait_online_cmd = [wait_online_bin]
4579
4580 if enable_debug:
4581 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
4582 if asan_options:
4583 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
4584 if lsan_options:
4585 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
4586 if ubsan_options:
4587 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
4588
4589 sys.argv[1:] = args
1f0e3109
SS
4590 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
4591 verbosity=3))