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