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