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