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