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