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