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