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