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