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