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