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