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