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