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