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