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