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