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