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