]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
test-network: Remove/replace non-capturing group regex
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: LGPL-2.1+
3 # systemd-networkd tests
4
5 import argparse
6 import os
7 import re
8 import shutil
9 import signal
10 import subprocess
11 import sys
12 import time
13 import unittest
14 from shutil import copytree
15
16 network_unit_file_path='/run/systemd/network'
17 networkd_runtime_directory='/run/systemd/netif'
18 networkd_ci_path='/run/networkd-ci'
19 network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
20 network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
21
22 dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
23 dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
24
25 systemd_lib_paths=['/usr/lib/systemd', '/lib/systemd']
26 which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':'))
27
28 networkd_bin=shutil.which('systemd-networkd', path=which_paths)
29 resolved_bin=shutil.which('systemd-resolved', path=which_paths)
30 wait_online_bin=shutil.which('systemd-networkd-wait-online', path=which_paths)
31 networkctl_bin=shutil.which('networkctl', path=which_paths)
32 resolvectl_bin=shutil.which('resolvectl', path=which_paths)
33 timedatectl_bin=shutil.which('timedatectl', path=which_paths)
34
35 use_valgrind=False
36 enable_debug=True
37 env = {}
38 asan_options=None
39 lsan_options=None
40 ubsan_options=None
41
42 running_units = []
43
44 def 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
49 def call(*command, **kwargs):
50 command = command[0].split() + list(command[1:])
51 return subprocess.call(command, universal_newlines=True, **kwargs)
52
53 def run(*command, **kwargs):
54 command = command[0].split() + list(command[1:])
55 return subprocess.run(command, universal_newlines=True, **kwargs)
56
57 def 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
62 def 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
70 def 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
81 def 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
92 def 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
103 def 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
120 def 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
130 def 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
204 def 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
219 def 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
223 def 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
231 def link_exists(link):
232 return os.path.exists(os.path.join('/sys/class/net', link))
233
234 def 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
240 def remove_fou_ports(ports):
241 for port in ports:
242 call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
243
244 def 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
250 def 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
254 def 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
262 def 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
266 def 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
270 def 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
277 def 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
284 def 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
288 def 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
296 def 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
309 def 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
313 def remove_log_file():
314 if os.path.exists(dnsmasq_log_file):
315 os.remove(dnsmasq_log_file)
316
317 def 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
321 def 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
330 def start_networkd(sleep_sec=0):
331 check_output('systemctl start systemd-networkd')
332 if sleep_sec > 0:
333 time.sleep(sleep_sec)
334
335 def 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
339 def 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
348 class 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
384 class 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
537 class 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
1382 class 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
1465 class 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.network',
1502 '25-route-ipv6-src.network',
1503 '25-route-static.network',
1504 '25-gateway-static.network',
1505 '25-gateway-next-static.network',
1506 '25-sysctl-disable-ipv6.network',
1507 '25-sysctl.network',
1508 '25-veth-peer.network',
1509 '25-veth.netdev',
1510 '26-link-local-addressing-ipv6.network',
1511 'configure-without-carrier.network',
1512 'routing-policy-rule-dummy98.network',
1513 'routing-policy-rule-test1.network']
1514
1515 routing_policy_rule_tables = ['7', '8', '9']
1516 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1517
1518 def setUp(self):
1519 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1520 remove_routes(self.routes)
1521 remove_links(self.links)
1522 stop_networkd(show_logs=False)
1523
1524 def tearDown(self):
1525 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1526 remove_routes(self.routes)
1527 remove_links(self.links)
1528 remove_unit_from_networkd_path(self.units)
1529 stop_networkd(show_logs=True)
1530
1531 def test_address_static(self):
1532 copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1533 start_networkd()
1534
1535 self.wait_online(['dummy98:routable'])
1536
1537 output = check_output('ip -4 address show dev dummy98')
1538 print(output)
1539 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1540 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1541 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1542
1543 # invalid sections
1544 self.assertNotRegex(output, '10.10.0.1/16')
1545 self.assertNotRegex(output, '10.10.0.2/16')
1546
1547 output = check_output('ip -4 address show dev dummy98 label 32')
1548 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1549
1550 output = check_output('ip -4 address show dev dummy98 label 33')
1551 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1552
1553 output = check_output('ip -4 address show dev dummy98 label 34')
1554 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1555
1556 output = check_output('ip -4 address show dev dummy98 label 35')
1557 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1558
1559 output = check_output('ip -6 address show dev dummy98')
1560 print(output)
1561 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1562 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1563 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1564 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1565 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1566 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1567
1568 def test_address_preferred_lifetime_zero_ipv6(self):
1569 copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev')
1570 start_networkd(5)
1571
1572 self.wait_online(['dummy98:routable'])
1573
1574 output = check_output('ip address show dummy98')
1575 print(output)
1576 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1577 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1578
1579 output = check_output('ip route show dev dummy98')
1580 print(output)
1581 self.assertRegex(output, 'default via 20.20.20.1 proto static')
1582
1583 def test_configure_without_carrier(self):
1584 copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1585 start_networkd()
1586 self.wait_online(['test1:routable'])
1587
1588 output = check_output(*networkctl_cmd, 'status', 'test1')
1589 print(output)
1590 self.assertRegex(output, '192.168.0.15')
1591 self.assertRegex(output, '192.168.0.1')
1592 self.assertRegex(output, 'routable')
1593
1594 def test_routing_policy_rule(self):
1595 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1596 start_networkd()
1597 self.wait_online(['test1:degraded'])
1598
1599 output = check_output('ip rule list iif test1 priority 111')
1600 print(output)
1601 self.assertRegex(output, '111:')
1602 self.assertRegex(output, 'from 192.168.100.18')
1603 self.assertRegex(output, r'tos (0x08|throughput)\s')
1604 self.assertRegex(output, 'iif test1')
1605 self.assertRegex(output, 'oif test1')
1606 self.assertRegex(output, 'lookup 7')
1607
1608 output = check_output('ip rule list iif test1 priority 101')
1609 print(output)
1610 self.assertRegex(output, '101:')
1611 self.assertRegex(output, 'from all')
1612 self.assertRegex(output, 'iif test1')
1613 self.assertRegex(output, 'lookup 9')
1614
1615 output = check_output('ip -6 rule list iif test1 priority 100')
1616 print(output)
1617 self.assertRegex(output, '100:')
1618 self.assertRegex(output, 'from all')
1619 self.assertRegex(output, 'iif test1')
1620 self.assertRegex(output, 'lookup 8')
1621
1622 output = check_output('ip -6 rule list iif test1 priority 101')
1623 print(output)
1624 self.assertRegex(output, '101:')
1625 self.assertRegex(output, 'from all')
1626 self.assertRegex(output, 'iif test1')
1627 self.assertRegex(output, 'lookup 9')
1628
1629 def test_routing_policy_rule_issue_11280(self):
1630 copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1631 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1632
1633 for trial in range(3):
1634 # Remove state files only first time
1635 start_networkd(3)
1636 self.wait_online(['test1:degraded', 'dummy98:degraded'])
1637 time.sleep(1)
1638
1639 output = check_output('ip rule list table 7')
1640 print(output)
1641 self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7')
1642
1643 output = check_output('ip rule list table 8')
1644 print(output)
1645 self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1646
1647 stop_networkd(remove_state_files=False)
1648
1649 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1650 def test_routing_policy_rule_port_range(self):
1651 copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1652 start_networkd()
1653 self.wait_online(['test1:degraded'])
1654
1655 output = check_output('ip rule')
1656 print(output)
1657 self.assertRegex(output, '111')
1658 self.assertRegex(output, 'from 192.168.100.18')
1659 self.assertRegex(output, '1123-1150')
1660 self.assertRegex(output, '3224-3290')
1661 self.assertRegex(output, 'tcp')
1662 self.assertRegex(output, 'lookup 7')
1663
1664 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1665 def test_routing_policy_rule_invert(self):
1666 copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1667 start_networkd()
1668 self.wait_online(['test1:degraded'])
1669
1670 output = check_output('ip rule')
1671 print(output)
1672 self.assertRegex(output, '111')
1673 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1674 self.assertRegex(output, 'tcp')
1675 self.assertRegex(output, 'lookup 7')
1676
1677 def test_route_static(self):
1678 copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1679 start_networkd()
1680 self.wait_online(['dummy98:routable'])
1681
1682 output = check_output(*networkctl_cmd, 'status', 'dummy98', env=env)
1683 print(output)
1684
1685 print('### ip -6 route show dev dummy98')
1686 output = check_output('ip -6 route show dev dummy98')
1687 print(output)
1688 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1689 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1690
1691 print('### ip -6 route show dev dummy98 default')
1692 output = check_output('ip -6 route show dev dummy98 default')
1693 print(output)
1694 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1695
1696 print('### ip -4 route show dev dummy98')
1697 output = check_output('ip -4 route show dev dummy98')
1698 print(output)
1699 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1700 self.assertRegex(output, '149.10.124.64 proto static scope link')
1701 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
1702 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1703 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
1704 self.assertRegex(output, 'multicast 149.10.123.4 proto static')
1705
1706 print('### ip -4 route show dev dummy98 default')
1707 output = check_output('ip -4 route show dev dummy98 default')
1708 print(output)
1709 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1710 self.assertRegex(output, 'default via 149.10.124.64 proto static')
1711 self.assertRegex(output, 'default proto static')
1712
1713 print('### ip -4 route show table local dev dummy98')
1714 output = check_output('ip -4 route show table local dev dummy98')
1715 print(output)
1716 self.assertRegex(output, 'local 149.10.123.1 proto static scope host')
1717 self.assertRegex(output, 'anycast 149.10.123.2 proto static scope link')
1718 self.assertRegex(output, 'broadcast 149.10.123.3 proto static scope link')
1719
1720 print('### ip route show type blackhole')
1721 output = check_output('ip route show type blackhole')
1722 print(output)
1723 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
1724
1725 print('### ip route show type unreachable')
1726 output = check_output('ip route show type unreachable')
1727 print(output)
1728 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
1729
1730 print('### ip route show type prohibit')
1731 output = check_output('ip route show type prohibit')
1732 print(output)
1733 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
1734
1735 def test_gateway_reconfigure(self):
1736 copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev')
1737 start_networkd()
1738 self.wait_online(['dummy98:routable'])
1739 print('### ip -4 route show dev dummy98 default')
1740 output = check_output('ip -4 route show dev dummy98 default')
1741 print(output)
1742 self.assertRegex(output, 'default via 149.10.124.59 proto static')
1743 self.assertNotRegex(output, '149.10.124.60')
1744
1745 remove_unit_from_networkd_path(['25-gateway-static.network'])
1746 copy_unit_to_networkd_unit_path('25-gateway-next-static.network')
1747 restart_networkd(3)
1748 self.wait_online(['dummy98:routable'])
1749 print('### ip -4 route show dev dummy98 default')
1750 output = check_output('ip -4 route show dev dummy98 default')
1751 print(output)
1752 self.assertNotRegex(output, '149.10.124.59')
1753 self.assertRegex(output, 'default via 149.10.124.60 proto static')
1754
1755 def test_ip_route_ipv6_src_route(self):
1756 # a dummy device does not make the addresses go through tentative state, so we
1757 # reuse a bond from an earlier test, which does make the addresses go through
1758 # tentative state, and do our test on that
1759 copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1760 start_networkd()
1761 self.wait_online(['dummy98:enslaved', 'bond199:routable'])
1762
1763 output = check_output('ip -6 route list dev bond199')
1764 print(output)
1765 self.assertRegex(output, 'abcd::/16')
1766 self.assertRegex(output, 'src')
1767 self.assertRegex(output, '2001:1234:56:8f63::2')
1768
1769 def test_ip_link_mac_address(self):
1770 copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1771 start_networkd()
1772 self.wait_online(['dummy98:degraded'])
1773
1774 output = check_output('ip link show dummy98')
1775 print(output)
1776 self.assertRegex(output, '00:01:02:aa:bb:cc')
1777
1778 def test_ip_link_unmanaged(self):
1779 copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
1780 start_networkd(5)
1781
1782 self.check_link_exists('dummy98')
1783
1784 self.check_operstate('dummy98', 'off', setup_state='unmanaged')
1785
1786 def test_ipv6_address_label(self):
1787 copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
1788 start_networkd()
1789 self.wait_online(['dummy98:degraded'])
1790
1791 output = check_output('ip addrlabel list')
1792 print(output)
1793 self.assertRegex(output, '2004:da8:1::/64')
1794
1795 def test_neighbor_section(self):
1796 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1797 start_networkd()
1798 self.wait_online(['dummy98:degraded'], timeout='40s')
1799
1800 print('### ip neigh list dev dummy98')
1801 output = check_output('ip neigh list dev dummy98')
1802 print(output)
1803 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1804 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1805
1806 def test_neighbor_reconfigure(self):
1807 copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1808 start_networkd()
1809 self.wait_online(['dummy98:degraded'], timeout='40s')
1810
1811 print('### ip neigh list dev dummy98')
1812 output = check_output('ip neigh list dev dummy98')
1813 print(output)
1814 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1815 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1816
1817 remove_unit_from_networkd_path(['25-neighbor-section.network'])
1818 copy_unit_to_networkd_unit_path('25-neighbor-next.network')
1819 restart_networkd(3)
1820 self.wait_online(['dummy98:degraded'], timeout='40s')
1821 print('### ip neigh list dev dummy98')
1822 output = check_output('ip neigh list dev dummy98')
1823 print(output)
1824 self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1825 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT')
1826 self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT')
1827
1828 def test_neighbor_gre(self):
1829 copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network',
1830 '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
1831 start_networkd()
1832 self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s')
1833
1834 output = check_output('ip neigh list dev gretun97')
1835 print(output)
1836 self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT')
1837
1838 output = check_output('ip neigh list dev ip6gretun97')
1839 print(output)
1840 self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT')
1841
1842 def test_link_local_addressing(self):
1843 copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1844 '25-link-local-addressing-no.network', '12-dummy.netdev')
1845 start_networkd()
1846 self.wait_online(['test1:degraded', 'dummy98:carrier'])
1847
1848 output = check_output('ip address show dev test1')
1849 print(output)
1850 self.assertRegex(output, 'inet .* scope link')
1851 self.assertRegex(output, 'inet6 .* scope link')
1852
1853 output = check_output('ip address show dev dummy98')
1854 print(output)
1855 self.assertNotRegex(output, 'inet6* .* scope link')
1856
1857 '''
1858 Documentation/networking/ip-sysctl.txt
1859
1860 addr_gen_mode - INTEGER
1861 Defines how link-local and autoconf addresses are generated.
1862
1863 0: generate address based on EUI64 (default)
1864 1: do no generate a link-local address, use EUI64 for addresses generated
1865 from autoconf
1866 2: generate stable privacy addresses, using the secret from
1867 stable_secret (RFC7217)
1868 3: generate stable privacy addresses, using a random secret if unset
1869 '''
1870
1871 test1_addr_gen_mode = ''
1872 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
1873 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
1874 try:
1875 f.readline()
1876 except IOError:
1877 # if stable_secret is unset, then EIO is returned
1878 test1_addr_gen_mode = '0'
1879 else:
1880 test1_addr_gen_mode = '2'
1881 else:
1882 test1_addr_gen_mode = '0'
1883
1884 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
1885 self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
1886
1887 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
1888 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1889
1890 def test_link_local_addressing_remove_ipv6ll(self):
1891 copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')
1892 start_networkd()
1893 self.wait_online(['dummy98:degraded'])
1894
1895 output = check_output('ip address show dev dummy98')
1896 print(output)
1897 self.assertRegex(output, 'inet6 .* scope link')
1898
1899 copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network')
1900 restart_networkd(1)
1901 self.wait_online(['dummy98:carrier'])
1902
1903 output = check_output('ip address show dev dummy98')
1904 print(output)
1905 self.assertNotRegex(output, 'inet6* .* scope link')
1906
1907 def test_sysctl(self):
1908 copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1909 start_networkd()
1910 self.wait_online(['dummy98:degraded'])
1911
1912 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1913 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1914 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1915 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1916 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1917 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1918 self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1919
1920 def test_sysctl_disable_ipv6(self):
1921 copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1922
1923 print('## Disable ipv6')
1924 check_output('sysctl net.ipv6.conf.all.disable_ipv6=1')
1925 check_output('sysctl net.ipv6.conf.default.disable_ipv6=1')
1926
1927 start_networkd()
1928 self.wait_online(['dummy98:routable'])
1929
1930 output = check_output('ip -4 address show dummy98')
1931 print(output)
1932 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1933 output = check_output('ip -6 address show dummy98')
1934 print(output)
1935 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
1936 self.assertRegex(output, 'inet6 .* scope link')
1937 output = check_output('ip -4 route show dev dummy98')
1938 print(output)
1939 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1940 output = check_output('ip -6 route show dev dummy98')
1941 print(output)
1942 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1943
1944 check_output('ip link del dummy98')
1945
1946 print('## Enable ipv6')
1947 check_output('sysctl net.ipv6.conf.all.disable_ipv6=0')
1948 check_output('sysctl net.ipv6.conf.default.disable_ipv6=0')
1949
1950 restart_networkd(3)
1951 self.wait_online(['dummy98:routable'])
1952
1953 output = check_output('ip -4 address show dummy98')
1954 print(output)
1955 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1956 output = check_output('ip -6 address show dummy98')
1957 print(output)
1958 self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global')
1959 self.assertRegex(output, 'inet6 .* scope link')
1960 output = check_output('ip -4 route show dev dummy98')
1961 print(output)
1962 self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4')
1963 output = check_output('ip -6 route show dev dummy98')
1964 print(output)
1965 self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static')
1966
1967 def test_bind_carrier(self):
1968 copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1969 start_networkd()
1970 self.wait_online(['test1:routable'])
1971
1972 check_output('ip link add dummy98 type dummy')
1973 check_output('ip link set dummy98 up')
1974 time.sleep(2)
1975 output = check_output('ip address show test1')
1976 print(output)
1977 self.assertRegex(output, 'UP,LOWER_UP')
1978 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1979 self.check_operstate('test1', 'routable')
1980
1981 check_output('ip link add dummy99 type dummy')
1982 check_output('ip link set dummy99 up')
1983 time.sleep(2)
1984 output = check_output('ip address show test1')
1985 print(output)
1986 self.assertRegex(output, 'UP,LOWER_UP')
1987 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1988 self.check_operstate('test1', 'routable')
1989
1990 check_output('ip link del dummy98')
1991 time.sleep(2)
1992 output = check_output('ip address show test1')
1993 print(output)
1994 self.assertRegex(output, 'UP,LOWER_UP')
1995 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1996 self.check_operstate('test1', 'routable')
1997
1998 check_output('ip link del dummy99')
1999 time.sleep(2)
2000 output = check_output('ip address show test1')
2001 print(output)
2002 self.assertNotRegex(output, 'UP,LOWER_UP')
2003 self.assertRegex(output, 'DOWN')
2004 self.assertNotRegex(output, '192.168.10')
2005 self.check_operstate('test1', 'off')
2006
2007 check_output('ip link add dummy98 type dummy')
2008 check_output('ip link set dummy98 up')
2009 time.sleep(2)
2010 output = check_output('ip address show test1')
2011 print(output)
2012 self.assertRegex(output, 'UP,LOWER_UP')
2013 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
2014 self.check_operstate('test1', 'routable')
2015
2016 def test_domain(self):
2017 copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
2018 start_networkd()
2019 self.wait_online(['dummy98:routable'])
2020
2021 output = check_output(*networkctl_cmd, 'status', 'dummy98', env=env)
2022 print(output)
2023 self.assertRegex(output, 'Address: 192.168.42.100')
2024 self.assertRegex(output, 'DNS: 192.168.42.1')
2025 self.assertRegex(output, 'Search Domains: one')
2026
2027 def test_keep_configuration_static(self):
2028 check_output('systemctl stop systemd-networkd')
2029
2030 check_output('ip link add name dummy98 type dummy')
2031 check_output('ip address add 10.1.2.3/16 dev dummy98')
2032 check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500')
2033 output = check_output('ip address show dummy98')
2034 print(output)
2035 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2036 self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2037 output = check_output('ip route show dev dummy98')
2038 print(output)
2039
2040 copy_unit_to_networkd_unit_path('24-keep-configuration-static.network')
2041 start_networkd()
2042 self.wait_online(['dummy98:routable'])
2043
2044 output = check_output('ip address show dummy98')
2045 print(output)
2046 self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98')
2047 self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98')
2048
2049 @expectedFailureIfNexthopIsNotAvailable()
2050 def test_nexthop(self):
2051 copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network')
2052 start_networkd()
2053 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2054
2055 output = check_output('ip nexthop list dev veth99')
2056 print(output)
2057 self.assertRegex(output, '192.168.5.1')
2058
2059 def test_qdisc(self):
2060 copy_unit_to_networkd_unit_path('25-qdisc.network', '12-dummy.netdev')
2061 start_networkd()
2062
2063 self.wait_online(['dummy98:routable'])
2064
2065 output = check_output('tc qdisc show dev dummy98')
2066 print(output)
2067 self.assertRegex(output, 'limit 100 delay 50.0ms 10.0ms loss 20%')
2068 self.assertRegex(output, 'limit 200 delay 100.0ms 13.0ms loss 20.5%')
2069
2070 class NetworkdStateFileTests(unittest.TestCase, Utilities):
2071 links = [
2072 'dummy98',
2073 ]
2074
2075 units = [
2076 '12-dummy.netdev',
2077 'state-file-tests.network',
2078 ]
2079
2080 def setUp(self):
2081 remove_links(self.links)
2082 stop_networkd(show_logs=False)
2083
2084 def tearDown(self):
2085 remove_links(self.links)
2086 remove_unit_from_networkd_path(self.units)
2087 stop_networkd(show_logs=True)
2088
2089 def test_state_file(self):
2090 copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network')
2091 start_networkd()
2092 self.wait_online(['dummy98:routable'])
2093
2094 output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env)
2095 print(output)
2096 ifindex = output.split()[0]
2097
2098 path = os.path.join('/run/systemd/netif/links/', ifindex)
2099 self.assertTrue(os.path.exists(path))
2100 time.sleep(2)
2101
2102 with open(path) as f:
2103 data = f.read()
2104 self.assertRegex(data, r'ADMIN_STATE=configured')
2105 self.assertRegex(data, r'OPER_STATE=routable')
2106 self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes')
2107 self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable')
2108 self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network')
2109 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2110 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2111 self.assertRegex(data, r'DOMAINS=hogehoge')
2112 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2113 self.assertRegex(data, r'LLMNR=no')
2114 self.assertRegex(data, r'MDNS=yes')
2115 self.assertRegex(data, r'DNSSEC=no')
2116 self.assertRegex(data, r'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24')
2117
2118 check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env)
2119 check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env)
2120 check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env)
2121 check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env)
2122 check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env)
2123 check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env)
2124 time.sleep(2)
2125
2126 with open(path) as f:
2127 data = f.read()
2128 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2129 self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org')
2130 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2131 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2132 self.assertRegex(data, r'LLMNR=yes')
2133 self.assertRegex(data, r'MDNS=no')
2134 self.assertRegex(data, r'DNSSEC=yes')
2135
2136 check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env)
2137 time.sleep(2)
2138
2139 with open(path) as f:
2140 data = f.read()
2141 self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13')
2142 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2143 self.assertRegex(data, r'DOMAINS=hogehogehoge')
2144 self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo')
2145 self.assertRegex(data, r'LLMNR=yes')
2146 self.assertRegex(data, r'MDNS=no')
2147 self.assertRegex(data, r'DNSSEC=yes')
2148
2149 check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env)
2150 time.sleep(2)
2151
2152 with open(path) as f:
2153 data = f.read()
2154 self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11')
2155 self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org')
2156 self.assertRegex(data, r'DOMAINS=hogehoge')
2157 self.assertRegex(data, r'ROUTE_DOMAINS=foofoo')
2158 self.assertRegex(data, r'LLMNR=no')
2159 self.assertRegex(data, r'MDNS=yes')
2160 self.assertRegex(data, r'DNSSEC=no')
2161
2162 class NetworkdBondTests(unittest.TestCase, Utilities):
2163 links = [
2164 'bond199',
2165 'bond99',
2166 'dummy98',
2167 'test1']
2168
2169 units = [
2170 '11-dummy.netdev',
2171 '12-dummy.netdev',
2172 '23-active-slave.network',
2173 '23-bond199.network',
2174 '23-primary-slave.network',
2175 '25-bond-active-backup-slave.netdev',
2176 '25-bond.netdev',
2177 'bond99.network',
2178 'bond-slave.network']
2179
2180 def setUp(self):
2181 remove_links(self.links)
2182 stop_networkd(show_logs=False)
2183
2184 def tearDown(self):
2185 remove_links(self.links)
2186 remove_unit_from_networkd_path(self.units)
2187 stop_networkd(show_logs=True)
2188
2189 def test_bond_active_slave(self):
2190 copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
2191 start_networkd()
2192 self.wait_online(['dummy98:enslaved', 'bond199:degraded'])
2193
2194 output = check_output('ip -d link show bond199')
2195 print(output)
2196 self.assertRegex(output, 'active_slave dummy98')
2197
2198 def test_bond_primary_slave(self):
2199 copy_unit_to_networkd_unit_path('23-primary-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, 'primary dummy98')
2206
2207 def test_bond_operstate(self):
2208 copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
2209 'bond99.network','bond-slave.network')
2210 start_networkd()
2211 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable'])
2212
2213 output = check_output('ip -d link show dummy98')
2214 print(output)
2215 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2216
2217 output = check_output('ip -d link show test1')
2218 print(output)
2219 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
2220
2221 output = check_output('ip -d link show bond99')
2222 print(output)
2223 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
2224
2225 self.check_operstate('dummy98', 'enslaved')
2226 self.check_operstate('test1', 'enslaved')
2227 self.check_operstate('bond99', 'routable')
2228
2229 check_output('ip link set dummy98 down')
2230 time.sleep(2)
2231
2232 self.check_operstate('dummy98', 'off')
2233 self.check_operstate('test1', 'enslaved')
2234 self.check_operstate('bond99', 'degraded-carrier')
2235
2236 check_output('ip link set dummy98 up')
2237 time.sleep(2)
2238
2239 self.check_operstate('dummy98', 'enslaved')
2240 self.check_operstate('test1', 'enslaved')
2241 self.check_operstate('bond99', 'routable')
2242
2243 check_output('ip link set dummy98 down')
2244 check_output('ip link set test1 down')
2245 time.sleep(2)
2246
2247 self.check_operstate('dummy98', 'off')
2248 self.check_operstate('test1', 'off')
2249
2250 for trial in range(30):
2251 if trial > 0:
2252 time.sleep(1)
2253 output = check_output('ip address show bond99')
2254 print(output)
2255 if get_operstate('bond99') == 'no-carrier':
2256 break
2257 else:
2258 # Huh? Kernel does not recognize that all slave interfaces are down?
2259 # Let's confirm that networkd's operstate is consistent with ip's result.
2260 self.assertNotRegex(output, 'NO-CARRIER')
2261
2262 class NetworkdBridgeTests(unittest.TestCase, Utilities):
2263 links = [
2264 'bridge99',
2265 'dummy98',
2266 'test1']
2267
2268 units = [
2269 '11-dummy.netdev',
2270 '12-dummy.netdev',
2271 '26-bridge.netdev',
2272 '26-bridge-slave-interface-1.network',
2273 '26-bridge-slave-interface-2.network',
2274 '26-bridge-vlan-master.network',
2275 '26-bridge-vlan-slave.network',
2276 'bridge99-ignore-carrier-loss.network',
2277 'bridge99.network']
2278
2279 routing_policy_rule_tables = ['100']
2280
2281 def setUp(self):
2282 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
2283 remove_links(self.links)
2284 stop_networkd(show_logs=False)
2285
2286 def tearDown(self):
2287 remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
2288 remove_links(self.links)
2289 remove_unit_from_networkd_path(self.units)
2290 stop_networkd(show_logs=True)
2291
2292 def test_bridge_vlan(self):
2293 copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network',
2294 '26-bridge.netdev', '26-bridge-vlan-master.network')
2295 start_networkd()
2296 self.wait_online(['test1:enslaved', 'bridge99:degraded'])
2297
2298 output = check_output('bridge vlan show dev test1')
2299 print(output)
2300 self.assertNotRegex(output, '4063')
2301 for i in range(4064, 4095):
2302 self.assertRegex(output, f'{i}')
2303 self.assertNotRegex(output, '4095')
2304
2305 output = check_output('bridge vlan show dev bridge99')
2306 print(output)
2307 self.assertNotRegex(output, '4059')
2308 for i in range(4060, 4095):
2309 self.assertRegex(output, f'{i}')
2310 self.assertNotRegex(output, '4095')
2311
2312 def test_bridge_property(self):
2313 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2314 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2315 'bridge99.network')
2316 start_networkd()
2317 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2318
2319 output = check_output('ip -d link show test1')
2320 print(output)
2321 self.assertRegex(output, 'master')
2322 self.assertRegex(output, 'bridge')
2323
2324 output = check_output('ip -d link show dummy98')
2325 print(output)
2326 self.assertRegex(output, 'master')
2327 self.assertRegex(output, 'bridge')
2328
2329 output = check_output('ip addr show bridge99')
2330 print(output)
2331 self.assertRegex(output, '192.168.0.15/24')
2332
2333 output = check_output('bridge -d link show dummy98')
2334 print(output)
2335 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
2336 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
2337 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
2338 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
2339 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
2340 # CONFIG_BRIDGE_IGMP_SNOOPING=y
2341 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
2342 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
2343 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
2344 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
2345 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
2346 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23')
2347 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1')
2348 self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1')
2349
2350 output = check_output('bridge -d link show test1')
2351 print(output)
2352 self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0')
2353
2354 check_output('ip address add 192.168.0.16/24 dev bridge99')
2355 time.sleep(1)
2356
2357 output = check_output('ip addr show bridge99')
2358 print(output)
2359 self.assertRegex(output, '192.168.0.16/24')
2360
2361 # for issue #6088
2362 print('### ip -6 route list table all dev bridge99')
2363 output = check_output('ip -6 route list table all dev bridge99')
2364 print(output)
2365 self.assertRegex(output, 'ff00::/8 table local metric 256 pref medium')
2366
2367 self.assertEqual(call('ip link del test1'), 0)
2368 time.sleep(3)
2369
2370 self.check_operstate('bridge99', 'degraded-carrier')
2371
2372 check_output('ip link del dummy98')
2373 time.sleep(3)
2374
2375 self.check_operstate('bridge99', 'no-carrier')
2376
2377 output = check_output('ip address show bridge99')
2378 print(output)
2379 self.assertRegex(output, 'NO-CARRIER')
2380 self.assertNotRegex(output, '192.168.0.15/24')
2381 self.assertNotRegex(output, '192.168.0.16/24')
2382
2383 print('### ip -6 route list table all dev bridge99')
2384 output = check_output('ip -6 route list table all dev bridge99')
2385 print(output)
2386 self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium')
2387
2388 def test_bridge_ignore_carrier_loss(self):
2389 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2390 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2391 'bridge99-ignore-carrier-loss.network')
2392 start_networkd()
2393 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2394
2395 check_output('ip address add 192.168.0.16/24 dev bridge99')
2396 time.sleep(1)
2397
2398 check_output('ip link del test1')
2399 check_output('ip link del dummy98')
2400 time.sleep(3)
2401
2402 output = check_output('ip address show bridge99')
2403 print(output)
2404 self.assertRegex(output, 'NO-CARRIER')
2405 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2406 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
2407
2408 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
2409 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2410 'bridge99-ignore-carrier-loss.network')
2411 start_networkd()
2412 self.wait_online(['bridge99:no-carrier'])
2413
2414 for trial in range(4):
2415 check_output('ip link add dummy98 type dummy')
2416 check_output('ip link set dummy98 up')
2417 if trial < 3:
2418 check_output('ip link del dummy98')
2419
2420 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
2421
2422 output = check_output('ip address show bridge99')
2423 print(output)
2424 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2425
2426 output = check_output('ip rule list table 100')
2427 print(output)
2428 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
2429
2430 class NetworkdLLDPTests(unittest.TestCase, Utilities):
2431 links = ['veth99']
2432
2433 units = [
2434 '23-emit-lldp.network',
2435 '24-lldp.network',
2436 '25-veth.netdev']
2437
2438 def setUp(self):
2439 remove_links(self.links)
2440 stop_networkd(show_logs=False)
2441
2442 def tearDown(self):
2443 remove_links(self.links)
2444 remove_unit_from_networkd_path(self.units)
2445 stop_networkd(show_logs=True)
2446
2447 def test_lldp(self):
2448 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2449 start_networkd()
2450 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
2451
2452 output = check_output(*networkctl_cmd, 'lldp', env=env)
2453 print(output)
2454 self.assertRegex(output, 'veth-peer')
2455 self.assertRegex(output, 'veth99')
2456
2457 class NetworkdRATests(unittest.TestCase, Utilities):
2458 links = ['veth99']
2459
2460 units = [
2461 '25-veth.netdev',
2462 'ipv6-prefix.network',
2463 'ipv6-prefix-veth.network']
2464
2465 def setUp(self):
2466 remove_links(self.links)
2467 stop_networkd(show_logs=False)
2468
2469 def tearDown(self):
2470 remove_links(self.links)
2471 remove_unit_from_networkd_path(self.units)
2472 stop_networkd(show_logs=True)
2473
2474 def test_ipv6_prefix_delegation(self):
2475 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
2476 start_networkd()
2477 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
2478
2479 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2480 print(output)
2481 self.assertRegex(output, '2002:da8:1:0')
2482
2483 class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
2484 links = ['veth99']
2485
2486 units = [
2487 '25-veth.netdev',
2488 'dhcp-client.network',
2489 'dhcp-client-timezone-router.network',
2490 'dhcp-server.network',
2491 'dhcp-server-timezone-router.network']
2492
2493 def setUp(self):
2494 remove_links(self.links)
2495 stop_networkd(show_logs=False)
2496
2497 def tearDown(self):
2498 remove_links(self.links)
2499 remove_unit_from_networkd_path(self.units)
2500 stop_networkd(show_logs=True)
2501
2502 def test_dhcp_server(self):
2503 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
2504 start_networkd()
2505 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2506
2507 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2508 print(output)
2509 self.assertRegex(output, '192.168.5.*')
2510 self.assertRegex(output, 'Gateway: 192.168.5.1')
2511 self.assertRegex(output, 'DNS: 192.168.5.1')
2512 self.assertRegex(output, 'NTP: 192.168.5.1')
2513
2514 def test_emit_router_timezone(self):
2515 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
2516 start_networkd()
2517 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2518
2519 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2520 print(output)
2521 self.assertRegex(output, 'Gateway: 192.168.5.*')
2522 self.assertRegex(output, '192.168.5.*')
2523 self.assertRegex(output, 'Europe/Berlin')
2524
2525 class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
2526 links = [
2527 'veth99',
2528 'vrf99']
2529
2530 units = [
2531 '25-veth.netdev',
2532 '25-vrf.netdev',
2533 '25-vrf.network',
2534 'dhcp-client-anonymize.network',
2535 'dhcp-client-gateway-onlink-implicit.network',
2536 'dhcp-client-ipv4-dhcp-settings.network',
2537 'dhcp-client-ipv4-only-ipv6-disabled.network',
2538 'dhcp-client-ipv4-only.network',
2539 'dhcp-client-ipv6-only.network',
2540 'dhcp-client-ipv6-rapid-commit.network',
2541 'dhcp-client-keep-configuration-dhcp-on-stop.network',
2542 'dhcp-client-keep-configuration-dhcp.network',
2543 'dhcp-client-listen-port.network',
2544 'dhcp-client-reassign-static-routes-ipv4.network',
2545 'dhcp-client-reassign-static-routes-ipv6.network',
2546 'dhcp-client-route-metric.network',
2547 'dhcp-client-route-table.network',
2548 'dhcp-client-use-dns-ipv4-and-ra.network',
2549 'dhcp-client-use-dns-ipv4.network',
2550 'dhcp-client-use-dns-no.network',
2551 'dhcp-client-use-dns-yes.network',
2552 'dhcp-client-use-domains.network',
2553 'dhcp-client-use-routes-no.network',
2554 'dhcp-client-vrf.network',
2555 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
2556 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
2557 'dhcp-client-with-static-address.network',
2558 'dhcp-client.network',
2559 'dhcp-server-veth-peer.network',
2560 'dhcp-v4-server-veth-peer.network',
2561 'dhcp-client-use-domains.network',
2562 'static.network']
2563
2564 def setUp(self):
2565 stop_dnsmasq(dnsmasq_pid_file)
2566 remove_links(self.links)
2567 stop_networkd(show_logs=False)
2568
2569 def tearDown(self):
2570 stop_dnsmasq(dnsmasq_pid_file)
2571 remove_lease_file()
2572 remove_log_file()
2573 remove_links(self.links)
2574 remove_unit_from_networkd_path(self.units)
2575 stop_networkd(show_logs=True)
2576
2577 def test_dhcp_client_ipv6_only(self):
2578 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2579
2580 start_networkd()
2581 self.wait_online(['veth-peer:carrier'])
2582 start_dnsmasq()
2583 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2584
2585 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2586 print(output)
2587 self.assertRegex(output, '2600::')
2588 self.assertNotRegex(output, '192.168.5')
2589
2590 # Confirm that ipv6 token is not set in the kernel
2591 output = check_output('ip token show dev veth99')
2592 print(output)
2593 self.assertRegex(output, 'token :: dev veth99')
2594
2595 def test_dhcp_client_ipv4_only(self):
2596 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
2597
2598 start_networkd()
2599 self.wait_online(['veth-peer:carrier'])
2600 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
2601 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2602
2603 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2604 print(output)
2605 self.assertNotRegex(output, '2600::')
2606 self.assertRegex(output, '192.168.5')
2607 self.assertRegex(output, '192.168.5.6')
2608 self.assertRegex(output, '192.168.5.7')
2609
2610 # checking routes to DNS servers
2611 output = check_output('ip route show dev veth99')
2612 print(output)
2613 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2614 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
2615 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2616
2617 stop_dnsmasq(dnsmasq_pid_file)
2618 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
2619
2620 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2621 print('Wait for the dynamic address to be renewed')
2622 time.sleep(125)
2623
2624 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2625
2626 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2627 print(output)
2628 self.assertNotRegex(output, '2600::')
2629 self.assertRegex(output, '192.168.5')
2630 self.assertNotRegex(output, '192.168.5.6')
2631 self.assertRegex(output, '192.168.5.7')
2632 self.assertRegex(output, '192.168.5.8')
2633
2634 # checking routes to DNS servers
2635 output = check_output('ip route show dev veth99')
2636 print(output)
2637 self.assertNotRegex(output, r'192.168.5.6')
2638 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
2639 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
2640 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
2641
2642 def test_dhcp_client_ipv4_ipv6(self):
2643 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2644 'dhcp-client-ipv4-only.network')
2645 start_networkd()
2646 self.wait_online(['veth-peer:carrier'])
2647 start_dnsmasq()
2648 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2649
2650 # link become 'routable' when at least one protocol provide an valid address.
2651 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2652 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2653
2654 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2655 print(output)
2656 self.assertRegex(output, '2600::')
2657 self.assertRegex(output, '192.168.5')
2658
2659 def test_dhcp_client_settings(self):
2660 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
2661
2662 start_networkd()
2663 self.wait_online(['veth-peer:carrier'])
2664 start_dnsmasq()
2665 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2666
2667 print('## ip address show dev veth99')
2668 output = check_output('ip address show dev veth99')
2669 print(output)
2670 self.assertRegex(output, '12:34:56:78:9a:bc')
2671 self.assertRegex(output, '192.168.5')
2672 self.assertRegex(output, '1492')
2673
2674 print('## ip route show table main dev veth99')
2675 output = check_output('ip route show table main dev veth99')
2676 print(output)
2677 # See issue #8726
2678 main_table_is_empty = output == ''
2679 if not main_table_is_empty:
2680 self.assertNotRegex(output, 'proto dhcp')
2681
2682 print('## ip route show table 211 dev veth99')
2683 output = check_output('ip route show table 211 dev veth99')
2684 print(output)
2685 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
2686 if main_table_is_empty:
2687 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
2688 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2689 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
2690
2691 print('## dnsmasq log')
2692 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2693 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2694 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
2695 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
2696
2697 def test_dhcp6_client_settings_rapidcommit_true(self):
2698 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2699 start_networkd()
2700 self.wait_online(['veth-peer:carrier'])
2701 start_dnsmasq()
2702 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2703
2704 output = check_output('ip address show dev veth99')
2705 print(output)
2706 self.assertRegex(output, '12:34:56:78:9a:bc')
2707 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
2708
2709 def test_dhcp6_client_settings_rapidcommit_false(self):
2710 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2711 start_networkd()
2712 self.wait_online(['veth-peer:carrier'])
2713 start_dnsmasq()
2714 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2715
2716 output = check_output('ip address show dev veth99')
2717 print(output)
2718 self.assertRegex(output, '12:34:56:78:9a:bc')
2719 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
2720
2721 def test_dhcp_client_settings_anonymize(self):
2722 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2723 start_networkd()
2724 self.wait_online(['veth-peer:carrier'])
2725 start_dnsmasq()
2726 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2727
2728 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2729 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
2730 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
2731
2732 def test_dhcp_client_listen_port(self):
2733 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2734 start_networkd()
2735 self.wait_online(['veth-peer:carrier'])
2736 start_dnsmasq('--dhcp-alternate-port=67,5555')
2737 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2738
2739 output = check_output('ip -4 address show dev veth99')
2740 print(output)
2741 self.assertRegex(output, '192.168.5.* dynamic')
2742
2743 def test_dhcp_client_with_static_address(self):
2744 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
2745 'dhcp-client-with-static-address.network')
2746 start_networkd()
2747 self.wait_online(['veth-peer:carrier'])
2748 start_dnsmasq()
2749 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2750
2751 output = check_output('ip address show dev veth99 scope global')
2752 print(output)
2753 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
2754 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
2755
2756 output = check_output('ip route show dev veth99')
2757 print(output)
2758 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
2759 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
2760 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
2761 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
2762
2763 def test_dhcp_route_table_id(self):
2764 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2765 start_networkd()
2766 self.wait_online(['veth-peer:carrier'])
2767 start_dnsmasq()
2768 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2769
2770 output = check_output('ip route show table 12')
2771 print(output)
2772 self.assertRegex(output, 'veth99 proto dhcp')
2773 self.assertRegex(output, '192.168.5.1')
2774
2775 def test_dhcp_route_metric(self):
2776 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2777 start_networkd()
2778 self.wait_online(['veth-peer:carrier'])
2779 start_dnsmasq()
2780 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2781
2782 output = check_output('ip route show dev veth99')
2783 print(output)
2784 self.assertRegex(output, 'metric 24')
2785
2786 def test_dhcp_client_reassign_static_routes_ipv4(self):
2787 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2788 'dhcp-client-reassign-static-routes-ipv4.network')
2789 start_networkd()
2790 self.wait_online(['veth-peer:carrier'])
2791 start_dnsmasq(lease_time='2m')
2792 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2793
2794 output = check_output('ip address show dev veth99 scope global')
2795 print(output)
2796 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2797
2798 output = check_output('ip route show dev veth99')
2799 print(output)
2800 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2801 self.assertRegex(output, r'192.168.5.0/24 proto static')
2802 self.assertRegex(output, r'192.168.6.0/24 proto static')
2803 self.assertRegex(output, r'192.168.7.0/24 proto static')
2804
2805 stop_dnsmasq(dnsmasq_pid_file)
2806 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
2807
2808 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2809 print('Wait for the dynamic address to be renewed')
2810 time.sleep(125)
2811
2812 self.wait_online(['veth99:routable'])
2813
2814 output = check_output('ip route show dev veth99')
2815 print(output)
2816 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
2817 self.assertRegex(output, r'192.168.5.0/24 proto static')
2818 self.assertRegex(output, r'192.168.6.0/24 proto static')
2819 self.assertRegex(output, r'192.168.7.0/24 proto static')
2820
2821 def test_dhcp_client_reassign_static_routes_ipv6(self):
2822 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2823 'dhcp-client-reassign-static-routes-ipv6.network')
2824 start_networkd()
2825 self.wait_online(['veth-peer:carrier'])
2826 start_dnsmasq(lease_time='2m')
2827 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2828
2829 output = check_output('ip address show dev veth99 scope global')
2830 print(output)
2831 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
2832
2833 output = check_output('ip -6 route show dev veth99')
2834 print(output)
2835 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
2836 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
2837
2838 stop_dnsmasq(dnsmasq_pid_file)
2839 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
2840
2841 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2842 print('Wait for the dynamic address to be renewed')
2843 time.sleep(125)
2844
2845 self.wait_online(['veth99:routable'])
2846
2847 output = check_output('ip -6 route show dev veth99')
2848 print(output)
2849 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
2850 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
2851
2852 def test_dhcp_keep_configuration_dhcp(self):
2853 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
2854 start_networkd()
2855 self.wait_online(['veth-peer:carrier'])
2856 start_dnsmasq(lease_time='2m')
2857 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2858
2859 output = check_output('ip address show dev veth99 scope global')
2860 print(output)
2861 self.assertRegex(output, r'192.168.5.*')
2862
2863 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2864 print(output)
2865 self.assertRegex(output, r'192.168.5.*')
2866
2867 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
2868 stop_dnsmasq(dnsmasq_pid_file)
2869
2870 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2871 print('Wait for the dynamic address to be expired')
2872 time.sleep(125)
2873
2874 print('The lease address should be kept after lease expired')
2875 output = check_output('ip address show dev veth99 scope global')
2876 print(output)
2877 self.assertRegex(output, r'192.168.5.*')
2878
2879 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2880 print(output)
2881 self.assertRegex(output, r'192.168.5.*')
2882
2883 check_output('systemctl stop systemd-networkd')
2884
2885 print('The lease address should be kept after networkd stopped')
2886 output = check_output('ip address show dev veth99 scope global')
2887 print(output)
2888 self.assertRegex(output, r'192.168.5.*')
2889
2890 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2891 print(output)
2892 self.assertRegex(output, r'192.168.5.*')
2893
2894 start_networkd(3)
2895 self.wait_online(['veth-peer:routable'])
2896
2897 print('Still the lease address should be kept after networkd restarted')
2898 output = check_output('ip address show dev veth99 scope global')
2899 print(output)
2900 self.assertRegex(output, r'192.168.5.*')
2901
2902 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
2903 print(output)
2904 self.assertRegex(output, r'192.168.5.*')
2905
2906 def test_dhcp_keep_configuration_dhcp_on_stop(self):
2907 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
2908 start_networkd()
2909 self.wait_online(['veth-peer:carrier'])
2910 start_dnsmasq(lease_time='2m')
2911 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2912
2913 output = check_output('ip address show dev veth99 scope global')
2914 print(output)
2915 self.assertRegex(output, r'192.168.5.*')
2916
2917 stop_dnsmasq(dnsmasq_pid_file)
2918 check_output('systemctl stop systemd-networkd')
2919
2920 output = check_output('ip address show dev veth99 scope global')
2921 print(output)
2922 self.assertRegex(output, r'192.168.5.*')
2923
2924 restart_networkd(3)
2925 self.wait_online(['veth-peer:routable'])
2926
2927 output = check_output('ip address show dev veth99 scope global')
2928 print(output)
2929 self.assertNotRegex(output, r'192.168.5.*')
2930
2931 def test_dhcp_client_reuse_address_as_static(self):
2932 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2933 start_networkd()
2934 self.wait_online(['veth-peer:carrier'])
2935 start_dnsmasq()
2936 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2937
2938 # link become 'routable' when at least one protocol provide an valid address.
2939 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2940 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2941
2942 output = check_output('ip address show dev veth99 scope global')
2943 print(output)
2944 self.assertRegex(output, '192.168.5')
2945 self.assertRegex(output, '2600::')
2946
2947 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
2948 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
2949 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
2950 print(static_network)
2951
2952 remove_unit_from_networkd_path(['dhcp-client.network'])
2953
2954 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
2955 f.write(static_network)
2956
2957 # When networkd started, the links are already configured, so let's wait for 5 seconds
2958 # the links to be re-configured.
2959 restart_networkd(5)
2960 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2961
2962 output = check_output('ip -4 address show dev veth99 scope global')
2963 print(output)
2964 self.assertRegex(output, '192.168.5')
2965 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2966
2967 output = check_output('ip -6 address show dev veth99 scope global')
2968 print(output)
2969 self.assertRegex(output, '2600::')
2970 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2971
2972 @expectedFailureIfModuleIsNotAvailable('vrf')
2973 def test_dhcp_client_vrf(self):
2974 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2975 '25-vrf.netdev', '25-vrf.network')
2976 start_networkd()
2977 self.wait_online(['veth-peer:carrier'])
2978 start_dnsmasq()
2979 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2980
2981 # link become 'routable' when at least one protocol provide an valid address.
2982 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
2983 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
2984
2985 print('## ip -d link show dev vrf99')
2986 output = check_output('ip -d link show dev vrf99')
2987 print(output)
2988 self.assertRegex(output, 'vrf table 42')
2989
2990 print('## ip address show vrf vrf99')
2991 output = check_output('ip address show vrf vrf99')
2992 print(output)
2993 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2994 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2995 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
2996 self.assertRegex(output, 'inet6 .* scope link')
2997
2998 print('## ip address show dev veth99')
2999 output = check_output('ip address show dev veth99')
3000 print(output)
3001 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3002 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3003 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3004 self.assertRegex(output, 'inet6 .* scope link')
3005
3006 print('## ip route show vrf vrf99')
3007 output = check_output('ip route show vrf vrf99')
3008 print(output)
3009 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
3010 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3011 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3012 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3013 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3014
3015 print('## ip route show table main dev veth99')
3016 output = check_output('ip route show table main dev veth99')
3017 print(output)
3018 self.assertEqual(output, '')
3019
3020 def test_dhcp_client_gateway_onlink_implicit(self):
3021 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3022 'dhcp-client-gateway-onlink-implicit.network')
3023 start_networkd()
3024 self.wait_online(['veth-peer:carrier'])
3025 start_dnsmasq()
3026 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3027
3028 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
3029 print(output)
3030 self.assertRegex(output, '192.168.5')
3031
3032 output = check_output('ip route list dev veth99 10.0.0.0/8')
3033 print(output)
3034 self.assertRegex(output, 'onlink')
3035 output = check_output('ip route list dev veth99 192.168.100.0/24')
3036 print(output)
3037 self.assertRegex(output, 'onlink')
3038
3039 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
3040 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3041 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
3042 start_networkd()
3043 self.wait_online(['veth-peer:carrier'])
3044 start_dnsmasq(lease_time='2m')
3045 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3046
3047 output = check_output('ip address show dev veth99')
3048 print(output)
3049
3050 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3051 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3052 output = check_output('ip -6 address show dev veth99 scope link')
3053 self.assertRegex(output, 'inet6 .* scope link')
3054 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3055 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3056 output = check_output('ip -4 address show dev veth99 scope link')
3057 self.assertNotRegex(output, 'inet .* scope link')
3058
3059 print('Wait for the dynamic address to be expired')
3060 time.sleep(130)
3061
3062 output = check_output('ip address show dev veth99')
3063 print(output)
3064
3065 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3066 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3067 output = check_output('ip -6 address show dev veth99 scope link')
3068 self.assertRegex(output, 'inet6 .* scope link')
3069 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3070 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3071 output = check_output('ip -4 address show dev veth99 scope link')
3072 self.assertNotRegex(output, 'inet .* scope link')
3073
3074 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
3075
3076 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
3077 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3078 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
3079 start_networkd()
3080 self.wait_online(['veth99:degraded', 'veth-peer:routable'])
3081
3082 output = check_output('ip address show dev veth99')
3083 print(output)
3084
3085 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3086 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3087 output = check_output('ip -6 address show dev veth99 scope link')
3088 self.assertRegex(output, 'inet6 .* scope link')
3089 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3090 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3091 output = check_output('ip -4 address show dev veth99 scope link')
3092 self.assertRegex(output, 'inet .* scope link')
3093
3094 def test_dhcp_client_route_remove_on_renew(self):
3095 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3096 'dhcp-client-ipv4-only-ipv6-disabled.network')
3097 start_networkd()
3098 self.wait_online(['veth-peer:carrier'])
3099 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
3100 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3101
3102 # test for issue #12490
3103
3104 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3105 print(output)
3106 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3107 address1=None
3108 for line in output.splitlines():
3109 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3110 address1 = line.split()[1].split('/')[0]
3111 break
3112
3113 output = check_output('ip -4 route show dev veth99')
3114 print(output)
3115 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3116 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3117
3118 stop_dnsmasq(dnsmasq_pid_file)
3119 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
3120
3121 print('Wait for the dynamic address to be expired')
3122 time.sleep(130)
3123
3124 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3125 print(output)
3126 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3127 address2=None
3128 for line in output.splitlines():
3129 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3130 address2 = line.split()[1].split('/')[0]
3131 break
3132
3133 self.assertNotEqual(address1, address2)
3134
3135 output = check_output('ip -4 route show dev veth99')
3136 print(output)
3137 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3138 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3139 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3140 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3141
3142 def test_dhcp_client_use_dns_yes(self):
3143 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3144
3145 start_networkd()
3146 self.wait_online(['veth-peer:carrier'])
3147 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3148 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3149
3150 # link become 'routable' when at least one protocol provide an valid address.
3151 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3152 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3153
3154 time.sleep(3)
3155 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3156 print(output)
3157 self.assertRegex(output, '192.168.5.1')
3158 self.assertRegex(output, '2600::1')
3159
3160 def test_dhcp_client_use_dns_no(self):
3161 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3162
3163 start_networkd()
3164 self.wait_online(['veth-peer:carrier'])
3165 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3166 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3167
3168 # link become 'routable' when at least one protocol provide an valid address.
3169 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3170 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3171
3172 time.sleep(3)
3173 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3174 print(output)
3175 self.assertNotRegex(output, '192.168.5.1')
3176 self.assertNotRegex(output, '2600::1')
3177
3178 def test_dhcp_client_use_dns_ipv4(self):
3179 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3180
3181 start_networkd()
3182 self.wait_online(['veth-peer:carrier'])
3183 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3184 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3185
3186 # link become 'routable' when at least one protocol provide an valid address.
3187 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3188 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3189
3190 time.sleep(3)
3191 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3192 print(output)
3193 self.assertRegex(output, '192.168.5.1')
3194 self.assertNotRegex(output, '2600::1')
3195
3196 def test_dhcp_client_use_dns_ipv4_and_ra(self):
3197 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3198
3199 start_networkd()
3200 self.wait_online(['veth-peer:carrier'])
3201 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3202 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3203
3204 # link become 'routable' when at least one protocol provide an valid address.
3205 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3206 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3207
3208 time.sleep(3)
3209 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3210 print(output)
3211 self.assertRegex(output, '192.168.5.1')
3212 self.assertRegex(output, '2600::1')
3213
3214 def test_dhcp_client_use_domains(self):
3215 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3216
3217 start_networkd()
3218 self.wait_online(['veth-peer:carrier'])
3219 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
3220 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3221
3222 output = check_output(*networkctl_cmd, 'status', 'veth99', env=env)
3223 print(output)
3224 self.assertRegex(output, 'Search Domains: example.com')
3225
3226 time.sleep(3)
3227 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3228 print(output)
3229 self.assertRegex(output, 'example.com')
3230
3231 class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
3232 links = ['veth99']
3233
3234 units = [
3235 '25-veth.netdev',
3236 'ipv6ra-prefix-client.network',
3237 'ipv6ra-prefix.network'
3238 ]
3239
3240 def setUp(self):
3241 remove_links(self.links)
3242 stop_networkd(show_logs=False)
3243
3244 def tearDown(self):
3245 remove_log_file()
3246 remove_links(self.links)
3247 remove_unit_from_networkd_path(self.units)
3248 stop_networkd(show_logs=True)
3249
3250 def test_ipv6_route_prefix(self):
3251 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3252
3253 start_networkd()
3254 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3255
3256 output = check_output('ip', '-6', 'route', 'show', 'dev', 'veth-peer')
3257 print(output)
3258 self.assertRegex(output, '2001:db8:0:1::/64 proto ra')
3259
3260 if __name__ == '__main__':
3261 parser = argparse.ArgumentParser()
3262 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
3263 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
3264 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
3265 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
3266 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
3267 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
3268 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
3269 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
3270 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
3271 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
3272 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
3273 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
3274 ns, args = parser.parse_known_args(namespace=unittest)
3275
3276 if ns.build_dir:
3277 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:
3278 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
3279 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
3280 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
3281 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
3282 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
3283 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
3284 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
3285 else:
3286 if ns.networkd_bin:
3287 networkd_bin = ns.networkd_bin
3288 if ns.resolved_bin:
3289 resolved_bin = ns.resolved_bin
3290 if ns.wait_online_bin:
3291 wait_online_bin = ns.wait_online_bin
3292 if ns.networkctl_bin:
3293 networkctl_bin = ns.networkctl_bin
3294 if ns.resolvectl_bin:
3295 resolvectl_bin = ns.resolvectl_bin
3296 if ns.timedatectl_bin:
3297 timedatectl_bin = ns.timedatectl_bin
3298
3299 use_valgrind = ns.use_valgrind
3300 enable_debug = ns.enable_debug
3301 asan_options = ns.asan_options
3302 lsan_options = ns.lsan_options
3303 ubsan_options = ns.ubsan_options
3304
3305 if use_valgrind:
3306 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
3307 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
3308 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
3309 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
3310 else:
3311 networkctl_cmd = [networkctl_bin]
3312 resolvectl_cmd = [resolvectl_bin]
3313 timedatectl_cmd = [timedatectl_bin]
3314 wait_online_cmd = [wait_online_bin]
3315
3316 if enable_debug:
3317 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
3318 if asan_options:
3319 env.update({ 'ASAN_OPTIONS' : asan_options })
3320 if lsan_options:
3321 env.update({ 'LSAN_OPTIONS' : lsan_options })
3322 if ubsan_options:
3323 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
3324
3325 sys.argv[1:] = args
3326 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
3327 verbosity=3))