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