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