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