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