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