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