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