]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
networkd: bridge add support to set IGMP version
[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
707 def test_bond(self):
708 copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
709 start_networkd()
710
711 self.wait_online(['bond99:off', 'bond98:off'], setup_state='unmanaged')
712
713 self.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode'))
714 self.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
715 self.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon'))
716 self.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate'))
717 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay'))
718 self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay'))
719 self.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp'))
720 self.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links'))
721 self.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
722 self.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
723 self.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system'))
724
725 self.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode'))
726 self.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
727
728 def test_vlan(self):
729 copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
730 '21-vlan.network', '21-vlan-test1.network')
731 start_networkd()
732
733 self.wait_online(['test1:degraded', 'vlan99:routable'])
734
735 output = check_output('ip -d link show test1')
736 print(output)
737 self.assertRegex(output, ' mtu 2000 ')
738
739 output = check_output('ip -d link show vlan99')
740 print(output)
741 self.assertRegex(output, ' mtu 2000 ')
742 self.assertRegex(output, 'REORDER_HDR')
743 self.assertRegex(output, 'LOOSE_BINDING')
744 self.assertRegex(output, 'GVRP')
745 self.assertRegex(output, 'MVRP')
746 self.assertRegex(output, ' id 99 ')
747
748 output = check_output('ip -4 address show dev test1')
749 print(output)
750 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
751 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
752
753 output = check_output('ip -4 address show dev vlan99')
754 print(output)
755 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
756
757 def test_macvtap(self):
758 for mode in ['private', 'vepa', 'bridge', 'passthru']:
759 with self.subTest(mode=mode):
760 if mode != 'private':
761 self.tearDown()
762 copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
763 '11-dummy.netdev', 'macvtap.network')
764 with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f:
765 f.write('[MACVTAP]\nMode=' + mode)
766 start_networkd()
767
768 self.wait_online(['macvtap99:degraded', 'test1:degraded'])
769
770 output = check_output('ip -d link show macvtap99')
771 print(output)
772 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
773
774 def test_macvlan(self):
775 for mode in ['private', 'vepa', 'bridge', 'passthru']:
776 with self.subTest(mode=mode):
777 if mode != 'private':
778 self.tearDown()
779 copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
780 '11-dummy.netdev', 'macvlan.network')
781 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
782 f.write('[MACVLAN]\nMode=' + mode)
783 start_networkd()
784
785 self.wait_online(['macvlan99:degraded', 'test1:degraded'])
786
787 output = check_output('ip -d link show test1')
788 print(output)
789 self.assertRegex(output, ' mtu 2000 ')
790
791 output = check_output('ip -d link show macvlan99')
792 print(output)
793 self.assertRegex(output, ' mtu 2000 ')
794 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
795
796 @expectedFailureIfModuleIsNotAvailable('ipvlan')
797 def test_ipvlan(self):
798 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
799 with self.subTest(mode=mode, flag=flag):
800 if mode != 'L2':
801 self.tearDown()
802 copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
803 '11-dummy.netdev', 'ipvlan.network')
804 with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f:
805 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
806
807 start_networkd()
808 self.wait_online(['ipvlan99:degraded', 'test1:degraded'])
809
810 output = check_output('ip -d link show ipvlan99')
811 print(output)
812 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
813
814 @expectedFailureIfModuleIsNotAvailable('ipvtap')
815 def test_ipvtap(self):
816 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
817 with self.subTest(mode=mode, flag=flag):
818 if mode != 'L2':
819 self.tearDown()
820 copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
821 '11-dummy.netdev', 'ipvtap.network')
822 with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f:
823 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
824
825 start_networkd()
826 self.wait_online(['ipvtap99:degraded', 'test1:degraded'])
827
828 output = check_output('ip -d link show ipvtap99')
829 print(output)
830 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
831
832 def test_veth(self):
833 copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
834 start_networkd()
835
836 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
837
838 output = check_output('ip -d link show veth99')
839 print(output)
840 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
841 output = check_output('ip -d link show veth-peer')
842 print(output)
843 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
844
845 def test_tun(self):
846 copy_unit_to_networkd_unit_path('25-tun.netdev')
847 start_networkd()
848
849 self.wait_online(['tun99:off'], setup_state='unmanaged')
850
851 output = check_output('ip -d link show tun99')
852 print(output)
853 # Old ip command does not support IFF_ flags
854 self.assertRegex(output, 'tun (?:type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
855
856 def test_tap(self):
857 copy_unit_to_networkd_unit_path('25-tap.netdev')
858 start_networkd()
859
860 self.wait_online(['tap99:off'], setup_state='unmanaged')
861
862 output = check_output('ip -d link show tap99')
863 print(output)
864 # Old ip command does not support IFF_ flags
865 self.assertRegex(output, 'tun (?:type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
866
867 @expectedFailureIfModuleIsNotAvailable('vrf')
868 def test_vrf(self):
869 copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
870 start_networkd()
871
872 self.wait_online(['vrf99:carrier'])
873
874 @expectedFailureIfModuleIsNotAvailable('vcan')
875 def test_vcan(self):
876 copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
877 start_networkd()
878
879 self.wait_online(['vcan99:carrier'])
880
881 @expectedFailureIfModuleIsNotAvailable('vxcan')
882 def test_vxcan(self):
883 copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
884 start_networkd()
885
886 self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
887
888 @expectedFailureIfModuleIsNotAvailable('wireguard')
889 def test_wireguard(self):
890 copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
891 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
892 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
893 start_networkd()
894 self.wait_online(['wg99:carrier', 'wg98:routable'])
895
896 if shutil.which('wg'):
897 call('wg')
898
899 output = check_output('wg show wg99 listen-port')
900 self.assertRegex(output, '51820')
901 output = check_output('wg show wg99 fwmark')
902 self.assertRegex(output, '0x4d2')
903 output = check_output('wg show wg99 allowed-ips')
904 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
905 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
906 output = check_output('wg show wg99 persistent-keepalive')
907 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
908 output = check_output('wg show wg99 endpoints')
909 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
910 output = check_output('wg show wg99 private-key')
911 self.assertRegex(output, r'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
912 output = check_output('wg show wg99 preshared-keys')
913 self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
914 self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
915
916 output = check_output('wg show wg98 private-key')
917 self.assertRegex(output, r'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
918
919 def test_geneve(self):
920 copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
921 start_networkd()
922
923 self.wait_online(['geneve99:degraded'])
924
925 output = check_output('ip -d link show geneve99')
926 print(output)
927 self.assertRegex(output, '192.168.22.1')
928 self.assertRegex(output, '6082')
929 self.assertRegex(output, 'udpcsum')
930 self.assertRegex(output, 'udp6zerocsumrx')
931
932 def test_ipip_tunnel(self):
933 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
934 '25-ipip-tunnel.netdev', '25-tunnel.network',
935 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
936 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
937 '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network')
938 start_networkd()
939 self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded'])
940
941 output = check_output('ip -d link show ipiptun99')
942 print(output)
943 self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local 192.168.223.238 dev dummy98')
944 output = check_output('ip -d link show ipiptun98')
945 print(output)
946 self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local any dev dummy98')
947 output = check_output('ip -d link show ipiptun97')
948 print(output)
949 self.assertRegex(output, 'ipip (?:ipip |)remote any local 192.168.223.238 dev dummy98')
950 output = check_output('ip -d link show ipiptun96')
951 print(output)
952 self.assertRegex(output, 'ipip (?:ipip |)remote any local any dev dummy98')
953
954 def test_gre_tunnel(self):
955 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
956 '25-gre-tunnel.netdev', '25-tunnel.network',
957 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
958 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
959 '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
960 start_networkd()
961 self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded'])
962
963 output = check_output('ip -d link show gretun99')
964 print(output)
965 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
966 self.assertRegex(output, 'ikey 1.2.3.103')
967 self.assertRegex(output, 'okey 1.2.4.103')
968 self.assertRegex(output, 'iseq')
969 self.assertRegex(output, 'oseq')
970 output = check_output('ip -d link show gretun98')
971 print(output)
972 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
973 self.assertRegex(output, 'ikey 0.0.0.104')
974 self.assertRegex(output, 'okey 0.0.0.104')
975 self.assertNotRegex(output, 'iseq')
976 self.assertNotRegex(output, 'oseq')
977 output = check_output('ip -d link show gretun97')
978 print(output)
979 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
980 self.assertRegex(output, 'ikey 0.0.0.105')
981 self.assertRegex(output, 'okey 0.0.0.105')
982 self.assertNotRegex(output, 'iseq')
983 self.assertNotRegex(output, 'oseq')
984 output = check_output('ip -d link show gretun96')
985 print(output)
986 self.assertRegex(output, 'gre remote any local any dev dummy98')
987 self.assertRegex(output, 'ikey 0.0.0.106')
988 self.assertRegex(output, 'okey 0.0.0.106')
989 self.assertNotRegex(output, 'iseq')
990 self.assertNotRegex(output, 'oseq')
991
992 def test_ip6gre_tunnel(self):
993 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
994 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
995 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
996 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
997 '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network')
998 start_networkd(5)
999
1000 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
1001
1002 self.check_link_exists('dummy98')
1003 self.check_link_exists('ip6gretun99')
1004 self.check_link_exists('ip6gretun98')
1005 self.check_link_exists('ip6gretun97')
1006 self.check_link_exists('ip6gretun96')
1007
1008 output = check_output('ip -d link show ip6gretun99')
1009 print(output)
1010 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1011 output = check_output('ip -d link show ip6gretun98')
1012 print(output)
1013 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
1014 output = check_output('ip -d link show ip6gretun97')
1015 print(output)
1016 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
1017 output = check_output('ip -d link show ip6gretun96')
1018 print(output)
1019 self.assertRegex(output, 'ip6gre remote any local any dev dummy98')
1020
1021 def test_gretap_tunnel(self):
1022 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
1023 '25-gretap-tunnel.netdev', '25-tunnel.network',
1024 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1025 start_networkd()
1026 self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
1027
1028 output = check_output('ip -d link show gretap99')
1029 print(output)
1030 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1031 self.assertRegex(output, 'ikey 0.0.0.106')
1032 self.assertRegex(output, 'okey 0.0.0.106')
1033 self.assertRegex(output, 'iseq')
1034 self.assertRegex(output, 'oseq')
1035 output = check_output('ip -d link show gretap98')
1036 print(output)
1037 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
1038 self.assertRegex(output, 'ikey 0.0.0.107')
1039 self.assertRegex(output, 'okey 0.0.0.107')
1040 self.assertRegex(output, 'iseq')
1041 self.assertRegex(output, 'oseq')
1042
1043 def test_ip6gretap_tunnel(self):
1044 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
1045 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
1046 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1047 start_networkd()
1048 self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
1049
1050 output = check_output('ip -d link show ip6gretap99')
1051 print(output)
1052 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1053 output = check_output('ip -d link show ip6gretap98')
1054 print(output)
1055 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
1056
1057 def test_vti_tunnel(self):
1058 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
1059 '25-vti-tunnel.netdev', '25-tunnel.network',
1060 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1061 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1062 '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1063 start_networkd()
1064 self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded'])
1065
1066 output = check_output('ip -d link show vtitun99')
1067 print(output)
1068 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
1069 output = check_output('ip -d link show vtitun98')
1070 print(output)
1071 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
1072 output = check_output('ip -d link show vtitun97')
1073 print(output)
1074 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
1075 output = check_output('ip -d link show vtitun96')
1076 print(output)
1077 self.assertRegex(output, 'vti remote any local any dev dummy98')
1078
1079 def test_vti6_tunnel(self):
1080 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
1081 '25-vti6-tunnel.netdev', '25-tunnel.network',
1082 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1083 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1084 start_networkd()
1085 self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
1086
1087 output = check_output('ip -d link show vti6tun99')
1088 print(output)
1089 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1090 output = check_output('ip -d link show vti6tun98')
1091 print(output)
1092 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
1093 output = check_output('ip -d link show vti6tun97')
1094 print(output)
1095 self.assertRegex(output, 'vti6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1096
1097 def test_ip6tnl_tunnel(self):
1098 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
1099 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
1100 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1101 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
1102 start_networkd()
1103 self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
1104
1105 output = check_output('ip -d link show ip6tnl99')
1106 print(output)
1107 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
1108 output = check_output('ip -d link show ip6tnl98')
1109 print(output)
1110 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
1111 output = check_output('ip -d link show ip6tnl97')
1112 print(output)
1113 self.assertRegex(output, 'ip6tnl ip6ip6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
1114
1115 def test_sit_tunnel(self):
1116 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
1117 '25-sit-tunnel.netdev', '25-tunnel.network',
1118 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
1119 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',
1120 '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network')
1121 start_networkd()
1122 self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded'])
1123
1124 output = check_output('ip -d link show sittun99')
1125 print(output)
1126 self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local 10.65.223.238 dev dummy98")
1127 output = check_output('ip -d link show sittun98')
1128 print(output)
1129 self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local any dev dummy98")
1130 output = check_output('ip -d link show sittun97')
1131 print(output)
1132 self.assertRegex(output, "sit (?:ip6ip |)remote any local 10.65.223.238 dev dummy98")
1133 output = check_output('ip -d link show sittun96')
1134 print(output)
1135 self.assertRegex(output, "sit (?:ip6ip |)remote any local any dev dummy98")
1136
1137 def test_isatap_tunnel(self):
1138 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
1139 '25-isatap-tunnel.netdev', '25-tunnel.network')
1140 start_networkd()
1141 self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
1142
1143 output = check_output('ip -d link show isataptun99')
1144 print(output)
1145 self.assertRegex(output, "isatap ")
1146
1147 def test_6rd_tunnel(self):
1148 copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
1149 '25-6rd-tunnel.netdev', '25-tunnel.network')
1150 start_networkd()
1151 self.wait_online(['sittun99:routable', 'dummy98:degraded'])
1152
1153 output = check_output('ip -d link show sittun99')
1154 print(output)
1155 self.assertRegex(output, '6rd-prefix 2602::/24')
1156
1157 @expectedFailureIfERSPANModuleIsNotAvailable()
1158 def test_erspan_tunnel(self):
1159 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
1160 '25-erspan-tunnel.netdev', '25-tunnel.network',
1161 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
1162 start_networkd()
1163 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
1164
1165 output = check_output('ip -d link show erspan99')
1166 print(output)
1167 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
1168 self.assertRegex(output, 'ikey 0.0.0.101')
1169 self.assertRegex(output, 'okey 0.0.0.101')
1170 self.assertRegex(output, 'iseq')
1171 self.assertRegex(output, 'oseq')
1172 output = check_output('ip -d link show erspan98')
1173 print(output)
1174 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
1175 self.assertRegex(output, '102')
1176 self.assertRegex(output, 'ikey 0.0.0.102')
1177 self.assertRegex(output, 'okey 0.0.0.102')
1178 self.assertRegex(output, 'iseq')
1179 self.assertRegex(output, 'oseq')
1180
1181 def test_tunnel_independent(self):
1182 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
1183 start_networkd()
1184
1185 self.wait_online(['ipiptun99:carrier'])
1186
1187 def test_tunnel_independent_loopback(self):
1188 copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network')
1189 start_networkd()
1190
1191 self.wait_online(['ipiptun99:carrier'])
1192
1193 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1194 def test_xfrm(self):
1195 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network',
1196 '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network')
1197 start_networkd()
1198
1199 self.wait_online(['xfrm99:degraded', 'dummy98:degraded'])
1200
1201 output = check_output('ip link show dev xfrm99')
1202 print(output)
1203
1204 @expectedFailureIfModuleIsNotAvailable('xfrm_interface')
1205 def test_xfrm_independent(self):
1206 copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network')
1207 start_networkd()
1208
1209 self.wait_online(['xfrm99:degraded'])
1210
1211 @expectedFailureIfModuleIsNotAvailable('fou')
1212 def test_fou(self):
1213 # The following redundant check is necessary for CentOS CI.
1214 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
1215 self.assertTrue(is_module_available('fou'))
1216
1217 copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
1218 '25-fou-ipip.netdev', '25-fou-sit.netdev',
1219 '25-fou-gre.netdev', '25-fou-gretap.netdev')
1220 start_networkd()
1221
1222 self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged')
1223
1224 output = check_output('ip fou show')
1225 print(output)
1226 self.assertRegex(output, 'port 55555 ipproto 4')
1227 self.assertRegex(output, 'port 55556 ipproto 47')
1228
1229 output = check_output('ip -d link show ipiptun96')
1230 print(output)
1231 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
1232 output = check_output('ip -d link show sittun96')
1233 print(output)
1234 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
1235 output = check_output('ip -d link show gretun96')
1236 print(output)
1237 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
1238 output = check_output('ip -d link show gretap96')
1239 print(output)
1240 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1241
1242 def test_vxlan(self):
1243 copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1244 '11-dummy.netdev', 'vxlan-test1.network')
1245 start_networkd()
1246
1247 self.wait_online(['test1:degraded', 'vxlan99:degraded'])
1248
1249 output = check_output('ip -d link show vxlan99')
1250 print(output)
1251 self.assertRegex(output, '999')
1252 self.assertRegex(output, '5555')
1253 self.assertRegex(output, 'l2miss')
1254 self.assertRegex(output, 'l3miss')
1255 self.assertRegex(output, 'udpcsum')
1256 self.assertRegex(output, 'udp6zerocsumtx')
1257 self.assertRegex(output, 'udp6zerocsumrx')
1258 self.assertRegex(output, 'remcsumtx')
1259 self.assertRegex(output, 'remcsumrx')
1260 self.assertRegex(output, 'gbp')
1261
1262 output = check_output('bridge fdb show dev vxlan99')
1263 print(output)
1264 self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1265 self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1266 self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1267
1268 def test_macsec(self):
1269 copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1270 'macsec.network', '12-dummy.netdev')
1271 start_networkd()
1272
1273 self.wait_online(['dummy98:degraded', 'macsec99:routable'])
1274
1275 output = check_output('ip -d link show macsec99')
1276 print(output)
1277 self.assertRegex(output, 'macsec99@dummy98')
1278 self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
1279 self.assertRegex(output, 'encrypt on')
1280
1281 output = check_output('ip macsec show macsec99')
1282 print(output)
1283 self.assertRegex(output, 'encrypt on')
1284 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
1285 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1286 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1287 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on')
1288 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1289 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1290 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1291 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1292 self.assertNotRegex(output, 'key 02030405067080900000000000000000')
1293 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
1294 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1295
1296 def test_nlmon(self):
1297 copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
1298 start_networkd()
1299
1300 self.wait_online(['nlmon99:carrier'])
1301
1302 class NetworkdL2TPTests(unittest.TestCase, Utilities):
1303
1304 links =[
1305 'l2tp-ses1',
1306 'l2tp-ses2',
1307 'l2tp-ses3',
1308 'l2tp-ses4',
1309 'test1']
1310
1311 units = [
1312 '11-dummy.netdev',
1313 '25-l2tp-dummy.network',
1314 '25-l2tp.network',
1315 '25-l2tp-ip.netdev',
1316 '25-l2tp-udp.netdev']
1317
1318 l2tp_tunnel_ids = [ '10' ]
1319
1320 def setUp(self):
1321 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
1322 remove_links(self.links)
1323 stop_networkd(show_logs=False)
1324
1325 def tearDown(self):
1326 remove_l2tp_tunnels(self.l2tp_tunnel_ids)
1327 remove_links(self.links)
1328 remove_unit_from_networkd_path(self.units)
1329 stop_networkd(show_logs=True)
1330
1331 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1332 def test_l2tp_udp(self):
1333 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1334 '25-l2tp-udp.netdev', '25-l2tp.network')
1335 start_networkd()
1336
1337 self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded'])
1338
1339 output = check_output('ip l2tp show tunnel tunnel_id 10')
1340 print(output)
1341 self.assertRegex(output, "Tunnel 10, encap UDP")
1342 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1343 self.assertRegex(output, "Peer tunnel 11")
1344 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
1345 self.assertRegex(output, "UDP checksum: enabled")
1346
1347 output = check_output('ip l2tp show session tid 10 session_id 15')
1348 print(output)
1349 self.assertRegex(output, "Session 15 in tunnel 10")
1350 self.assertRegex(output, "Peer session 16, tunnel 11")
1351 self.assertRegex(output, "interface name: l2tp-ses1")
1352
1353 output = check_output('ip l2tp show session tid 10 session_id 17')
1354 print(output)
1355 self.assertRegex(output, "Session 17 in tunnel 10")
1356 self.assertRegex(output, "Peer session 18, tunnel 11")
1357 self.assertRegex(output, "interface name: l2tp-ses2")
1358
1359 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1360 def test_l2tp_ip(self):
1361 copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network',
1362 '25-l2tp-ip.netdev', '25-l2tp.network')
1363 start_networkd()
1364
1365 self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded'])
1366
1367 output = check_output('ip l2tp show tunnel tunnel_id 10')
1368 print(output)
1369 self.assertRegex(output, "Tunnel 10, encap IP")
1370 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1371 self.assertRegex(output, "Peer tunnel 12")
1372
1373 output = check_output('ip l2tp show session tid 10 session_id 25')
1374 print(output)
1375 self.assertRegex(output, "Session 25 in tunnel 10")
1376 self.assertRegex(output, "Peer session 26, tunnel 12")
1377 self.assertRegex(output, "interface name: l2tp-ses3")
1378
1379 output = check_output('ip l2tp show session tid 10 session_id 27')
1380 print(output)
1381 self.assertRegex(output, "Session 27 in tunnel 10")
1382 self.assertRegex(output, "Peer session 28, tunnel 12")
1383 self.assertRegex(output, "interface name: l2tp-ses4")
1384
1385 class NetworkdNetworkTests(unittest.TestCase, Utilities):
1386 links = [
1387 'bond199',
1388 'dummy98',
1389 'dummy99',
1390 'gretun97',
1391 'ip6gretun97',
1392 'test1'
1393 ]
1394
1395 units = [
1396 '11-dummy.netdev',
1397 '12-dummy.netdev',
1398 '23-active-slave.network',
1399 '24-keep-configuration-static.network',
1400 '24-search-domain.network',
1401 '25-address-link-section.network',
1402 '25-address-preferred-lifetime-zero-ipv6.network',
1403 '25-address-static.network',
1404 '25-bind-carrier.network',
1405 '25-bond-active-backup-slave.netdev',
1406 '25-fibrule-invert.network',
1407 '25-fibrule-port-range.network',
1408 '25-gre-tunnel-remote-any.netdev',
1409 '25-ip6gre-tunnel-remote-any.netdev',
1410 '25-ipv6-address-label-section.network',
1411 '25-neighbor-section.network',
1412 '25-neighbor-ipv6.network',
1413 '25-neighbor-ip-dummy.network',
1414 '25-neighbor-ip.network',
1415 '25-link-local-addressing-no.network',
1416 '25-link-local-addressing-yes.network',
1417 '25-link-section-unmanaged.network',
1418 '25-route-ipv6-src.network',
1419 '25-route-static.network',
1420 '25-sysctl-disable-ipv6.network',
1421 '25-sysctl.network',
1422 'configure-without-carrier.network',
1423 'routing-policy-rule-dummy98.network',
1424 'routing-policy-rule-test1.network']
1425
1426 routing_policy_rule_tables = ['7', '8']
1427 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1428
1429 def setUp(self):
1430 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1431 remove_routes(self.routes)
1432 remove_links(self.links)
1433 stop_networkd(show_logs=False)
1434
1435 def tearDown(self):
1436 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1437 remove_routes(self.routes)
1438 remove_links(self.links)
1439 remove_unit_from_networkd_path(self.units)
1440 stop_networkd(show_logs=True)
1441
1442 def test_address_static(self):
1443 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1444 start_networkd()
1445
1446 self.wait_online(['dummy98:routable'])
1447
1448 output = check_output('ip -4 address show dev dummy98')
1449 print(output)
1450 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1451 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1452 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1453
1454 # invalid sections
1455 self.assertNotRegex(output, '10.10.0.1/16')
1456 self.assertNotRegex(output, '10.10.0.2/16')
1457
1458 output = check_output('ip -4 address show dev dummy98 label 32')
1459 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1460
1461 output = check_output('ip -4 address show dev dummy98 label 33')
1462 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1463
1464 output = check_output('ip -4 address show dev dummy98 label 34')
1465 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1466
1467 output = check_output('ip -4 address show dev dummy98 label 35')
1468 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1469
1470 output = check_output('ip -6 address show dev dummy98')
1471 print(output)
1472 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1473 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1474 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1475 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1476 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1477 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1478
1479 def test_address_preferred_lifetime_zero_ipv6(self):
1480 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero-ipv6.network', '12-dummy.netdev')
1481 start_networkd(5)
1482
1483 self.check_link_exists('dummy98')
1484 self.check_operstate('dummy98', 'routable', setup_state='configuring')
1485
1486 output = check_output('ip address show dummy98')
1487 print(output)
1488 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1489 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1490
1491 def test_configure_without_carrier(self):
1492 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1493 start_networkd()
1494 self.wait_online(['test1:routable'])
1495
1496 output = check_output(*networkctl_cmd, 'status', 'test1')
1497 print(output)
1498 self.assertRegex(output, '192.168.0.15')
1499 self.assertRegex(output, '192.168.0.1')
1500 self.assertRegex(output, 'routable')
1501
1502 def test_routing_policy_rule(self):
1503 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1504 start_networkd()
1505 self.wait_online(['test1:degraded'])
1506
1507 output = check_output('ip rule')
1508 print(output)
1509 self.assertRegex(output, '111')
1510 self.assertRegex(output, 'from 192.168.100.18')
1511 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
1512 self.assertRegex(output, 'iif test1')
1513 self.assertRegex(output, 'oif test1')
1514 self.assertRegex(output, 'lookup 7')
1515
1516 def test_routing_policy_rule_issue_11280(self):
1517 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1518 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1519
1520 for trial in range(3):
1521 # Remove state files only first time
1522 start_networkd(3)
1523 self.wait_online(['test1:degraded', 'dummy98:degraded'])
1524 time.sleep(1)
1525
1526 output = check_output('ip rule list table 7')
1527 print(output)
1528 self.assertRegex(output, '111: from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
1529
1530 output = check_output('ip rule list table 8')
1531 print(output)
1532 self.assertRegex(output, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1533
1534 stop_networkd(remove_state_files=False)
1535
1536 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1537 def test_routing_policy_rule_port_range(self):
1538 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1539 start_networkd()
1540 self.wait_online(['test1:degraded'])
1541
1542 output = check_output('ip rule')
1543 print(output)
1544 self.assertRegex(output, '111')
1545 self.assertRegex(output, 'from 192.168.100.18')
1546 self.assertRegex(output, '1123-1150')
1547 self.assertRegex(output, '3224-3290')
1548 self.assertRegex(output, 'tcp')
1549 self.assertRegex(output, 'lookup 7')
1550
1551 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1552 def test_routing_policy_rule_invert(self):
1553 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1554 start_networkd()
1555 self.wait_online(['test1:degraded'])
1556
1557 output = check_output('ip rule')
1558 print(output)
1559 self.assertRegex(output, '111')
1560 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1561 self.assertRegex(output, 'tcp')
1562 self.assertRegex(output, 'lookup 7')
1563
1564 def test_route_static(self):
1565 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1566 start_networkd()
1567 self.wait_online(['dummy98:routable'])
1568
1569 output = check_output(*networkctl_cmd, 'status', 'dummy98', env=env)
1570 print(output)
1571
1572 print('### ip -6 route show dev dummy98')
1573 output = check_output('ip -6 route show dev dummy98')
1574 print(output)
1575 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1576 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1577
1578 print('### ip -6 route show dev dummy98 default')
1579 output = check_output('ip -6 route show dev dummy98 default')
1580 print(output)
1581 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1582
1583 print('### ip -4 route show dev dummy98')
1584 output = check_output('ip -4 route show dev dummy98')
1585 print(output)
1586 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1587 self.assertRegex(output, '149.10.124.64 proto static scope link')
1588 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
1589 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1590 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
1591 self.assertRegex(output, 'multicast 149.10.123.4 proto static')
1592
1593 print('### ip -4 route show dev dummy98 default')
1594 output = check_output('ip -4 route show dev dummy98 default')
1595 print(output)
1596 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1597 self.assertRegex(output, 'default via 149.10.124.64 proto static')
1598 self.assertRegex(output, 'default proto static')
1599
1600 print('### ip -4 route show table local dev dummy98')
1601 output = check_output('ip -4 route show table local dev dummy98')
1602 print(output)
1603 self.assertRegex(output, 'local 149.10.123.1 proto static scope host')
1604 self.assertRegex(output, 'anycast 149.10.123.2 proto static scope link')
1605 self.assertRegex(output, 'broadcast 149.10.123.3 proto static scope link')
1606
1607 print('### ip route show type blackhole')
1608 output = check_output('ip route show type blackhole')
1609 print(output)
1610 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
1611
1612 print('### ip route show type unreachable')
1613 output = check_output('ip route show type unreachable')
1614 print(output)
1615 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
1616
1617 print('### ip route show type prohibit')
1618 output = check_output('ip route show type prohibit')
1619 print(output)
1620 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
1621
1622 def test_ip_route_ipv6_src_route(self):
1623 # a dummy device does not make the addresses go through tentative state, so we
1624 # reuse a bond from an earlier test, which does make the addresses go through
1625 # tentative state, and do our test on that
1626 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1627 start_networkd()
1628 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
1629
1630 output = check_output('ip -6 route list dev bond199')
1631 print(output)
1632 self.assertRegex(output, 'abcd::/16')
1633 self.assertRegex(output, 'src')
1634 self.assertRegex(output, '2001:1234:56:8f63::2')
1635
1636 def test_ip_link_mac_address(self):
1637 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1638 start_networkd()
1639 self.wait_online(['dummy98:degraded'])
1640
1641 output = check_output('ip link show dummy98')
1642 print(output)
1643 self.assertRegex(output, '00:01:02:aa:bb:cc')
1644
1645 def test_ip_link_unmanaged(self):
1646 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
1647 start_networkd(5)
1648
1649 self.check_link_exists('dummy98')
1650
1651 self.check_operstate('dummy98', 'off', setup_state='unmanaged')
1652
1653 def test_ipv6_address_label(self):
1654 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
1655 start_networkd()
1656 self.wait_online(['dummy98:degraded'])
1657
1658 output = check_output('ip addrlabel list')
1659 print(output)
1660 self.assertRegex(output, '2004:da8:1::/64')
1661
1662 def test_neighbor_section(self):
1663 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1664 start_networkd()
1665 self.wait_online(['dummy98:degraded'], timeout='40s')
1666
1667 output = check_output('ip neigh list dev dummy98')
1668 print(output)
1669 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1670 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1671
1672 def test_neighbor_gre(self):
1673 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
1674 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
1675 start_networkd()
1676 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
1677
1678 output = check_output('ip neigh list dev gretun97')
1679 print(output)
1680 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
1681
1682 output = check_output('ip neigh list dev ip6gretun97')
1683 print(output)
1684 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
1685
1686 def test_link_local_addressing(self):
1687 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1688 '25-link-local-addressing-no.network', '12-dummy.netdev')
1689 start_networkd()
1690 self.wait_online(['test1:degraded', 'dummy98:carrier'])
1691
1692 output = check_output('ip address show dev test1')
1693 print(output)
1694 self.assertRegex(output, 'inet .* scope link')
1695 self.assertRegex(output, 'inet6 .* scope link')
1696
1697 output = check_output('ip address show dev dummy98')
1698 print(output)
1699 self.assertNotRegex(output, 'inet6* .* scope link')
1700
1701 '''
1702 Documentation/networking/ip-sysctl.txt
1703
1704 addr_gen_mode - INTEGER
1705 Defines how link-local and autoconf addresses are generated.
1706
1707 0: generate address based on EUI64 (default)
1708 1: do no generate a link-local address, use EUI64 for addresses generated
1709 from autoconf
1710 2: generate stable privacy addresses, using the secret from
1711 stable_secret (RFC7217)
1712 3: generate stable privacy addresses, using a random secret if unset
1713 '''
1714
1715 test1_addr_gen_mode = ''
1716 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
1717 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
1718 try:
1719 f.readline()
1720 except IOError:
1721 # if stable_secret is unset, then EIO is returned
1722 test1_addr_gen_mode = '0'
1723 else:
1724 test1_addr_gen_mode = '2'
1725 else:
1726 test1_addr_gen_mode = '0'
1727
1728 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
1729 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
1730
1731 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
1732 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1733
1734 def test_sysctl(self):
1735 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1736 start_networkd()
1737 self.wait_online(['dummy98:degraded'])
1738
1739 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1740 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1741 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1742 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1743 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1744 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1745 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1746
1747 def test_sysctl_disable_ipv6(self):
1748 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1749
1750 print('## Disable ipv6')
1751 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
1752 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
1753
1754 start_networkd()
1755 self.wait_online(['dummy98:routable'])
1756
1757 output = check_output('ip -4 address show dummy98')
1758 print(output)
1759 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1760 output = check_output('ip -6 address show dummy98')
1761 print(output)
1762 self.assertEqual(output, '')
1763 output = check_output('ip -4 route show dev dummy98')
1764 print(output)
1765 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1766 output = check_output('ip -6 route show dev dummy98')
1767 print(output)
1768 self.assertEqual(output, '')
1769
1770 check_output('ip link del dummy98')
1771
1772 print('## Enable ipv6')
1773 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
1774 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
1775
1776 restart_networkd(3)
1777 self.wait_online(['dummy98:routable'])
1778
1779 output = check_output('ip -4 address show dummy98')
1780 print(output)
1781 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1782 output = check_output('ip -6 address show dummy98')
1783 print(output)
1784 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
1785 self.assertRegex(output, 'inet6 .* scope link')
1786 output = check_output('ip -4 route show dev dummy98')
1787 print(output)
1788 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1789 output = check_output('ip -6 route show dev dummy98')
1790 print(output)
1791 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1792
1793 def test_bind_carrier(self):
1794 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1795 start_networkd()
1796 self.wait_online(['test1:routable'])
1797
1798 check_output('ip link add dummy98 type dummy')
1799 check_output('ip link set dummy98 up')
1800 time.sleep(2)
1801 output = check_output('ip address show test1')
1802 print(output)
1803 self.assertRegex(output, 'UP,LOWER_UP')
1804 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1805 self.check_operstate('test1', 'routable')
1806
1807 check_output('ip link add dummy99 type dummy')
1808 check_output('ip link set dummy99 up')
1809 time.sleep(2)
1810 output = check_output('ip address show test1')
1811 print(output)
1812 self.assertRegex(output, 'UP,LOWER_UP')
1813 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1814 self.check_operstate('test1', 'routable')
1815
1816 check_output('ip link del dummy98')
1817 time.sleep(2)
1818 output = check_output('ip address show test1')
1819 print(output)
1820 self.assertRegex(output, 'UP,LOWER_UP')
1821 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1822 self.check_operstate('test1', 'routable')
1823
1824 check_output('ip link del dummy99')
1825 time.sleep(2)
1826 output = check_output('ip address show test1')
1827 print(output)
1828 self.assertNotRegex(output, 'UP,LOWER_UP')
1829 self.assertRegex(output, 'DOWN')
1830 self.assertNotRegex(output, '192.168.10')
1831 self.check_operstate('test1', 'off')
1832
1833 check_output('ip link add dummy98 type dummy')
1834 check_output('ip link set dummy98 up')
1835 time.sleep(2)
1836 output = check_output('ip address show test1')
1837 print(output)
1838 self.assertRegex(output, 'UP,LOWER_UP')
1839 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1840 self.check_operstate('test1', 'routable')
1841
1842 def test_domain(self):
1843 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1844 start_networkd()
1845 self.wait_online(['dummy98:routable'])
1846
1847 output = check_output(*networkctl_cmd, 'status', 'dummy98', env=env)
1848 print(output)
1849 self.assertRegex(output, 'Address: 192.168.42.100')
1850 self.assertRegex(output, 'DNS: 192.168.42.1')
1851 self.assertRegex(output, 'Search Domains: one')
1852
1853 def test_keep_configuration_static(self):
1854 check_output('systemctl stop systemd-networkd')
1855
1856 check_output('ip link add name dummy98 type dummy')
1857 check_output('ip address add 10.1.2.3/16 dev dummy98')
1858 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
1859 output = check_output('ip address show dummy98')
1860 print(output)
1861 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
1862 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
1863 output = check_output('ip route show dev dummy98')
1864 print(output)
1865
1866 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
1867 start_networkd()
1868 self.wait_online(['dummy98:routable'])
1869
1870 output = check_output('ip address show dummy98')
1871 print(output)
1872 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
1873 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
1874
1875 class NetworkdStateFileTests(unittest.TestCase, Utilities):
1876 links = [
1877 'dummy98',
1878 ]
1879
1880 units = [
1881 '12-dummy.netdev',
1882 'state-file-tests.network',
1883 ]
1884
1885 def setUp(self):
1886 remove_links(self.links)
1887 stop_networkd(show_logs=False)
1888
1889 def tearDown(self):
1890 remove_links(self.links)
1891 remove_unit_from_networkd_path(self.units)
1892 stop_networkd(show_logs=True)
1893
1894 def test_state_file(self):
1895 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
1896 start_networkd()
1897 self.wait_online(['dummy98:routable'])
1898
1899 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
1900 print(output)
1901 ifindex = output.split()[0]
1902
1903 path = os.path.join('/run/systemd/netif/links/', ifindex)
1904 self.assertTrue(os.path.exists(path))
1905 time.sleep(2)
1906
1907 with open(path) as f:
1908 data = f.read()
1909 self.assertRegex(data, r'ADMIN_STATE=configured')
1910 self.assertRegex(data, r'OPER_STATE=routable')
1911 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
1912 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
1913 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
1914 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
1915 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
1916 self.assertRegex(data, r'DOMAINS=hogehoge')
1917 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
1918 self.assertRegex(data, r'LLMNR=no')
1919 self.assertRegex(data, r'MDNS=yes')
1920 self.assertRegex(data, r'DNSSEC=no')
1921 self.assertRegex(data, r'ADDRESSES=192.168.(?:10.10|12.12)/24 192.168.(?:12.12|10.10)/24')
1922
1923 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env)
1924 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
1925 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
1926 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
1927 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
1928 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
1929 time.sleep(2)
1930
1931 with open(path) as f:
1932 data = f.read()
1933 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
1934 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
1935 self.assertRegex(data, r'DOMAINS=hogehogehoge')
1936 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
1937 self.assertRegex(data, r'LLMNR=yes')
1938 self.assertRegex(data, r'MDNS=no')
1939 self.assertRegex(data, r'DNSSEC=yes')
1940
1941 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
1942 time.sleep(2)
1943
1944 with open(path) as f:
1945 data = f.read()
1946 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
1947 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
1948 self.assertRegex(data, r'DOMAINS=hogehogehoge')
1949 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
1950 self.assertRegex(data, r'LLMNR=yes')
1951 self.assertRegex(data, r'MDNS=no')
1952 self.assertRegex(data, r'DNSSEC=yes')
1953
1954 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
1955 time.sleep(2)
1956
1957 with open(path) as f:
1958 data = f.read()
1959 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
1960 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
1961 self.assertRegex(data, r'DOMAINS=hogehoge')
1962 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
1963 self.assertRegex(data, r'LLMNR=no')
1964 self.assertRegex(data, r'MDNS=yes')
1965 self.assertRegex(data, r'DNSSEC=no')
1966
1967 class NetworkdBondTests(unittest.TestCase, Utilities):
1968 links = [
1969 'bond199',
1970 'bond99',
1971 'dummy98',
1972 'test1']
1973
1974 units = [
1975 '11-dummy.netdev',
1976 '12-dummy.netdev',
1977 '23-active-slave.network',
1978 '23-bond199.network',
1979 '23-primary-slave.network',
1980 '25-bond-active-backup-slave.netdev',
1981 '25-bond.netdev',
1982 'bond99.network',
1983 'bond-slave.network']
1984
1985 def setUp(self):
1986 remove_links(self.links)
1987 stop_networkd(show_logs=False)
1988
1989 def tearDown(self):
1990 remove_links(self.links)
1991 remove_unit_from_networkd_path(self.units)
1992 stop_networkd(show_logs=True)
1993
1994 def test_bond_active_slave(self):
1995 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1996 start_networkd()
1997 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
1998
1999 output = check_output('ip -d link show bond199')
2000 print(output)
2001 self.assertRegex(output, 'active_slave dummy98')
2002
2003 def test_bond_primary_slave(self):
2004 copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2005 start_networkd()
2006 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2007
2008 output = check_output('ip -d link show bond199')
2009 print(output)
2010 self.assertRegex(output, 'primary dummy98')
2011
2012 def test_bond_operstate(self):
2013 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2014 'bond99.network','bond-slave.network')
2015 start_networkd()
2016 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
2017
2018 output = check_output('ip -d link show dummy98')
2019 print(output)
2020 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2021
2022 output = check_output('ip -d link show test1')
2023 print(output)
2024 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2025
2026 output = check_output('ip -d link show bond99')
2027 print(output)
2028 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
2029
2030 self.check_operstate('dummy98', 'enslaved')
2031 self.check_operstate('test1', 'enslaved')
2032 self.check_operstate('bond99', 'routable')
2033
2034 check_output('ip link set dummy98 down')
2035 time.sleep(2)
2036
2037 self.check_operstate('dummy98', 'off')
2038 self.check_operstate('test1', 'enslaved')
2039 self.check_operstate('bond99', 'degraded-carrier')
2040
2041 check_output('ip link set dummy98 up')
2042 time.sleep(2)
2043
2044 self.check_operstate('dummy98', 'enslaved')
2045 self.check_operstate('test1', 'enslaved')
2046 self.check_operstate('bond99', 'routable')
2047
2048 check_output('ip link set dummy98 down')
2049 check_output('ip link set test1 down')
2050 time.sleep(2)
2051
2052 self.check_operstate('dummy98', 'off')
2053 self.check_operstate('test1', 'off')
2054
2055 for trial in range(30):
2056 if trial > 0:
2057 time.sleep(1)
2058 output = check_output('ip address show bond99')
2059 print(output)
2060 if get_operstate('bond99') == 'no-carrier':
2061 break
2062 else:
2063 # Huh? Kernel does not recognize that all slave interfaces are down?
2064 # Let's confirm that networkd's operstate is consistent with ip's result.
2065 self.assertNotRegex(output, 'NO-CARRIER')
2066
2067 class NetworkdBridgeTests(unittest.TestCase, Utilities):
2068 links = [
2069 'bridge99',
2070 'dummy98',
2071 'test1']
2072
2073 units = [
2074 '11-dummy.netdev',
2075 '12-dummy.netdev',
2076 '26-bridge.netdev',
2077 '26-bridge-slave-interface-1.network',
2078 '26-bridge-slave-interface-2.network',
2079 '26-bridge-vlan-master.network',
2080 '26-bridge-vlan-slave.network',
2081 'bridge99-ignore-carrier-loss.network',
2082 'bridge99.network']
2083
2084 routing_policy_rule_tables = ['100']
2085
2086 def setUp(self):
2087 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
2088 remove_links(self.links)
2089 stop_networkd(show_logs=False)
2090
2091 def tearDown(self):
2092 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
2093 remove_links(self.links)
2094 remove_unit_from_networkd_path(self.units)
2095 stop_networkd(show_logs=True)
2096
2097 def test_bridge_vlan(self):
2098 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2099 '26-bridge.netdev', '26-bridge-vlan-master.network')
2100 start_networkd()
2101 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
2102
2103 output = check_output('bridge vlan show dev test1')
2104 print(output)
2105 self.assertNotRegex(output, '4063')
2106 for i in range(4064, 4095):
2107 self.assertRegex(output, f'{i}')
2108 self.assertNotRegex(output, '4095')
2109
2110 output = check_output('bridge vlan show dev bridge99')
2111 print(output)
2112 self.assertNotRegex(output, '4059')
2113 for i in range(4060, 4095):
2114 self.assertRegex(output, f'{i}')
2115 self.assertNotRegex(output, '4095')
2116
2117 def test_bridge_property(self):
2118 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2119 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2120 'bridge99.network')
2121 start_networkd()
2122 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2123
2124 output = check_output('ip -d link show test1')
2125 print(output)
2126 self.assertRegex(output, 'master')
2127 self.assertRegex(output, 'bridge')
2128
2129 output = check_output('ip -d link show dummy98')
2130 print(output)
2131 self.assertRegex(output, 'master')
2132 self.assertRegex(output, 'bridge')
2133
2134 output = check_output('ip addr show bridge99')
2135 print(output)
2136 self.assertRegex(output, '192.168.0.15/24')
2137
2138 output = check_output('bridge -d link show dummy98')
2139 print(output)
2140 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
2141 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2142 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
2143 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2144 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
2145 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2146 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2147 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
2148 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
2149 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2150 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
2151 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2152 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2153 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
2154
2155 output = check_output('bridge -d link show test1')
2156 print(output)
2157 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
2158
2159 check_output('ip address add 192.168.0.16/24 dev bridge99')
2160 time.sleep(1)
2161
2162 output = check_output('ip addr show bridge99')
2163 print(output)
2164 self.assertRegex(output, '192.168.0.16/24')
2165
2166 # for issue #6088
2167 print('### ip -6 route list table all dev bridge99')
2168 output = check_output('ip -6 route list table all dev bridge99')
2169 print(output)
2170 self.assertRegex(output, 'ff00::/8 table local metric 256 pref medium')
2171
2172 self.assertEqual(call('ip link del test1'), 0)
2173 time.sleep(3)
2174
2175 self.check_operstate('bridge99', 'degraded-carrier')
2176
2177 check_output('ip link del dummy98')
2178 time.sleep(3)
2179
2180 self.check_operstate('bridge99', 'no-carrier')
2181
2182 output = check_output('ip address show bridge99')
2183 print(output)
2184 self.assertRegex(output, 'NO-CARRIER')
2185 self.assertNotRegex(output, '192.168.0.15/24')
2186 self.assertNotRegex(output, '192.168.0.16/24')
2187
2188 print('### ip -6 route list table all dev bridge99')
2189 output = check_output('ip -6 route list table all dev bridge99')
2190 print(output)
2191 self.assertRegex(output, 'ff00::/8 table local metric 256 (?:linkdown |)pref medium')
2192
2193 def test_bridge_ignore_carrier_loss(self):
2194 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2195 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2196 'bridge99-ignore-carrier-loss.network')
2197 start_networkd()
2198 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2199
2200 check_output('ip address add 192.168.0.16/24 dev bridge99')
2201 time.sleep(1)
2202
2203 check_output('ip link del test1')
2204 check_output('ip link del dummy98')
2205 time.sleep(3)
2206
2207 output = check_output('ip address show bridge99')
2208 print(output)
2209 self.assertRegex(output, 'NO-CARRIER')
2210 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2211 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
2212
2213 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
2214 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2215 'bridge99-ignore-carrier-loss.network')
2216 start_networkd()
2217 self.wait_online(['bridge99:no-carrier'])
2218
2219 for trial in range(4):
2220 check_output('ip link add dummy98 type dummy')
2221 check_output('ip link set dummy98 up')
2222 if trial < 3:
2223 check_output('ip link del dummy98')
2224
2225 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
2226
2227 output = check_output('ip address show bridge99')
2228 print(output)
2229 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2230
2231 output = check_output('ip rule list table 100')
2232 print(output)
2233 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
2234
2235 class NetworkdLLDPTests(unittest.TestCase, Utilities):
2236 links = ['veth99']
2237
2238 units = [
2239 '23-emit-lldp.network',
2240 '24-lldp.network',
2241 '25-veth.netdev']
2242
2243 def setUp(self):
2244 remove_links(self.links)
2245 stop_networkd(show_logs=False)
2246
2247 def tearDown(self):
2248 remove_links(self.links)
2249 remove_unit_from_networkd_path(self.units)
2250 stop_networkd(show_logs=True)
2251
2252 def test_lldp(self):
2253 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2254 start_networkd()
2255 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
2256
2257 output = check_output(*networkctl_cmd, 'lldp', env=env)
2258 print(output)
2259 self.assertRegex(output, 'veth-peer')
2260 self.assertRegex(output, 'veth99')
2261
2262 class NetworkdRATests(unittest.TestCase, Utilities):
2263 links = ['veth99']
2264
2265 units = [
2266 '25-veth.netdev',
2267 'ipv6-prefix.network',
2268 'ipv6-prefix-veth.network']
2269
2270 def setUp(self):
2271 remove_links(self.links)
2272 stop_networkd(show_logs=False)
2273
2274 def tearDown(self):
2275 remove_links(self.links)
2276 remove_unit_from_networkd_path(self.units)
2277 stop_networkd(show_logs=True)
2278
2279 def test_ipv6_prefix_delegation(self):
2280 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2281 start_networkd()
2282 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2283
2284 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2285 print(output)
2286 self.assertRegex(output, '2002:da8:1:0')
2287
2288 class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
2289 links = ['veth99']
2290
2291 units = [
2292 '25-veth.netdev',
2293 'dhcp-client.network',
2294 'dhcp-client-timezone-router.network',
2295 'dhcp-server.network',
2296 'dhcp-server-timezone-router.network']
2297
2298 def setUp(self):
2299 remove_links(self.links)
2300 stop_networkd(show_logs=False)
2301
2302 def tearDown(self):
2303 remove_links(self.links)
2304 remove_unit_from_networkd_path(self.units)
2305 stop_networkd(show_logs=True)
2306
2307 def test_dhcp_server(self):
2308 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2309 start_networkd()
2310 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2311
2312 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2313 print(output)
2314 self.assertRegex(output, '192.168.5.*')
2315 self.assertRegex(output, 'Gateway: 192.168.5.1')
2316 self.assertRegex(output, 'DNS: 192.168.5.1')
2317 self.assertRegex(output, 'NTP: 192.168.5.1')
2318
2319 def test_emit_router_timezone(self):
2320 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2321 start_networkd()
2322 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2323
2324 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2325 print(output)
2326 self.assertRegex(output, 'Gateway: 192.168.5.*')
2327 self.assertRegex(output, '192.168.5.*')
2328 self.assertRegex(output, 'Europe/Berlin')
2329
2330 class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
2331 links = [
2332 'veth99',
2333 'vrf99']
2334
2335 units = [
2336 '25-veth.netdev',
2337 '25-vrf.netdev',
2338 '25-vrf.network',
2339 'dhcp-client-anonymize.network',
2340 'dhcp-client-gateway-onlink-implicit.network',
2341 'dhcp-client-ipv4-dhcp-settings.network',
2342 'dhcp-client-ipv4-only-ipv6-disabled.network',
2343 'dhcp-client-ipv4-only.network',
2344 'dhcp-client-ipv6-only.network',
2345 'dhcp-client-ipv6-rapid-commit.network',
2346 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2347 'dhcp-client-keep-configuration-dhcp.network',
2348 'dhcp-client-listen-port.network',
2349 'dhcp-client-reassign-static-routes-ipv4.network',
2350 'dhcp-client-reassign-static-routes-ipv6.network',
2351 'dhcp-client-route-metric.network',
2352 'dhcp-client-route-table.network',
2353 'dhcp-client-use-dns-ipv4-and-ra.network',
2354 'dhcp-client-use-dns-ipv4.network',
2355 'dhcp-client-use-dns-no.network',
2356 'dhcp-client-use-dns-yes.network',
2357 'dhcp-client-use-domains.network',
2358 'dhcp-client-use-routes-no.network',
2359 'dhcp-client-vrf.network',
2360 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2361 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
2362 'dhcp-client-with-static-address.network',
2363 'dhcp-client.network',
2364 'dhcp-server-veth-peer.network',
2365 'dhcp-v4-server-veth-peer.network',
2366 'dhcp-client-use-domains.network',
2367 'static.network']
2368
2369 def setUp(self):
2370 stop_dnsmasq(dnsmasq_pid_file)
2371 remove_links(self.links)
2372 stop_networkd(show_logs=False)
2373
2374 def tearDown(self):
2375 stop_dnsmasq(dnsmasq_pid_file)
2376 remove_lease_file()
2377 remove_log_file()
2378 remove_links(self.links)
2379 remove_unit_from_networkd_path(self.units)
2380 stop_networkd(show_logs=True)
2381
2382 def test_dhcp_client_ipv6_only(self):
2383 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2384
2385 start_networkd()
2386 self.wait_online(['veth-peer:carrier'])
2387 start_dnsmasq()
2388 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2389
2390 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2391 print(output)
2392 self.assertRegex(output, '2600::')
2393 self.assertNotRegex(output, '192.168.5')
2394
2395 # Confirm that ipv6 token is not set in the kernel
2396 output = check_output('ip token show dev veth99')
2397 print(output)
2398 self.assertRegex(output, 'token :: dev veth99')
2399
2400 def test_dhcp_client_ipv4_only(self):
2401 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
2402
2403 start_networkd()
2404 self.wait_online(['veth-peer:carrier'])
2405 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
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.assertNotRegex(output, '2600::')
2411 self.assertRegex(output, '192.168.5')
2412 self.assertRegex(output, '192.168.5.6')
2413 self.assertRegex(output, '192.168.5.7')
2414
2415 # checking routes to DNS servers
2416 output = check_output('ip route show dev veth99')
2417 print(output)
2418 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2419 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2420 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2421
2422 stop_dnsmasq(dnsmasq_pid_file)
2423 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
2424
2425 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2426 print('Wait for the dynamic address to be renewed')
2427 time.sleep(125)
2428
2429 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2430
2431 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2432 print(output)
2433 self.assertNotRegex(output, '2600::')
2434 self.assertRegex(output, '192.168.5')
2435 self.assertNotRegex(output, '192.168.5.6')
2436 self.assertRegex(output, '192.168.5.7')
2437 self.assertRegex(output, '192.168.5.8')
2438
2439 # checking routes to DNS servers
2440 output = check_output('ip route show dev veth99')
2441 print(output)
2442 self.assertNotRegex(output, r'192.168.5.6')
2443 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2444 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2445 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
2446
2447 def test_dhcp_client_ipv4_ipv6(self):
2448 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2449 'dhcp-client-ipv4-only.network')
2450 start_networkd()
2451 self.wait_online(['veth-peer:carrier'])
2452 start_dnsmasq()
2453 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2454
2455 # link become 'routable' when at least one protocol provide an valid address.
2456 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2457 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2458
2459 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2460 print(output)
2461 self.assertRegex(output, '2600::')
2462 self.assertRegex(output, '192.168.5')
2463
2464 def test_dhcp_client_settings(self):
2465 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
2466
2467 start_networkd()
2468 self.wait_online(['veth-peer:carrier'])
2469 start_dnsmasq()
2470 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2471
2472 print('## ip address show dev veth99')
2473 output = check_output('ip address show dev veth99')
2474 print(output)
2475 self.assertRegex(output, '12:34:56:78:9a:bc')
2476 self.assertRegex(output, '192.168.5')
2477 self.assertRegex(output, '1492')
2478
2479 # issue #8726
2480 print('## ip route show table main dev veth99')
2481 output = check_output('ip route show table main dev veth99')
2482 print(output)
2483 self.assertNotRegex(output, 'proto dhcp')
2484
2485 print('## ip route show table 211 dev veth99')
2486 output = check_output('ip route show table 211 dev veth99')
2487 print(output)
2488 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
2489 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2490 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
2491
2492 print('## dnsmasq log')
2493 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2494 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2495 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
2496 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
2497
2498 def test_dhcp6_client_settings_rapidcommit_true(self):
2499 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2500 start_networkd()
2501 self.wait_online(['veth-peer:carrier'])
2502 start_dnsmasq()
2503 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2504
2505 output = check_output('ip address show dev veth99')
2506 print(output)
2507 self.assertRegex(output, '12:34:56:78:9a:bc')
2508 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
2509
2510 def test_dhcp6_client_settings_rapidcommit_false(self):
2511 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2512 start_networkd()
2513 self.wait_online(['veth-peer:carrier'])
2514 start_dnsmasq()
2515 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2516
2517 output = check_output('ip address show dev veth99')
2518 print(output)
2519 self.assertRegex(output, '12:34:56:78:9a:bc')
2520 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
2521
2522 def test_dhcp_client_settings_anonymize(self):
2523 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2524 start_networkd()
2525 self.wait_online(['veth-peer:carrier'])
2526 start_dnsmasq()
2527 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2528
2529 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2530 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
2531 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
2532
2533 def test_dhcp_client_listen_port(self):
2534 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2535 start_networkd()
2536 self.wait_online(['veth-peer:carrier'])
2537 start_dnsmasq('--dhcp-alternate-port=67,5555')
2538 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2539
2540 # link become 'routable' when at least one protocol provide an valid address.
2541 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2542 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2543
2544 output = check_output('ip -4 address show dev veth99')
2545 print(output)
2546 self.assertRegex(output, '192.168.5.* dynamic')
2547
2548 def test_dhcp_client_with_static_address(self):
2549 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
2550 'dhcp-client-with-static-address.network')
2551 start_networkd()
2552 self.wait_online(['veth-peer:carrier'])
2553 start_dnsmasq()
2554 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2555
2556 output = check_output('ip address show dev veth99 scope global')
2557 print(output)
2558 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
2559 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
2560
2561 output = check_output('ip route show dev veth99')
2562 print(output)
2563 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
2564 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
2565 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
2566 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
2567
2568 def test_dhcp_route_table_id(self):
2569 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2570 start_networkd()
2571 self.wait_online(['veth-peer:carrier'])
2572 start_dnsmasq()
2573 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2574
2575 output = check_output('ip route show table 12')
2576 print(output)
2577 self.assertRegex(output, 'veth99 proto dhcp')
2578 self.assertRegex(output, '192.168.5.1')
2579
2580 def test_dhcp_route_metric(self):
2581 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2582 start_networkd()
2583 self.wait_online(['veth-peer:carrier'])
2584 start_dnsmasq()
2585 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2586
2587 output = check_output('ip route show dev veth99')
2588 print(output)
2589 self.assertRegex(output, 'metric 24')
2590
2591 def test_dhcp_client_reassign_static_routes_ipv4(self):
2592 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2593 'dhcp-client-reassign-static-routes-ipv4.network')
2594 start_networkd()
2595 self.wait_online(['veth-peer:carrier'])
2596 start_dnsmasq(lease_time='2m')
2597 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2598
2599 output = check_output('ip address show dev veth99 scope global')
2600 print(output)
2601 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2602
2603 output = check_output('ip route show dev veth99')
2604 print(output)
2605 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2606 self.assertRegex(output, r'192.168.5.0/24 proto static')
2607 self.assertRegex(output, r'192.168.6.0/24 proto static')
2608 self.assertRegex(output, r'192.168.7.0/24 proto static')
2609
2610 stop_dnsmasq(dnsmasq_pid_file)
2611 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
2612
2613 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2614 print('Wait for the dynamic address to be renewed')
2615 time.sleep(125)
2616
2617 self.wait_online(['veth99:routable'])
2618
2619 output = check_output('ip route show dev veth99')
2620 print(output)
2621 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2622 self.assertRegex(output, r'192.168.5.0/24 proto static')
2623 self.assertRegex(output, r'192.168.6.0/24 proto static')
2624 self.assertRegex(output, r'192.168.7.0/24 proto static')
2625
2626 def test_dhcp_client_reassign_static_routes_ipv6(self):
2627 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2628 'dhcp-client-reassign-static-routes-ipv6.network')
2629 start_networkd()
2630 self.wait_online(['veth-peer:carrier'])
2631 start_dnsmasq(lease_time='2m')
2632 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2633
2634 output = check_output('ip address show dev veth99 scope global')
2635 print(output)
2636 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (?:noprefixroute dynamic|dynamic noprefixroute)')
2637
2638 output = check_output('ip -6 route show dev veth99')
2639 print(output)
2640 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
2641 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
2642
2643 stop_dnsmasq(dnsmasq_pid_file)
2644 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
2645
2646 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2647 print('Wait for the dynamic address to be renewed')
2648 time.sleep(125)
2649
2650 self.wait_online(['veth99:routable'])
2651
2652 output = check_output('ip -6 route show dev veth99')
2653 print(output)
2654 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
2655 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
2656
2657 def test_dhcp_keep_configuration_dhcp(self):
2658 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2659 start_networkd()
2660 self.wait_online(['veth-peer:carrier'])
2661 start_dnsmasq(lease_time='2m')
2662 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2663
2664 output = check_output('ip address show dev veth99 scope global')
2665 print(output)
2666 self.assertRegex(output, r'192.168.5.*')
2667
2668 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2669 print(output)
2670 self.assertRegex(output, r'192.168.5.*')
2671
2672 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
2673 stop_dnsmasq(dnsmasq_pid_file)
2674
2675 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2676 print('Wait for the dynamic address to be expired')
2677 time.sleep(125)
2678
2679 print('The lease address should be kept after lease expired')
2680 output = check_output('ip address show dev veth99 scope global')
2681 print(output)
2682 self.assertRegex(output, r'192.168.5.*')
2683
2684 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2685 print(output)
2686 self.assertRegex(output, r'192.168.5.*')
2687
2688 check_output('systemctl stop systemd-networkd')
2689
2690 print('The lease address should be kept after networkd stopped')
2691 output = check_output('ip address show dev veth99 scope global')
2692 print(output)
2693 self.assertRegex(output, r'192.168.5.*')
2694
2695 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2696 print(output)
2697 self.assertRegex(output, r'192.168.5.*')
2698
2699 start_networkd(3)
2700 self.wait_online(['veth-peer:routable'])
2701
2702 print('Still the lease address should be kept after networkd restarted')
2703 output = check_output('ip address show dev veth99 scope global')
2704 print(output)
2705 self.assertRegex(output, r'192.168.5.*')
2706
2707 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2708 print(output)
2709 self.assertRegex(output, r'192.168.5.*')
2710
2711 def test_dhcp_keep_configuration_dhcp_on_stop(self):
2712 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2713 start_networkd()
2714 self.wait_online(['veth-peer:carrier'])
2715 start_dnsmasq(lease_time='2m')
2716 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2717
2718 output = check_output('ip address show dev veth99 scope global')
2719 print(output)
2720 self.assertRegex(output, r'192.168.5.*')
2721
2722 stop_dnsmasq(dnsmasq_pid_file)
2723 check_output('systemctl stop systemd-networkd')
2724
2725 output = check_output('ip address show dev veth99 scope global')
2726 print(output)
2727 self.assertRegex(output, r'192.168.5.*')
2728
2729 restart_networkd(3)
2730 self.wait_online(['veth-peer:routable'])
2731
2732 output = check_output('ip address show dev veth99 scope global')
2733 print(output)
2734 self.assertNotRegex(output, r'192.168.5.*')
2735
2736 def test_dhcp_client_reuse_address_as_static(self):
2737 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2738 start_networkd()
2739 self.wait_online(['veth-peer:carrier'])
2740 start_dnsmasq()
2741 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2742
2743 # link become 'routable' when at least one protocol provide an valid address.
2744 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2745 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2746
2747 output = check_output('ip address show dev veth99 scope global')
2748 print(output)
2749 self.assertRegex(output, '192.168.5')
2750 self.assertRegex(output, '2600::')
2751
2752 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
2753 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
2754 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
2755 print(static_network)
2756
2757 remove_unit_from_networkd_path(['dhcp-client.network'])
2758
2759 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
2760 f.write(static_network)
2761
2762 # When networkd started, the links are already configured, so let's wait for 5 seconds
2763 # the links to be re-configured.
2764 restart_networkd(5)
2765 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2766
2767 output = check_output('ip -4 address show dev veth99 scope global')
2768 print(output)
2769 self.assertRegex(output, '192.168.5')
2770 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2771
2772 output = check_output('ip -6 address show dev veth99 scope global')
2773 print(output)
2774 self.assertRegex(output, '2600::')
2775 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2776
2777 @expectedFailureIfModuleIsNotAvailable('vrf')
2778 def test_dhcp_client_vrf(self):
2779 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2780 '25-vrf.netdev', '25-vrf.network')
2781 start_networkd()
2782 self.wait_online(['veth-peer:carrier'])
2783 start_dnsmasq()
2784 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2785
2786 # link become 'routable' when at least one protocol provide an valid address.
2787 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2788 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2789
2790 print('## ip -d link show dev vrf99')
2791 output = check_output('ip -d link show dev vrf99')
2792 print(output)
2793 self.assertRegex(output, 'vrf table 42')
2794
2795 print('## ip address show vrf vrf99')
2796 output = check_output('ip address show vrf vrf99')
2797 print(output)
2798 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2799 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2800 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
2801 self.assertRegex(output, 'inet6 .* scope link')
2802
2803 print('## ip address show dev veth99')
2804 output = check_output('ip address show dev veth99')
2805 print(output)
2806 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2807 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2808 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)')
2809 self.assertRegex(output, 'inet6 .* scope link')
2810
2811 print('## ip route show vrf vrf99')
2812 output = check_output('ip route show vrf vrf99')
2813 print(output)
2814 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
2815 self.assertRegex(output, 'default dev veth99 proto static scope link')
2816 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
2817 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
2818 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
2819 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
2820
2821 print('## ip route show table main dev veth99')
2822 output = check_output('ip route show table main dev veth99')
2823 print(output)
2824 self.assertEqual(output, '')
2825
2826 def test_dhcp_client_gateway_onlink_implicit(self):
2827 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2828 'dhcp-client-gateway-onlink-implicit.network')
2829 start_networkd()
2830 self.wait_online(['veth-peer:carrier'])
2831 start_dnsmasq()
2832 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2833
2834 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2835 print(output)
2836 self.assertRegex(output, '192.168.5')
2837
2838 output = check_output('ip route list dev veth99 10.0.0.0/8')
2839 print(output)
2840 self.assertRegex(output, 'onlink')
2841 output = check_output('ip route list dev veth99 192.168.100.0/24')
2842 print(output)
2843 self.assertRegex(output, 'onlink')
2844
2845 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
2846 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2847 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
2848 start_networkd()
2849 self.wait_online(['veth-peer:carrier'])
2850 start_dnsmasq(lease_time='2m')
2851 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2852
2853 output = check_output('ip address show dev veth99')
2854 print(output)
2855
2856 output = check_output('ip -6 address show dev veth99 scope global dynamic')
2857 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
2858 output = check_output('ip -6 address show dev veth99 scope link')
2859 self.assertRegex(output, 'inet6 .* scope link')
2860 output = check_output('ip -4 address show dev veth99 scope global dynamic')
2861 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2862 output = check_output('ip -4 address show dev veth99 scope link')
2863 self.assertNotRegex(output, 'inet .* scope link')
2864
2865 print('Wait for the dynamic address to be expired')
2866 time.sleep(130)
2867
2868 output = check_output('ip address show dev veth99')
2869 print(output)
2870
2871 output = check_output('ip -6 address show dev veth99 scope global dynamic')
2872 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
2873 output = check_output('ip -6 address show dev veth99 scope link')
2874 self.assertRegex(output, 'inet6 .* scope link')
2875 output = check_output('ip -4 address show dev veth99 scope global dynamic')
2876 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2877 output = check_output('ip -4 address show dev veth99 scope link')
2878 self.assertNotRegex(output, 'inet .* scope link')
2879
2880 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
2881
2882 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
2883 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2884 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
2885 start_networkd()
2886 self.wait_online(['veth99:degraded', 'veth-peer:routable'])
2887
2888 output = check_output('ip address show dev veth99')
2889 print(output)
2890
2891 output = check_output('ip -6 address show dev veth99 scope global dynamic')
2892 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
2893 output = check_output('ip -6 address show dev veth99 scope link')
2894 self.assertRegex(output, 'inet6 .* scope link')
2895 output = check_output('ip -4 address show dev veth99 scope global dynamic')
2896 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2897 output = check_output('ip -4 address show dev veth99 scope link')
2898 self.assertRegex(output, 'inet .* scope link')
2899
2900 def test_dhcp_client_route_remove_on_renew(self):
2901 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2902 'dhcp-client-ipv4-only-ipv6-disabled.network')
2903 start_networkd()
2904 self.wait_online(['veth-peer:carrier'])
2905 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
2906 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2907
2908 # test for issue #12490
2909
2910 output = check_output('ip -4 address show dev veth99 scope global dynamic')
2911 print(output)
2912 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2913 address1=None
2914 for line in output.splitlines():
2915 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
2916 address1 = line.split()[1].split('/')[0]
2917 break
2918
2919 output = check_output('ip -4 route show dev veth99')
2920 print(output)
2921 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
2922 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
2923
2924 stop_dnsmasq(dnsmasq_pid_file)
2925 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
2926
2927 print('Wait for the dynamic address to be expired')
2928 time.sleep(130)
2929
2930 output = check_output('ip -4 address show dev veth99 scope global dynamic')
2931 print(output)
2932 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2933 address2=None
2934 for line in output.splitlines():
2935 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
2936 address2 = line.split()[1].split('/')[0]
2937 break
2938
2939 self.assertNotEqual(address1, address2)
2940
2941 output = check_output('ip -4 route show dev veth99')
2942 print(output)
2943 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
2944 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
2945 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
2946 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
2947
2948 def test_dhcp_client_use_dns_yes(self):
2949 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
2950
2951 start_networkd()
2952 self.wait_online(['veth-peer:carrier'])
2953 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
2954 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2955
2956 # link become 'routable' when at least one protocol provide an valid address.
2957 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2958 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2959
2960 time.sleep(3)
2961 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2962 print(output)
2963 self.assertRegex(output, '192.168.5.1')
2964 self.assertRegex(output, '2600::1')
2965
2966 def test_dhcp_client_use_dns_no(self):
2967 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
2968
2969 start_networkd()
2970 self.wait_online(['veth-peer:carrier'])
2971 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
2972 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2973
2974 # link become 'routable' when at least one protocol provide an valid address.
2975 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2976 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2977
2978 time.sleep(3)
2979 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2980 print(output)
2981 self.assertNotRegex(output, '192.168.5.1')
2982 self.assertNotRegex(output, '2600::1')
2983
2984 def test_dhcp_client_use_dns_ipv4(self):
2985 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
2986
2987 start_networkd()
2988 self.wait_online(['veth-peer:carrier'])
2989 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
2990 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2991
2992 # link become 'routable' when at least one protocol provide an valid address.
2993 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2994 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2995
2996 time.sleep(3)
2997 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
2998 print(output)
2999 self.assertRegex(output, '192.168.5.1')
3000 self.assertNotRegex(output, '2600::1')
3001
3002 def test_dhcp_client_use_dns_ipv4_and_ra(self):
3003 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3004
3005 start_networkd()
3006 self.wait_online(['veth-peer:carrier'])
3007 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3008 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3009
3010 # link become 'routable' when at least one protocol provide an valid address.
3011 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3012 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (?:dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3013
3014 time.sleep(3)
3015 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3016 print(output)
3017 self.assertRegex(output, '192.168.5.1')
3018 self.assertRegex(output, '2600::1')
3019
3020 def test_dhcp_client_use_domains(self):
3021 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3022
3023 start_networkd()
3024 self.wait_online(['veth-peer:carrier'])
3025 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
3026 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3027
3028 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
3029 print(output)
3030 self.assertRegex(output, 'Search Domains: example.com')
3031
3032 time.sleep(3)
3033 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3034 print(output)
3035 self.assertRegex(output, 'example.com')
3036
3037 if __name__ == '__main__':
3038 parser = argparse.ArgumentParser()
3039 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
3040 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
3041 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
3042 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
3043 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
3044 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
3045 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
3046 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
3047 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
3048 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
3049 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
3050 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
3051 ns, args = parser.parse_known_args(namespace=unittest)
3052
3053 if ns.build_dir:
3054 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:
3055 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
3056 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
3057 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
3058 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
3059 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
3060 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
3061 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
3062 else:
3063 if ns.networkd_bin:
3064 networkd_bin = ns.networkd_bin
3065 if ns.resolved_bin:
3066 resolved_bin = ns.resolved_bin
3067 if ns.wait_online_bin:
3068 wait_online_bin = ns.wait_online_bin
3069 if ns.networkctl_bin:
3070 networkctl_bin = ns.networkctl_bin
3071 if ns.resolvectl_bin:
3072 resolvectl_bin = ns.resolvectl_bin
3073 if ns.timedatectl_bin:
3074 timedatectl_bin = ns.timedatectl_bin
3075
3076 use_valgrind = ns.use_valgrind
3077 enable_debug = ns.enable_debug
3078 asan_options = ns.asan_options
3079 lsan_options = ns.lsan_options
3080 ubsan_options = ns.ubsan_options
3081
3082 if use_valgrind:
3083 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
3084 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
3085 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
3086 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
3087 else:
3088 networkctl_cmd = [networkctl_bin]
3089 resolvectl_cmd = [resolvectl_bin]
3090 timedatectl_cmd = [timedatectl_bin]
3091 wait_online_cmd = [wait_online_bin]
3092
3093 if enable_debug:
3094 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
3095 if asan_options:
3096 env.update({ 'ASAN_OPTIONS' : asan_options })
3097 if lsan_options:
3098 env.update({ 'LSAN_OPTIONS' : lsan_options })
3099 if ubsan_options:
3100 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
3101
3102 sys.argv[1:] = args
3103 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
3104 verbosity=3))