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