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