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