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