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