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