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