]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
Merge pull request #16143 from fbuihuu/fstab-generator-fix
[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):
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 10.10.10.11')
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', '10.10.10.13', 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 10.10.10.13')
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 10.10.10.13')
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 10.10.10.11')
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 # It may take very long time that the interface become configured state.
2883 self.wait_online(['bridge99:no-carrier'], timeout='2m', setup_state=None)
2884 # due to a bug in the kernel, newly-created bridges are brought up
2885 # *with* carrier, unless they have had any setting changed; e.g.
2886 # their mac set, priority set, etc. Then, they will lose carrier
2887 # as soon as a (down) slave interface is added, and regain carrier
2888 # again once the slave interface is brought up.
2889 #self.check_link_attr('bridge99', 'carrier', '0')
2890 elif test == 'add-slave':
2891 # add slave to bridge, but leave it down; bridge is definitely no-carrier
2892 self.check_link_attr('test1', 'operstate', 'down')
2893 check_output('ip link set dev test1 master bridge99')
2894 self.wait_online(['bridge99:no-carrier:no-carrier'], setup_state=None)
2895 self.check_link_attr('bridge99', 'carrier', '0')
2896 elif test == 'slave-up':
2897 # bring up slave, which will have carrier; bridge gains carrier
2898 check_output('ip link set dev test1 up')
2899 self.wait_online(['bridge99:routable'])
2900 self.check_link_attr('bridge99', 'carrier', '1')
2901 elif test == 'slave-no-carrier':
2902 # drop slave carrier; bridge loses carrier
2903 check_output('ip link set dev test1 carrier off')
2904 self.wait_online(['bridge99:no-carrier:no-carrier'])
2905 self.check_link_attr('bridge99', 'carrier', '0')
2906 elif test == 'slave-carrier':
2907 # restore slave carrier; bridge gains carrier
2908 check_output('ip link set dev test1 carrier on')
2909 self.wait_online(['bridge99:routable'])
2910 self.check_link_attr('bridge99', 'carrier', '1')
2911 elif test == 'slave-down':
2912 # bring down slave; bridge loses carrier
2913 check_output('ip link set dev test1 down')
2914 self.wait_online(['bridge99:no-carrier:no-carrier'])
2915 self.check_link_attr('bridge99', 'carrier', '0')
2916
2917 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'bridge99', env=env)
2918 print(output)
2919 self.assertRegex(output, '10.1.2.3')
2920 self.assertRegex(output, '10.1.2.1')
2921
2922 def test_bridge_ignore_carrier_loss(self):
2923 copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
2924 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
2925 'bridge99-ignore-carrier-loss.network')
2926 start_networkd()
2927 self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable'])
2928
2929 check_output('ip address add 192.168.0.16/24 dev bridge99')
2930 time.sleep(1)
2931
2932 check_output('ip link del test1')
2933 check_output('ip link del dummy98')
2934 time.sleep(3)
2935
2936 output = check_output('ip address show bridge99')
2937 print(output)
2938 self.assertRegex(output, 'NO-CARRIER')
2939 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2940 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
2941
2942 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
2943 copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
2944 'bridge99-ignore-carrier-loss.network')
2945 start_networkd()
2946 self.wait_online(['bridge99:no-carrier'])
2947
2948 for trial in range(4):
2949 check_output('ip link add dummy98 type dummy')
2950 check_output('ip link set dummy98 up')
2951 if trial < 3:
2952 check_output('ip link del dummy98')
2953
2954 self.wait_online(['bridge99:routable', 'dummy98:enslaved'])
2955
2956 output = check_output('ip address show bridge99')
2957 print(output)
2958 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
2959
2960 output = check_output('ip rule list table 100')
2961 print(output)
2962 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
2963
2964 class NetworkdLLDPTests(unittest.TestCase, Utilities):
2965 links = ['veth99']
2966
2967 units = [
2968 '23-emit-lldp.network',
2969 '24-lldp.network',
2970 '25-veth.netdev']
2971
2972 def setUp(self):
2973 remove_links(self.links)
2974 stop_networkd(show_logs=False)
2975
2976 def tearDown(self):
2977 remove_links(self.links)
2978 remove_unit_from_networkd_path(self.units)
2979 stop_networkd(show_logs=True)
2980
2981 def test_lldp(self):
2982 copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
2983 start_networkd()
2984 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
2985
2986 output = check_output(*networkctl_cmd, 'lldp', env=env)
2987 print(output)
2988 self.assertRegex(output, 'veth-peer')
2989 self.assertRegex(output, 'veth99')
2990
2991 class NetworkdRATests(unittest.TestCase, Utilities):
2992 links = ['veth99']
2993
2994 units = [
2995 '25-veth.netdev',
2996 'ipv6-prefix.network',
2997 'ipv6-prefix-veth.network',
2998 'ipv6-prefix-veth-token-static.network',
2999 'ipv6-prefix-veth-token-static-explicit.network',
3000 'ipv6-prefix-veth-token-static-multiple.network',
3001 'ipv6-prefix-veth-token-prefixstable.network']
3002
3003 def setUp(self):
3004 remove_links(self.links)
3005 stop_networkd(show_logs=False)
3006
3007 def tearDown(self):
3008 remove_links(self.links)
3009 remove_unit_from_networkd_path(self.units)
3010 stop_networkd(show_logs=True)
3011
3012 def test_ipv6_prefix_delegation(self):
3013 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
3014 start_networkd()
3015 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3016
3017 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3018 print(output)
3019 self.assertRegex(output, 'fe80::')
3020 self.assertRegex(output, '2002:da8:1::1')
3021
3022 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3023 print(output)
3024 self.assertRegex(output, '2002:da8:1:0')
3025
3026 def test_ipv6_token_static(self):
3027 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static.network')
3028 start_networkd()
3029 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3030
3031 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3032 print(output)
3033 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
3034
3035 def test_ipv6_token_static_explicit(self):
3036 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-explicit.network')
3037 start_networkd()
3038 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3039
3040 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3041 print(output)
3042 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
3043
3044 def test_ipv6_token_static_multiple(self):
3045 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-static-multiple.network')
3046 start_networkd()
3047 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3048
3049 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3050 print(output)
3051 self.assertRegex(output, '2002:da8:1:0:1a:2b:3c:4d')
3052 self.assertRegex(output, '2002:da8:1:0:fa:de:ca:fe')
3053
3054 def test_ipv6_token_prefixstable(self):
3055 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth-token-prefixstable.network')
3056 start_networkd()
3057 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
3058
3059 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3060 print(output)
3061 self.assertRegex(output, '2002:da8:1:0')
3062
3063 class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
3064 links = ['veth99']
3065
3066 units = [
3067 '25-veth.netdev',
3068 'dhcp-client.network',
3069 'dhcp-client-timezone-router.network',
3070 'dhcp-server.network',
3071 'dhcp-server-timezone-router.network']
3072
3073 def setUp(self):
3074 remove_links(self.links)
3075 stop_networkd(show_logs=False)
3076
3077 def tearDown(self):
3078 remove_links(self.links)
3079 remove_unit_from_networkd_path(self.units)
3080 stop_networkd(show_logs=True)
3081
3082 def test_dhcp_server(self):
3083 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
3084 start_networkd()
3085 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3086
3087 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3088 print(output)
3089 self.assertRegex(output, '192.168.5.*')
3090 self.assertRegex(output, 'Gateway: 192.168.5.1')
3091 self.assertRegex(output, 'DNS: 192.168.5.1')
3092 self.assertRegex(output, 'NTP: 192.168.5.1')
3093
3094 def test_emit_router_timezone(self):
3095 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
3096 start_networkd()
3097 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3098
3099 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3100 print(output)
3101 self.assertRegex(output, 'Gateway: 192.168.5.*')
3102 self.assertRegex(output, '192.168.5.*')
3103 self.assertRegex(output, 'Europe/Berlin')
3104
3105 class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
3106 links = [
3107 'veth99',
3108 'vrf99']
3109
3110 units = [
3111 '25-veth.netdev',
3112 '25-vrf.netdev',
3113 '25-vrf.network',
3114 'dhcp-client-anonymize.network',
3115 'dhcp-client-decline.network',
3116 'dhcp-client-gateway-ipv4.network',
3117 'dhcp-client-gateway-ipv6.network',
3118 'dhcp-client-gateway-onlink-implicit.network',
3119 'dhcp-client-ipv4-dhcp-settings.network',
3120 'dhcp-client-ipv4-only-ipv6-disabled.network',
3121 'dhcp-client-ipv4-only.network',
3122 'dhcp-client-ipv4-use-routes-use-gateway.network',
3123 'dhcp-client-ipv6-only.network',
3124 'dhcp-client-ipv6-rapid-commit.network',
3125 'dhcp-client-keep-configuration-dhcp-on-stop.network',
3126 'dhcp-client-keep-configuration-dhcp.network',
3127 'dhcp-client-listen-port.network',
3128 'dhcp-client-reassign-static-routes-ipv4.network',
3129 'dhcp-client-reassign-static-routes-ipv6.network',
3130 'dhcp-client-route-metric.network',
3131 'dhcp-client-route-table.network',
3132 'dhcp-client-use-dns-ipv4-and-ra.network',
3133 'dhcp-client-use-dns-ipv4.network',
3134 'dhcp-client-use-dns-no.network',
3135 'dhcp-client-use-dns-yes.network',
3136 'dhcp-client-use-domains.network',
3137 'dhcp-client-vrf.network',
3138 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
3139 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
3140 'dhcp-client-with-static-address.network',
3141 'dhcp-client.network',
3142 'dhcp-server-decline.network',
3143 'dhcp-server-veth-peer.network',
3144 'dhcp-v4-server-veth-peer.network',
3145 'static.network']
3146
3147 def setUp(self):
3148 stop_dnsmasq(dnsmasq_pid_file)
3149 remove_links(self.links)
3150 stop_networkd(show_logs=False)
3151
3152 def tearDown(self):
3153 stop_dnsmasq(dnsmasq_pid_file)
3154 remove_lease_file()
3155 remove_log_file()
3156 remove_links(self.links)
3157 remove_unit_from_networkd_path(self.units)
3158 stop_networkd(show_logs=True)
3159
3160 def test_dhcp_client_ipv6_only(self):
3161 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
3162
3163 start_networkd()
3164 self.wait_online(['veth-peer:carrier'])
3165 start_dnsmasq()
3166 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3167
3168 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3169 print(output)
3170 self.assertRegex(output, '2600::')
3171 self.assertNotRegex(output, '192.168.5')
3172
3173 # Confirm that ipv6 token is not set in the kernel
3174 output = check_output('ip token show dev veth99')
3175 print(output)
3176 self.assertRegex(output, 'token :: dev veth99')
3177
3178 def test_dhcp_client_ipv4_only(self):
3179 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
3180
3181 start_networkd()
3182 self.wait_online(['veth-peer:carrier'])
3183 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
3184 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3185
3186 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3187 print(output)
3188 self.assertNotRegex(output, '2600::')
3189 self.assertRegex(output, '192.168.5')
3190 self.assertRegex(output, '192.168.5.6')
3191 self.assertRegex(output, '192.168.5.7')
3192
3193 # checking routes to DNS servers
3194 output = check_output('ip route show dev veth99')
3195 print(output)
3196 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
3197 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
3198 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
3199
3200 stop_dnsmasq(dnsmasq_pid_file)
3201 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m')
3202
3203 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3204 print('Wait for the dynamic address to be renewed')
3205 time.sleep(125)
3206
3207 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3208
3209 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3210 print(output)
3211 self.assertNotRegex(output, '2600::')
3212 self.assertRegex(output, '192.168.5')
3213 self.assertNotRegex(output, '192.168.5.6')
3214 self.assertRegex(output, '192.168.5.7')
3215 self.assertRegex(output, '192.168.5.8')
3216
3217 # checking routes to DNS servers
3218 output = check_output('ip route show dev veth99')
3219 print(output)
3220 self.assertNotRegex(output, r'192.168.5.6')
3221 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024')
3222 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
3223 self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024')
3224
3225 def test_dhcp_client_ipv4_use_routes_gateway(self):
3226 for (routes, gateway, dnsroutes) in itertools.product([True, False, None], repeat=3):
3227 self.setUp()
3228 with self.subTest(routes=routes, gateway=gateway, dnsroutes=dnsroutes):
3229 self._test_dhcp_client_ipv4_use_routes_gateway(routes, gateway, dnsroutes)
3230 self.tearDown()
3231
3232 def _test_dhcp_client_ipv4_use_routes_gateway(self, routes, gateway, dnsroutes):
3233 testunit = 'dhcp-client-ipv4-use-routes-use-gateway.network'
3234 testunits = ['25-veth.netdev', 'dhcp-server-veth-peer.network', testunit]
3235 if routes != None:
3236 testunits.append(f'{testunit}.d/use-routes-{routes}.conf');
3237 if gateway != None:
3238 testunits.append(f'{testunit}.d/use-gateway-{gateway}.conf');
3239 if dnsroutes != None:
3240 testunits.append(f'{testunit}.d/use-dns-routes-{dnsroutes}.conf');
3241 copy_unit_to_networkd_unit_path(*testunits, dropins=False)
3242
3243 start_networkd()
3244 self.wait_online(['veth-peer:carrier'])
3245 start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m')
3246 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3247
3248 output = check_output('ip route show dev veth99')
3249 print(output)
3250
3251 # UseRoutes= defaults to true
3252 useroutes = routes in [True, None]
3253 # UseGateway= defaults to useroutes
3254 usegateway = useroutes if gateway == None else gateway
3255
3256 # Check UseRoutes=
3257 if useroutes:
3258 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.181 metric 1024')
3259 else:
3260 self.assertNotRegex(output, r'192.168.5.5')
3261
3262 # Check UseGateway=
3263 if usegateway:
3264 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.181 metric 1024')
3265 else:
3266 self.assertNotRegex(output, r'default via 192.168.5.1')
3267
3268 # Check RoutesToDNS=, which defaults to false
3269 if dnsroutes:
3270 self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024')
3271 self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024')
3272 else:
3273 self.assertNotRegex(output, r'192.168.5.6')
3274 self.assertNotRegex(output, r'192.168.5.7')
3275
3276 def test_dhcp_client_ipv4_ipv6(self):
3277 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
3278 'dhcp-client-ipv4-only.network')
3279 start_networkd()
3280 self.wait_online(['veth-peer:carrier'])
3281 start_dnsmasq()
3282 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3283
3284 # link become 'routable' when at least one protocol provide an valid address.
3285 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3286 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3287
3288 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3289 print(output)
3290 self.assertRegex(output, '2600::')
3291 self.assertRegex(output, '192.168.5')
3292
3293 def test_dhcp_client_settings(self):
3294 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
3295
3296 start_networkd()
3297 self.wait_online(['veth-peer:carrier'])
3298 start_dnsmasq()
3299 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3300
3301 print('## ip address show dev veth99')
3302 output = check_output('ip address show dev veth99')
3303 print(output)
3304 self.assertRegex(output, '12:34:56:78:9a:bc')
3305 self.assertRegex(output, '192.168.5')
3306 self.assertRegex(output, '1492')
3307
3308 print('## ip route show table main dev veth99')
3309 output = check_output('ip route show table main dev veth99')
3310 print(output)
3311 # See issue #8726
3312 main_table_is_empty = output == ''
3313 if not main_table_is_empty:
3314 self.assertNotRegex(output, 'proto dhcp')
3315
3316 print('## ip route show table 211 dev veth99')
3317 output = check_output('ip route show table 211 dev veth99')
3318 print(output)
3319 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
3320 if main_table_is_empty:
3321 self.assertRegex(output, '192.168.5.0/24 proto dhcp')
3322 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
3323 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
3324
3325 print('## dnsmasq log')
3326 self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
3327 self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
3328 self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname'))
3329 self.assertTrue(search_words_in_dnsmasq_log('26:mtu'))
3330
3331 def test_dhcp6_client_settings_rapidcommit_true(self):
3332 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
3333 start_networkd()
3334 self.wait_online(['veth-peer:carrier'])
3335 start_dnsmasq()
3336 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3337
3338 output = check_output('ip address show dev veth99')
3339 print(output)
3340 self.assertRegex(output, '12:34:56:78:9a:bc')
3341 self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True))
3342
3343 def test_dhcp6_client_settings_rapidcommit_false(self):
3344 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
3345 start_networkd()
3346 self.wait_online(['veth-peer:carrier'])
3347 start_dnsmasq()
3348 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3349
3350 output = check_output('ip address show dev veth99')
3351 print(output)
3352 self.assertRegex(output, '12:34:56:78:9a:bc')
3353 self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True))
3354
3355 def test_dhcp_client_settings_anonymize(self):
3356 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
3357 start_networkd()
3358 self.wait_online(['veth-peer:carrier'])
3359 start_dnsmasq()
3360 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3361
3362 self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
3363 self.assertFalse(search_words_in_dnsmasq_log('test-hostname'))
3364 self.assertFalse(search_words_in_dnsmasq_log('26:mtu'))
3365
3366 def test_dhcp_client_listen_port(self):
3367 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
3368 start_networkd()
3369 self.wait_online(['veth-peer:carrier'])
3370 start_dnsmasq('--dhcp-alternate-port=67,5555')
3371 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3372
3373 output = check_output('ip -4 address show dev veth99')
3374 print(output)
3375 self.assertRegex(output, '192.168.5.* dynamic')
3376
3377 def test_dhcp_client_with_static_address(self):
3378 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network',
3379 'dhcp-client-with-static-address.network')
3380 start_networkd()
3381 self.wait_online(['veth-peer:carrier'])
3382 start_dnsmasq()
3383 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3384
3385 output = check_output('ip address show dev veth99 scope global')
3386 print(output)
3387 self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99')
3388 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99')
3389
3390 output = check_output('ip route show dev veth99')
3391 print(output)
3392 self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024')
3393 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250')
3394 self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024')
3395 self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024')
3396
3397 def test_dhcp_route_table_id(self):
3398 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
3399 start_networkd()
3400 self.wait_online(['veth-peer:carrier'])
3401 start_dnsmasq()
3402 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3403
3404 output = check_output('ip route show table 12')
3405 print(output)
3406 self.assertRegex(output, 'veth99 proto dhcp')
3407 self.assertRegex(output, '192.168.5.1')
3408
3409 def test_dhcp_route_metric(self):
3410 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
3411 start_networkd()
3412 self.wait_online(['veth-peer:carrier'])
3413 start_dnsmasq()
3414 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3415
3416 output = check_output('ip route show dev veth99')
3417 print(output)
3418 self.assertRegex(output, 'metric 24')
3419
3420 def test_dhcp_client_reassign_static_routes_ipv4(self):
3421 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3422 'dhcp-client-reassign-static-routes-ipv4.network')
3423 start_networkd()
3424 self.wait_online(['veth-peer:carrier'])
3425 start_dnsmasq(lease_time='2m')
3426 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3427
3428 output = check_output('ip address show dev veth99 scope global')
3429 print(output)
3430 self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3431
3432 output = check_output('ip route show dev veth99')
3433 print(output)
3434 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3435 self.assertRegex(output, r'192.168.5.0/24 proto static')
3436 self.assertRegex(output, r'192.168.6.0/24 proto static')
3437 self.assertRegex(output, r'192.168.7.0/24 proto static')
3438
3439 stop_dnsmasq(dnsmasq_pid_file)
3440 start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m')
3441
3442 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3443 print('Wait for the dynamic address to be renewed')
3444 time.sleep(125)
3445
3446 self.wait_online(['veth99:routable'])
3447
3448 output = check_output('ip route show dev veth99')
3449 print(output)
3450 self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*')
3451 self.assertRegex(output, r'192.168.5.0/24 proto static')
3452 self.assertRegex(output, r'192.168.6.0/24 proto static')
3453 self.assertRegex(output, r'192.168.7.0/24 proto static')
3454
3455 def test_dhcp_client_reassign_static_routes_ipv6(self):
3456 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3457 'dhcp-client-reassign-static-routes-ipv6.network')
3458 start_networkd()
3459 self.wait_online(['veth-peer:carrier'])
3460 start_dnsmasq(lease_time='2m')
3461 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3462
3463 output = check_output('ip address show dev veth99 scope global')
3464 print(output)
3465 self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)')
3466
3467 output = check_output('ip -6 route show dev veth99')
3468 print(output)
3469 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3470 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3471
3472 stop_dnsmasq(dnsmasq_pid_file)
3473 start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m')
3474
3475 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3476 print('Wait for the dynamic address to be renewed')
3477 time.sleep(125)
3478
3479 self.wait_online(['veth99:routable'])
3480
3481 output = check_output('ip -6 route show dev veth99')
3482 print(output)
3483 self.assertRegex(output, r'2600::/64 proto ra metric 1024')
3484 self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium')
3485
3486 def test_dhcp_keep_configuration_dhcp(self):
3487 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network')
3488 start_networkd()
3489 self.wait_online(['veth-peer:carrier'])
3490 start_dnsmasq(lease_time='2m')
3491 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3492
3493 output = check_output('ip address show dev veth99 scope global')
3494 print(output)
3495 self.assertRegex(output, r'192.168.5.*')
3496
3497 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3498 print(output)
3499 self.assertRegex(output, r'192.168.5.*')
3500
3501 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
3502 stop_dnsmasq(dnsmasq_pid_file)
3503
3504 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
3505 print('Wait for the dynamic address to be expired')
3506 time.sleep(125)
3507
3508 print('The lease address should be kept after lease expired')
3509 output = check_output('ip address show dev veth99 scope global')
3510 print(output)
3511 self.assertRegex(output, r'192.168.5.*')
3512
3513 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3514 print(output)
3515 self.assertRegex(output, r'192.168.5.*')
3516
3517 check_output('systemctl stop systemd-networkd')
3518
3519 print('The lease address should be kept after networkd stopped')
3520 output = check_output('ip address show dev veth99 scope global')
3521 print(output)
3522 self.assertRegex(output, r'192.168.5.*')
3523
3524 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3525 print(output)
3526 self.assertRegex(output, r'192.168.5.*')
3527
3528 start_networkd(3)
3529 self.wait_online(['veth-peer:routable'])
3530
3531 print('Still the lease address should be kept after networkd restarted')
3532 output = check_output('ip address show dev veth99 scope global')
3533 print(output)
3534 self.assertRegex(output, r'192.168.5.*')
3535
3536 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3537 print(output)
3538 self.assertRegex(output, r'192.168.5.*')
3539
3540 def test_dhcp_keep_configuration_dhcp_on_stop(self):
3541 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network')
3542 start_networkd()
3543 self.wait_online(['veth-peer:carrier'])
3544 start_dnsmasq(lease_time='2m')
3545 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3546
3547 output = check_output('ip address show dev veth99 scope global')
3548 print(output)
3549 self.assertRegex(output, r'192.168.5.*')
3550
3551 stop_dnsmasq(dnsmasq_pid_file)
3552 check_output('systemctl stop systemd-networkd')
3553
3554 output = check_output('ip address show dev veth99 scope global')
3555 print(output)
3556 self.assertRegex(output, r'192.168.5.*')
3557
3558 restart_networkd(3)
3559 self.wait_online(['veth-peer:routable'])
3560
3561 output = check_output('ip address show dev veth99 scope global')
3562 print(output)
3563 self.assertNotRegex(output, r'192.168.5.*')
3564
3565 def test_dhcp_client_reuse_address_as_static(self):
3566 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
3567 start_networkd()
3568 self.wait_online(['veth-peer:carrier'])
3569 start_dnsmasq()
3570 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3571
3572 # link become 'routable' when at least one protocol provide an valid address.
3573 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3574 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3575
3576 output = check_output('ip address show dev veth99 scope global')
3577 print(output)
3578 self.assertRegex(output, '192.168.5')
3579 self.assertRegex(output, '2600::')
3580
3581 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
3582 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
3583 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
3584 print(static_network)
3585
3586 remove_unit_from_networkd_path(['dhcp-client.network'])
3587
3588 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
3589 f.write(static_network)
3590
3591 # When networkd started, the links are already configured, so let's wait for 5 seconds
3592 # the links to be re-configured.
3593 restart_networkd(5)
3594 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3595
3596 output = check_output('ip -4 address show dev veth99 scope global')
3597 print(output)
3598 self.assertRegex(output, '192.168.5')
3599 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3600
3601 output = check_output('ip -6 address show dev veth99 scope global')
3602 print(output)
3603 self.assertRegex(output, '2600::')
3604 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
3605
3606 @expectedFailureIfModuleIsNotAvailable('vrf')
3607 def test_dhcp_client_vrf(self):
3608 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
3609 '25-vrf.netdev', '25-vrf.network')
3610 start_networkd()
3611 self.wait_online(['veth-peer:carrier'])
3612 start_dnsmasq()
3613 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
3614
3615 # link become 'routable' when at least one protocol provide an valid address.
3616 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3617 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3618
3619 print('## ip -d link show dev vrf99')
3620 output = check_output('ip -d link show dev vrf99')
3621 print(output)
3622 self.assertRegex(output, 'vrf table 42')
3623
3624 print('## ip address show vrf vrf99')
3625 output = check_output('ip address show vrf vrf99')
3626 print(output)
3627 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3628 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3629 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3630 self.assertRegex(output, 'inet6 .* scope link')
3631
3632 print('## ip address show dev veth99')
3633 output = check_output('ip address show dev veth99')
3634 print(output)
3635 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
3636 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3637 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)')
3638 self.assertRegex(output, 'inet6 .* scope link')
3639
3640 print('## ip route show vrf vrf99')
3641 output = check_output('ip route show vrf vrf99')
3642 print(output)
3643 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
3644 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
3645 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
3646 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
3647 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
3648
3649 print('## ip route show table main dev veth99')
3650 output = check_output('ip route show table main dev veth99')
3651 print(output)
3652 self.assertEqual(output, '')
3653
3654 def test_dhcp_client_gateway_ipv4(self):
3655 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3656 'dhcp-client-gateway-ipv4.network')
3657 start_networkd()
3658 self.wait_online(['veth-peer:carrier'])
3659 start_dnsmasq()
3660 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3661
3662 output = check_output('ip route list dev veth99 10.0.0.0/8')
3663 print(output)
3664 self.assertRegex(output, '10.0.0.0/8 via 192.168.5.1 proto static')
3665
3666 def test_dhcp_client_gateway_ipv6(self):
3667 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3668 'dhcp-client-gateway-ipv6.network')
3669 start_networkd()
3670 self.wait_online(['veth-peer:carrier'])
3671 start_dnsmasq()
3672 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3673
3674 output = check_output('ip -6 route list dev veth99 2001:1234:5:9fff:ff:ff:ff:ff')
3675 print(output)
3676 self.assertRegex(output, 'via fe80::1034:56ff:fe78:9abd')
3677
3678 def test_dhcp_client_gateway_onlink_implicit(self):
3679 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3680 'dhcp-client-gateway-onlink-implicit.network')
3681 start_networkd()
3682 self.wait_online(['veth-peer:carrier'])
3683 start_dnsmasq()
3684 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3685
3686 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3687 print(output)
3688 self.assertRegex(output, '192.168.5')
3689
3690 output = check_output('ip route list dev veth99 10.0.0.0/8')
3691 print(output)
3692 self.assertRegex(output, 'onlink')
3693 output = check_output('ip route list dev veth99 192.168.100.0/24')
3694 print(output)
3695 self.assertRegex(output, 'onlink')
3696
3697 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
3698 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3699 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
3700 start_networkd()
3701 self.wait_online(['veth-peer:carrier'])
3702 start_dnsmasq(lease_time='2m')
3703 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3704
3705 output = check_output('ip address show dev veth99')
3706 print(output)
3707
3708 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3709 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3710 output = check_output('ip -6 address show dev veth99 scope link')
3711 self.assertRegex(output, 'inet6 .* scope link')
3712 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3713 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3714 output = check_output('ip -4 address show dev veth99 scope link')
3715 self.assertNotRegex(output, 'inet .* scope link')
3716
3717 print('Wait for the dynamic address to be expired')
3718 time.sleep(130)
3719
3720 output = check_output('ip address show dev veth99')
3721 print(output)
3722
3723 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3724 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3725 output = check_output('ip -6 address show dev veth99 scope link')
3726 self.assertRegex(output, 'inet6 .* scope link')
3727 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3728 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3729 output = check_output('ip -4 address show dev veth99 scope link')
3730 self.assertNotRegex(output, 'inet .* scope link')
3731
3732 search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
3733
3734 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
3735 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3736 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
3737 start_networkd()
3738 self.wait_online(['veth99:degraded', 'veth-peer:routable'])
3739
3740 output = check_output('ip address show dev veth99')
3741 print(output)
3742
3743 output = check_output('ip -6 address show dev veth99 scope global dynamic')
3744 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
3745 output = check_output('ip -6 address show dev veth99 scope link')
3746 self.assertRegex(output, 'inet6 .* scope link')
3747 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3748 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3749 output = check_output('ip -4 address show dev veth99 scope link')
3750 self.assertRegex(output, 'inet .* scope link')
3751
3752 def test_dhcp_client_route_remove_on_renew(self):
3753 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
3754 'dhcp-client-ipv4-only-ipv6-disabled.network')
3755 start_networkd()
3756 self.wait_online(['veth-peer:carrier'])
3757 start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
3758 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3759
3760 # test for issue #12490
3761
3762 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3763 print(output)
3764 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3765 address1=None
3766 for line in output.splitlines():
3767 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3768 address1 = line.split()[1].split('/')[0]
3769 break
3770
3771 output = check_output('ip -4 route show dev veth99')
3772 print(output)
3773 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3774 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3775
3776 stop_dnsmasq(dnsmasq_pid_file)
3777 start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
3778
3779 print('Wait for the dynamic address to be expired')
3780 time.sleep(130)
3781
3782 output = check_output('ip -4 address show dev veth99 scope global dynamic')
3783 print(output)
3784 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
3785 address2=None
3786 for line in output.splitlines():
3787 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
3788 address2 = line.split()[1].split('/')[0]
3789 break
3790
3791 self.assertNotEqual(address1, address2)
3792
3793 output = check_output('ip -4 route show dev veth99')
3794 print(output)
3795 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
3796 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
3797 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
3798 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
3799
3800 def test_dhcp_client_use_dns_yes(self):
3801 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network')
3802
3803 start_networkd()
3804 self.wait_online(['veth-peer:carrier'])
3805 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3806 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3807
3808 # link become 'routable' when at least one protocol provide an valid address.
3809 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3810 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3811
3812 time.sleep(3)
3813 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3814 print(output)
3815 self.assertRegex(output, '192.168.5.1')
3816 self.assertRegex(output, '2600::1')
3817
3818 def test_dhcp_client_use_dns_no(self):
3819 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network')
3820
3821 start_networkd()
3822 self.wait_online(['veth-peer:carrier'])
3823 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3824 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3825
3826 # link become 'routable' when at least one protocol provide an valid address.
3827 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3828 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3829
3830 time.sleep(3)
3831 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3832 print(output)
3833 self.assertNotRegex(output, '192.168.5.1')
3834 self.assertNotRegex(output, '2600::1')
3835
3836 def test_dhcp_client_use_dns_ipv4(self):
3837 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network')
3838
3839 start_networkd()
3840 self.wait_online(['veth-peer:carrier'])
3841 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3842 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3843
3844 # link become 'routable' when at least one protocol provide an valid address.
3845 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3846 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3847
3848 time.sleep(3)
3849 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3850 print(output)
3851 self.assertRegex(output, '192.168.5.1')
3852 self.assertNotRegex(output, '2600::1')
3853
3854 def test_dhcp_client_use_dns_ipv4_and_ra(self):
3855 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network')
3856
3857 start_networkd()
3858 self.wait_online(['veth-peer:carrier'])
3859 start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]')
3860 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3861
3862 # link become 'routable' when at least one protocol provide an valid address.
3863 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4')
3864 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6')
3865
3866 time.sleep(3)
3867 output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env)
3868 print(output)
3869 self.assertRegex(output, '192.168.5.1')
3870 self.assertRegex(output, '2600::1')
3871
3872 def test_dhcp_client_use_domains(self):
3873 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network')
3874
3875 start_networkd()
3876 self.wait_online(['veth-peer:carrier'])
3877 start_dnsmasq('--dhcp-option=option:domain-search,example.com')
3878 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3879
3880 output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
3881 print(output)
3882 self.assertRegex(output, 'Search Domains: example.com')
3883
3884 time.sleep(3)
3885 output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env)
3886 print(output)
3887 self.assertRegex(output, 'example.com')
3888
3889 def test_dhcp_client_decline(self):
3890 copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-decline.network', 'dhcp-client-decline.network')
3891
3892 start_networkd()
3893 self.wait_online(['veth-peer:carrier'])
3894 rc = call(*wait_online_cmd, '--timeout=10s', '--interface=veth99:routable', env=env)
3895 self.assertTrue(rc == 1)
3896
3897 class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities):
3898 links = ['veth99']
3899
3900 units = [
3901 '25-veth.netdev',
3902 'ipv6ra-prefix-client.network',
3903 'ipv6ra-prefix.network'
3904 ]
3905
3906 def setUp(self):
3907 remove_links(self.links)
3908 stop_networkd(show_logs=False)
3909
3910 def tearDown(self):
3911 remove_log_file()
3912 remove_links(self.links)
3913 remove_unit_from_networkd_path(self.units)
3914 stop_networkd(show_logs=True)
3915
3916 def test_ipv6_route_prefix(self):
3917 copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network')
3918
3919 start_networkd()
3920 self.wait_online(['veth99:routable', 'veth-peer:routable'])
3921
3922 output = check_output('ip -6 route show dev veth-peer')
3923 print(output)
3924 self.assertRegex(output, '2001:db8:0:1::/64 proto ra')
3925
3926 output = check_output('ip addr show dev veth99')
3927 print(output)
3928 self.assertNotRegex(output, '2001:db8:0:1')
3929 self.assertRegex(output, '2001:db8:0:2')
3930
3931 class NetworkdMTUTests(unittest.TestCase, Utilities):
3932 links = ['dummy98']
3933
3934 units = [
3935 '12-dummy.netdev',
3936 '12-dummy-mtu.netdev',
3937 '12-dummy-mtu.link',
3938 '12-dummy.network',
3939 ]
3940
3941 def setUp(self):
3942 remove_links(self.links)
3943 stop_networkd(show_logs=False)
3944
3945 def tearDown(self):
3946 remove_log_file()
3947 remove_links(self.links)
3948 remove_unit_from_networkd_path(self.units)
3949 stop_networkd(show_logs=True)
3950
3951 def check_mtu(self, mtu, ipv6_mtu=None, reset=True):
3952 if not ipv6_mtu:
3953 ipv6_mtu = mtu
3954
3955 # test normal start
3956 start_networkd()
3957 self.wait_online(['dummy98:routable'])
3958 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3959 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3960
3961 # test normal restart
3962 restart_networkd()
3963 self.wait_online(['dummy98:routable'])
3964 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), ipv6_mtu)
3965 self.assertEqual(read_link_attr('dummy98', 'mtu'), mtu)
3966
3967 if reset:
3968 self.reset_check_mtu(mtu, ipv6_mtu)
3969
3970 def reset_check_mtu(self, mtu, ipv6_mtu=None):
3971 ''' test setting mtu/ipv6_mtu with interface already up '''
3972 stop_networkd()
3973
3974 # note - changing the device mtu resets the ipv6 mtu
3975 run('ip link set up mtu 1501 dev dummy98')
3976 run('ip link set up mtu 1500 dev dummy98')
3977 self.assertEqual(read_link_attr('dummy98', 'mtu'), '1500')
3978 self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'mtu'), '1500')
3979
3980 self.check_mtu(mtu, ipv6_mtu, reset=False)
3981
3982 def test_mtu_network(self):
3983 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf')
3984 self.check_mtu('1600')
3985
3986 def test_mtu_netdev(self):
3987 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network', dropins=False)
3988 # note - MTU set by .netdev happens ONLY at device creation!
3989 self.check_mtu('1600', reset=False)
3990
3991 def test_mtu_link(self):
3992 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network', dropins=False)
3993 # must reload udev because it only picks up new files after 3 second delay
3994 call('udevadm control --reload')
3995 # note - MTU set by .link happens ONLY at udev processing of device 'add' uevent!
3996 self.check_mtu('1600', reset=False)
3997
3998 def test_ipv6_mtu(self):
3999 ''' set ipv6 mtu without setting device mtu '''
4000 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1400.conf')
4001 self.check_mtu('1500', '1400')
4002
4003 def test_ipv6_mtu_toolarge(self):
4004 ''' try set ipv6 mtu over device mtu (it shouldn't work) '''
4005 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
4006 self.check_mtu('1500', '1500')
4007
4008 def test_mtu_network_ipv6_mtu(self):
4009 ''' set ipv6 mtu and set device mtu via network file '''
4010 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy.network.d/mtu.conf', '12-dummy.network.d/ipv6-mtu-1550.conf')
4011 self.check_mtu('1600', '1550')
4012
4013 def test_mtu_netdev_ipv6_mtu(self):
4014 ''' set ipv6 mtu and set device mtu via netdev file '''
4015 copy_unit_to_networkd_unit_path('12-dummy-mtu.netdev', '12-dummy.network.d/ipv6-mtu-1550.conf')
4016 self.check_mtu('1600', '1550', reset=False)
4017
4018 def test_mtu_link_ipv6_mtu(self):
4019 ''' set ipv6 mtu and set device mtu via link file '''
4020 copy_unit_to_networkd_unit_path('12-dummy.netdev', '12-dummy-mtu.link', '12-dummy.network.d/ipv6-mtu-1550.conf')
4021 # must reload udev because it only picks up new files after 3 second delay
4022 call('udevadm control --reload')
4023 self.check_mtu('1600', '1550', reset=False)
4024
4025
4026 if __name__ == '__main__':
4027 parser = argparse.ArgumentParser()
4028 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
4029 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
4030 parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin')
4031 parser.add_argument('--udevd', help='Path to systemd-udevd', dest='udevd_bin')
4032 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
4033 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
4034 parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin')
4035 parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin')
4036 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
4037 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
4038 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
4039 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
4040 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
4041 ns, args = parser.parse_known_args(namespace=unittest)
4042
4043 if ns.build_dir:
4044 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:
4045 print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.')
4046 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
4047 resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved')
4048 udevd_bin = os.path.join(ns.build_dir, 'systemd-udevd')
4049 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
4050 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
4051 resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl')
4052 timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl')
4053 else:
4054 if ns.networkd_bin:
4055 networkd_bin = ns.networkd_bin
4056 if ns.resolved_bin:
4057 resolved_bin = ns.resolved_bin
4058 if ns.udevd_bin:
4059 udevd_bin = ns.udevd_bin
4060 if ns.wait_online_bin:
4061 wait_online_bin = ns.wait_online_bin
4062 if ns.networkctl_bin:
4063 networkctl_bin = ns.networkctl_bin
4064 if ns.resolvectl_bin:
4065 resolvectl_bin = ns.resolvectl_bin
4066 if ns.timedatectl_bin:
4067 timedatectl_bin = ns.timedatectl_bin
4068
4069 use_valgrind = ns.use_valgrind
4070 enable_debug = ns.enable_debug
4071 asan_options = ns.asan_options
4072 lsan_options = ns.lsan_options
4073 ubsan_options = ns.ubsan_options
4074
4075 if use_valgrind:
4076 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
4077 resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin]
4078 timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin]
4079 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
4080 else:
4081 networkctl_cmd = [networkctl_bin]
4082 resolvectl_cmd = [resolvectl_bin]
4083 timedatectl_cmd = [timedatectl_bin]
4084 wait_online_cmd = [wait_online_bin]
4085
4086 if enable_debug:
4087 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
4088 if asan_options:
4089 env.update({ 'ASAN_OPTIONS' : asan_options })
4090 if lsan_options:
4091 env.update({ 'LSAN_OPTIONS' : lsan_options })
4092 if ubsan_options:
4093 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
4094
4095 sys.argv[1:] = args
4096 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
4097 verbosity=3))