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