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