]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
Merge pull request #13054 from yuwata/network-dhcp-use-domains-8174
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: LGPL-2.1+
3 # systemd-networkd tests
4
5 import argparse
6 import os
7 import re
8 import shutil
9 import signal
10 import subprocess
11 import sys
12 import time
13 import unittest
14 from shutil import copytree
15
16 network_unit_file_path='/run/systemd/network'
17 networkd_runtime_directory='/run/systemd/netif'
18 networkd_ci_path='/run/networkd-ci'
19 network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
20 network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
21
22 dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
23 dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
24
25 networkd_bin='/usr/lib/systemd/systemd-networkd'
26 resolved_bin='/usr/lib/systemd/systemd-resolved'
27 wait_online_bin='/usr/lib/systemd/systemd-networkd-wait-online'
28 networkctl_bin='/usr/bin/networkctl'
29 resolvectl_bin='/usr/bin/resolvectl'
30 timedatectl_bin='/usr/bin/timedatectl'
31 use_valgrind=False
32 enable_debug=True
33 env = {}
34 asan_options=None
35 lsan_options=None
36 ubsan_options=None
37
38 def 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
43 def call(*command, **kwargs):
44 command = command[0].split() + list(command[1:])
45 return subprocess.call(command, universal_newlines=True, **kwargs)
46
47 def run(*command, **kwargs):
48 command = command[0].split() + list(command[1:])
49 return subprocess.run(command, universal_newlines=True, **kwargs)
50
51 def 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
56 def 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
64 def 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
75 def 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
86 def 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
97 def 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
114 def 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
185 def 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
198 def 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
202 def 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
210 def link_exists(link):
211 return os.path.exists(os.path.join('/sys/class/net', link))
212
213 def 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
219 def remove_fou_ports(ports):
220 for port in ports:
221 call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
222
223 def 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
229 def 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
233 def 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
241 def 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
245 def 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
249 def 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
256 def 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
263 def 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
268 def 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
273 def 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
281 def 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
294 def 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
298 def remove_log_file():
299 if os.path.exists(dnsmasq_log_file):
300 os.remove(dnsmasq_log_file)
301
302 def 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
306 def 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
315 def start_networkd(sleep_sec=0):
316 check_output('systemctl start systemd-networkd')
317 if sleep_sec > 0:
318 time.sleep(sleep_sec)
319
320 def 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
324 def 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
336 def 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
345 class 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
362 class 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
462 class 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
1294 class 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
1374 class NetworkdNetworkTests(unittest.TestCase, Utilities):
1375 links = [
1376 'bond199',
1377 'dummy98',
1378 'dummy99',
1379 'gretun97',
1380 'test1'
1381 ]
1382
1383 units = [
1384 '11-dummy.netdev',
1385 '12-dummy.netdev',
1386 '23-active-slave.network',
1387 '24-keep-configuration-static.network',
1388 '24-search-domain.network',
1389 '25-address-link-section.network',
1390 '25-address-preferred-lifetime-zero-ipv6.network',
1391 '25-address-static.network',
1392 '25-bind-carrier.network',
1393 '25-bond-active-backup-slave.netdev',
1394 '25-fibrule-invert.network',
1395 '25-fibrule-port-range.network',
1396 '25-gre-tunnel-remote-any.netdev',
1397 '25-ipv6-address-label-section.network',
1398 '25-neighbor-section.network',
1399 '25-neighbor-ip-dummy.network',
1400 '25-neighbor-ip.network',
1401 '25-link-local-addressing-no.network',
1402 '25-link-local-addressing-yes.network',
1403 '25-link-section-unmanaged.network',
1404 '25-route-ipv6-src.network',
1405 '25-route-static.network',
1406 '25-sysctl-disable-ipv6.network',
1407 '25-sysctl.network',
1408 'configure-without-carrier.network',
1409 'routing-policy-rule-dummy98.network',
1410 'routing-policy-rule-test1.network']
1411
1412 routing_policy_rule_tables = ['7', '8']
1413 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1414
1415 def setUp(self):
1416 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1417 remove_routes(self.routes)
1418 remove_links(self.links)
1419 stop_networkd(show_logs=False)
1420
1421 def tearDown(self):
1422 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1423 remove_routes(self.routes)
1424 remove_links(self.links)
1425 remove_unit_from_networkd_path(self.units)
1426 stop_networkd(show_logs=True)
1427
1428 def test_address_static(self):
1429 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1430 start_networkd()
1431
1432 wait_online(['dummy98:routable'])
1433
1434 output = check_output('ip -4 address show dev dummy98')
1435 print(output)
1436 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1437 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1438 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1439
1440 # invalid sections
1441 self.assertNotRegex(output, '10.10.0.1/16')
1442 self.assertNotRegex(output, '10.10.0.2/16')
1443
1444 output = check_output('ip -4 address show dev dummy98 label 32')
1445 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1446
1447 output = check_output('ip -4 address show dev dummy98 label 33')
1448 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1449
1450 output = check_output('ip -4 address show dev dummy98 label 34')
1451 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1452
1453 output = check_output('ip -4 address show dev dummy98 label 35')
1454 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1455
1456 output = check_output('ip -6 address show dev dummy98')
1457 print(output)
1458 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1459 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1460 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1461 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1462 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1463 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1464
1465 def test_address_preferred_lifetime_zero_ipv6(self):
1466 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero-ipv6.network', '12-dummy.netdev')
1467 start_networkd(5)
1468
1469 self.check_link_exists('dummy98')
1470 self.check_operstate('dummy98', 'routable', setup_state='configuring')
1471
1472 output = check_output('ip address show dummy98')
1473 print(output)
1474 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1475 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1476
1477 def test_configure_without_carrier(self):
1478 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1479 start_networkd()
1480 wait_online(['test1:routable'])
1481
1482 output = check_output(*networkctl_cmd, 'status', 'test1')
1483 print(output)
1484 self.assertRegex(output, '192.168.0.15')
1485 self.assertRegex(output, '192.168.0.1')
1486 self.assertRegex(output, 'routable')
1487
1488 def test_routing_policy_rule(self):
1489 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1490 start_networkd()
1491 wait_online(['test1:degraded'])
1492
1493 output = check_output('ip rule')
1494 print(output)
1495 self.assertRegex(output, '111')
1496 self.assertRegex(output, 'from 192.168.100.18')
1497 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
1498 self.assertRegex(output, 'iif test1')
1499 self.assertRegex(output, 'oif test1')
1500 self.assertRegex(output, 'lookup 7')
1501
1502 def test_routing_policy_rule_issue_11280(self):
1503 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1504 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1505
1506 for trial in range(3):
1507 # Remove state files only first time
1508 start_networkd()
1509 wait_online(['test1:degraded', 'dummy98:degraded'])
1510 time.sleep(1)
1511
1512 output = check_output('ip rule list table 7')
1513 print(output)
1514 self.assertRegex(output, '111: from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
1515
1516 output = check_output('ip rule list table 8')
1517 print(output)
1518 self.assertRegex(output, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1519
1520 stop_networkd(remove_state_files=False)
1521
1522 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1523 def test_routing_policy_rule_port_range(self):
1524 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1525 start_networkd()
1526 wait_online(['test1:degraded'])
1527
1528 output = check_output('ip rule')
1529 print(output)
1530 self.assertRegex(output, '111')
1531 self.assertRegex(output, 'from 192.168.100.18')
1532 self.assertRegex(output, '1123-1150')
1533 self.assertRegex(output, '3224-3290')
1534 self.assertRegex(output, 'tcp')
1535 self.assertRegex(output, 'lookup 7')
1536
1537 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1538 def test_routing_policy_rule_invert(self):
1539 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1540 start_networkd()
1541 wait_online(['test1:degraded'])
1542
1543 output = check_output('ip rule')
1544 print(output)
1545 self.assertRegex(output, '111')
1546 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1547 self.assertRegex(output, 'tcp')
1548 self.assertRegex(output, 'lookup 7')
1549
1550 def test_route_static(self):
1551 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1552 start_networkd()
1553 wait_online(['dummy98:routable'])
1554
1555 print('### ip -6 route show dev dummy98')
1556 output = check_output('ip -6 route show dev dummy98')
1557 print(output)
1558 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1559 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1560
1561 print('### ip -6 route show dev dummy98 default')
1562 output = check_output('ip -6 route show dev dummy98 default')
1563 print(output)
1564 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1565
1566 print('### ip -4 route show dev dummy98')
1567 output = check_output('ip -4 route show dev dummy98')
1568 print(output)
1569 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1570 self.assertRegex(output, '149.10.124.64 proto static scope link')
1571 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
1572 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1573 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
1574 self.assertRegex(output, 'multicast 149.10.123.4 proto static')
1575
1576 print('### ip -4 route show dev dummy98 default')
1577 output = check_output('ip -4 route show dev dummy98 default')
1578 print(output)
1579 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1580 self.assertRegex(output, 'default via 149.10.124.64 proto static')
1581 self.assertRegex(output, 'default proto static')
1582
1583 print('### ip -4 route show table local dev dummy98')
1584 output = check_output('ip -4 route show table local dev dummy98')
1585 print(output)
1586 self.assertRegex(output, 'local 149.10.123.1 proto static scope host')
1587 self.assertRegex(output, 'anycast 149.10.123.2 proto static scope link')
1588 self.assertRegex(output, 'broadcast 149.10.123.3 proto static scope link')
1589
1590 print('### ip route show type blackhole')
1591 output = check_output('ip route show type blackhole')
1592 print(output)
1593 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
1594
1595 print('### ip route show type unreachable')
1596 output = check_output('ip route show type unreachable')
1597 print(output)
1598 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
1599
1600 print('### ip route show type prohibit')
1601 output = check_output('ip route show type prohibit')
1602 print(output)
1603 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
1604
1605 def test_ip_route_ipv6_src_route(self):
1606 # a dummy device does not make the addresses go through tentative state, so we
1607 # reuse a bond from an earlier test, which does make the addresses go through
1608 # tentative state, and do our test on that
1609 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1610 start_networkd()
1611 wait_online(['dummy98:enslaved', 'bond199:routable'])
1612
1613 output = check_output('ip -6 route list dev bond199')
1614 print(output)
1615 self.assertRegex(output, 'abcd::/16')
1616 self.assertRegex(output, 'src')
1617 self.assertRegex(output, '2001:1234:56:8f63::2')
1618
1619 def test_ip_link_mac_address(self):
1620 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1621 start_networkd()
1622 wait_online(['dummy98:degraded'])
1623
1624 output = check_output('ip link show dummy98')
1625 print(output)
1626 self.assertRegex(output, '00:01:02:aa:bb:cc')
1627
1628 def test_ip_link_unmanaged(self):
1629 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
1630 start_networkd(5)
1631
1632 self.check_link_exists('dummy98')
1633
1634 self.check_operstate('dummy98', 'off', setup_state='unmanaged')
1635
1636 def test_ipv6_address_label(self):
1637 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
1638 start_networkd()
1639 wait_online(['dummy98:degraded'])
1640
1641 output = check_output('ip addrlabel list')
1642 print(output)
1643 self.assertRegex(output, '2004:da8:1::/64')
1644
1645 def test_neighbor_section(self):
1646 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1647 start_networkd()
1648 wait_online(['dummy98:degraded'], timeout='40s')
1649
1650 output = check_output('ip neigh list dev dummy98')
1651 print(output)
1652 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1653 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1654
1655 def test_neighbor_gre(self):
1656 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ip-dummy.network',
1657 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev')
1658 start_networkd()
1659 wait_online(['dummy98:degraded', 'gretun97:routable'], timeout='40s')
1660
1661 output = check_output('ip neigh list dev gretun97')
1662 print(output)
1663 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
1664
1665 def test_link_local_addressing(self):
1666 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1667 '25-link-local-addressing-no.network', '12-dummy.netdev')
1668 start_networkd()
1669 wait_online(['test1:degraded', 'dummy98:carrier'])
1670
1671 output = check_output('ip address show dev test1')
1672 print(output)
1673 self.assertRegex(output, 'inet .* scope link')
1674 self.assertRegex(output, 'inet6 .* scope link')
1675
1676 output = check_output('ip address show dev dummy98')
1677 print(output)
1678 self.assertNotRegex(output, 'inet6* .* scope link')
1679
1680 '''
1681 Documentation/networking/ip-sysctl.txt
1682
1683 addr_gen_mode - INTEGER
1684 Defines how link-local and autoconf addresses are generated.
1685
1686 0: generate address based on EUI64 (default)
1687 1: do no generate a link-local address, use EUI64 for addresses generated
1688 from autoconf
1689 2: generate stable privacy addresses, using the secret from
1690 stable_secret (RFC7217)
1691 3: generate stable privacy addresses, using a random secret if unset
1692 '''
1693
1694 test1_addr_gen_mode = ''
1695 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
1696 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
1697 try:
1698 f.readline()
1699 except IOError:
1700 # if stable_secret is unset, then EIO is returned
1701 test1_addr_gen_mode = '0'
1702 else:
1703 test1_addr_gen_mode = '2'
1704 else:
1705 test1_addr_gen_mode = '0'
1706
1707 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
1708 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
1709
1710 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
1711 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1712
1713 def test_sysctl(self):
1714 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1715 start_networkd()
1716 wait_online(['dummy98:degraded'])
1717
1718 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1719 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1720 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1721 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1722 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1723 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1724 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1725
1726 def test_sysctl_disable_ipv6(self):
1727 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1728
1729 print('## Disable ipv6')
1730 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
1731 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
1732
1733 start_networkd()
1734 wait_online(['dummy98:routable'])
1735
1736 output = check_output('ip -4 address show dummy98')
1737 print(output)
1738 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1739 output = check_output('ip -6 address show dummy98')
1740 print(output)
1741 self.assertEqual(output, '')
1742 output = check_output('ip -4 route show dev dummy98')
1743 print(output)
1744 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1745 output = check_output('ip -6 route show dev dummy98')
1746 print(output)
1747 self.assertEqual(output, '')
1748
1749 check_output('ip link del dummy98')
1750
1751 print('## Enable ipv6')
1752 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
1753 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
1754
1755 restart_networkd()
1756 wait_online(['dummy98:routable'])
1757
1758 output = check_output('ip -4 address show dummy98')
1759 print(output)
1760 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1761 output = check_output('ip -6 address show dummy98')
1762 print(output)
1763 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
1764 self.assertRegex(output, 'inet6 .* scope link')
1765 output = check_output('ip -4 route show dev dummy98')
1766 print(output)
1767 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1768 output = check_output('ip -6 route show dev dummy98')
1769 print(output)
1770 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1771
1772 def test_bind_carrier(self):
1773 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1774 start_networkd()
1775 wait_online(['test1:routable'])
1776
1777 check_output('ip link add dummy98 type dummy')
1778 check_output('ip link set dummy98 up')
1779 time.sleep(2)
1780 output = check_output('ip address show test1')
1781 print(output)
1782 self.assertRegex(output, 'UP,LOWER_UP')
1783 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1784 self.check_operstate('test1', 'routable')
1785
1786 check_output('ip link add dummy99 type dummy')
1787 check_output('ip link set dummy99 up')
1788 time.sleep(2)
1789 output = check_output('ip address show test1')
1790 print(output)
1791 self.assertRegex(output, 'UP,LOWER_UP')
1792 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1793 self.check_operstate('test1', 'routable')
1794
1795 check_output('ip link del dummy98')
1796 time.sleep(2)
1797 output = check_output('ip address show test1')
1798 print(output)
1799 self.assertRegex(output, 'UP,LOWER_UP')
1800 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1801 self.check_operstate('test1', 'routable')
1802
1803 check_output('ip link del dummy99')
1804 time.sleep(2)
1805 output = check_output('ip address show test1')
1806 print(output)
1807 self.assertNotRegex(output, 'UP,LOWER_UP')
1808 self.assertRegex(output, 'DOWN')
1809 self.assertNotRegex(output, '192.168.10')
1810 self.check_operstate('test1', 'off')
1811
1812 check_output('ip link add dummy98 type dummy')
1813 check_output('ip link set dummy98 up')
1814 time.sleep(2)
1815 output = check_output('ip address show test1')
1816 print(output)
1817 self.assertRegex(output, 'UP,LOWER_UP')
1818 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1819 self.check_operstate('test1', 'routable')
1820
1821 def test_domain(self):
1822 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1823 start_networkd()
1824 wait_online(['dummy98:routable'])
1825
1826 output = check_output(*networkctl_cmd, 'status', 'dummy98', env=env)
1827 print(output)
1828 self.assertRegex(output, 'Address: 192.168.42.100')
1829 self.assertRegex(output, 'DNS: 192.168.42.1')
1830 self.assertRegex(output, 'Search Domains: one')
1831
1832 def test_keep_configuration_static(self):
1833 check_output('systemctl stop systemd-networkd')
1834
1835 check_output('ip link add name dummy98 type dummy')
1836 check_output('ip address add 10.1.2.3/16 dev dummy98')
1837 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
1838 output = check_output('ip address show dummy98')
1839 print(output)
1840 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
1841 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
1842 output = check_output('ip route show dev dummy98')
1843 print(output)
1844
1845 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
1846 start_networkd()
1847 wait_online(['dummy98:routable'])
1848
1849 output = check_output('ip address show dummy98')
1850 print(output)
1851 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
1852 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
1853
1854 class NetworkdBondTests(unittest.TestCase, Utilities):
1855 links = [
1856 'bond199',
1857 'bond99',
1858 'dummy98',
1859 'test1']
1860
1861 units = [
1862 '11-dummy.netdev',
1863 '12-dummy.netdev',
1864 '23-active-slave.network',
1865 '23-bond199.network',
1866 '23-primary-slave.network',
1867 '25-bond-active-backup-slave.netdev',
1868 '25-bond.netdev',
1869 'bond99.network',
1870 'bond-slave.network']
1871
1872 def setUp(self):
1873 remove_links(self.links)
1874 stop_networkd(show_logs=False)
1875
1876 def tearDown(self):
1877 remove_links(self.links)
1878 remove_unit_from_networkd_path(self.units)
1879 stop_networkd(show_logs=True)
1880
1881 def test_bond_active_slave(self):
1882 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1883 start_networkd()
1884 wait_online(['dummy98:enslaved', 'bond199:degraded'])
1885
1886 output = check_output('ip -d link show bond199')
1887 print(output)
1888 self.assertRegex(output, 'active_slave dummy98')
1889
1890 def test_bond_primary_slave(self):
1891 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1892 start_networkd()
1893 wait_online(['dummy98:enslaved', 'bond199:degraded'])
1894
1895 output = check_output('ip -d link show bond199')
1896 print(output)
1897 self.assertRegex(output, 'primary dummy98')
1898
1899 def test_bond_operstate(self):
1900 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
1901 'bond99.network','bond-slave.network')
1902 start_networkd()
1903 wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
1904
1905 output = check_output('ip -d link show dummy98')
1906 print(output)
1907 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1908
1909 output = check_output('ip -d link show test1')
1910 print(output)
1911 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1912
1913 output = check_output('ip -d link show bond99')
1914 print(output)
1915 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
1916
1917 self.check_operstate('dummy98', 'enslaved')
1918 self.check_operstate('test1', 'enslaved')
1919 self.check_operstate('bond99', 'routable')
1920
1921 check_output('ip link set dummy98 down')
1922 time.sleep(2)
1923
1924 self.check_operstate('dummy98', 'off')
1925 self.check_operstate('test1', 'enslaved')
1926 self.check_operstate('bond99', 'degraded-carrier')
1927
1928 check_output('ip link set dummy98 up')
1929 time.sleep(2)
1930
1931 self.check_operstate('dummy98', 'enslaved')
1932 self.check_operstate('test1', 'enslaved')
1933 self.check_operstate('bond99', 'routable')
1934
1935 check_output('ip link set dummy98 down')
1936 check_output('ip link set test1 down')
1937 time.sleep(2)
1938
1939 self.check_operstate('dummy98', 'off')
1940 self.check_operstate('test1', 'off')
1941
1942 for trial in range(30):
1943 if trial > 0:
1944 time.sleep(1)
1945 output = check_output('ip address show bond99')
1946 print(output)
1947 if get_operstate('bond99') == 'no-carrier':
1948 break
1949 else:
1950 # Huh? Kernel does not recognize that all slave interfaces are down?
1951 # Let's confirm that networkd's operstate is consistent with ip's result.
1952 self.assertNotRegex(output, 'NO-CARRIER')
1953
1954 class NetworkdBridgeTests(unittest.TestCase, Utilities):
1955 links = [
1956 'bridge99',
1957 'dummy98',
1958 'test1']
1959
1960 units = [
1961 '11-dummy.netdev',
1962 '12-dummy.netdev',
1963 '26-bridge.netdev',
1964 '26-bridge-slave-interface-1.network',
1965 '26-bridge-slave-interface-2.network',
1966 '26-bridge-vlan-master.network',
1967 '26-bridge-vlan-slave.network',
1968 'bridge99-ignore-carrier-loss.network',
1969 'bridge99.network']
1970
1971 routing_policy_rule_tables = ['100']
1972
1973 def setUp(self):
1974 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1975 remove_links(self.links)
1976 stop_networkd(show_logs=False)
1977
1978 def tearDown(self):
1979 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1980 remove_links(self.links)
1981 remove_unit_from_networkd_path(self.units)
1982 stop_networkd(show_logs=True)
1983
1984 def test_bridge_vlan(self):
1985 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
1986 '26-bridge.netdev', '26-bridge-vlan-master.network')
1987 start_networkd()
1988 wait_online(['test1:enslaved', 'bridge99:degraded'])
1989
1990 output = check_output('bridge vlan show dev test1')
1991 print(output)
1992 self.assertNotRegex(output, '4063')
1993 for i in range(4064, 4095):
1994 self.assertRegex(output, f'{i}')
1995 self.assertNotRegex(output, '4095')
1996
1997 output = check_output('bridge vlan show dev bridge99')
1998 print(output)
1999 self.assertNotRegex(output, '4059')
2000 for i in range(4060, 4095):
2001 self.assertRegex(output, f'{i}')
2002 self.assertNotRegex(output, '4095')
2003
2004 def test_bridge_property(self):
2005 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2006 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2007 'bridge99.network')
2008 start_networkd()
2009 wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2010
2011 output = check_output('ip -d link show test1')
2012 print(output)
2013 self.assertRegex(output, 'master')
2014 self.assertRegex(output, 'bridge')
2015
2016 output = check_output('ip -d link show dummy98')
2017 print(output)
2018 self.assertRegex(output, 'master')
2019 self.assertRegex(output, 'bridge')
2020
2021 output = check_output('ip addr show bridge99')
2022 print(output)
2023 self.assertRegex(output, '192.168.0.15/24')
2024
2025 output = check_output('bridge -d link show dummy98')
2026 print(output)
2027 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
2028 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2029 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
2030 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2031 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
2032 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2033 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2034 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
2035 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
2036 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2037 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
2038 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2039 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2040 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
2041
2042 output = check_output('bridge -d link show test1')
2043 print(output)
2044 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
2045
2046 check_output('ip address add 192.168.0.16/24 dev bridge99')
2047 time.sleep(1)
2048
2049 output = check_output('ip addr show bridge99')
2050 print(output)
2051 self.assertRegex(output, '192.168.0.16/24')
2052
2053 self.assertEqual(call('ip link del test1'), 0)
2054 time.sleep(3)
2055
2056 self.check_operstate('bridge99', 'degraded-carrier')
2057
2058 check_output('ip link del dummy98')
2059 time.sleep(3)
2060
2061 self.check_operstate('bridge99', 'no-carrier')
2062
2063 output = check_output('ip address show bridge99')
2064 print(output)
2065 self.assertRegex(output, 'NO-CARRIER')
2066 self.assertNotRegex(output, '192.168.0.15/24')
2067 self.assertNotRegex(output, '192.168.0.16/24')
2068
2069 def test_bridge_ignore_carrier_loss(self):
2070 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2071 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2072 'bridge99-ignore-carrier-loss.network')
2073 start_networkd()
2074 wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2075
2076 check_output('ip address add 192.168.0.16/24 dev bridge99')
2077 time.sleep(1)
2078
2079 check_output('ip link del test1')
2080 check_output('ip link del dummy98')
2081 time.sleep(3)
2082
2083 output = check_output('ip address show bridge99')
2084 print(output)
2085 self.assertRegex(output, 'NO-CARRIER')
2086 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2087 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
2088
2089 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
2090 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2091 'bridge99-ignore-carrier-loss.network')
2092 start_networkd()
2093 wait_online(['bridge99:no-carrier'])
2094
2095 for trial in range(4):
2096 check_output('ip link add dummy98 type dummy')
2097 check_output('ip link set dummy98 up')
2098 if trial < 3:
2099 check_output('ip link del dummy98')
2100
2101 wait_online(['bridge99:routable', 'dummy98:enslaved'])
2102
2103 output = check_output('ip address show bridge99')
2104 print(output)
2105 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2106
2107 output = check_output('ip rule list table 100')
2108 print(output)
2109 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
2110
2111 class NetworkdLLDPTests(unittest.TestCase, Utilities):
2112 links = ['veth99']
2113
2114 units = [
2115 '23-emit-lldp.network',
2116 '24-lldp.network',
2117 '25-veth.netdev']
2118
2119 def setUp(self):
2120 remove_links(self.links)
2121 stop_networkd(show_logs=False)
2122
2123 def tearDown(self):
2124 remove_links(self.links)
2125 remove_unit_from_networkd_path(self.units)
2126 stop_networkd(show_logs=True)
2127
2128 def test_lldp(self):
2129 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2130 start_networkd()
2131 wait_online(['veth99:degraded', 'veth-peer:degraded'])
2132
2133 output = check_output(*networkctl_cmd, 'lldp', env=env)
2134 print(output)
2135 self.assertRegex(output, 'veth-peer')
2136 self.assertRegex(output, 'veth99')
2137
2138 class NetworkdRATests(unittest.TestCase, Utilities):
2139 links = ['veth99']
2140
2141 units = [
2142 '25-veth.netdev',
2143 'ipv6-prefix.network',
2144 'ipv6-prefix-veth.network']
2145
2146 def setUp(self):
2147 remove_links(self.links)
2148 stop_networkd(show_logs=False)
2149
2150 def tearDown(self):
2151 remove_links(self.links)
2152 remove_unit_from_networkd_path(self.units)
2153 stop_networkd(show_logs=True)
2154
2155 def test_ipv6_prefix_delegation(self):
2156 warn_about_firewalld()
2157 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2158 start_networkd()
2159 wait_online(['veth99:routable', 'veth-peer:degraded'])
2160
2161 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2162 print(output)
2163 self.assertRegex(output, '2002:da8:1:0')
2164
2165 class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
2166 links = ['veth99']
2167
2168 units = [
2169 '25-veth.netdev',
2170 'dhcp-client.network',
2171 'dhcp-client-timezone-router.network',
2172 'dhcp-server.network',
2173 'dhcp-server-timezone-router.network']
2174
2175 def setUp(self):
2176 remove_links(self.links)
2177 stop_networkd(show_logs=False)
2178
2179 def tearDown(self):
2180 remove_links(self.links)
2181 remove_unit_from_networkd_path(self.units)
2182 stop_networkd(show_logs=True)
2183
2184 def test_dhcp_server(self):
2185 warn_about_firewalld()
2186 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2187 start_networkd()
2188 wait_online(['veth99:routable', 'veth-peer:routable'])
2189
2190 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2191 print(output)
2192 self.assertRegex(output, '192.168.5.*')
2193 self.assertRegex(output, 'Gateway: 192.168.5.1')
2194 self.assertRegex(output, 'DNS: 192.168.5.1')
2195 self.assertRegex(output, 'NTP: 192.168.5.1')
2196
2197 def test_emit_router_timezone(self):
2198 warn_about_firewalld()
2199 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2200 start_networkd()
2201 wait_online(['veth99:routable', 'veth-peer:routable'])
2202
2203 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2204 print(output)
2205 self.assertRegex(output, 'Gateway: 192.168.5.*')
2206 self.assertRegex(output, '192.168.5.*')
2207 self.assertRegex(output, 'Europe/Berlin')
2208
2209 class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
2210 links = [
2211 'veth99',
2212 'vrf99']
2213
2214 units = [
2215 '25-veth.netdev',
2216 '25-vrf.netdev',
2217 '25-vrf.network',
2218 'dhcp-client-anonymize.network',
2219 'dhcp-client-gateway-onlink-implicit.network',
2220 'dhcp-client-ipv4-dhcp-settings.network',
2221 'dhcp-client-ipv4-only-ipv6-disabled.network',
2222 'dhcp-client-ipv4-only.network',
2223 'dhcp-client-ipv6-only.network',
2224 'dhcp-client-ipv6-rapid-commit.network',
2225 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2226 'dhcp-client-keep-configuration-dhcp.network',
2227 'dhcp-client-listen-port.network',
2228 'dhcp-client-reassign-static-routes-ipv4.network',
2229 'dhcp-client-reassign-static-routes-ipv6.network',
2230 'dhcp-client-route-metric.network',
2231 'dhcp-client-route-table.network',
2232 'dhcp-client-use-dns-ipv4-and-ra.network',
2233 'dhcp-client-use-dns-ipv4.network',
2234 'dhcp-client-use-dns-no.network',
2235 'dhcp-client-use-dns-yes.network',
2236 'dhcp-client-use-domains.network',
2237 'dhcp-client-use-routes-no.network',
2238 'dhcp-client-vrf.network',
2239 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2240 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
2241 'dhcp-client-with-static-address.network',
2242 'dhcp-client.network',
2243 'dhcp-server-veth-peer.network',
2244 'dhcp-v4-server-veth-peer.network',
2245 'dhcp-client-use-domains.network',
2246 'static.network']
2247
2248 def setUp(self):
2249 stop_dnsmasq(dnsmasq_pid_file)
2250 remove_links(self.links)
2251 stop_networkd(show_logs=False)
2252
2253 def tearDown(self):
2254 stop_dnsmasq(dnsmasq_pid_file)
2255 remove_lease_file()
2256 remove_log_file()
2257 remove_links(self.links)
2258 remove_unit_from_networkd_path(self.units)
2259 stop_networkd(show_logs=True)
2260
2261 def test_dhcp_client_ipv6_only(self):
2262 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2263
2264 start_networkd()
2265 wait_online(['veth-peer:carrier'])
2266 start_dnsmasq()
2267 wait_online(['veth99:routable', 'veth-peer:routable'])
2268
2269 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2270 print(output)
2271 self.assertRegex(output, '2600::')
2272 self.assertNotRegex(output, '192.168.5')
2273
2274 # Confirm that ipv6 token is not set in the kernel
2275 output = check_output('ip token show dev veth99')
2276 print(output)
2277 self.assertRegex(output, 'token :: dev veth99')
2278
2279 def test_dhcp_client_ipv4_only(self):
2280 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
2281
2282 start_networkd()
2283 wait_online(['veth-peer:carrier'])
2284 start_dnsmasq()
2285 wait_online(['veth99:routable', 'veth-peer:routable'])
2286
2287 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2288 print(output)
2289 self.assertNotRegex(output, '2600::')
2290 self.assertRegex(output, '192.168.5')
2291
2292 def test_dhcp_client_ipv4_ipv6(self):
2293 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2294 'dhcp-client-ipv4-only.network')
2295 start_networkd()
2296 wait_online(['veth-peer:carrier'])
2297 start_dnsmasq()
2298 wait_online(['veth99:routable', 'veth-peer:routable'])
2299
2300 # link become 'routable' when at least one protocol provide an valid address.
2301 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2302 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2303
2304 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2305 print(output)
2306 self.assertRegex(output, '2600::')
2307 self.assertRegex(output, '192.168.5')
2308
2309 def test_dhcp_client_settings(self):
2310 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
2311
2312 start_networkd()
2313 wait_online(['veth-peer:carrier'])
2314 start_dnsmasq()
2315 wait_online(['veth99:routable', 'veth-peer:routable'])
2316
2317 print('## ip address show dev veth99')
2318 output = check_output('ip address show dev veth99')
2319 print(output)
2320 self.assertRegex(output, '12:34:56:78:9a:bc')
2321 self.assertRegex(output, '192.168.5')
2322 self.assertRegex(output, '1492')
2323
2324 # issue #8726
2325 print('## ip route show table main dev veth99')
2326 output = check_output('ip route show table main dev veth99')
2327 print(output)
2328 self.assertNotRegex(output, 'proto dhcp')
2329
2330 print('## ip route show table 211 dev veth99')
2331 output = check_output('ip route show table 211 dev veth99')
2332 print(output)
2333 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
2334 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2335 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
2336
2337 print('## dnsmasq log')
2338 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2339 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2340 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
2341 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
2342
2343 def test_dhcp6_client_settings_rapidcommit_true(self):
2344 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2345 start_networkd()
2346 wait_online(['veth-peer:carrier'])
2347 start_dnsmasq()
2348 wait_online(['veth99:routable', 'veth-peer:routable'])
2349
2350 output = check_output('ip address show dev veth99')
2351 print(output)
2352 self.assertRegex(output, '12:34:56:78:9a:bc')
2353 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
2354
2355 def test_dhcp6_client_settings_rapidcommit_false(self):
2356 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2357 start_networkd()
2358 wait_online(['veth-peer:carrier'])
2359 start_dnsmasq()
2360 wait_online(['veth99:routable', 'veth-peer:routable'])
2361
2362 output = check_output('ip address show dev veth99')
2363 print(output)
2364 self.assertRegex(output, '12:34:56:78:9a:bc')
2365 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
2366
2367 def test_dhcp_client_settings_anonymize(self):
2368 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2369 start_networkd()
2370 wait_online(['veth-peer:carrier'])
2371 start_dnsmasq()
2372 wait_online(['veth99:routable', 'veth-peer:routable'])
2373
2374 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2375 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
2376 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
2377
2378 def test_dhcp_client_listen_port(self):
2379 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2380 start_networkd()
2381 wait_online(['veth-peer:carrier'])
2382 start_dnsmasq('--dhcp-alternate-port=67,5555')
2383 wait_online(['veth99:routable', 'veth-peer:routable'])
2384
2385 # link become 'routable' when at least one protocol provide an valid address.
2386 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2387 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2388
2389 output = check_output('ip -4 address show dev veth99')
2390 print(output)
2391 self.assertRegex(output, '192.168.5.* dynamic')
2392
2393 def test_dhcp_client_with_static_address(self):
2394 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
2395 'dhcp-client-with-static-address.network')
2396 start_networkd()
2397 wait_online(['veth-peer:carrier'])
2398 start_dnsmasq()
2399 wait_online(['veth99:routable', 'veth-peer:routable'])
2400
2401 output = check_output('ip address show dev veth99 scope global')
2402 print(output)
2403 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
2404 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
2405
2406 output = check_output('ip route show dev veth99')
2407 print(output)
2408 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
2409 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
2410 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
2411 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
2412
2413 def test_dhcp_route_table_id(self):
2414 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2415 start_networkd()
2416 wait_online(['veth-peer:carrier'])
2417 start_dnsmasq()
2418 wait_online(['veth99:routable', 'veth-peer:routable'])
2419
2420 output = check_output('ip route show table 12')
2421 print(output)
2422 self.assertRegex(output, 'veth99 proto dhcp')
2423 self.assertRegex(output, '192.168.5.1')
2424
2425 def test_dhcp_route_metric(self):
2426 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2427 start_networkd()
2428 wait_online(['veth-peer:carrier'])
2429 start_dnsmasq()
2430 wait_online(['veth99:routable', 'veth-peer:routable'])
2431
2432 output = check_output('ip route show dev veth99')
2433 print(output)
2434 self.assertRegex(output, 'metric 24')
2435
2436 def test_dhcp_client_reassign_static_routes_ipv4(self):
2437 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2438 'dhcp-client-reassign-static-routes-ipv4.network')
2439 start_networkd()
2440 wait_online(['veth-peer:carrier'])
2441 start_dnsmasq(lease_time='2m')
2442 wait_online(['veth99:routable', 'veth-peer:routable'])
2443
2444 output = check_output('ip address show dev veth99 scope global')
2445 print(output)
2446 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2447
2448 output = check_output('ip route show dev veth99')
2449 print(output)
2450 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2451 self.assertRegex(output, r'192.168.5.0/24 proto static')
2452 self.assertRegex(output, r'192.168.6.0/24 proto static')
2453 self.assertRegex(output, r'192.168.7.0/24 proto static')
2454
2455 stop_dnsmasq(dnsmasq_pid_file)
2456 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
2457
2458 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2459 print('Wait for the dynamic address to be renewed')
2460 time.sleep(125)
2461
2462 wait_online(['veth99:routable'])
2463
2464 output = check_output('ip route show dev veth99')
2465 print(output)
2466 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2467 self.assertRegex(output, r'192.168.5.0/24 proto static')
2468 self.assertRegex(output, r'192.168.6.0/24 proto static')
2469 self.assertRegex(output, r'192.168.7.0/24 proto static')
2470
2471 def test_dhcp_client_reassign_static_routes_ipv6(self):
2472 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2473 'dhcp-client-reassign-static-routes-ipv6.network')
2474 start_networkd()
2475 wait_online(['veth-peer:carrier'])
2476 start_dnsmasq(lease_time='2m')
2477 wait_online(['veth99:routable', 'veth-peer:routable'])
2478
2479 output = check_output('ip address show dev veth99 scope global')
2480 print(output)
2481 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (?:noprefixroute dynamic|dynamic noprefixroute)')
2482
2483 output = check_output('ip -6 route show dev veth99')
2484 print(output)
2485 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
2486 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
2487
2488 stop_dnsmasq(dnsmasq_pid_file)
2489 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
2490
2491 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2492 print('Wait for the dynamic address to be renewed')
2493 time.sleep(125)
2494
2495 wait_online(['veth99:routable'])
2496
2497 output = check_output('ip -6 route show dev veth99')
2498 print(output)
2499 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
2500 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
2501
2502 def test_dhcp_keep_configuration_dhcp(self):
2503 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2504 start_networkd()
2505 wait_online(['veth-peer:carrier'])
2506 start_dnsmasq(lease_time='2m')
2507 wait_online(['veth99:routable', 'veth-peer:routable'])
2508
2509 output = check_output('ip address show dev veth99 scope global')
2510 print(output)
2511 self.assertRegex(output, r'192.168.5.*')
2512
2513 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2514 print(output)
2515 self.assertRegex(output, r'192.168.5.*')
2516
2517 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
2518 stop_dnsmasq(dnsmasq_pid_file)
2519
2520 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2521 print('Wait for the dynamic address to be expired')
2522 time.sleep(125)
2523
2524 print('The lease address should be kept after lease expired')
2525 output = check_output('ip address show dev veth99 scope global')
2526 print(output)
2527 self.assertRegex(output, r'192.168.5.*')
2528
2529 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2530 print(output)
2531 self.assertRegex(output, r'192.168.5.*')
2532
2533 check_output('systemctl stop systemd-networkd')
2534
2535 print('The lease address should be kept after networkd stopped')
2536 output = check_output('ip address show dev veth99 scope global')
2537 print(output)
2538 self.assertRegex(output, r'192.168.5.*')
2539
2540 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2541 print(output)
2542 self.assertRegex(output, r'192.168.5.*')
2543
2544 check_output('systemctl start systemd-networkd')
2545 wait_online(['veth-peer:routable'])
2546
2547 print('Still the lease address should be kept after networkd restarted')
2548 output = check_output('ip address show dev veth99 scope global')
2549 print(output)
2550 self.assertRegex(output, r'192.168.5.*')
2551
2552 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2553 print(output)
2554 self.assertRegex(output, r'192.168.5.*')
2555
2556 def test_dhcp_keep_configuration_dhcp_on_stop(self):
2557 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2558 start_networkd()
2559 wait_online(['veth-peer:carrier'])
2560 start_dnsmasq(lease_time='2m')
2561 wait_online(['veth99:routable', 'veth-peer:routable'])
2562
2563 output = check_output('ip address show dev veth99 scope global')
2564 print(output)
2565 self.assertRegex(output, r'192.168.5.*')
2566
2567 stop_dnsmasq(dnsmasq_pid_file)
2568 check_output('systemctl stop systemd-networkd')
2569
2570 output = check_output('ip address show dev veth99 scope global')
2571 print(output)
2572 self.assertRegex(output, r'192.168.5.*')
2573
2574 restart_networkd()
2575 wait_online(['veth-peer:routable'])
2576
2577 output = check_output('ip address show dev veth99 scope global')
2578 print(output)
2579 self.assertNotRegex(output, r'192.168.5.*')
2580
2581 def test_dhcp_client_reuse_address_as_static(self):
2582 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2583 start_networkd()
2584 wait_online(['veth-peer:carrier'])
2585 start_dnsmasq()
2586 wait_online(['veth99:routable', 'veth-peer:routable'])
2587
2588 # link become 'routable' when at least one protocol provide an valid address.
2589 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2590 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2591
2592 output = check_output('ip address show dev veth99 scope global')
2593 print(output)
2594 self.assertRegex(output, '192.168.5')
2595 self.assertRegex(output, '2600::')
2596
2597 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
2598 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
2599 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
2600 print(static_network)
2601
2602 remove_unit_from_networkd_path(['dhcp-client.network'])
2603
2604 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
2605 f.write(static_network)
2606
2607 # When networkd started, the links are already configured, so let's wait for 5 seconds
2608 # the links to be re-configured.
2609 restart_networkd(5)
2610 wait_online(['veth99:routable', 'veth-peer:routable'])
2611
2612 output = check_output('ip -4 address show dev veth99 scope global')
2613 print(output)
2614 self.assertRegex(output, '192.168.5')
2615 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2616
2617 output = check_output('ip -6 address show dev veth99 scope global')
2618 print(output)
2619 self.assertRegex(output, '2600::')
2620 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2621
2622 @expectedFailureIfModuleIsNotAvailable('vrf')
2623 def test_dhcp_client_vrf(self):
2624 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2625 '25-vrf.netdev', '25-vrf.network')
2626 start_networkd()
2627 wait_online(['veth-peer:carrier'])
2628 start_dnsmasq()
2629 wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2630
2631 # link become 'routable' when at least one protocol provide an valid address.
2632 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2633 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2634
2635 print('## ip -d link show dev vrf99')
2636 output = check_output('ip -d link show dev vrf99')
2637 print(output)
2638 self.assertRegex(output, 'vrf table 42')
2639
2640 print('## ip address show vrf vrf99')
2641 output = check_output('ip address show vrf vrf99')
2642 print(output)
2643 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2644 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2645 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
2646 self.assertRegex(output, 'inet6 .* scope link')
2647
2648 print('## ip address show dev veth99')
2649 output = check_output('ip address show dev veth99')
2650 print(output)
2651 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2652 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2653 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
2654 self.assertRegex(output, 'inet6 .* scope link')
2655
2656 print('## ip route show vrf vrf99')
2657 output = check_output('ip route show vrf vrf99')
2658 print(output)
2659 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
2660 self.assertRegex(output, 'default dev veth99 proto static scope link')
2661 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
2662 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
2663 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
2664 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
2665
2666 print('## ip route show table main dev veth99')
2667 output = check_output('ip route show table main dev veth99')
2668 print(output)
2669 self.assertEqual(output, '')
2670
2671 def test_dhcp_client_gateway_onlink_implicit(self):
2672 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2673 'dhcp-client-gateway-onlink-implicit.network')
2674 start_networkd()
2675 wait_online(['veth-peer:carrier'])
2676 start_dnsmasq()
2677 wait_online(['veth99:routable', 'veth-peer:routable'])
2678
2679 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2680 print(output)
2681 self.assertRegex(output, '192.168.5')
2682
2683 output = check_output('ip route list dev veth99 10.0.0.0/8')
2684 print(output)
2685 self.assertRegex(output, 'onlink')
2686 output = check_output('ip route list dev veth99 192.168.100.0/24')
2687 print(output)
2688 self.assertRegex(output, 'onlink')
2689
2690 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
2691 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2692 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
2693 start_networkd()
2694 wait_online(['veth-peer:carrier'])
2695 start_dnsmasq(lease_time='2m')
2696 wait_online(['veth99:routable', 'veth-peer:routable'])
2697
2698 output = check_output('ip address show dev veth99')
2699 print(output)
2700
2701 output = check_output('ip -6 address show dev veth99 scope global dynamic')
2702 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
2703 output = check_output('ip -6 address show dev veth99 scope link')
2704 self.assertRegex(output, 'inet6 .* scope link')
2705 output = check_output('ip -4 address show dev veth99 scope global dynamic')
2706 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2707 output = check_output('ip -4 address show dev veth99 scope link')
2708 self.assertNotRegex(output, 'inet .* scope link')
2709
2710 print('Wait for the dynamic address to be expired')
2711 time.sleep(130)
2712
2713 output = check_output('ip address show dev veth99')
2714 print(output)
2715
2716 output = check_output('ip -6 address show dev veth99 scope global dynamic')
2717 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
2718 output = check_output('ip -6 address show dev veth99 scope link')
2719 self.assertRegex(output, 'inet6 .* scope link')
2720 output = check_output('ip -4 address show dev veth99 scope global dynamic')
2721 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2722 output = check_output('ip -4 address show dev veth99 scope link')
2723 self.assertNotRegex(output, 'inet .* scope link')
2724
2725 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
2726
2727 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
2728 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2729 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
2730 start_networkd()
2731 wait_online(['veth99:degraded', 'veth-peer:routable'])
2732
2733 output = check_output('ip address show dev veth99')
2734 print(output)
2735
2736 output = check_output('ip -6 address show dev veth99 scope global dynamic')
2737 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
2738 output = check_output('ip -6 address show dev veth99 scope link')
2739 self.assertRegex(output, 'inet6 .* scope link')
2740 output = check_output('ip -4 address show dev veth99 scope global dynamic')
2741 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2742 output = check_output('ip -4 address show dev veth99 scope link')
2743 self.assertRegex(output, 'inet .* scope link')
2744
2745 def test_dhcp_client_route_remove_on_renew(self):
2746 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2747 'dhcp-client-ipv4-only-ipv6-disabled.network')
2748 start_networkd()
2749 wait_online(['veth-peer:carrier'])
2750 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
2751 wait_online(['veth99:routable', 'veth-peer:routable'])
2752
2753 # test for issue #12490
2754
2755 output = check_output('ip -4 address show dev veth99 scope global dynamic')
2756 print(output)
2757 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2758 address1=None
2759 for line in output.splitlines():
2760 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
2761 address1 = line.split()[1].split('/')[0]
2762 break
2763
2764 output = check_output('ip -4 route show dev veth99')
2765 print(output)
2766 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
2767 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
2768
2769 stop_dnsmasq(dnsmasq_pid_file)
2770 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
2771
2772 print('Wait for the dynamic address to be expired')
2773 time.sleep(130)
2774
2775 output = check_output('ip -4 address show dev veth99 scope global dynamic')
2776 print(output)
2777 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2778 address2=None
2779 for line in output.splitlines():
2780 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
2781 address2 = line.split()[1].split('/')[0]
2782 break
2783
2784 self.assertNotEqual(address1, address2)
2785
2786 output = check_output('ip -4 route show dev veth99')
2787 print(output)
2788 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
2789 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
2790 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
2791 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
2792
2793 def test_dhcp_client_use_dns_yes(self):
2794 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
2795
2796 start_networkd()
2797 wait_online(['veth-peer:carrier'])
2798 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
2799 wait_online(['veth99:routable', 'veth-peer:routable'])
2800
2801 # link become 'routable' when at least one protocol provide an valid address.
2802 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2803 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2804
2805 time.sleep(3)
2806 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2807 print(output)
2808 self.assertRegex(output, '192.168.5.1')
2809 self.assertRegex(output, '2600::1')
2810
2811 def test_dhcp_client_use_dns_no(self):
2812 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
2813
2814 start_networkd()
2815 wait_online(['veth-peer:carrier'])
2816 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
2817 wait_online(['veth99:routable', 'veth-peer:routable'])
2818
2819 # link become 'routable' when at least one protocol provide an valid address.
2820 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2821 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2822
2823 time.sleep(3)
2824 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2825 print(output)
2826 self.assertNotRegex(output, '192.168.5.1')
2827 self.assertNotRegex(output, '2600::1')
2828
2829 def test_dhcp_client_use_dns_ipv4(self):
2830 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
2831
2832 start_networkd()
2833 wait_online(['veth-peer:carrier'])
2834 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
2835 wait_online(['veth99:routable', 'veth-peer:routable'])
2836
2837 # link become 'routable' when at least one protocol provide an valid address.
2838 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2839 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2840
2841 time.sleep(3)
2842 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2843 print(output)
2844 self.assertRegex(output, '192.168.5.1')
2845 self.assertNotRegex(output, '2600::1')
2846
2847 def test_dhcp_client_use_dns_ipv4_and_ra(self):
2848 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
2849
2850 start_networkd()
2851 wait_online(['veth-peer:carrier'])
2852 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
2853 wait_online(['veth99:routable', 'veth-peer:routable'])
2854
2855 # link become 'routable' when at least one protocol provide an valid address.
2856 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2857 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2858
2859 time.sleep(3)
2860 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2861 print(output)
2862 self.assertRegex(output, '192.168.5.1')
2863 self.assertRegex(output, '2600::1')
2864
2865 def test_dhcp_client_use_domains(self):
2866 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
2867
2868 start_networkd()
2869 wait_online(['veth-peer:carrier'])
2870 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
2871 wait_online(['veth99:routable', 'veth-peer:routable'])
2872
2873 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2874 print(output)
2875 self.assertRegex(output, 'Search Domains: example.com')
2876
2877 time.sleep(3)
2878 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
2879 print(output)
2880 self.assertRegex(output, 'example.com')
2881
2882 if __name__ == '__main__':
2883 parser = argparse.ArgumentParser()
2884 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
2885 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
2886 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
2887 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
2888 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
2889 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
2890 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
2891 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
2892 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
2893 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
2894 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
2895 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
2896 ns, args = parser.parse_known_args(namespace=unittest)
2897
2898 if ns.build_dir:
2899 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:
2900 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
2901 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
2902 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
2903 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
2904 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
2905 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
2906 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
2907 else:
2908 if ns.networkd_bin:
2909 networkd_bin = ns.networkd_bin
2910 if ns.resolved_bin:
2911 resolved_bin = ns.resolved_bin
2912 if ns.wait_online_bin:
2913 wait_online_bin = ns.wait_online_bin
2914 if ns.networkctl_bin:
2915 networkctl_bin = ns.networkctl_bin
2916 if ns.resolvectl_bin:
2917 resolvectl_bin = ns.resolvectl_bin
2918 if ns.timedatectl_bin:
2919 timedatectl_bin = ns.timedatectl_bin
2920
2921 use_valgrind = ns.use_valgrind
2922 enable_debug = ns.enable_debug
2923 asan_options = ns.asan_options
2924 lsan_options = ns.lsan_options
2925 ubsan_options = ns.ubsan_options
2926
2927 if use_valgrind:
2928 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
2929 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
2930 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
2931 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
2932 else:
2933 networkctl_cmd = [networkctl_bin]
2934 resolvectl_cmd = [resolvectl_bin]
2935 timedatectl_cmd = [timedatectl_bin]
2936 wait_online_cmd = [wait_online_bin]
2937
2938 if enable_debug:
2939 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
2940 if asan_options:
2941 env.update({ 'ASAN_OPTIONS' : asan_options })
2942 if lsan_options:
2943 env.update({ 'LSAN_OPTIONS' : lsan_options })
2944 if ubsan_options:
2945 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
2946
2947 sys.argv[1:] = args
2948 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
2949 verbosity=3))