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