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