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