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