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