]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
test-network: replace check_link_exists() with wait_online()
[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'
5aa58329 26wait_online_bin='/usr/lib/systemd/systemd-networkd-wait-online'
9c1ae484
YW
27networkctl_bin='/usr/bin/networkctl'
28use_valgrind=False
29enable_debug=False
30env = {}
94c03122 31asan_options=None
fa4c6095 32lsan_options=None
94c03122 33ubsan_options=None
5aa58329 34
371810d1
ZJS
35def check_output(*command, **kwargs):
36 # This replaces both check_output and check_call (output can be ignored)
37 command = command[0].split() + list(command[1:])
38 return subprocess.check_output(command, universal_newlines=True, **kwargs).rstrip()
39
40def call(*command, **kwargs):
41 command = command[0].split() + list(command[1:])
42 return subprocess.call(command, universal_newlines=True, **kwargs)
43
44def run(*command, **kwargs):
45 command = command[0].split() + list(command[1:])
46 return subprocess.run(command, universal_newlines=True, **kwargs)
47
7a0a37b2 48def is_module_available(module_name):
371810d1
ZJS
49 lsmod_output = check_output('lsmod')
50 module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE)
51 return module_re.search(lsmod_output) or not call('modprobe', module_name)
7a0a37b2
EV
52
53def expectedFailureIfModuleIsNotAvailable(module_name):
54 def f(func):
55 if not is_module_available(module_name):
56 return unittest.expectedFailure(func)
57 return func
58
59 return f
60
7bea7f9b
SS
61def expectedFailureIfERSPANModuleIsNotAvailable():
62 def f(func):
371810d1 63 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 64 if rc == 0:
371810d1 65 call('ip link del erspan99')
7bea7f9b
SS
66 return func
67 else:
68 return unittest.expectedFailure(func)
69
70 return f
71
d586a2c3
YW
72def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
73 def f(func):
371810d1 74 rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
d586a2c3 75 if rc == 0:
371810d1 76 call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7')
d586a2c3
YW
77 return func
78 else:
79 return unittest.expectedFailure(func)
80
81 return f
82
83def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
84 def f(func):
371810d1 85 rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7')
d586a2c3 86 if rc == 0:
371810d1 87 call('ip rule del not from 192.168.100.19 ipproto tcp table 7')
d586a2c3
YW
88 return func
89 else:
90 return unittest.expectedFailure(func)
91
92 return f
93
1ca44d7d
YW
94def expectedFailureIfEthtoolDoesNotSupportDriver():
95 def f(func):
96 support = False
371810d1 97 rc = call('ip link add name dummy99 type dummy')
1ca44d7d 98 if rc == 0:
371810d1 99 ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
1ca44d7d
YW
100 if ret.returncode == 0 and 'E: ID_NET_DRIVER=dummy' in ret.stdout.rstrip():
101 support = True
371810d1 102 call('ip link del dummy99')
1ca44d7d
YW
103
104 if support:
105 return func
106 else:
107 return unittest.expectedFailure(func)
108
109 return f
110
1f0e3109 111def setUpModule():
1f0e3109
SS
112 os.makedirs(network_unit_file_path, exist_ok=True)
113 os.makedirs(networkd_ci_path, exist_ok=True)
114
115 shutil.rmtree(networkd_ci_path)
6aea9276 116 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
1f0e3109 117
371810d1
ZJS
118 check_output('systemctl stop systemd-networkd.socket')
119 check_output('systemctl stop systemd-networkd.service')
c0bf6733 120
9c1ae484
YW
121 drop_in = [
122 '[Service]',
123 'Restart=no',
124 'ExecStart=',
125 ]
126 if use_valgrind:
127 drop_in += [
128 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin,
94c03122 129 'PrivateTmp=yes'
9c1ae484
YW
130 ]
131 else:
132 drop_in += ['ExecStart=!!' + networkd_bin]
133 if enable_debug:
134 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
94c03122
YW
135 if asan_options:
136 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
fa4c6095
YW
137 if lsan_options:
138 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
94c03122
YW
139 if ubsan_options:
140 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
78690bb5
YW
141 if asan_options or lsan_options or ubsan_options:
142 drop_in += ['SystemCallFilter=']
fa4c6095 143 if use_valgrind or asan_options or lsan_options or ubsan_options:
94c03122 144 drop_in += ['MemoryDenyWriteExecute=no']
9c1ae484 145
9c1ae484
YW
146 os.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok=True)
147 with open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode='w') as f:
72917fcc 148 f.write('\n'.join(drop_in))
9c1ae484 149
371810d1
ZJS
150 check_output('systemctl daemon-reload')
151 print(check_output('systemctl cat systemd-networkd.service'))
9c1ae484 152
1f0e3109
SS
153def tearDownModule():
154 shutil.rmtree(networkd_ci_path)
d4fda2a5 155
371810d1 156 check_output('systemctl stop systemd-networkd.service')
d4fda2a5 157
9c1ae484 158 shutil.rmtree('/run/systemd/system/systemd-networkd.service.d')
371810d1 159 check_output('systemctl daemon-reload')
1f0e3109 160
371810d1
ZJS
161 check_output('systemctl start systemd-networkd.socket')
162 check_output('systemctl start systemd-networkd.service')
c0bf6733 163
ec38833c
ZJS
164def read_link_attr(link, dev, attribute):
165 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
166 return f.readline().strip()
167
168def read_bridge_port_attr(bridge, link, attribute):
169 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
170 path_port = 'lower_' + link + '/brport'
171 path = os.path.join(path_bridge, path_port)
172
173 with open(os.path.join(path, attribute)) as f:
174 return f.readline().strip()
175
176def link_exists(link):
177 return os.path.exists(os.path.join('/sys/class/net', link))
178
179def remove_links(links):
180 for link in links:
181 if link_exists(link):
182 call('ip link del dev', link)
183 time.sleep(1)
184
185def remove_fou_ports(ports):
186 for port in ports:
5239d7b3 187 call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
188
189def remove_routing_policy_rule_tables(tables):
190 for table in tables:
5239d7b3 191 call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
192
193def remove_routes(routes):
194 for route_type, addr in routes:
5239d7b3 195 call('ip route del', route_type, addr, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
ec38833c
ZJS
196
197def l2tp_tunnel_remove(tunnel_ids):
198 output = check_output('ip l2tp show tunnel')
199 for tid in tunnel_ids:
200 words='Tunnel ' + tid + ', encap'
201 if words in output:
202 call('ip l2tp del tunnel tid', tid)
203 time.sleep(1)
204
205def read_ipv6_sysctl_attr(link, attribute):
206 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
207 return f.readline().strip()
208
209def read_ipv4_sysctl_attr(link, attribute):
210 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
211 return f.readline().strip()
212
213def copy_unit_to_networkd_unit_path(*units):
214 print()
215 for unit in units:
216 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
217 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
218 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
219
220def remove_unit_from_networkd_path(units):
221 for unit in units:
222 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
223 os.remove(os.path.join(network_unit_file_path, unit))
224 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
225 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
226
227def warn_about_firewalld():
228 rc = call('systemctl -q is-active firewalld.service')
229 if rc == 0:
230 print('\nWARNING: firewalld.service is active. The test may fail.')
231
232def start_dnsmasq(additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'):
233 warn_about_firewalld()
234 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
235 check_output(dnsmasq_command)
236
237def stop_dnsmasq(pid_file):
238 if os.path.exists(pid_file):
239 with open(pid_file, 'r') as f:
240 pid = f.read().rstrip(' \t\r\n\0')
241 os.kill(int(pid), signal.SIGTERM)
242
243 os.remove(pid_file)
244
245def search_words_in_dnsmasq_log(words, show_all=False):
246 if os.path.exists(dnsmasq_log_file):
247 with open (dnsmasq_log_file) as in_file:
248 contents = in_file.read()
249 if show_all:
250 print(contents)
251 for line in contents.splitlines():
252 if words in line:
253 in_file.close()
254 print("%s, %s" % (words, line))
255 return True
256 return False
257
258def remove_lease_file():
259 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
260 os.remove(os.path.join(networkd_ci_path, 'lease'))
261
262def remove_log_file():
263 if os.path.exists(dnsmasq_log_file):
264 os.remove(dnsmasq_log_file)
265
266def start_networkd(sleep_sec=5, remove_state_files=True):
267 if (remove_state_files and
268 os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
269 check_output('systemctl stop systemd-networkd')
270 os.remove(os.path.join(networkd_runtime_directory, 'state'))
271 check_output('systemctl start systemd-networkd')
272 else:
273 check_output('systemctl restart systemd-networkd')
274 if sleep_sec > 0:
275 time.sleep(sleep_sec)
276
277def wait_online(links_with_operstate, timeout='20s', bool_any=False):
278 args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
279 if bool_any:
280 args += ['--any']
281 try:
282 check_output(*args, env=env)
283 except subprocess.CalledProcessError:
284 for link in links_with_operstate:
285 output = check_output(*networkctl_cmd, 'status', link.split(':')[0], env=env)
286 print(output)
287 raise
4d7ed14f 288
ec38833c
ZJS
289def get_operstate(link, show_status=True, setup_state='configured'):
290 output = check_output(*networkctl_cmd, 'status', link, env=env)
291 if show_status:
292 print(output)
293 for line in output.splitlines():
294 if 'State:' in line and (not setup_state or setup_state in line):
295 return line.split()[1]
296 return None
1f0e3109 297
ec38833c 298class Utilities():
e39cc445 299 def check_link_exists(self, link):
ec38833c 300 self.assertTrue(link_exists(link))
2be0b6fc
YW
301
302 def check_operstate(self, link, expected, show_status=True, setup_state='configured'):
ec38833c 303 self.assertRegex(get_operstate(link, show_status, setup_state), expected)
2be0b6fc 304
53c32c2b 305 def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
2629df47
YW
306 for i in range(timeout_sec):
307 if i > 0:
308 time.sleep(1)
371810d1 309 output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
2629df47
YW
310 if re.search(address_regex, output):
311 break
312 else:
313 self.assertRegex(output, address_regex)
314
1ca44d7d
YW
315class NetworkctlTests(unittest.TestCase, Utilities):
316
317 links = [
318 'test1',
319 'veth99',
320 ]
321
322 units = [
323 '11-dummy.netdev',
6d5b4efe 324 '11-dummy-mtu.netdev',
1ca44d7d
YW
325 '11-dummy.network',
326 '25-veth.netdev',
327 'netdev-link-local-addressing-yes.network',
328 ]
329
330 def setUp(self):
ec38833c 331 remove_links(self.links)
1ca44d7d
YW
332
333 def tearDown(self):
ec38833c
ZJS
334 remove_links(self.links)
335 remove_unit_from_networkd_path(self.units)
1ca44d7d
YW
336
337 def test_glob(self):
ec38833c
ZJS
338 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
339 start_networkd(0)
1ca44d7d 340
ec38833c 341 wait_online(['test1:degraded'])
1ca44d7d 342
371810d1 343 output = check_output(*networkctl_cmd, 'list', env=env)
1ca44d7d
YW
344 self.assertRegex(output, '1 lo ')
345 self.assertRegex(output, 'test1')
346
371810d1 347 output = check_output(*networkctl_cmd, 'list', 'test1', env=env)
1ca44d7d
YW
348 self.assertNotRegex(output, '1 lo ')
349 self.assertRegex(output, 'test1')
350
371810d1 351 output = check_output(*networkctl_cmd, 'list', 'te*', env=env)
1ca44d7d
YW
352 self.assertNotRegex(output, '1 lo ')
353 self.assertRegex(output, 'test1')
354
371810d1 355 output = check_output(*networkctl_cmd, 'status', 'te*', env=env)
1ca44d7d
YW
356 self.assertNotRegex(output, '1: lo ')
357 self.assertRegex(output, 'test1')
358
371810d1 359 output = check_output(*networkctl_cmd, 'status', 'tes[a-z][0-9]', env=env)
1ca44d7d
YW
360 self.assertNotRegex(output, '1: lo ')
361 self.assertRegex(output, 'test1')
362
6d5b4efe 363 def test_mtu(self):
ec38833c
ZJS
364 copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network')
365 start_networkd(0)
6d5b4efe 366
ec38833c 367 wait_online(['test1:degraded'])
6d5b4efe 368
371810d1 369 output = check_output(*networkctl_cmd, 'status', 'test1', env=env)
6d5b4efe
YW
370 self.assertRegex(output, 'MTU: 1600')
371
1ca44d7d
YW
372 @expectedFailureIfEthtoolDoesNotSupportDriver()
373 def test_udev_driver(self):
ec38833c
ZJS
374 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
375 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
376 start_networkd(0)
1ca44d7d 377
ec38833c 378 wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
1ca44d7d 379
371810d1 380 output = check_output(*networkctl_cmd, 'status', 'test1', env=env)
1ca44d7d
YW
381 self.assertRegex(output, 'Driver: dummy')
382
371810d1 383 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1ca44d7d
YW
384 self.assertRegex(output, 'Driver: veth')
385
371810d1 386 output = check_output(*networkctl_cmd, 'status', 'veth-peer', env=env)
1ca44d7d 387 self.assertRegex(output, 'Driver: veth')
2be0b6fc 388
bee692fd 389 def test_delete_links(self):
ec38833c
ZJS
390 copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network',
391 '25-veth.netdev', 'netdev-link-local-addressing-yes.network')
392 start_networkd(0)
bee692fd 393
ec38833c 394 wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
bee692fd 395
371810d1 396 check_output(*networkctl_cmd, 'delete', 'test1', 'veth99')
ec38833c
ZJS
397 self.assertFalse(link_exists('test1'))
398 self.assertFalse(link_exists('veth99'))
399 self.assertFalse(link_exists('veth-peer'))
bee692fd 400
1f0e3109
SS
401class NetworkdNetDevTests(unittest.TestCase, Utilities):
402
09ea6724
YW
403 links =[
404 '6rdtun99',
405 'bond99',
406 'bridge99',
407 'dropin-test',
408 'dummy98',
6a97a864
YW
409 'erspan98',
410 'erspan99',
09ea6724 411 'geneve99',
4b6a6d1e 412 'gretap96',
6a97a864 413 'gretap98',
09ea6724 414 'gretap99',
4b6a6d1e 415 'gretun96',
6a97a864
YW
416 'gretun97',
417 'gretun98',
09ea6724 418 'gretun99',
6a97a864 419 'ip6gretap98',
09ea6724 420 'ip6gretap99',
6a97a864
YW
421 'ip6gretun97',
422 'ip6gretun98',
423 'ip6gretun99',
424 'ip6tnl97',
425 'ip6tnl98',
09ea6724 426 'ip6tnl99',
4b6a6d1e 427 'ipiptun96',
6a97a864
YW
428 'ipiptun97',
429 'ipiptun98',
09ea6724
YW
430 'ipiptun99',
431 'ipvlan99',
956c8fec 432 'ipvtap99',
09ea6724
YW
433 'isataptun99',
434 'macvlan99',
435 'macvtap99',
811f33d0 436 'nlmon99',
4b6a6d1e 437 'sittun96',
6a97a864
YW
438 'sittun97',
439 'sittun98',
09ea6724
YW
440 'sittun99',
441 'tap99',
442 'test1',
443 'tun99',
444 'vcan99',
445 'veth99',
446 'vlan99',
447 'vrf99',
6a97a864
YW
448 'vti6tun97',
449 'vti6tun98',
09ea6724 450 'vti6tun99',
6a97a864
YW
451 'vtitun97',
452 'vtitun98',
09ea6724 453 'vtitun99',
f63b14d3 454 'vxcan99',
09ea6724 455 'vxlan99',
da44fb8a 456 'wg98',
09ea6724
YW
457 'wg99']
458
459 units = [
460 '10-dropin-test.netdev',
461 '11-dummy.netdev',
03db80b2 462 '11-dummy.network',
09ea6724 463 '12-dummy.netdev',
753e0a24 464 '15-name-conflict-test.netdev',
09ea6724
YW
465 '21-macvlan.netdev',
466 '21-macvtap.netdev',
7f45d738 467 '21-vlan-test1.network',
09ea6724
YW
468 '21-vlan.netdev',
469 '21-vlan.network',
470 '25-6rd-tunnel.netdev',
471 '25-bond.netdev',
fde60a42 472 '25-bond-balanced-tlb.netdev',
09ea6724 473 '25-bridge.netdev',
03db80b2 474 '25-bridge.network',
6a97a864 475 '25-erspan-tunnel-local-any.netdev',
09ea6724 476 '25-erspan-tunnel.netdev',
4b6a6d1e
YW
477 '25-fou-gretap.netdev',
478 '25-fou-gre.netdev',
479 '25-fou-ipip.netdev',
480 '25-fou-ipproto-gre.netdev',
481 '25-fou-ipproto-ipip.netdev',
482 '25-fou-sit.netdev',
09ea6724 483 '25-geneve.netdev',
6a97a864 484 '25-gretap-tunnel-local-any.netdev',
09ea6724 485 '25-gretap-tunnel.netdev',
6a97a864
YW
486 '25-gre-tunnel-local-any.netdev',
487 '25-gre-tunnel-remote-any.netdev',
09ea6724 488 '25-gre-tunnel.netdev',
6a97a864
YW
489 '25-ip6gretap-tunnel-local-any.netdev',
490 '25-ip6gretap-tunnel.netdev',
491 '25-ip6gre-tunnel-local-any.netdev',
492 '25-ip6gre-tunnel-remote-any.netdev',
09ea6724 493 '25-ip6gre-tunnel.netdev',
6a97a864
YW
494 '25-ip6tnl-tunnel-remote-any.netdev',
495 '25-ip6tnl-tunnel-local-any.netdev',
09ea6724
YW
496 '25-ip6tnl-tunnel.netdev',
497 '25-ipip-tunnel-independent.netdev',
6a97a864
YW
498 '25-ipip-tunnel-local-any.netdev',
499 '25-ipip-tunnel-remote-any.netdev',
09ea6724
YW
500 '25-ipip-tunnel.netdev',
501 '25-ipvlan.netdev',
956c8fec 502 '25-ipvtap.netdev',
09ea6724 503 '25-isatap-tunnel.netdev',
02849d8b
YW
504 '25-macsec.key',
505 '25-macsec.netdev',
506 '25-macsec.network',
811f33d0 507 '25-nlmon.netdev',
6a97a864
YW
508 '25-sit-tunnel-local-any.netdev',
509 '25-sit-tunnel-remote-any.netdev',
09ea6724
YW
510 '25-sit-tunnel.netdev',
511 '25-tap.netdev',
512 '25-tun.netdev',
11309591
YW
513 '25-tunnel-local-any.network',
514 '25-tunnel-remote-any.network',
515 '25-tunnel.network',
09ea6724
YW
516 '25-vcan.netdev',
517 '25-veth.netdev',
518 '25-vrf.netdev',
6a97a864
YW
519 '25-vti6-tunnel-local-any.netdev',
520 '25-vti6-tunnel-remote-any.netdev',
09ea6724 521 '25-vti6-tunnel.netdev',
6a97a864
YW
522 '25-vti-tunnel-local-any.netdev',
523 '25-vti-tunnel-remote-any.netdev',
09ea6724 524 '25-vti-tunnel.netdev',
f63b14d3 525 '25-vxcan.netdev',
09ea6724 526 '25-vxlan.netdev',
da44fb8a
YW
527 '25-wireguard-23-peers.netdev',
528 '25-wireguard-23-peers.network',
9e5d79e7 529 '25-wireguard-preshared-key.txt',
39bcff3b 530 '25-wireguard-private-key.txt',
09ea6724 531 '25-wireguard.netdev',
5a0bd90b 532 '25-wireguard.network',
09ea6724 533 '6rd.network',
6730a1f3 534 'erspan.network',
09ea6724
YW
535 'gre.network',
536 'gretap.network',
537 'gretun.network',
538 'ip6gretap.network',
6a97a864 539 'ip6gretun.network',
09ea6724
YW
540 'ip6tnl.network',
541 'ipip.network',
542 'ipvlan.network',
956c8fec 543 'ipvtap.network',
09ea6724 544 'isatap.network',
02849d8b 545 'macsec.network',
09ea6724
YW
546 'macvlan.network',
547 'macvtap.network',
077f9abc 548 'netdev-link-local-addressing-yes.network',
09ea6724
YW
549 'sit.network',
550 'vti6.network',
551 'vti.network',
1c862fe0 552 'vxlan-test1.network',
09ea6724 553 'vxlan.network']
1f0e3109 554
def9fc0d
YW
555 fou_ports = [
556 '55555',
557 '55556']
558
1f0e3109 559 def setUp(self):
ec38833c
ZJS
560 remove_fou_ports(self.fou_ports)
561 remove_links(self.links)
1f0e3109
SS
562
563 def tearDown(self):
ec38833c
ZJS
564 remove_fou_ports(self.fou_ports)
565 remove_links(self.links)
566 remove_unit_from_networkd_path(self.units)
1f0e3109 567
1ca44d7d 568 def test_dropin_and_name_conflict(self):
ec38833c
ZJS
569 copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
570 start_networkd(0)
d80734f7 571
ec38833c 572 wait_online(['dropin-test:off'])
d80734f7 573
371810d1 574 output = check_output('ip link show dropin-test')
d80734f7
YW
575 print(output)
576 self.assertRegex(output, '00:50:56:c0:00:28')
577
03db80b2 578 def test_wait_online_any(self):
ec38833c
ZJS
579 copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
580 start_networkd(0)
03db80b2 581
ec38833c 582 wait_online(['bridge99', 'test1:degraded'], bool_any=True)
03db80b2 583
791c1140
YW
584 self.check_operstate('bridge99', '(?:off|no-carrier)', setup_state='configuring')
585 self.check_operstate('test1', 'degraded')
03db80b2 586
1f0e3109 587 def test_bridge(self):
ec38833c
ZJS
588 copy_unit_to_networkd_unit_path('25-bridge.netdev')
589 start_networkd(0)
1f0e3109 590
ec38833c 591 wait_online(['bridge99:off'])
1f0e3109 592
3d165124 593 tick = os.sysconf('SC_CLK_TCK')
ec38833c
ZJS
594 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick))
595 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick))
596 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge','forward_delay')) / tick))
597 self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge','ageing_time')) / tick))
598 self.assertEqual(9, int(read_link_attr('bridge99', 'bridge','priority')))
599 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge','multicast_querier')))
600 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge','multicast_snooping')))
601 self.assertEqual(1, int(read_link_attr('bridge99', 'bridge','stp_state')))
1f0e3109
SS
602
603 def test_bond(self):
ec38833c
ZJS
604 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
605 start_networkd(0)
606
607 wait_online(['bond99:off', 'bond98:off'])
608
609 self.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
610 self.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
611 self.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
612 self.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
613 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
614 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
615 self.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
616 self.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
617 self.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
618 self.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
619 self.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
620
621 self.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
622 self.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
fde60a42 623
1f0e3109 624 def test_vlan(self):
ec38833c
ZJS
625 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
626 '21-vlan.network', '21-vlan-test1.network')
627 start_networkd(0)
1f0e3109 628
ec38833c 629 wait_online(['test1:degraded', 'vlan99:routable'])
1f0e3109 630
371810d1 631 output = check_output('ip -d link show test1')
72b7f1b9 632 print(output)
7d7be1b9 633 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 634
371810d1 635 output = check_output('ip -d link show vlan99')
14ecd604 636 print(output)
06895a1d
YW
637 self.assertRegex(output, ' mtu 2000 ')
638 self.assertRegex(output, 'REORDER_HDR')
639 self.assertRegex(output, 'LOOSE_BINDING')
640 self.assertRegex(output, 'GVRP')
641 self.assertRegex(output, 'MVRP')
642 self.assertRegex(output, ' id 99 ')
1f0e3109 643
371810d1 644 output = check_output('ip -4 address show dev test1')
7f45d738
YW
645 print(output)
646 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
647 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
648
371810d1 649 output = check_output('ip -4 address show dev vlan99')
7f45d738
YW
650 print(output)
651 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
652
1f0e3109 653 def test_macvtap(self):
460feb61
YW
654 for mode in ['private', 'vepa', 'bridge', 'passthru']:
655 with self.subTest(mode=mode):
656 if mode != 'private':
657 self.tearDown()
ec38833c
ZJS
658 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
659 '11-dummy.netdev', 'macvtap.network')
460feb61
YW
660 with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f:
661 f.write('[MACVTAP]\nMode=' + mode)
ec38833c 662 start_networkd(0)
1f0e3109 663
ec38833c 664 wait_online(['macvtap99:degraded', 'test1:degraded'])
460feb61 665
371810d1 666 output = check_output('ip -d link show macvtap99')
460feb61
YW
667 print(output)
668 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
1f0e3109
SS
669
670 def test_macvlan(self):
dff9792b
YW
671 for mode in ['private', 'vepa', 'bridge', 'passthru']:
672 with self.subTest(mode=mode):
673 if mode != 'private':
674 self.tearDown()
ec38833c
ZJS
675 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
676 '11-dummy.netdev', 'macvlan.network')
dff9792b
YW
677 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
678 f.write('[MACVLAN]\nMode=' + mode)
ec38833c 679 start_networkd(0)
dff9792b 680
ec38833c 681 wait_online(['macvlan99:degraded', 'test1:degraded'])
dff9792b 682
371810d1 683 output = check_output('ip -d link show test1')
dff9792b
YW
684 print(output)
685 self.assertRegex(output, ' mtu 2000 ')
72b7f1b9 686
371810d1 687 output = check_output('ip -d link show macvlan99')
dff9792b
YW
688 print(output)
689 self.assertRegex(output, ' mtu 2000 ')
690 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
72b7f1b9 691
7a0a37b2 692 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109 693 def test_ipvlan(self):
bc6dff6e
YW
694 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
695 with self.subTest(mode=mode, flag=flag):
696 if mode != 'L2':
697 self.tearDown()
ec38833c
ZJS
698 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
699 '11-dummy.netdev', 'ipvlan.network')
bc6dff6e
YW
700 with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f:
701 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
1f0e3109 702
ec38833c
ZJS
703 start_networkd(0)
704 wait_online(['ipvlan99:degraded', 'test1:degraded'])
bc6dff6e 705
371810d1 706 output = check_output('ip -d link show ipvlan99')
bc6dff6e
YW
707 print(output)
708 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
1f0e3109 709
956c8fec
YW
710 @expectedFailureIfModuleIsNotAvailable('ipvtap')
711 def test_ipvtap(self):
40921f08
YW
712 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
713 with self.subTest(mode=mode, flag=flag):
714 if mode != 'L2':
715 self.tearDown()
ec38833c
ZJS
716 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
717 '11-dummy.netdev', 'ipvtap.network')
40921f08
YW
718 with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f:
719 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
720
ec38833c
ZJS
721 start_networkd(0)
722 wait_online(['ipvtap99:degraded', 'test1:degraded'])
956c8fec 723
371810d1 724 output = check_output('ip -d link show ipvtap99')
40921f08
YW
725 print(output)
726 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
956c8fec 727
1f0e3109 728 def test_veth(self):
ec38833c
ZJS
729 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
730 start_networkd(0)
1f0e3109 731
ec38833c 732 wait_online(['veth99:degraded', 'veth-peer:degraded'])
671dacdf 733
371810d1 734 output = check_output('ip -d link show veth99')
671dacdf
YW
735 print(output)
736 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
371810d1 737 output = check_output('ip -d link show veth-peer')
671dacdf
YW
738 print(output)
739 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
1f0e3109 740
1f0e3109 741 def test_tun(self):
ec38833c
ZJS
742 copy_unit_to_networkd_unit_path('25-tun.netdev')
743 start_networkd(0)
1f0e3109 744
ec38833c 745 wait_online(['tun99:off'])
1f0e3109 746
371810d1 747 output = check_output('ip -d link show tun99')
2746d307
YW
748 print(output)
749 # Old ip command does not support IFF_ flags
750 self.assertRegex(output, 'tun (?:type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
751
1f0e3109 752 def test_tap(self):
ec38833c
ZJS
753 copy_unit_to_networkd_unit_path('25-tap.netdev')
754 start_networkd(0)
1f0e3109 755
ec38833c 756 wait_online(['tap99:off'])
1f0e3109 757
371810d1 758 output = check_output('ip -d link show tap99')
2746d307
YW
759 print(output)
760 # Old ip command does not support IFF_ flags
761 self.assertRegex(output, 'tun (?:type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
762
7a0a37b2 763 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109 764 def test_vrf(self):
ec38833c
ZJS
765 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
766 start_networkd(0)
1f0e3109 767
ec38833c 768 wait_online(['vrf99:carrier'])
1f0e3109 769
7a0a37b2 770 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109 771 def test_vcan(self):
ec38833c
ZJS
772 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
773 start_networkd(0)
1f0e3109 774
ec38833c 775 wait_online(['vcan99:carrier'])
1f0e3109 776
f63b14d3
YW
777 @expectedFailureIfModuleIsNotAvailable('vxcan')
778 def test_vxcan(self):
ec38833c
ZJS
779 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
780 start_networkd(0)
f63b14d3 781
ec38833c 782 wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
f63b14d3 783
7a3bc5a8
EV
784 @expectedFailureIfModuleIsNotAvailable('wireguard')
785 def test_wireguard(self):
ec38833c
ZJS
786 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
787 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
788 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
789 start_networkd(0)
790 wait_online(['wg99:carrier', 'wg98:routable'])
5a0bd90b 791
7a3bc5a8 792 if shutil.which('wg'):
371810d1 793 call('wg')
5a0bd90b 794
371810d1 795 output = check_output('wg show wg99 listen-port')
06895a1d 796 self.assertRegex(output, '51820')
371810d1 797 output = check_output('wg show wg99 fwmark')
06895a1d 798 self.assertRegex(output, '0x4d2')
371810d1 799 output = check_output('wg show wg99 allowed-ips')
88aaf89e
ZJS
800 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
801 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
371810d1 802 output = check_output('wg show wg99 persistent-keepalive')
88aaf89e 803 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
371810d1 804 output = check_output('wg show wg99 endpoints')
88aaf89e 805 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
371810d1 806 output = check_output('wg show wg99 private-key')
88aaf89e 807 self.assertRegex(output, r'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
371810d1 808 output = check_output('wg show wg99 preshared-keys')
88aaf89e
ZJS
809 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
810 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
7a3bc5a8 811
371810d1 812 output = check_output('wg show wg98 private-key')
88aaf89e 813 self.assertRegex(output, r'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
da44fb8a 814
1f0e3109 815 def test_geneve(self):
ec38833c
ZJS
816 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
817 start_networkd(0)
1f0e3109 818
ec38833c 819 wait_online(['geneve99:degraded'])
1f0e3109 820
371810d1 821 output = check_output('ip -d link show geneve99')
14ecd604 822 print(output)
06895a1d
YW
823 self.assertRegex(output, '192.168.22.1')
824 self.assertRegex(output, '6082')
825 self.assertRegex(output, 'udpcsum')
826 self.assertRegex(output, 'udp6zerocsumrx')
1f0e3109
SS
827
828 def test_ipip_tunnel(self):
ec38833c
ZJS
829 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
830 '25-ipip-tunnel.netdev', '25-tunnel.network',
831 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
832 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
833 start_networkd(0)
834 wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'dummy98:degraded'])
6a97a864 835
371810d1 836 output = check_output('ip -d link show ipiptun99')
6a97a864
YW
837 print(output)
838 self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local 192.168.223.238 dev dummy98')
371810d1 839 output = check_output('ip -d link show ipiptun98')
6a97a864
YW
840 print(output)
841 self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local any dev dummy98')
371810d1 842 output = check_output('ip -d link show ipiptun97')
6a97a864
YW
843 print(output)
844 self.assertRegex(output, 'ipip (?:ipip |)remote any local 192.168.223.238 dev dummy98')
1f0e3109
SS
845
846 def test_gre_tunnel(self):
ec38833c
ZJS
847 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
848 '25-gre-tunnel.netdev', '25-tunnel.network',
849 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
850 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
851 start_networkd(0)
852 wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'dummy98:degraded'])
6a97a864 853
371810d1 854 output = check_output('ip -d link show gretun99')
6a97a864
YW
855 print(output)
856 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
857 self.assertRegex(output, 'ikey 1.2.3.103')
858 self.assertRegex(output, 'okey 1.2.4.103')
859 self.assertRegex(output, 'iseq')
860 self.assertRegex(output, 'oseq')
371810d1 861 output = check_output('ip -d link show gretun98')
6a97a864
YW
862 print(output)
863 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
864 self.assertRegex(output, 'ikey 0.0.0.104')
865 self.assertRegex(output, 'okey 0.0.0.104')
866 self.assertNotRegex(output, 'iseq')
867 self.assertNotRegex(output, 'oseq')
371810d1 868 output = check_output('ip -d link show gretun97')
6a97a864
YW
869 print(output)
870 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
38f4bb44
YW
871 self.assertRegex(output, 'ikey 0.0.0.105')
872 self.assertRegex(output, 'okey 0.0.0.105')
873 self.assertNotRegex(output, 'iseq')
874 self.assertNotRegex(output, 'oseq')
6a97a864
YW
875
876 def test_ip6gre_tunnel(self):
ec38833c
ZJS
877 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
878 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
879 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
880 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
01943d43 881 start_networkd(5)
6a97a864 882
17bcf0a0
YW
883 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
884
e39cc445
YW
885 self.check_link_exists('dummy98')
886 self.check_link_exists('ip6gretun99')
887 self.check_link_exists('ip6gretun98')
888 self.check_link_exists('ip6gretun97')
6a97a864 889
371810d1 890 output = check_output('ip -d link show ip6gretun99')
6a97a864
YW
891 print(output)
892 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 893 output = check_output('ip -d link show ip6gretun98')
6a97a864
YW
894 print(output)
895 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
371810d1 896 output = check_output('ip -d link show ip6gretun97')
6a97a864
YW
897 print(output)
898 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109 899
11309591 900 def test_gretap_tunnel(self):
ec38833c
ZJS
901 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
902 '25-gretap-tunnel.netdev', '25-tunnel.network',
903 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
904 start_networkd(0)
905 wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
6a97a864 906
371810d1 907 output = check_output('ip -d link show gretap99')
6a97a864
YW
908 print(output)
909 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
38f4bb44
YW
910 self.assertRegex(output, 'ikey 0.0.0.106')
911 self.assertRegex(output, 'okey 0.0.0.106')
912 self.assertRegex(output, 'iseq')
913 self.assertRegex(output, 'oseq')
371810d1 914 output = check_output('ip -d link show gretap98')
6a97a864
YW
915 print(output)
916 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
38f4bb44
YW
917 self.assertRegex(output, 'ikey 0.0.0.107')
918 self.assertRegex(output, 'okey 0.0.0.107')
919 self.assertRegex(output, 'iseq')
920 self.assertRegex(output, 'oseq')
1f0e3109
SS
921
922 def test_ip6gretap_tunnel(self):
ec38833c
ZJS
923 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
924 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
925 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
926 start_networkd(0)
927 wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
6a97a864 928
371810d1 929 output = check_output('ip -d link show ip6gretap99')
6a97a864
YW
930 print(output)
931 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 932 output = check_output('ip -d link show ip6gretap98')
6a97a864
YW
933 print(output)
934 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1f0e3109
SS
935
936 def test_vti_tunnel(self):
ec38833c
ZJS
937 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
938 '25-vti-tunnel.netdev', '25-tunnel.network',
939 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
940 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
941 start_networkd(0)
942 wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'dummy98:degraded'])
6a97a864 943
371810d1 944 output = check_output('ip -d link show vtitun99')
6a97a864
YW
945 print(output)
946 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
371810d1 947 output = check_output('ip -d link show vtitun98')
6a97a864
YW
948 print(output)
949 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
371810d1 950 output = check_output('ip -d link show vtitun97')
6a97a864
YW
951 print(output)
952 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
1f0e3109
SS
953
954 def test_vti6_tunnel(self):
ec38833c
ZJS
955 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
956 '25-vti6-tunnel.netdev', '25-tunnel.network',
957 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
958 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
959 start_networkd(0)
960 wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
6a97a864 961
371810d1 962 output = check_output('ip -d link show vti6tun99')
6a97a864
YW
963 print(output)
964 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 965 output = check_output('ip -d link show vti6tun98')
6a97a864
YW
966 print(output)
967 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
371810d1 968 output = check_output('ip -d link show vti6tun97')
6a97a864
YW
969 print(output)
970 self.assertRegex(output, 'vti6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
971
972 def test_ip6tnl_tunnel(self):
ec38833c
ZJS
973 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
974 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
975 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
976 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
977 start_networkd(0)
978 wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
6a97a864 979
371810d1 980 output = check_output('ip -d link show ip6tnl99')
6a97a864
YW
981 print(output)
982 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
371810d1 983 output = check_output('ip -d link show ip6tnl98')
6a97a864
YW
984 print(output)
985 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
371810d1 986 output = check_output('ip -d link show ip6tnl97')
6a97a864
YW
987 print(output)
988 self.assertRegex(output, 'ip6tnl ip6ip6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1f0e3109
SS
989
990 def test_sit_tunnel(self):
ec38833c
ZJS
991 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
992 '25-sit-tunnel.netdev', '25-tunnel.network',
993 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
994 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
995 start_networkd(0)
996 wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'dummy98:degraded'])
6a97a864 997
371810d1 998 output = check_output('ip -d link show sittun99')
6a97a864
YW
999 print(output)
1000 self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local 10.65.223.238 dev dummy98")
371810d1 1001 output = check_output('ip -d link show sittun98')
6a97a864
YW
1002 print(output)
1003 self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local any dev dummy98")
371810d1 1004 output = check_output('ip -d link show sittun97')
6a97a864
YW
1005 print(output)
1006 self.assertRegex(output, "sit (?:ip6ip |)remote any local 10.65.223.238 dev dummy98")
1f0e3109 1007
d0e728b6 1008 def test_isatap_tunnel(self):
ec38833c
ZJS
1009 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1010 '25-isatap-tunnel.netdev', '25-tunnel.network')
1011 start_networkd(0)
1012 wait_online(['isataptun99:routable', 'dummy98:degraded'])
d0e728b6 1013
371810d1 1014 output = check_output('ip -d link show isataptun99')
14ecd604 1015 print(output)
d0e728b6
SS
1016 self.assertRegex(output, "isatap ")
1017
d29dc4f1 1018 def test_6rd_tunnel(self):
ec38833c
ZJS
1019 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1020 '25-6rd-tunnel.netdev', '25-tunnel.network')
1021 start_networkd(0)
1022 wait_online(['sittun99:routable', 'dummy98:degraded'])
d29dc4f1 1023
371810d1 1024 output = check_output('ip -d link show sittun99')
6a97a864
YW
1025 print(output)
1026 self.assertRegex(output, '6rd-prefix 2602::/24')
1027
7bea7f9b 1028 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b 1029 def test_erspan_tunnel(self):
ec38833c
ZJS
1030 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1031 '25-erspan-tunnel.netdev', '25-tunnel.network',
1032 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1033 start_networkd(0)
1034 wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
2266864b 1035
371810d1 1036 output = check_output('ip -d link show erspan99')
6a97a864
YW
1037 print(output)
1038 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
38f4bb44
YW
1039 self.assertRegex(output, 'ikey 0.0.0.101')
1040 self.assertRegex(output, 'okey 0.0.0.101')
1041 self.assertRegex(output, 'iseq')
1042 self.assertRegex(output, 'oseq')
371810d1 1043 output = check_output('ip -d link show erspan98')
2266864b 1044 print(output)
6a97a864
YW
1045 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
1046 self.assertRegex(output, '102')
38f4bb44
YW
1047 self.assertRegex(output, 'ikey 0.0.0.102')
1048 self.assertRegex(output, 'okey 0.0.0.102')
1049 self.assertRegex(output, 'iseq')
1050 self.assertRegex(output, 'oseq')
2266864b 1051
1f0e3109 1052 def test_tunnel_independent(self):
ec38833c
ZJS
1053 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
1054 start_networkd(0)
e40a58b5 1055
ec38833c 1056 wait_online(['ipiptun99:carrier'])
1f0e3109 1057
4b6a6d1e
YW
1058 @expectedFailureIfModuleIsNotAvailable('fou')
1059 def test_fou(self):
1060 # The following redundant check is necessary for CentOS CI.
1061 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1062 self.assertTrue(is_module_available('fou'))
1063
ec38833c
ZJS
1064 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1065 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1066 '25-fou-gre.netdev', '25-fou-gretap.netdev')
1067 start_networkd(0)
4b6a6d1e 1068
ec38833c 1069 wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'])
4b6a6d1e 1070
371810d1 1071 output = check_output('ip fou show')
4b6a6d1e
YW
1072 print(output)
1073 self.assertRegex(output, 'port 55555 ipproto 4')
1074 self.assertRegex(output, 'port 55556 ipproto 47')
1075
371810d1 1076 output = check_output('ip -d link show ipiptun96')
4b6a6d1e
YW
1077 print(output)
1078 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1079 output = check_output('ip -d link show sittun96')
4b6a6d1e
YW
1080 print(output)
1081 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
371810d1 1082 output = check_output('ip -d link show gretun96')
4b6a6d1e
YW
1083 print(output)
1084 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
371810d1 1085 output = check_output('ip -d link show gretap96')
4b6a6d1e
YW
1086 print(output)
1087 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1088
1f0e3109 1089 def test_vxlan(self):
ec38833c
ZJS
1090 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1091 '11-dummy.netdev', 'vxlan-test1.network')
1092 start_networkd(0)
1f0e3109 1093
ec38833c 1094 wait_online(['test1:degraded', 'vxlan99:degraded'])
1f0e3109 1095
371810d1 1096 output = check_output('ip -d link show vxlan99')
14ecd604 1097 print(output)
1c862fe0 1098 self.assertRegex(output, '999')
1f0e3109
SS
1099 self.assertRegex(output, '5555')
1100 self.assertRegex(output, 'l2miss')
1101 self.assertRegex(output, 'l3miss')
1102 self.assertRegex(output, 'udpcsum')
1103 self.assertRegex(output, 'udp6zerocsumtx')
1104 self.assertRegex(output, 'udp6zerocsumrx')
1105 self.assertRegex(output, 'remcsumtx')
1106 self.assertRegex(output, 'remcsumrx')
1107 self.assertRegex(output, 'gbp')
1108
371810d1 1109 output = check_output('bridge fdb show dev vxlan99')
1c862fe0
YW
1110 print(output)
1111 self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1112 self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1113 self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1114
02849d8b 1115 def test_macsec(self):
ec38833c
ZJS
1116 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1117 'macsec.network', '12-dummy.netdev')
1118 start_networkd(0)
02849d8b 1119
ec38833c 1120 wait_online(['dummy98:degraded', 'macsec99:routable'])
02849d8b 1121
371810d1 1122 output = check_output('ip -d link show macsec99')
02849d8b
YW
1123 print(output)
1124 self.assertRegex(output, 'macsec99@dummy98')
1125 self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
1126 self.assertRegex(output, 'encrypt on')
1127
371810d1 1128 output = check_output('ip macsec show macsec99')
02849d8b
YW
1129 print(output)
1130 self.assertRegex(output, 'encrypt on')
1131 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
1132 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1133 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1134 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on')
1135 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1136 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1137 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1138 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1139 self.assertNotRegex(output, 'key 02030405067080900000000000000000')
1140 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
1141 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1142
811f33d0 1143 def test_nlmon(self):
ec38833c 1144 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
df7f9afa 1145 start_networkd(0)
811f33d0 1146
ec38833c 1147 wait_online(['nlmon99:carrier'])
02849d8b 1148
cff83db9
YW
1149class NetworkdL2TPTests(unittest.TestCase, Utilities):
1150
1151 links =[
1152 'l2tp-ses1',
1153 'l2tp-ses2',
1154 'l2tp-ses3',
1155 'l2tp-ses4',
1156 'test1']
1157
1158 units = [
1159 '11-dummy.netdev',
1160 '25-l2tp-dummy.network',
1161 '25-l2tp-ip.netdev',
1162 '25-l2tp-udp.netdev']
1163
1164 l2tp_tunnel_ids = [ '10' ]
1165
1166 def setUp(self):
ec38833c
ZJS
1167 l2tp_tunnel_remove(self.l2tp_tunnel_ids)
1168 remove_links(self.links)
cff83db9
YW
1169
1170 def tearDown(self):
ec38833c
ZJS
1171 l2tp_tunnel_remove(self.l2tp_tunnel_ids)
1172 remove_links(self.links)
1173 remove_unit_from_networkd_path(self.units)
cff83db9
YW
1174
1175 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1176 def test_l2tp_udp(self):
ec38833c
ZJS
1177 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', '25-l2tp-udp.netdev')
1178 start_networkd(0)
cff83db9 1179
ec38833c 1180 wait_online(['test1:routable', 'l2tp-ses1:off', 'l2tp-ses2:off'])
cff83db9 1181
371810d1 1182 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1183 print(output)
1184 self.assertRegex(output, "Tunnel 10, encap UDP")
1185 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1186 self.assertRegex(output, "Peer tunnel 11")
1187 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
1188 self.assertRegex(output, "UDP checksum: enabled")
1189
371810d1 1190 output = check_output('ip l2tp show session tid 10 session_id 15')
cff83db9
YW
1191 print(output)
1192 self.assertRegex(output, "Session 15 in tunnel 10")
1193 self.assertRegex(output, "Peer session 16, tunnel 11")
1194 self.assertRegex(output, "interface name: l2tp-ses1")
1195
371810d1 1196 output = check_output('ip l2tp show session tid 10 session_id 17')
cff83db9
YW
1197 print(output)
1198 self.assertRegex(output, "Session 17 in tunnel 10")
1199 self.assertRegex(output, "Peer session 18, tunnel 11")
1200 self.assertRegex(output, "interface name: l2tp-ses2")
1201
1202 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1203 def test_l2tp_ip(self):
ec38833c
ZJS
1204 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', '25-l2tp-ip.netdev')
1205 start_networkd(0)
cff83db9 1206
ec38833c 1207 wait_online(['test1:routable', 'l2tp-ses3:off', 'l2tp-ses4:off'])
cff83db9 1208
371810d1 1209 output = check_output('ip l2tp show tunnel tunnel_id 10')
cff83db9
YW
1210 print(output)
1211 self.assertRegex(output, "Tunnel 10, encap IP")
1212 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1213 self.assertRegex(output, "Peer tunnel 12")
1214
371810d1 1215 output = check_output('ip l2tp show session tid 10 session_id 25')
cff83db9
YW
1216 print(output)
1217 self.assertRegex(output, "Session 25 in tunnel 10")
1218 self.assertRegex(output, "Peer session 26, tunnel 12")
1219 self.assertRegex(output, "interface name: l2tp-ses3")
1220
371810d1 1221 output = check_output('ip l2tp show session tid 10 session_id 27')
cff83db9
YW
1222 print(output)
1223 self.assertRegex(output, "Session 27 in tunnel 10")
1224 self.assertRegex(output, "Peer session 28, tunnel 12")
1225 self.assertRegex(output, "interface name: l2tp-ses4")
1226
be68c2c9 1227class NetworkdNetworkTests(unittest.TestCase, Utilities):
09ea6724
YW
1228 links = [
1229 'bond199',
1230 'dummy98',
cd65d067 1231 'dummy99',
09ea6724
YW
1232 'test1']
1233
1234 units = [
1235 '11-dummy.netdev',
1236 '12-dummy.netdev',
1237 '23-active-slave.network',
1e498853 1238 '24-keep-configuration-static.network',
fdcd1ec5 1239 '24-search-domain.network',
09ea6724 1240 '25-address-link-section.network',
b8102725
YW
1241 '25-address-preferred-lifetime-zero-ipv6.network',
1242 '25-address-static.network',
cd65d067 1243 '25-bind-carrier.network',
09ea6724
YW
1244 '25-bond-active-backup-slave.netdev',
1245 '25-fibrule-invert.network',
1246 '25-fibrule-port-range.network',
1247 '25-ipv6-address-label-section.network',
e4a71bf3 1248 '25-neighbor-section.network',
05514ae1
YW
1249 '25-link-local-addressing-no.network',
1250 '25-link-local-addressing-yes.network',
09ea6724 1251 '25-link-section-unmanaged.network',
20ca06a6 1252 '25-route-ipv6-src.network',
0ef830cf 1253 '25-route-static.network',
4da33154 1254 '25-sysctl-disable-ipv6.network',
09ea6724
YW
1255 '25-sysctl.network',
1256 'configure-without-carrier.network',
b677774d 1257 'routing-policy-rule-dummy98.network',
b8102725 1258 'routing-policy-rule-test1.network']
1f0e3109 1259
95c74b0a 1260 routing_policy_rule_tables = ['7', '8']
5f68a6a4 1261 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
95c74b0a 1262
1f0e3109 1263 def setUp(self):
ec38833c
ZJS
1264 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1265 remove_routes(self.routes)
1266 remove_links(self.links)
1f0e3109
SS
1267
1268 def tearDown(self):
ec38833c
ZJS
1269 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1270 remove_routes(self.routes)
1271 remove_links(self.links)
1272 remove_unit_from_networkd_path(self.units)
1f0e3109 1273
b8102725 1274 def test_address_static(self):
ec38833c
ZJS
1275 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1276 start_networkd(0)
b8102725 1277
ec38833c 1278 wait_online(['dummy98:routable'])
b8102725 1279
371810d1 1280 output = check_output('ip -4 address show dev dummy98')
b8102725
YW
1281 print(output)
1282 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1283 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1284 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1285
1286 # invalid sections
1287 self.assertNotRegex(output, '10.10.0.1/16')
1288 self.assertNotRegex(output, '10.10.0.2/16')
1289
371810d1 1290 output = check_output('ip -4 address show dev dummy98 label 32')
b8102725
YW
1291 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1292
371810d1 1293 output = check_output('ip -4 address show dev dummy98 label 33')
b8102725
YW
1294 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1295
371810d1 1296 output = check_output('ip -4 address show dev dummy98 label 34')
b8102725
YW
1297 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1298
371810d1 1299 output = check_output('ip -4 address show dev dummy98 label 35')
b8102725
YW
1300 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1301
371810d1 1302 output = check_output('ip -6 address show dev dummy98')
b8102725
YW
1303 print(output)
1304 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1305 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1306 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1307 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1308 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1309 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1310
1311 def test_address_preferred_lifetime_zero_ipv6(self):
ec38833c 1312 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero-ipv6.network', '12-dummy.netdev')
01943d43 1313 start_networkd(5)
1f0e3109 1314
e39cc445 1315 self.check_link_exists('dummy98')
791c1140 1316 self.check_operstate('dummy98', 'routable', setup_state='configuring')
b8102725 1317
371810d1 1318 output = check_output('ip address show dummy98')
b8102725
YW
1319 print(output)
1320 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1321 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1f0e3109
SS
1322
1323 def test_configure_without_carrier(self):
ec38833c 1324 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
df7f9afa
YW
1325 start_networkd(0)
1326 wait_online(['test1:routable'])
e40a58b5 1327
371810d1 1328 output = check_output(*networkctl_cmd, 'status', 'test1')
1f0e3109
SS
1329 print(output)
1330 self.assertRegex(output, '192.168.0.15')
1331 self.assertRegex(output, '192.168.0.1')
1332 self.assertRegex(output, 'routable')
1333
1f0e3109 1334 def test_routing_policy_rule(self):
ec38833c 1335 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
df7f9afa
YW
1336 start_networkd(0)
1337 wait_online(['test1:degraded'])
e40a58b5 1338
371810d1 1339 output = check_output('ip rule')
1f0e3109
SS
1340 print(output)
1341 self.assertRegex(output, '111')
1342 self.assertRegex(output, 'from 192.168.100.18')
f7bdd562 1343 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
1f0e3109
SS
1344 self.assertRegex(output, 'iif test1')
1345 self.assertRegex(output, 'oif test1')
1346 self.assertRegex(output, 'lookup 7')
1347
b677774d 1348 def test_routing_policy_rule_issue_11280(self):
ec38833c
ZJS
1349 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1350 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
b677774d 1351
b677774d
YW
1352 for trial in range(3):
1353 # Remove state files only first time
df7f9afa
YW
1354 start_networkd(0, remove_state_files=(trial == 0))
1355 wait_online(['test1:degraded', 'dummy98:degraded'])
1356 time.sleep(1)
b677774d 1357
371810d1 1358 output = check_output('ip rule list table 7')
b677774d
YW
1359 print(output)
1360 self.assertRegex(output, '111: from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
1361
371810d1 1362 output = check_output('ip rule list table 8')
b677774d
YW
1363 print(output)
1364 self.assertRegex(output, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1365
d586a2c3 1366 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0 1367 def test_routing_policy_rule_port_range(self):
ec38833c 1368 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
df7f9afa
YW
1369 start_networkd(0)
1370 wait_online(['test1:degraded'])
e40a58b5 1371
371810d1 1372 output = check_output('ip rule')
926062f0
SS
1373 print(output)
1374 self.assertRegex(output, '111')
1375 self.assertRegex(output, 'from 192.168.100.18')
1376 self.assertRegex(output, '1123-1150')
1377 self.assertRegex(output, '3224-3290')
1378 self.assertRegex(output, 'tcp')
1379 self.assertRegex(output, 'lookup 7')
1f0e3109 1380
d586a2c3 1381 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd 1382 def test_routing_policy_rule_invert(self):
ec38833c 1383 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
df7f9afa
YW
1384 start_networkd(0)
1385 wait_online(['test1:degraded'])
e40a58b5 1386
371810d1 1387 output = check_output('ip rule')
efecf9cd 1388 print(output)
efecf9cd
SS
1389 self.assertRegex(output, '111')
1390 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1391 self.assertRegex(output, 'tcp')
1392 self.assertRegex(output, 'lookup 7')
1393
0ef830cf 1394 def test_route_static(self):
ec38833c
ZJS
1395 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1396 start_networkd(0)
ec38833c 1397 wait_online(['dummy98:routable'])
0d34228f 1398
371810d1 1399 output = check_output('ip -6 route show dev dummy98')
0d34228f 1400 print(output)
0ef830cf
YW
1401 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1402 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1f0e3109 1403
371810d1 1404 output = check_output('ip -6 route show dev dummy98 default')
0ef830cf 1405 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1f0e3109 1406
371810d1 1407 output = check_output('ip -4 route show dev dummy98')
1f0e3109 1408 print(output)
0ef830cf
YW
1409 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1410 self.assertRegex(output, '149.10.124.64 proto static scope link')
2b00dff8 1411 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
0ef830cf
YW
1412 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1413 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
1f0e3109 1414
371810d1 1415 output = check_output('ip -4 route show dev dummy98 default')
0ef830cf
YW
1416 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1417 self.assertRegex(output, 'default via 149.10.124.64 proto static')
6543b7fd 1418 self.assertRegex(output, 'default proto static')
1f0e3109 1419
371810d1 1420 output = check_output('ip route show type blackhole')
1f0e3109 1421 print(output)
0ef830cf 1422 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
f5050e48 1423
371810d1 1424 output = check_output('ip route show type unreachable')
f5050e48 1425 print(output)
0ef830cf 1426 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
f5050e48 1427
371810d1 1428 output = check_output('ip route show type prohibit')
f5050e48 1429 print(output)
0ef830cf 1430 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
f5050e48 1431
20ca06a6
DA
1432 def test_ip_route_ipv6_src_route(self):
1433 # a dummy device does not make the addresses go through tentative state, so we
1434 # reuse a bond from an earlier test, which does make the addresses go through
1435 # tentative state, and do our test on that
ec38833c 1436 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
df7f9afa
YW
1437 start_networkd(0)
1438 wait_online(['dummy98:enslaved', 'bond199:routable'])
20ca06a6 1439
371810d1 1440 output = check_output('ip -6 route list dev bond199')
20ca06a6
DA
1441 print(output)
1442 self.assertRegex(output, 'abcd::/16')
1443 self.assertRegex(output, 'src')
1444 self.assertRegex(output, '2001:1234:56:8f63::2')
1445
1f0e3109 1446 def test_ip_link_mac_address(self):
ec38833c 1447 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
df7f9afa
YW
1448 start_networkd(0)
1449 wait_online(['dummy98:degraded'])
1f0e3109 1450
371810d1 1451 output = check_output('ip link show dummy98')
1f0e3109
SS
1452 print(output)
1453 self.assertRegex(output, '00:01:02:aa:bb:cc')
1454
1455 def test_ip_link_unmanaged(self):
ec38833c 1456 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
df7f9afa 1457 start_networkd(5)
1f0e3109 1458
e39cc445 1459 self.check_link_exists('dummy98')
1f0e3109 1460
df7f9afa 1461 self.check_operstate('dummy98', 'off', setup_state='unmanaged')
1f0e3109
SS
1462
1463 def test_ipv6_address_label(self):
ec38833c 1464 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
df7f9afa
YW
1465 start_networkd(0)
1466 wait_online(['dummy98:degraded'])
1f0e3109 1467
371810d1 1468 output = check_output('ip addrlabel list')
1f0e3109
SS
1469 print(output)
1470 self.assertRegex(output, '2004:da8:1::/64')
1471
e4a71bf3 1472 def test_ipv6_neighbor(self):
ec38833c 1473 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
df7f9afa
YW
1474 start_networkd(0)
1475 wait_online(['dummy98:degraded'], timeout='40s')
e4a71bf3 1476
df7f9afa 1477 output = check_output('ip neigh list dev dummy98')
e4a71bf3
WKI
1478 print(output)
1479 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 1480 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 1481
05514ae1 1482 def test_link_local_addressing(self):
ec38833c
ZJS
1483 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1484 '25-link-local-addressing-no.network', '12-dummy.netdev')
1485 start_networkd(0)
1486 wait_online(['test1:degraded', 'dummy98:carrier'])
05514ae1 1487
e39cc445
YW
1488 self.check_link_exists('test1')
1489 self.check_link_exists('dummy98')
05514ae1 1490
371810d1 1491 output = check_output('ip address show dev test1')
05514ae1
YW
1492 print(output)
1493 self.assertRegex(output, 'inet .* scope link')
1494 self.assertRegex(output, 'inet6 .* scope link')
1495
371810d1 1496 output = check_output('ip address show dev dummy98')
05514ae1
YW
1497 print(output)
1498 self.assertNotRegex(output, 'inet6* .* scope link')
1499
791c1140
YW
1500 self.check_operstate('test1', 'degraded')
1501 self.check_operstate('dummy98', 'carrier')
05514ae1
YW
1502
1503 '''
1504 Documentation/networking/ip-sysctl.txt
1505
1506 addr_gen_mode - INTEGER
1507 Defines how link-local and autoconf addresses are generated.
1508
1509 0: generate address based on EUI64 (default)
1510 1: do no generate a link-local address, use EUI64 for addresses generated
1511 from autoconf
1512 2: generate stable privacy addresses, using the secret from
1513 stable_secret (RFC7217)
1514 3: generate stable privacy addresses, using a random secret if unset
1515 '''
1516
1517 test1_addr_gen_mode = ''
1518 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
1519 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
1520 try:
1521 f.readline()
1522 except IOError:
1523 # if stable_secret is unset, then EIO is returned
1524 test1_addr_gen_mode = '0'
1525 else:
1526 test1_addr_gen_mode = '2'
1527 else:
1528 test1_addr_gen_mode = '0'
1529
1530 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
ec38833c 1531 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
05514ae1
YW
1532
1533 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
ec38833c 1534 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
05514ae1 1535
1f0e3109 1536 def test_sysctl(self):
ec38833c
ZJS
1537 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1538 start_networkd(0)
1539 wait_online(['dummy98:degraded'])
1540
1541 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1542 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1543 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1544 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1545 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1546 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1547 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1f0e3109 1548
4da33154 1549 def test_sysctl_disable_ipv6(self):
ec38833c 1550 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
4da33154
YW
1551
1552 print('## Disable ipv6')
cefd6b3d
ZJS
1553 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
1554 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
4da33154 1555
ec38833c
ZJS
1556 start_networkd(0)
1557 wait_online(['dummy98:routable'])
4da33154 1558
371810d1 1559 output = check_output('ip -4 address show dummy98')
4da33154
YW
1560 print(output)
1561 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 1562 output = check_output('ip -6 address show dummy98')
4da33154
YW
1563 print(output)
1564 self.assertEqual(output, '')
4933b97d
YW
1565 output = check_output('ip -4 route show dev dummy98')
1566 print(output)
1567 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1568 output = check_output('ip -6 route show dev dummy98')
1569 print(output)
1570 self.assertEqual(output, '')
4da33154 1571
cefd6b3d 1572 check_output('ip link del dummy98')
4da33154
YW
1573
1574 print('## Enable ipv6')
cefd6b3d
ZJS
1575 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
1576 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
4da33154 1577
ec38833c
ZJS
1578 start_networkd(0)
1579 wait_online(['dummy98:routable'])
4da33154 1580
371810d1 1581 output = check_output('ip -4 address show dummy98')
4da33154
YW
1582 print(output)
1583 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
371810d1 1584 output = check_output('ip -6 address show dummy98')
4da33154 1585 print(output)
4933b97d 1586 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
4da33154 1587 self.assertRegex(output, 'inet6 .* scope link')
4933b97d
YW
1588 output = check_output('ip -4 route show dev dummy98')
1589 print(output)
1590 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1591 output = check_output('ip -6 route show dev dummy98')
1592 print(output)
1593 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
4da33154 1594
cd65d067 1595 def test_bind_carrier(self):
ec38833c 1596 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
df7f9afa
YW
1597 start_networkd(0)
1598 wait_online(['test1:routable'])
cd65d067 1599
cefd6b3d
ZJS
1600 check_output('ip link add dummy98 type dummy')
1601 check_output('ip link set dummy98 up')
b117044c 1602 time.sleep(2)
371810d1 1603 output = check_output('ip address show test1')
cd65d067
YW
1604 print(output)
1605 self.assertRegex(output, 'UP,LOWER_UP')
1606 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
791c1140 1607 self.check_operstate('test1', 'routable')
cd65d067 1608
cefd6b3d
ZJS
1609 check_output('ip link add dummy99 type dummy')
1610 check_output('ip link set dummy99 up')
b117044c 1611 time.sleep(2)
371810d1 1612 output = check_output('ip address show test1')
cd65d067
YW
1613 print(output)
1614 self.assertRegex(output, 'UP,LOWER_UP')
1615 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
791c1140 1616 self.check_operstate('test1', 'routable')
cd65d067 1617
cefd6b3d 1618 check_output('ip link del dummy98')
b117044c 1619 time.sleep(2)
371810d1 1620 output = check_output('ip address show test1')
cd65d067
YW
1621 print(output)
1622 self.assertRegex(output, 'UP,LOWER_UP')
1623 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
791c1140 1624 self.check_operstate('test1', 'routable')
cd65d067 1625
cefd6b3d 1626 check_output('ip link del dummy99')
b117044c 1627 time.sleep(2)
371810d1 1628 output = check_output('ip address show test1')
cd65d067
YW
1629 print(output)
1630 self.assertNotRegex(output, 'UP,LOWER_UP')
1631 self.assertRegex(output, 'DOWN')
1632 self.assertNotRegex(output, '192.168.10')
791c1140 1633 self.check_operstate('test1', 'off')
cd65d067 1634
cefd6b3d
ZJS
1635 check_output('ip link add dummy98 type dummy')
1636 check_output('ip link set dummy98 up')
b117044c 1637 time.sleep(2)
371810d1 1638 output = check_output('ip address show test1')
cd65d067
YW
1639 print(output)
1640 self.assertRegex(output, 'UP,LOWER_UP')
1641 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
791c1140 1642 self.check_operstate('test1', 'routable')
cd65d067 1643
fdcd1ec5 1644 def test_domain(self):
ec38833c
ZJS
1645 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1646 start_networkd(0)
1647 wait_online(['dummy98:routable'])
fdcd1ec5 1648
371810d1 1649 output = check_output(*networkctl_cmd, 'status', 'dummy98', env=env)
fdcd1ec5
YW
1650 print(output)
1651 self.assertRegex(output, 'Address: 192.168.42.100')
1652 self.assertRegex(output, 'DNS: 192.168.42.1')
1653 self.assertRegex(output, 'Search Domains: one')
1654
1e498853
YW
1655 def test_keep_configuration_static(self):
1656 check_output('systemctl stop systemd-networkd')
1657
1658 check_output('ip link add name dummy98 type dummy')
1659 check_output('ip address add 10.1.2.3/16 dev dummy98')
1660 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
1661 output = check_output('ip address show dummy98')
1662 print(output)
1663 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
1664 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
1665 output = check_output('ip route show dev dummy98')
1666 print(output)
1667
1668 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
1669 start_networkd(0)
1670 wait_online(['dummy98:routable'])
1671
1672 output = check_output('ip address show dummy98')
1673 print(output)
1674 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
1675 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
1676
be68c2c9 1677class NetworkdBondTests(unittest.TestCase, Utilities):
c3a8853f 1678 links = [
c2990ec3 1679 'bond199',
c3a8853f 1680 'bond99',
cc3e488c
YW
1681 'dummy98',
1682 'test1']
c3a8853f
YW
1683
1684 units = [
cc3e488c
YW
1685 '11-dummy.netdev',
1686 '12-dummy.netdev',
c2990ec3
YW
1687 '23-active-slave.network',
1688 '23-bond199.network',
1689 '23-primary-slave.network',
1690 '23-test1-bond199.network',
1691 '25-bond-active-backup-slave.netdev',
c3a8853f 1692 '25-bond.netdev',
c3a8853f 1693 'bond99.network',
cc3e488c 1694 'bond-slave.network']
c3a8853f
YW
1695
1696 def setUp(self):
ec38833c 1697 remove_links(self.links)
c3a8853f
YW
1698
1699 def tearDown(self):
ec38833c
ZJS
1700 remove_links(self.links)
1701 remove_unit_from_networkd_path(self.units)
c3a8853f 1702
c2990ec3 1703 def test_bond_active_slave(self):
ec38833c
ZJS
1704 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1705 start_networkd()
c2990ec3 1706
e39cc445
YW
1707 self.check_link_exists('dummy98')
1708 self.check_link_exists('bond199')
c2990ec3 1709
371810d1 1710 output = check_output('ip -d link show bond199')
c2990ec3
YW
1711 print(output)
1712 self.assertRegex(output, 'active_slave dummy98')
1713
1714 def test_bond_primary_slave(self):
ec38833c
ZJS
1715 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
1716 start_networkd()
c2990ec3 1717
e39cc445
YW
1718 self.check_link_exists('test1')
1719 self.check_link_exists('bond199')
c2990ec3 1720
371810d1 1721 output = check_output('ip -d link show bond199')
c2990ec3
YW
1722 print(output)
1723 self.assertRegex(output, 'primary test1')
1724
cc3e488c 1725 def test_bond_operstate(self):
ec38833c
ZJS
1726 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
1727 'bond99.network','bond-slave.network')
1728 start_networkd()
c3a8853f 1729
e39cc445
YW
1730 self.check_link_exists('bond99')
1731 self.check_link_exists('dummy98')
1732 self.check_link_exists('test1')
c3a8853f 1733
371810d1 1734 output = check_output('ip -d link show dummy98')
c3a8853f 1735 print(output)
cc3e488c 1736 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 1737
371810d1 1738 output = check_output('ip -d link show test1')
c3a8853f
YW
1739 print(output)
1740 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1741
371810d1 1742 output = check_output('ip -d link show bond99')
c3a8853f
YW
1743 print(output)
1744 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
1745
791c1140
YW
1746 self.check_operstate('dummy98', 'enslaved')
1747 self.check_operstate('test1', 'enslaved')
1748 self.check_operstate('bond99', 'routable')
c3a8853f 1749
cefd6b3d 1750 check_output('ip link set dummy98 down')
c3a8853f
YW
1751 time.sleep(2)
1752
791c1140
YW
1753 self.check_operstate('dummy98', 'off')
1754 self.check_operstate('test1', 'enslaved')
1755 self.check_operstate('bond99', 'degraded-carrier')
c3a8853f 1756
cefd6b3d 1757 check_output('ip link set dummy98 up')
c3a8853f
YW
1758 time.sleep(2)
1759
791c1140
YW
1760 self.check_operstate('dummy98', 'enslaved')
1761 self.check_operstate('test1', 'enslaved')
1762 self.check_operstate('bond99', 'routable')
c3a8853f 1763
cefd6b3d
ZJS
1764 check_output('ip link set dummy98 down')
1765 check_output('ip link set test1 down')
2700d2c7 1766 time.sleep(2)
cc3e488c 1767
791c1140
YW
1768 self.check_operstate('dummy98', 'off')
1769 self.check_operstate('test1', 'off')
2700d2c7 1770
2700d2c7
YW
1771 for trial in range(30):
1772 if trial > 0:
1773 time.sleep(1)
371810d1 1774 output = check_output('ip address show bond99')
2700d2c7 1775 print(output)
ec38833c 1776 if get_operstate('bond99') == 'no-carrier':
2700d2c7
YW
1777 break
1778 else:
1779 # Huh? Kernel does not recognize that all slave interfaces are down?
1780 # Let's confirm that networkd's operstate is consistent with ip's result.
1781 self.assertNotRegex(output, 'NO-CARRIER')
cc3e488c 1782
be68c2c9 1783class NetworkdBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
1784 links = [
1785 'bridge99',
1786 'dummy98',
1787 'test1']
1788
1789 units = [
1790 '11-dummy.netdev',
1791 '12-dummy.netdev',
1792 '26-bridge.netdev',
1793 '26-bridge-slave-interface-1.network',
1794 '26-bridge-slave-interface-2.network',
804b6cd2 1795 'bridge99-ignore-carrier-loss.network',
09ea6724 1796 'bridge99.network']
1f0e3109
SS
1797
1798 def setUp(self):
ec38833c 1799 remove_links(self.links)
1f0e3109
SS
1800
1801 def tearDown(self):
ec38833c
ZJS
1802 remove_links(self.links)
1803 remove_unit_from_networkd_path(self.units)
1f0e3109
SS
1804
1805 def test_bridge_property(self):
ec38833c
ZJS
1806 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1807 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1808 'bridge99.network')
1809 start_networkd()
1f0e3109 1810
e39cc445
YW
1811 self.check_link_exists('dummy98')
1812 self.check_link_exists('test1')
1813 self.check_link_exists('bridge99')
1f0e3109 1814
371810d1 1815 output = check_output('ip -d link show test1')
1f0e3109
SS
1816 print(output)
1817 self.assertRegex(output, 'master')
1818 self.assertRegex(output, 'bridge')
1819
371810d1 1820 output = check_output('ip -d link show dummy98')
1f0e3109
SS
1821 print(output)
1822 self.assertRegex(output, 'master')
1823 self.assertRegex(output, 'bridge')
1824
371810d1 1825 output = check_output('ip addr show bridge99')
1f0e3109 1826 print(output)
2be6c5d2 1827 self.assertRegex(output, '192.168.0.15/24')
1f0e3109 1828
371810d1 1829 output = check_output('bridge -d link show dummy98')
1f0e3109 1830 print(output)
ec38833c
ZJS
1831 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
1832 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
1833 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
1834 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
1835 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
7f15b714 1836 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
ec38833c
ZJS
1837 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
1838 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
4d7ed14f
SS
1839
1840 # CONFIG_BRIDGE_IGMP_SNOOPING=y
1841 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
ec38833c 1842 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1f0e3109 1843
791c1140
YW
1844 self.check_operstate('test1', 'enslaved')
1845 self.check_operstate('dummy98', 'enslaved')
1846 self.check_operstate('bridge99', 'routable')
2be6c5d2 1847
371810d1 1848 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
1849 time.sleep(1)
1850
371810d1 1851 output = check_output('ip addr show bridge99')
2be6c5d2
YW
1852 print(output)
1853 self.assertRegex(output, '192.168.0.16/24')
1854
791c1140 1855 self.check_operstate('bridge99', 'routable')
2be6c5d2 1856
371810d1 1857 self.assertEqual(call('ip link del test1'), 0)
2be6c5d2
YW
1858 time.sleep(3)
1859
791c1140 1860 self.check_operstate('bridge99', 'degraded-carrier')
2be6c5d2 1861
cefd6b3d 1862 check_output('ip link del dummy98')
804b6cd2
YW
1863 time.sleep(3)
1864
791c1140 1865 self.check_operstate('bridge99', 'no-carrier')
2be6c5d2 1866
371810d1 1867 output = check_output('ip address show bridge99')
804b6cd2
YW
1868 print(output)
1869 self.assertRegex(output, 'NO-CARRIER')
1870 self.assertNotRegex(output, '192.168.0.15/24')
1871 self.assertNotRegex(output, '192.168.0.16/24')
1872
1873 def test_bridge_ignore_carrier_loss(self):
ec38833c
ZJS
1874 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1875 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1876 'bridge99-ignore-carrier-loss.network')
371810d1 1877 call('ip rule del table 100')
703bc7a2 1878
ec38833c 1879 start_networkd()
804b6cd2 1880
e39cc445
YW
1881 self.check_link_exists('dummy98')
1882 self.check_link_exists('test1')
1883 self.check_link_exists('bridge99')
804b6cd2 1884
371810d1 1885 check_output('ip address add 192.168.0.16/24 dev bridge99')
804b6cd2
YW
1886 time.sleep(1)
1887
371810d1
ZJS
1888 check_output('ip link del test1')
1889 check_output('ip link del dummy98')
804b6cd2
YW
1890 time.sleep(3)
1891
371810d1 1892 output = check_output('ip address show bridge99')
804b6cd2
YW
1893 print(output)
1894 self.assertRegex(output, 'NO-CARRIER')
1895 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1896 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
1897
371810d1 1898 call('ip rule del table 100')
6609924c
YW
1899
1900 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
ec38833c
ZJS
1901 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
1902 'bridge99-ignore-carrier-loss.network')
703bc7a2 1903
371810d1 1904 call('ip rule del table 100')
703bc7a2 1905
ec38833c 1906 start_networkd()
6609924c 1907
e39cc445 1908 self.check_link_exists('bridge99')
6609924c 1909
cefd6b3d
ZJS
1910 check_output('ip link add dummy98 type dummy')
1911 check_output('ip link set dummy98 up')
1912 check_output('ip link del dummy98')
6609924c 1913
cefd6b3d
ZJS
1914 check_output('ip link add dummy98 type dummy')
1915 check_output('ip link set dummy98 up')
1916 check_output('ip link del dummy98')
6609924c 1917
cefd6b3d
ZJS
1918 check_output('ip link add dummy98 type dummy')
1919 check_output('ip link set dummy98 up')
1920 check_output('ip link del dummy98')
6609924c 1921
cefd6b3d
ZJS
1922 check_output('ip link add dummy98 type dummy')
1923 check_output('ip link set dummy98 up')
6609924c 1924
be0e1ef9
YW
1925 for trial in range(30):
1926 if trial > 0:
1927 time.sleep(1)
ec38833c 1928 if get_operstate('bridge99') == 'routable' and get_operstate('dummy98') == 'enslaved':
be0e1ef9
YW
1929 break
1930 else:
1931 self.assertTrue(False)
6609924c 1932
371810d1 1933 output = check_output('ip address show bridge99')
6609924c
YW
1934 print(output)
1935 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1936
371810d1 1937 output = check_output('ip rule list table 100')
6609924c
YW
1938 print(output)
1939 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
1940
371810d1 1941 call('ip rule del table 100')
6609924c 1942
be68c2c9 1943class NetworkdLLDPTests(unittest.TestCase, Utilities):
1f0e3109
SS
1944 links = ['veth99']
1945
09ea6724
YW
1946 units = [
1947 '23-emit-lldp.network',
1948 '24-lldp.network',
1949 '25-veth.netdev']
1f0e3109
SS
1950
1951 def setUp(self):
ec38833c 1952 remove_links(self.links)
1f0e3109
SS
1953
1954 def tearDown(self):
ec38833c
ZJS
1955 remove_links(self.links)
1956 remove_unit_from_networkd_path(self.units)
1f0e3109
SS
1957
1958 def test_lldp(self):
ec38833c
ZJS
1959 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
1960 start_networkd(0)
1961 wait_online(['veth99:degraded', 'veth-peer:degraded'])
1f0e3109 1962
371810d1 1963 output = check_output(*networkctl_cmd, 'lldp', env=env)
1f0e3109
SS
1964 print(output)
1965 self.assertRegex(output, 'veth-peer')
1966 self.assertRegex(output, 'veth99')
1967
be68c2c9 1968class NetworkdRATests(unittest.TestCase, Utilities):
1f0e3109
SS
1969 links = ['veth99']
1970
09ea6724
YW
1971 units = [
1972 '25-veth.netdev',
1973 'ipv6-prefix.network',
1974 'ipv6-prefix-veth.network']
1f0e3109
SS
1975
1976 def setUp(self):
ec38833c 1977 remove_links(self.links)
1f0e3109
SS
1978
1979 def tearDown(self):
ec38833c
ZJS
1980 remove_links(self.links)
1981 remove_unit_from_networkd_path(self.units)
1f0e3109
SS
1982
1983 def test_ipv6_prefix_delegation(self):
ec38833c
ZJS
1984 warn_about_firewalld()
1985 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1986 start_networkd(0)
1987 wait_online(['veth99:routable', 'veth-peer:degraded'])
1f0e3109 1988
371810d1 1989 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
1990 print(output)
1991 self.assertRegex(output, '2002:da8:1:0')
1992
be68c2c9 1993class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
fdcd1ec5 1994 links = ['veth99']
09ea6724
YW
1995
1996 units = [
09ea6724
YW
1997 '25-veth.netdev',
1998 'dhcp-client.network',
1999 'dhcp-client-timezone-router.network',
2000 'dhcp-server.network',
2001 'dhcp-server-timezone-router.network']
1f0e3109
SS
2002
2003 def setUp(self):
ec38833c 2004 remove_links(self.links)
1f0e3109
SS
2005
2006 def tearDown(self):
ec38833c
ZJS
2007 remove_links(self.links)
2008 remove_unit_from_networkd_path(self.units)
1f0e3109
SS
2009
2010 def test_dhcp_server(self):
ec38833c
ZJS
2011 warn_about_firewalld()
2012 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2013 start_networkd(0)
2014 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2015
371810d1 2016 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
2017 print(output)
2018 self.assertRegex(output, '192.168.5.*')
2019 self.assertRegex(output, 'Gateway: 192.168.5.1')
2020 self.assertRegex(output, 'DNS: 192.168.5.1')
2021 self.assertRegex(output, 'NTP: 192.168.5.1')
2022
1f0e3109 2023 def test_emit_router_timezone(self):
ec38833c
ZJS
2024 warn_about_firewalld()
2025 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2026 start_networkd(0)
2027 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2028
371810d1 2029 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
2030 print(output)
2031 self.assertRegex(output, 'Gateway: 192.168.5.*')
2032 self.assertRegex(output, '192.168.5.*')
2033 self.assertRegex(output, 'Europe/Berlin')
2034
be68c2c9 2035class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
09ea6724 2036 links = [
18c613dc
YW
2037 'veth99',
2038 'vrf99']
09ea6724
YW
2039
2040 units = [
2041 '25-veth.netdev',
18c613dc
YW
2042 '25-vrf.netdev',
2043 '25-vrf.network',
09ea6724 2044 'dhcp-client-anonymize.network',
af3b1498 2045 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
2046 'dhcp-client-ipv4-dhcp-settings.network',
2047 'dhcp-client-ipv4-only-ipv6-disabled.network',
2048 'dhcp-client-ipv4-only.network',
2049 'dhcp-client-ipv6-only.network',
2050 'dhcp-client-ipv6-rapid-commit.network',
1e498853
YW
2051 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2052 'dhcp-client-keep-configuration-dhcp.network',
09ea6724
YW
2053 'dhcp-client-listen-port.network',
2054 'dhcp-client-route-metric.network',
2055 'dhcp-client-route-table.network',
18c613dc 2056 'dhcp-client-vrf.network',
117a55c7
YW
2057 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2058 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
3e9d5552 2059 'dhcp-client.network',
09ea6724 2060 'dhcp-server-veth-peer.network',
30d3b54e
YW
2061 'dhcp-v4-server-veth-peer.network',
2062 'static.network']
1f0e3109
SS
2063
2064 def setUp(self):
ec38833c
ZJS
2065 stop_dnsmasq(dnsmasq_pid_file)
2066 remove_links(self.links)
1f0e3109
SS
2067
2068 def tearDown(self):
ec38833c
ZJS
2069 stop_dnsmasq(dnsmasq_pid_file)
2070 remove_lease_file()
2071 remove_log_file()
2072 remove_links(self.links)
2073 remove_unit_from_networkd_path(self.units)
1f0e3109
SS
2074
2075 def test_dhcp_client_ipv6_only(self):
ec38833c 2076 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109 2077
ec38833c
ZJS
2078 start_networkd(0)
2079 wait_online(['veth-peer:carrier'])
2080 start_dnsmasq()
2081 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2082
371810d1 2083 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
2084 print(output)
2085 self.assertRegex(output, '2600::')
2086 self.assertNotRegex(output, '192.168.5')
2087
3a956d38 2088 # Confirm that ipv6 token is not set in the kernel
371810d1 2089 output = check_output('ip token show dev veth99')
3a956d38
YW
2090 print(output)
2091 self.assertRegex(output, 'token :: dev veth99')
2092
1f0e3109 2093 def test_dhcp_client_ipv4_only(self):
ec38833c 2094 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109 2095
ec38833c
ZJS
2096 start_networkd(0)
2097 wait_online(['veth-peer:carrier'])
2098 start_dnsmasq()
2099 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2100
371810d1 2101 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
2102 print(output)
2103 self.assertNotRegex(output, '2600::')
2104 self.assertRegex(output, '192.168.5')
2105
2106 def test_dhcp_client_ipv4_ipv6(self):
ec38833c
ZJS
2107 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2108 'dhcp-client-ipv4-only.network')
2109 start_networkd(0)
2110 wait_online(['veth-peer:carrier'])
2111 start_dnsmasq()
2112 wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
2113
2114 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79
YW
2115 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2116 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 2117
371810d1 2118 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109
SS
2119 print(output)
2120 self.assertRegex(output, '2600::')
2121 self.assertRegex(output, '192.168.5')
2122
2123 def test_dhcp_client_settings(self):
ec38833c 2124 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1f0e3109 2125
ec38833c
ZJS
2126 start_networkd(0)
2127 wait_online(['veth-peer:carrier'])
2128 start_dnsmasq()
2129 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2130
0ae7a66d 2131 print('## ip address show dev veth99')
371810d1 2132 output = check_output('ip address show dev veth99')
1f0e3109
SS
2133 print(output)
2134 self.assertRegex(output, '12:34:56:78:9a:bc')
2135 self.assertRegex(output, '192.168.5')
2136 self.assertRegex(output, '1492')
2137
0ae7a66d
YW
2138 # issue #8726
2139 print('## ip route show table main dev veth99')
371810d1 2140 output = check_output('ip route show table main dev veth99')
1f0e3109 2141 print(output)
0ae7a66d 2142 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 2143
0ae7a66d 2144 print('## ip route show table 211 dev veth99')
371810d1 2145 output = check_output('ip route show table 211 dev veth99')
0ae7a66d
YW
2146 print(output)
2147 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
2148 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2149 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
2150
2151 print('## dnsmasq log')
ec38833c
ZJS
2152 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2153 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2154 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
2155 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
2156
2157 def test_dhcp6_client_settings_rapidcommit_true(self):
ec38833c
ZJS
2158 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2159 start_networkd(0)
2160 wait_online(['veth-peer:carrier'])
2161 start_dnsmasq()
2162 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2163
371810d1 2164 output = check_output('ip address show dev veth99')
1f0e3109
SS
2165 print(output)
2166 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 2167 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
2168
2169 def test_dhcp6_client_settings_rapidcommit_false(self):
ec38833c
ZJS
2170 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2171 start_networkd(0)
2172 wait_online(['veth-peer:carrier'])
2173 start_dnsmasq()
2174 wait_online(['veth99:routable', 'veth-peer:routable'])
1f0e3109 2175
371810d1 2176 output = check_output('ip address show dev veth99')
1f0e3109
SS
2177 print(output)
2178 self.assertRegex(output, '12:34:56:78:9a:bc')
ec38833c 2179 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
2180
2181 def test_dhcp_client_settings_anonymize(self):
ec38833c
ZJS
2182 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2183 start_networkd(0)
2184 wait_online(['veth-peer:carrier'])
2185 start_dnsmasq()
2186 wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2187
ec38833c
ZJS
2188 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2189 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
2190 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
2191
2192 def test_dhcp_client_listen_port(self):
ec38833c
ZJS
2193 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2194 start_networkd(0)
2195 wait_online(['veth-peer:carrier'])
2196 start_dnsmasq('--dhcp-alternate-port=67,5555')
2197 wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
2198
2199 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79
YW
2200 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2201 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
1f0e3109 2202
371810d1 2203 output = check_output('ip -4 address show dev veth99')
b412fce8
YW
2204 print(output)
2205 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109
SS
2206
2207 def test_dhcp_route_table_id(self):
ec38833c
ZJS
2208 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2209 start_networkd(0)
2210 wait_online(['veth-peer:carrier'])
2211 start_dnsmasq()
2212 wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2213
371810d1 2214 output = check_output('ip route show table 12')
1f0e3109 2215 print(output)
1f0e3109
SS
2216 self.assertRegex(output, 'veth99 proto dhcp')
2217 self.assertRegex(output, '192.168.5.1')
2218
2219 def test_dhcp_route_metric(self):
ec38833c
ZJS
2220 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2221 start_networkd(0)
2222 wait_online(['veth-peer:carrier'])
2223 start_dnsmasq()
2224 wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2225
371810d1 2226 output = check_output('ip route show dev veth99')
1f0e3109 2227 print(output)
1f0e3109
SS
2228 self.assertRegex(output, 'metric 24')
2229
1e498853
YW
2230 def test_dhcp_keep_configuration_dhcp(self):
2231 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
ec38833c
ZJS
2232 start_networkd(0)
2233 wait_online(['veth-peer:carrier'])
1e498853 2234 start_dnsmasq(lease_time='2m')
ec38833c 2235 wait_online(['veth99:routable', 'veth-peer:routable'])
e40a58b5 2236
1e498853
YW
2237 output = check_output('ip address show dev veth99 scope global')
2238 print(output)
2239 self.assertRegex(output, r'192.168.5.*')
2240
371810d1 2241 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109 2242 print(output)
1e498853 2243 self.assertRegex(output, r'192.168.5.*')
e40a58b5 2244
5238e957 2245 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
ec38833c 2246 stop_dnsmasq(dnsmasq_pid_file)
1f0e3109
SS
2247
2248 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1e498853 2249 print('Wait for the dynamic address to be expired')
1f0e3109
SS
2250 time.sleep(125)
2251
1e498853
YW
2252 print('The lease address should be kept after lease expired')
2253 output = check_output('ip address show dev veth99 scope global')
2254 print(output)
2255 self.assertRegex(output, r'192.168.5.*')
2256
371810d1 2257 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
1f0e3109 2258 print(output)
1e498853
YW
2259 self.assertRegex(output, r'192.168.5.*')
2260
2261 check_output('systemctl stop systemd-networkd')
2262
2263 print('The lease address should be kept after networkd stopped')
2264 output = check_output('ip address show dev veth99 scope global')
2265 print(output)
2266 self.assertRegex(output, r'192.168.5.*')
2267
2268 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2269 print(output)
2270 self.assertRegex(output, r'192.168.5.*')
2271
2272 check_output('systemctl start systemd-networkd')
2273 wait_online(['veth-peer:routable'])
2274
2275 print('Still the lease address should be kept after networkd restarted')
2276 output = check_output('ip address show dev veth99 scope global')
2277 print(output)
2278 self.assertRegex(output, r'192.168.5.*')
2279
2280 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2281 print(output)
2282 self.assertRegex(output, r'192.168.5.*')
2283
2284 def test_dhcp_keep_configuration_dhcp_on_stop(self):
2285 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2286 start_networkd(0)
2287 wait_online(['veth-peer:carrier'])
2288 start_dnsmasq(lease_time='2m')
2289 wait_online(['veth99:routable', 'veth-peer:routable'])
2290
2291 output = check_output('ip address show dev veth99 scope global')
2292 print(output)
2293 self.assertRegex(output, r'192.168.5.*')
2294
2295 stop_dnsmasq(dnsmasq_pid_file)
2296 check_output('systemctl stop systemd-networkd')
2297
2298 output = check_output('ip address show dev veth99 scope global')
2299 print(output)
2300 self.assertRegex(output, r'192.168.5.*')
2301
2302 start_networkd(0)
2303 wait_online(['veth-peer:routable'])
2304
2305 output = check_output('ip address show dev veth99 scope global')
2306 print(output)
2307 self.assertNotRegex(output, r'192.168.5.*')
1f0e3109 2308
30d3b54e 2309 def test_dhcp_client_reuse_address_as_static(self):
ec38833c
ZJS
2310 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2311 start_networkd(0)
2312 wait_online(['veth-peer:carrier'])
2313 start_dnsmasq()
2314 wait_online(['veth99:routable', 'veth-peer:routable'])
2629df47
YW
2315
2316 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79
YW
2317 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2318 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
30d3b54e 2319
371810d1 2320 output = check_output('ip address show dev veth99 scope global')
30d3b54e
YW
2321 print(output)
2322 self.assertRegex(output, '192.168.5')
2323 self.assertRegex(output, '2600::')
2324
2629df47
YW
2325 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
2326 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
30d3b54e
YW
2327 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
2328 print(static_network)
2329
ec38833c 2330 remove_unit_from_networkd_path(['dhcp-client.network'])
30d3b54e
YW
2331
2332 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
2333 f.write(static_network)
2334
2629df47
YW
2335 # When networkd started, the links are already configured, so let's wait for 5 seconds
2336 # the links to be re-configured.
ec38833c
ZJS
2337 start_networkd(5)
2338 wait_online(['veth99:routable', 'veth-peer:routable'])
30d3b54e 2339
371810d1 2340 output = check_output('ip -4 address show dev veth99 scope global')
30d3b54e
YW
2341 print(output)
2342 self.assertRegex(output, '192.168.5')
2343 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2344
371810d1 2345 output = check_output('ip -6 address show dev veth99 scope global')
30d3b54e
YW
2346 print(output)
2347 self.assertRegex(output, '2600::')
2348 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2349
18c613dc
YW
2350 @expectedFailureIfModuleIsNotAvailable('vrf')
2351 def test_dhcp_client_vrf(self):
ec38833c
ZJS
2352 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2353 '25-vrf.netdev', '25-vrf.network')
2354 start_networkd(0)
2355 wait_online(['veth-peer:carrier'])
2356 start_dnsmasq()
2357 wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2629df47
YW
2358
2359 # link become 'routable' when at least one protocol provide an valid address.
e16ffe79
YW
2360 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2361 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
18c613dc
YW
2362
2363 print('## ip -d link show dev vrf99')
371810d1 2364 output = check_output('ip -d link show dev vrf99')
18c613dc
YW
2365 print(output)
2366 self.assertRegex(output, 'vrf table 42')
2367
2368 print('## ip address show vrf vrf99')
371810d1 2369 output = check_output('ip address show vrf vrf99')
d90f4f7d
YW
2370 print(output)
2371 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2372 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2373 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
2374 self.assertRegex(output, 'inet6 .* scope link')
18c613dc
YW
2375
2376 print('## ip address show dev veth99')
371810d1 2377 output = check_output('ip address show dev veth99')
18c613dc 2378 print(output)
18c613dc
YW
2379 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2380 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
d90f4f7d 2381 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
18c613dc
YW
2382 self.assertRegex(output, 'inet6 .* scope link')
2383
2384 print('## ip route show vrf vrf99')
371810d1 2385 output = check_output('ip route show vrf vrf99')
18c613dc
YW
2386 print(output)
2387 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
2388 self.assertRegex(output, 'default dev veth99 proto static scope link')
2389 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
2390 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
2391 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
2392 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
2393
2394 print('## ip route show table main dev veth99')
371810d1 2395 output = check_output('ip route show table main dev veth99')
18c613dc
YW
2396 print(output)
2397 self.assertEqual(output, '')
2398
791c1140
YW
2399 self.check_operstate('vrf99', 'carrier')
2400 self.check_operstate('veth99', 'routable')
18c613dc 2401
af3b1498 2402 def test_dhcp_client_gateway_onlink_implicit(self):
ec38833c
ZJS
2403 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2404 'dhcp-client-gateway-onlink-implicit.network')
2405 start_networkd(0)
2406 wait_online(['veth-peer:carrier'])
2407 start_dnsmasq()
2408 wait_online(['veth99:routable', 'veth-peer:routable'])
af3b1498 2409
371810d1 2410 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
af3b1498
YW
2411 print(output)
2412 self.assertRegex(output, '192.168.5')
2413
371810d1 2414 output = check_output('ip route list dev veth99 10.0.0.0/8')
af3b1498
YW
2415 print(output)
2416 self.assertRegex(output, 'onlink')
371810d1 2417 output = check_output('ip route list dev veth99 192.168.100.0/24')
af3b1498
YW
2418 print(output)
2419 self.assertRegex(output, 'onlink')
2420
117a55c7 2421 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
ec38833c
ZJS
2422 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2423 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
2424 start_networkd(0)
2425 wait_online(['veth-peer:carrier'])
2426 start_dnsmasq(lease_time='2m')
2427 wait_online(['veth99:routable', 'veth-peer:routable'])
63c598ed 2428
371810d1 2429 output = check_output('ip address show dev veth99')
63c598ed
YW
2430 print(output)
2431
371810d1 2432 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 2433 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 2434 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 2435 self.assertRegex(output, 'inet6 .* scope link')
371810d1 2436 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 2437 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 2438 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
2439 self.assertNotRegex(output, 'inet .* scope link')
2440
2441 print('Wait for the dynamic address to be expired')
2442 time.sleep(130)
2443
371810d1 2444 output = check_output('ip address show dev veth99')
63c598ed
YW
2445 print(output)
2446
371810d1 2447 output = check_output('ip -6 address show dev veth99 scope global dynamic')
63c598ed 2448 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 2449 output = check_output('ip -6 address show dev veth99 scope link')
63c598ed 2450 self.assertRegex(output, 'inet6 .* scope link')
371810d1 2451 output = check_output('ip -4 address show dev veth99 scope global dynamic')
63c598ed 2452 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 2453 output = check_output('ip -4 address show dev veth99 scope link')
63c598ed
YW
2454 self.assertNotRegex(output, 'inet .* scope link')
2455
ec38833c 2456 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
63c598ed 2457
117a55c7 2458 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
ec38833c
ZJS
2459 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2460 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
2461 start_networkd(0)
2462 wait_online(['veth99:degraded', 'veth-peer:routable'])
117a55c7 2463
371810d1 2464 output = check_output('ip address show dev veth99')
117a55c7
YW
2465 print(output)
2466
371810d1 2467 output = check_output('ip -6 address show dev veth99 scope global dynamic')
117a55c7 2468 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
371810d1 2469 output = check_output('ip -6 address show dev veth99 scope link')
117a55c7 2470 self.assertRegex(output, 'inet6 .* scope link')
371810d1 2471 output = check_output('ip -4 address show dev veth99 scope global dynamic')
117a55c7 2472 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
371810d1 2473 output = check_output('ip -4 address show dev veth99 scope link')
117a55c7
YW
2474 self.assertRegex(output, 'inet .* scope link')
2475
b6efd661 2476 def test_dhcp_client_route_remove_on_renew(self):
ec38833c
ZJS
2477 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2478 'dhcp-client-ipv4-only-ipv6-disabled.network')
2479 start_networkd(0)
2480 wait_online(['veth-peer:carrier'])
2481 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
2482 wait_online(['veth99:routable', 'veth-peer:routable'])
b6efd661
YW
2483
2484 # test for issue #12490
2485
371810d1 2486 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
2487 print(output)
2488 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2489 address1=None
2490 for line in output.splitlines():
2491 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
2492 address1 = line.split()[1].split('/')[0]
2493 break
2494
371810d1 2495 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
2496 print(output)
2497 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
2498 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
2499
ec38833c
ZJS
2500 stop_dnsmasq(dnsmasq_pid_file)
2501 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
b6efd661
YW
2502
2503 print('Wait for the dynamic address to be expired')
2504 time.sleep(130)
2505
371810d1 2506 output = check_output('ip -4 address show dev veth99 scope global dynamic')
b6efd661
YW
2507 print(output)
2508 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2509 address2=None
2510 for line in output.splitlines():
2511 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
2512 address2 = line.split()[1].split('/')[0]
2513 break
2514
2515 self.assertNotEqual(address1, address2)
2516
371810d1 2517 output = check_output('ip -4 route show dev veth99')
b6efd661
YW
2518 print(output)
2519 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
2520 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
2521 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
2522 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
2523
1f0e3109 2524if __name__ == '__main__':
9c1ae484
YW
2525 parser = argparse.ArgumentParser()
2526 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
2527 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
2528 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
2529 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
2530 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
2531 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
94c03122 2532 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
fa4c6095 2533 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
94c03122 2534 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
9c1ae484
YW
2535 ns, args = parser.parse_known_args(namespace=unittest)
2536
2537 if ns.build_dir:
2538 if ns.networkd_bin or ns.wait_online_bin or ns.networkctl_bin:
2539 print('WARNING: --networkd, --wait-online, or --networkctl options are ignored when --build-dir is specified.')
2540 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
2541 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
2542 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
2543 else:
2544 if ns.networkd_bin:
2545 networkd_bin = ns.networkd_bin
2546 if ns.wait_online_bin:
2547 wait_online_bin = ns.wait_online_bin
2548 if ns.networkctl_bin:
2549 networkctl_bin = ns.networkctl_bin
2550
2551 use_valgrind = ns.use_valgrind
2552 enable_debug = ns.enable_debug
94c03122 2553 asan_options = ns.asan_options
fa4c6095 2554 lsan_options = ns.lsan_options
94c03122 2555 ubsan_options = ns.ubsan_options
9c1ae484
YW
2556
2557 if use_valgrind:
2558 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
2559 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
2560 else:
2561 networkctl_cmd = [networkctl_bin]
2562 wait_online_cmd = [wait_online_bin]
2563
2564 if enable_debug:
2565 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
94c03122
YW
2566 if asan_options:
2567 env.update({ 'ASAN_OPTIONS' : asan_options })
fa4c6095
YW
2568 if lsan_options:
2569 env.update({ 'LSAN_OPTIONS' : lsan_options })
94c03122
YW
2570 if ubsan_options:
2571 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
9c1ae484
YW
2572
2573 sys.argv[1:] = args
1f0e3109
SS
2574 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
2575 verbosity=3))