]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
test-network: stop service before editing unit file
[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 socket
11 import subprocess
12 import sys
13 import time
14 import unittest
15 from shutil import copytree
16
17 network_unit_file_path='/run/systemd/network'
18 networkd_runtime_directory='/run/systemd/netif'
19 networkd_ci_path='/run/networkd-ci'
20 network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
21 network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
22
23 dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
24 dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
25
26 networkd_bin='/usr/lib/systemd/systemd-networkd'
27 wait_online_bin='/usr/lib/systemd/systemd-networkd-wait-online'
28 networkctl_bin='/usr/bin/networkctl'
29 use_valgrind=False
30 enable_debug=False
31 env = {}
32 asan_options=None
33 lsan_options=None
34 ubsan_options=None
35
36 def is_module_available(module_name):
37 lsmod_output = subprocess.check_output('lsmod', universal_newlines=True)
38 module_re = re.compile(r'^{0}\b'.format(re.escape(module_name)), re.MULTILINE)
39 return module_re.search(lsmod_output) or not subprocess.call(["modprobe", module_name])
40
41 def expectedFailureIfModuleIsNotAvailable(module_name):
42 def f(func):
43 if not is_module_available(module_name):
44 return unittest.expectedFailure(func)
45 return func
46
47 return f
48
49 def expectedFailureIfERSPANModuleIsNotAvailable():
50 def f(func):
51 rc = subprocess.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'])
52 if rc == 0:
53 subprocess.call(['ip', 'link', 'del', 'erspan99'])
54 return func
55 else:
56 return unittest.expectedFailure(func)
57
58 return f
59
60 def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
61 def f(func):
62 rc = subprocess.call(['ip', 'rule', 'add', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7'])
63 if rc == 0:
64 subprocess.call(['ip', 'rule', 'del', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7'])
65 return func
66 else:
67 return unittest.expectedFailure(func)
68
69 return f
70
71 def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
72 def f(func):
73 rc = subprocess.call(['ip', 'rule', 'add', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7'])
74 if rc == 0:
75 subprocess.call(['ip', 'rule', 'del', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7'])
76 return func
77 else:
78 return unittest.expectedFailure(func)
79
80 return f
81
82 def setUpModule():
83 os.makedirs(network_unit_file_path, exist_ok=True)
84 os.makedirs(networkd_ci_path, exist_ok=True)
85
86 shutil.rmtree(networkd_ci_path)
87 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
88
89 subprocess.check_call('systemctl stop systemd-networkd.socket', shell=True)
90 subprocess.check_call('systemctl stop systemd-networkd.service', shell=True)
91
92 drop_in = [
93 '[Service]',
94 'Restart=no',
95 'ExecStart=',
96 ]
97 if use_valgrind:
98 drop_in += [
99 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin,
100 'PrivateTmp=yes'
101 ]
102 else:
103 drop_in += ['ExecStart=!!' + networkd_bin]
104 if enable_debug:
105 drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug']
106 if asan_options:
107 drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"']
108 if lsan_options:
109 drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"']
110 if ubsan_options:
111 drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"']
112 if use_valgrind or asan_options or lsan_options or ubsan_options:
113 drop_in += ['MemoryDenyWriteExecute=no']
114
115 drop_in_str = '\n'.join(drop_in)
116 print(drop_in_str)
117
118 os.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok=True)
119 with open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode='w') as f:
120 f.write(drop_in_str)
121
122 subprocess.check_call('systemctl daemon-reload', shell=True)
123
124 def tearDownModule():
125 shutil.rmtree(networkd_ci_path)
126
127 subprocess.check_call('systemctl stop systemd-networkd.service', shell=True)
128
129 shutil.rmtree('/run/systemd/system/systemd-networkd.service.d')
130 subprocess.check_call('systemctl daemon-reload', shell=True)
131
132 subprocess.check_call('systemctl start systemd-networkd.socket', shell=True)
133 subprocess.check_call('systemctl start systemd-networkd.service', shell=True)
134
135 class Utilities():
136 def read_link_attr(self, link, dev, attribute):
137 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
138 return f.readline().strip()
139
140 def read_bridge_port_attr(self, bridge, link, attribute):
141
142 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
143 path_port = 'lower_' + link + '/brport'
144 path = os.path.join(path_bridge, path_port)
145
146 with open(os.path.join(path, attribute)) as f:
147 return f.readline().strip()
148
149 def link_exists(self, link):
150 return os.path.exists(os.path.join('/sys/class/net', link))
151
152 def check_link_exists(self, link):
153 self.assertTrue(self.link_exists(link))
154
155 def remove_links(self, links):
156 for link in links:
157 if self.link_exists(link):
158 subprocess.call(['ip', 'link', 'del', 'dev', link])
159 time.sleep(1)
160
161 def remove_fou_ports(self, ports):
162 for port in ports:
163 subprocess.call(['ip', 'fou', 'del', 'port', port])
164
165 def remove_routing_policy_rule_tables(self, tables):
166 for table in tables:
167 subprocess.call(['ip', 'rule', 'del', 'table', table])
168
169 def remove_routes(self, routes):
170 for route_type, addr in routes:
171 subprocess.call(['ip', 'route', 'del', route_type, addr])
172
173 def l2tp_tunnel_remove(self, tunnel_ids):
174 output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel'], universal_newlines=True).rstrip()
175 for tid in tunnel_ids:
176 words='Tunnel ' + tid + ', encap'
177 if words in output:
178 subprocess.call(['ip', 'l2tp', 'del', 'tunnel', 'tid', tid])
179 time.sleep(1)
180
181 def read_ipv6_sysctl_attr(self, link, attribute):
182 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
183 return f.readline().strip()
184
185 def read_ipv4_sysctl_attr(self, link, attribute):
186 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
187 return f.readline().strip()
188
189 def copy_unit_to_networkd_unit_path(self, *units):
190 print()
191 for unit in units:
192 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
193 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
194 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
195
196 def remove_unit_from_networkd_path(self, units):
197 for unit in units:
198 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
199 os.remove(os.path.join(network_unit_file_path, unit))
200 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
201 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
202
203 def warn_about_firewalld(self):
204 rc = subprocess.call(['systemctl', '-q', 'is-active', 'firewalld.service'])
205 if rc == 0:
206 print('\nWARNING: firewalld.service is active. The test may fail.')
207
208 def start_dnsmasq(self, additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'):
209 self.warn_about_firewalld()
210 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
211 subprocess.check_call(dnsmasq_command, shell=True)
212
213 def stop_dnsmasq(self, pid_file):
214 if os.path.exists(pid_file):
215 with open(pid_file, 'r') as f:
216 pid = f.read().rstrip(' \t\r\n\0')
217 os.kill(int(pid), signal.SIGTERM)
218
219 os.remove(pid_file)
220
221 def search_words_in_dnsmasq_log(self, words, show_all=False):
222 if os.path.exists(dnsmasq_log_file):
223 with open (dnsmasq_log_file) as in_file:
224 contents = in_file.read()
225 if show_all:
226 print(contents)
227 for line in contents.splitlines():
228 if words in line:
229 in_file.close()
230 print("%s, %s" % (words, line))
231 return True
232 return False
233
234 def remove_lease_file(self):
235 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
236 os.remove(os.path.join(networkd_ci_path, 'lease'))
237
238 def remove_log_file(self):
239 if os.path.exists(dnsmasq_log_file):
240 os.remove(dnsmasq_log_file)
241
242 def start_networkd(self, sleep_sec=5, remove_state_files=True):
243 if (remove_state_files and
244 os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
245 subprocess.check_call('systemctl stop systemd-networkd', shell=True)
246 os.remove(os.path.join(networkd_runtime_directory, 'state'))
247 subprocess.check_call('systemctl start systemd-networkd', shell=True)
248 else:
249 subprocess.check_call('systemctl restart systemd-networkd', shell=True)
250 if sleep_sec > 0:
251 time.sleep(sleep_sec)
252
253 def wait_online(self, links_with_operstate, timeout='20s', bool_any=False):
254 args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate]
255 if bool_any:
256 args += ['--any']
257 try:
258 subprocess.check_call(args, env=env)
259 except subprocess.CalledProcessError:
260 for link in links_with_operstate:
261 output = subprocess.check_output(networkctl_cmd + ['status', link.split(':')[0]], universal_newlines=True, env=env).rstrip()
262 print(output)
263 raise
264
265 def get_operstate(self, link, show_status=True, setup_state='configured'):
266 output = subprocess.check_output(networkctl_cmd + ['status', link], universal_newlines=True, env=env).rstrip()
267 if show_status:
268 print(output)
269 for line in output.splitlines():
270 if 'State:' in line and (not setup_state or setup_state in line):
271 return line.split()[1]
272 return None
273
274 def check_operstate(self, link, expected, show_status=True, setup_state='configured'):
275 self.assertRegex(self.get_operstate(link, show_status, setup_state), expected)
276
277 def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100):
278 for i in range(timeout_sec):
279 if i > 0:
280 time.sleep(1)
281 output = subprocess.check_output(['ip', ipv, 'address', 'show', 'dev', link, 'scope', scope], universal_newlines=True).rstrip()
282 if re.search(address_regex, output):
283 break
284 else:
285 self.assertRegex(output, address_regex)
286
287
288 class NetworkdNetDevTests(unittest.TestCase, Utilities):
289
290 links =[
291 '6rdtun99',
292 'bond99',
293 'bridge99',
294 'dropin-test',
295 'dummy98',
296 'erspan98',
297 'erspan99',
298 'geneve99',
299 'gretap96',
300 'gretap98',
301 'gretap99',
302 'gretun96',
303 'gretun97',
304 'gretun98',
305 'gretun99',
306 'ip6gretap98',
307 'ip6gretap99',
308 'ip6gretun97',
309 'ip6gretun98',
310 'ip6gretun99',
311 'ip6tnl97',
312 'ip6tnl98',
313 'ip6tnl99',
314 'ipiptun96',
315 'ipiptun97',
316 'ipiptun98',
317 'ipiptun99',
318 'ipvlan99',
319 'ipvtap99',
320 'isataptun99',
321 'macvlan99',
322 'macvtap99',
323 'nlmon99',
324 'sittun96',
325 'sittun97',
326 'sittun98',
327 'sittun99',
328 'tap99',
329 'test1',
330 'tun99',
331 'vcan99',
332 'veth99',
333 'vlan99',
334 'vrf99',
335 'vti6tun97',
336 'vti6tun98',
337 'vti6tun99',
338 'vtitun97',
339 'vtitun98',
340 'vtitun99',
341 'vxcan99',
342 'vxlan99',
343 'wg98',
344 'wg99']
345
346 units = [
347 '10-dropin-test.netdev',
348 '11-dummy.netdev',
349 '11-dummy.network',
350 '12-dummy.netdev',
351 '15-name-conflict-test.netdev',
352 '21-macvlan.netdev',
353 '21-macvtap.netdev',
354 '21-vlan-test1.network',
355 '21-vlan.netdev',
356 '21-vlan.network',
357 '25-6rd-tunnel.netdev',
358 '25-bond.netdev',
359 '25-bond-balanced-tlb.netdev',
360 '25-bridge.netdev',
361 '25-bridge.network',
362 '25-erspan-tunnel-local-any.netdev',
363 '25-erspan-tunnel.netdev',
364 '25-fou-gretap.netdev',
365 '25-fou-gre.netdev',
366 '25-fou-ipip.netdev',
367 '25-fou-ipproto-gre.netdev',
368 '25-fou-ipproto-ipip.netdev',
369 '25-fou-sit.netdev',
370 '25-geneve.netdev',
371 '25-gretap-tunnel-local-any.netdev',
372 '25-gretap-tunnel.netdev',
373 '25-gre-tunnel-local-any.netdev',
374 '25-gre-tunnel-remote-any.netdev',
375 '25-gre-tunnel.netdev',
376 '25-ip6gretap-tunnel-local-any.netdev',
377 '25-ip6gretap-tunnel.netdev',
378 '25-ip6gre-tunnel-local-any.netdev',
379 '25-ip6gre-tunnel-remote-any.netdev',
380 '25-ip6gre-tunnel.netdev',
381 '25-ip6tnl-tunnel-remote-any.netdev',
382 '25-ip6tnl-tunnel-local-any.netdev',
383 '25-ip6tnl-tunnel.netdev',
384 '25-ipip-tunnel-independent.netdev',
385 '25-ipip-tunnel-local-any.netdev',
386 '25-ipip-tunnel-remote-any.netdev',
387 '25-ipip-tunnel.netdev',
388 '25-ipvlan.netdev',
389 '25-ipvtap.netdev',
390 '25-isatap-tunnel.netdev',
391 '25-macsec.key',
392 '25-macsec.netdev',
393 '25-macsec.network',
394 '25-nlmon.netdev',
395 '25-sit-tunnel-local-any.netdev',
396 '25-sit-tunnel-remote-any.netdev',
397 '25-sit-tunnel.netdev',
398 '25-tap.netdev',
399 '25-tun.netdev',
400 '25-tunnel-local-any.network',
401 '25-tunnel-remote-any.network',
402 '25-tunnel.network',
403 '25-vcan.netdev',
404 '25-veth.netdev',
405 '25-vrf.netdev',
406 '25-vti6-tunnel-local-any.netdev',
407 '25-vti6-tunnel-remote-any.netdev',
408 '25-vti6-tunnel.netdev',
409 '25-vti-tunnel-local-any.netdev',
410 '25-vti-tunnel-remote-any.netdev',
411 '25-vti-tunnel.netdev',
412 '25-vxcan.netdev',
413 '25-vxlan.netdev',
414 '25-wireguard-23-peers.netdev',
415 '25-wireguard-23-peers.network',
416 '25-wireguard-preshared-key.txt',
417 '25-wireguard-private-key.txt',
418 '25-wireguard.netdev',
419 '25-wireguard.network',
420 '6rd.network',
421 'erspan.network',
422 'gre.network',
423 'gretap.network',
424 'gretun.network',
425 'ip6gretap.network',
426 'ip6gretun.network',
427 'ip6tnl.network',
428 'ipip.network',
429 'ipvlan.network',
430 'ipvtap.network',
431 'isatap.network',
432 'macsec.network',
433 'macvlan.network',
434 'macvtap.network',
435 'netdev-link-local-addressing-yes.network',
436 'sit.network',
437 'vti6.network',
438 'vti.network',
439 'vxlan-test1.network',
440 'vxlan.network']
441
442 fou_ports = [
443 '55555',
444 '55556']
445
446 def setUp(self):
447 self.remove_fou_ports(self.fou_ports)
448 self.remove_links(self.links)
449
450 def tearDown(self):
451 self.remove_fou_ports(self.fou_ports)
452 self.remove_links(self.links)
453 self.remove_unit_from_networkd_path(self.units)
454
455 def test_dropin_and_networkctl_glob(self):
456 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev')
457 self.start_networkd(0)
458
459 self.wait_online(['dropin-test:off'])
460
461 # This also tests NetDev.Name= conflict and basic networkctl functionalities
462
463 output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test'], universal_newlines=True).rstrip()
464 print(output)
465 self.assertRegex(output, '00:50:56:c0:00:28')
466
467 output = subprocess.check_output(networkctl_cmd + ['list'], universal_newlines=True, env=env).rstrip()
468 self.assertRegex(output, '1 lo ')
469 self.assertRegex(output, 'dropin-test')
470
471 output = subprocess.check_output(networkctl_cmd + ['list', 'dropin-test'], universal_newlines=True, env=env).rstrip()
472 self.assertNotRegex(output, '1 lo ')
473 self.assertRegex(output, 'dropin-test')
474
475 output = subprocess.check_output(networkctl_cmd + ['list', 'dropin-*'], universal_newlines=True, env=env).rstrip()
476 self.assertNotRegex(output, '1 lo ')
477 self.assertRegex(output, 'dropin-test')
478
479 output = subprocess.check_output(networkctl_cmd + ['status', 'dropin-*'], universal_newlines=True, env=env).rstrip()
480 self.assertNotRegex(output, '1: lo ')
481 self.assertRegex(output, 'dropin-test')
482
483 ret = subprocess.run(['ethtool', '--driver', 'dropin-test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
484 print(ret.stdout.rstrip())
485 if ret.returncode == 0 and re.search('driver: dummy', ret.stdout.rstrip()) != None:
486 self.assertRegex(output, 'Driver: dummy')
487 else:
488 print('ethtool does not support driver field at least for dummy interfaces, skipping test for Driver field of networkctl.')
489
490 def test_wait_online_any(self):
491 self.copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network')
492 self.start_networkd(0)
493
494 self.wait_online(['bridge99', 'test1:degraded'], bool_any=True)
495
496 self.check_operstate('bridge99', '(?:off|no-carrier)', setup_state='configuring')
497 self.check_operstate('test1', 'degraded')
498
499 def test_bridge(self):
500 self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
501 self.start_networkd(0)
502
503 self.wait_online(['bridge99:off'])
504
505 tick = os.sysconf('SC_CLK_TCK')
506 self.assertEqual(9, round(float(self.read_link_attr('bridge99', 'bridge', 'hello_time')) / tick))
507 self.assertEqual(9, round(float(self.read_link_attr('bridge99', 'bridge', 'max_age')) / tick))
508 self.assertEqual(9, round(float(self.read_link_attr('bridge99', 'bridge','forward_delay')) / tick))
509 self.assertEqual(9, round(float(self.read_link_attr('bridge99', 'bridge','ageing_time')) / tick))
510 self.assertEqual(9, int(self.read_link_attr('bridge99', 'bridge','priority')))
511 self.assertEqual(1, int(self.read_link_attr('bridge99', 'bridge','multicast_querier')))
512 self.assertEqual(1, int(self.read_link_attr('bridge99', 'bridge','multicast_snooping')))
513 self.assertEqual(1, int(self.read_link_attr('bridge99', 'bridge','stp_state')))
514
515 def test_bond(self):
516 self.copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev')
517 self.start_networkd(0)
518
519 self.wait_online(['bond99:off', 'bond98:off'])
520
521 self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode'))
522 self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
523 self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon'))
524 self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate'))
525 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay'))
526 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay'))
527 self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp'))
528 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links'))
529 self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
530 self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
531 self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
532
533 self.assertEqual('balance-tlb 5', self.read_link_attr('bond98', 'bonding', 'mode'))
534 self.assertEqual('1', self.read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb'))
535
536 def test_vlan(self):
537 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev',
538 '21-vlan.network', '21-vlan-test1.network')
539 self.start_networkd(0)
540
541 self.wait_online(['test1:degraded', 'vlan99:routable'])
542
543 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
544 print(output)
545 self.assertRegex(output, ' mtu 2000 ')
546
547 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99'], universal_newlines=True).rstrip()
548 print(output)
549 self.assertRegex(output, ' mtu 2000 ')
550 self.assertRegex(output, 'REORDER_HDR')
551 self.assertRegex(output, 'LOOSE_BINDING')
552 self.assertRegex(output, 'GVRP')
553 self.assertRegex(output, 'MVRP')
554 self.assertRegex(output, ' id 99 ')
555
556 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'test1'], universal_newlines=True).rstrip()
557 print(output)
558 self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
559 self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
560
561 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'vlan99'], universal_newlines=True).rstrip()
562 print(output)
563 self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
564
565 def test_macvtap(self):
566 for mode in ['private', 'vepa', 'bridge', 'passthru']:
567 with self.subTest(mode=mode):
568 if mode != 'private':
569 self.tearDown()
570 self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network',
571 '11-dummy.netdev', 'macvtap.network')
572 with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f:
573 f.write('[MACVTAP]\nMode=' + mode)
574 self.start_networkd(0)
575
576 self.wait_online(['macvtap99:degraded', 'test1:degraded'])
577
578 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macvtap99'], universal_newlines=True).rstrip()
579 print(output)
580 self.assertRegex(output, 'macvtap mode ' + mode + ' ')
581
582 def test_macvlan(self):
583 for mode in ['private', 'vepa', 'bridge', 'passthru']:
584 with self.subTest(mode=mode):
585 if mode != 'private':
586 self.tearDown()
587 self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network',
588 '11-dummy.netdev', 'macvlan.network')
589 with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f:
590 f.write('[MACVLAN]\nMode=' + mode)
591 self.start_networkd(0)
592
593 self.wait_online(['macvlan99:degraded', 'test1:degraded'])
594
595 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
596 print(output)
597 self.assertRegex(output, ' mtu 2000 ')
598
599 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macvlan99'], universal_newlines=True).rstrip()
600 print(output)
601 self.assertRegex(output, ' mtu 2000 ')
602 self.assertRegex(output, 'macvlan mode ' + mode + ' ')
603
604 @expectedFailureIfModuleIsNotAvailable('ipvlan')
605 def test_ipvlan(self):
606 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
607 with self.subTest(mode=mode, flag=flag):
608 if mode != 'L2':
609 self.tearDown()
610 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network',
611 '11-dummy.netdev', 'ipvlan.network')
612 with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f:
613 f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag)
614
615 self.start_networkd(0)
616 self.wait_online(['ipvlan99:degraded', 'test1:degraded'])
617
618 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipvlan99'], universal_newlines=True).rstrip()
619 print(output)
620 self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag)
621
622 @expectedFailureIfModuleIsNotAvailable('ipvtap')
623 def test_ipvtap(self):
624 for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]:
625 with self.subTest(mode=mode, flag=flag):
626 if mode != 'L2':
627 self.tearDown()
628 self.copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network',
629 '11-dummy.netdev', 'ipvtap.network')
630 with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f:
631 f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag)
632
633 self.start_networkd(0)
634 self.wait_online(['ipvtap99:degraded', 'test1:degraded'])
635
636 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipvtap99'], universal_newlines=True).rstrip()
637 print(output)
638 self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag)
639
640 def test_veth(self):
641 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network')
642 self.start_networkd(0)
643
644 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
645
646 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'veth99'], universal_newlines=True).rstrip()
647 print(output)
648 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc')
649 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'veth-peer'], universal_newlines=True).rstrip()
650 print(output)
651 self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd')
652
653 def test_tun(self):
654 self.copy_unit_to_networkd_unit_path('25-tun.netdev')
655 self.start_networkd(0)
656
657 self.wait_online(['tun99:off'])
658
659 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'tun99'], universal_newlines=True).rstrip()
660 print(output)
661 # Old ip command does not support IFF_ flags
662 self.assertRegex(output, 'tun (?:type tun pi on vnet_hdr on multi_queue|addrgenmode) ')
663
664 def test_tap(self):
665 self.copy_unit_to_networkd_unit_path('25-tap.netdev')
666 self.start_networkd(0)
667
668 self.wait_online(['tap99:off'])
669
670 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'tap99'], universal_newlines=True).rstrip()
671 print(output)
672 # Old ip command does not support IFF_ flags
673 self.assertRegex(output, 'tun (?:type tap pi on vnet_hdr on multi_queue|addrgenmode) ')
674
675 @expectedFailureIfModuleIsNotAvailable('vrf')
676 def test_vrf(self):
677 self.copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network')
678 self.start_networkd(0)
679
680 self.wait_online(['vrf99:carrier'])
681
682 @expectedFailureIfModuleIsNotAvailable('vcan')
683 def test_vcan(self):
684 self.copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network')
685 self.start_networkd(0)
686
687 self.wait_online(['vcan99:carrier'])
688
689 @expectedFailureIfModuleIsNotAvailable('vxcan')
690 def test_vxcan(self):
691 self.copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network')
692 self.start_networkd(0)
693
694 self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier'])
695
696 @expectedFailureIfModuleIsNotAvailable('wireguard')
697 def test_wireguard(self):
698 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network',
699 '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network',
700 '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt')
701 self.start_networkd(0)
702 self.wait_online(['wg99:carrier', 'wg98:routable'])
703
704 if shutil.which('wg'):
705 subprocess.call('wg')
706
707 output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port'], universal_newlines=True).rstrip()
708 self.assertRegex(output, '51820')
709 output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark'], universal_newlines=True).rstrip()
710 self.assertRegex(output, '0x4d2')
711 output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips'], universal_newlines=True).rstrip()
712 self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
713 self.assertRegex(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
714 output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive'], universal_newlines=True).rstrip()
715 self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
716 output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints'], universal_newlines=True).rstrip()
717 self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
718 output = subprocess.check_output(['wg', 'show', 'wg99', 'private-key'], universal_newlines=True).rstrip()
719 self.assertRegex(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
720 output = subprocess.check_output(['wg', 'show', 'wg99', 'preshared-keys'], universal_newlines=True).rstrip()
721 self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
722 self.assertRegex(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
723
724 output = subprocess.check_output(['wg', 'show', 'wg98', 'private-key'], universal_newlines=True).rstrip()
725 self.assertRegex(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
726
727 def test_geneve(self):
728 self.copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network')
729 self.start_networkd(0)
730
731 self.wait_online(['geneve99:degraded'])
732
733 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99'], universal_newlines=True).rstrip()
734 print(output)
735 self.assertRegex(output, '192.168.22.1')
736 self.assertRegex(output, '6082')
737 self.assertRegex(output, 'udpcsum')
738 self.assertRegex(output, 'udp6zerocsumrx')
739
740 def test_ipip_tunnel(self):
741 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
742 '25-ipip-tunnel.netdev', '25-tunnel.network',
743 '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
744 '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
745 self.start_networkd(0)
746 self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'dummy98:degraded'])
747
748 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun99'], universal_newlines=True).rstrip()
749 print(output)
750 self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local 192.168.223.238 dev dummy98')
751 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun98'], universal_newlines=True).rstrip()
752 print(output)
753 self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local any dev dummy98')
754 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun97'], universal_newlines=True).rstrip()
755 print(output)
756 self.assertRegex(output, 'ipip (?:ipip |)remote any local 192.168.223.238 dev dummy98')
757
758 def test_gre_tunnel(self):
759 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
760 '25-gre-tunnel.netdev', '25-tunnel.network',
761 '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
762 '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
763 self.start_networkd(0)
764 self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'dummy98:degraded'])
765
766 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun99'], universal_newlines=True).rstrip()
767 print(output)
768 self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
769 self.assertRegex(output, 'ikey 1.2.3.103')
770 self.assertRegex(output, 'okey 1.2.4.103')
771 self.assertRegex(output, 'iseq')
772 self.assertRegex(output, 'oseq')
773 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun98'], universal_newlines=True).rstrip()
774 print(output)
775 self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
776 self.assertRegex(output, 'ikey 0.0.0.104')
777 self.assertRegex(output, 'okey 0.0.0.104')
778 self.assertNotRegex(output, 'iseq')
779 self.assertNotRegex(output, 'oseq')
780 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun97'], universal_newlines=True).rstrip()
781 print(output)
782 self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
783 self.assertRegex(output, 'ikey 0.0.0.105')
784 self.assertRegex(output, 'okey 0.0.0.105')
785 self.assertNotRegex(output, 'iseq')
786 self.assertNotRegex(output, 'oseq')
787
788 def test_ip6gre_tunnel(self):
789 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
790 '25-ip6gre-tunnel.netdev', '25-tunnel.network',
791 '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
792 '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
793 self.start_networkd()
794
795 # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here.
796
797 self.check_link_exists('dummy98')
798 self.check_link_exists('ip6gretun99')
799 self.check_link_exists('ip6gretun98')
800 self.check_link_exists('ip6gretun97')
801
802 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun99'], universal_newlines=True).rstrip()
803 print(output)
804 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
805 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun98'], universal_newlines=True).rstrip()
806 print(output)
807 self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
808 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun97'], universal_newlines=True).rstrip()
809 print(output)
810 self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
811
812 def test_gretap_tunnel(self):
813 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
814 '25-gretap-tunnel.netdev', '25-tunnel.network',
815 '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
816 self.start_networkd(0)
817 self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
818
819 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap99'], universal_newlines=True).rstrip()
820 print(output)
821 self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
822 self.assertRegex(output, 'ikey 0.0.0.106')
823 self.assertRegex(output, 'okey 0.0.0.106')
824 self.assertRegex(output, 'iseq')
825 self.assertRegex(output, 'oseq')
826 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap98'], universal_newlines=True).rstrip()
827 print(output)
828 self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
829 self.assertRegex(output, 'ikey 0.0.0.107')
830 self.assertRegex(output, 'okey 0.0.0.107')
831 self.assertRegex(output, 'iseq')
832 self.assertRegex(output, 'oseq')
833
834 def test_ip6gretap_tunnel(self):
835 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
836 '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
837 '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
838 self.start_networkd(0)
839 self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
840
841 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap99'], universal_newlines=True).rstrip()
842 print(output)
843 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
844 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap98'], universal_newlines=True).rstrip()
845 print(output)
846 self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
847
848 def test_vti_tunnel(self):
849 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
850 '25-vti-tunnel.netdev', '25-tunnel.network',
851 '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
852 '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
853 self.start_networkd(0)
854 self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'dummy98:degraded'])
855
856 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun99'], universal_newlines=True).rstrip()
857 print(output)
858 self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
859 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun98'], universal_newlines=True).rstrip()
860 print(output)
861 self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
862 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun97'], universal_newlines=True).rstrip()
863 print(output)
864 self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
865
866 def test_vti6_tunnel(self):
867 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
868 '25-vti6-tunnel.netdev', '25-tunnel.network',
869 '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
870 '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
871 self.start_networkd(0)
872 self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
873
874 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun99'], universal_newlines=True).rstrip()
875 print(output)
876 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
877 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun98'], universal_newlines=True).rstrip()
878 print(output)
879 self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
880 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun97'], universal_newlines=True).rstrip()
881 print(output)
882 self.assertRegex(output, 'vti6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
883
884 def test_ip6tnl_tunnel(self):
885 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
886 '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
887 '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
888 '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
889 self.start_networkd(0)
890 self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
891
892 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl99'], universal_newlines=True).rstrip()
893 print(output)
894 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
895 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl98'], universal_newlines=True).rstrip()
896 print(output)
897 self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
898 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl97'], universal_newlines=True).rstrip()
899 print(output)
900 self.assertRegex(output, 'ip6tnl ip6ip6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
901
902 def test_sit_tunnel(self):
903 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
904 '25-sit-tunnel.netdev', '25-tunnel.network',
905 '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
906 '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
907 self.start_networkd(0)
908 self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'dummy98:degraded'])
909
910 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99'], universal_newlines=True).rstrip()
911 print(output)
912 self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local 10.65.223.238 dev dummy98")
913 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun98'], universal_newlines=True).rstrip()
914 print(output)
915 self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local any dev dummy98")
916 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun97'], universal_newlines=True).rstrip()
917 print(output)
918 self.assertRegex(output, "sit (?:ip6ip |)remote any local 10.65.223.238 dev dummy98")
919
920 def test_isatap_tunnel(self):
921 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
922 '25-isatap-tunnel.netdev', '25-tunnel.network')
923 self.start_networkd(0)
924 self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
925
926 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99'], universal_newlines=True).rstrip()
927 print(output)
928 self.assertRegex(output, "isatap ")
929
930 def test_6rd_tunnel(self):
931 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
932 '25-6rd-tunnel.netdev', '25-tunnel.network')
933 self.start_networkd(0)
934 self.wait_online(['sittun99:routable', 'dummy98:degraded'])
935
936 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99'], universal_newlines=True).rstrip()
937 print(output)
938 self.assertRegex(output, '6rd-prefix 2602::/24')
939
940 @expectedFailureIfERSPANModuleIsNotAvailable()
941 def test_erspan_tunnel(self):
942 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
943 '25-erspan-tunnel.netdev', '25-tunnel.network',
944 '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
945 self.start_networkd(0)
946 self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
947
948 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan99'], universal_newlines=True).rstrip()
949 print(output)
950 self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
951 self.assertRegex(output, 'ikey 0.0.0.101')
952 self.assertRegex(output, 'okey 0.0.0.101')
953 self.assertRegex(output, 'iseq')
954 self.assertRegex(output, 'oseq')
955 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan98'], universal_newlines=True).rstrip()
956 print(output)
957 self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
958 self.assertRegex(output, '102')
959 self.assertRegex(output, 'ikey 0.0.0.102')
960 self.assertRegex(output, 'okey 0.0.0.102')
961 self.assertRegex(output, 'iseq')
962 self.assertRegex(output, 'oseq')
963
964 def test_tunnel_independent(self):
965 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network')
966 self.start_networkd(0)
967
968 self.wait_online(['ipiptun99:carrier'])
969
970 @expectedFailureIfModuleIsNotAvailable('fou')
971 def test_fou(self):
972 # The following redundant check is necessary for CentOS CI.
973 # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated.
974 self.assertTrue(is_module_available('fou'))
975
976 self.copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev',
977 '25-fou-ipip.netdev', '25-fou-sit.netdev',
978 '25-fou-gre.netdev', '25-fou-gretap.netdev')
979 self.start_networkd(0)
980
981 self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'])
982
983 output = subprocess.check_output(['ip', 'fou', 'show'], universal_newlines=True).rstrip()
984 print(output)
985 self.assertRegex(output, 'port 55555 ipproto 4')
986 self.assertRegex(output, 'port 55556 ipproto 47')
987
988 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun96'], universal_newlines=True).rstrip()
989 print(output)
990 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
991 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun96'], universal_newlines=True).rstrip()
992 print(output)
993 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
994 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun96'], universal_newlines=True).rstrip()
995 print(output)
996 self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
997 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap96'], universal_newlines=True).rstrip()
998 print(output)
999 self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
1000
1001 def test_vxlan(self):
1002 self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
1003 '11-dummy.netdev', 'vxlan-test1.network')
1004 self.start_networkd(0)
1005
1006 self.wait_online(['test1:degraded', 'vxlan99:degraded'])
1007
1008 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99'], universal_newlines=True).rstrip()
1009 print(output)
1010 self.assertRegex(output, '999')
1011 self.assertRegex(output, '5555')
1012 self.assertRegex(output, 'l2miss')
1013 self.assertRegex(output, 'l3miss')
1014 self.assertRegex(output, 'udpcsum')
1015 self.assertRegex(output, 'udp6zerocsumtx')
1016 self.assertRegex(output, 'udp6zerocsumrx')
1017 self.assertRegex(output, 'remcsumtx')
1018 self.assertRegex(output, 'remcsumrx')
1019 self.assertRegex(output, 'gbp')
1020
1021 output = subprocess.check_output(['bridge', 'fdb', 'show', 'dev', 'vxlan99'], universal_newlines=True).rstrip()
1022 print(output)
1023 self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
1024 self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
1025 self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
1026
1027 def test_macsec(self):
1028 self.copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
1029 'macsec.network', '12-dummy.netdev')
1030 self.start_networkd(0)
1031
1032 self.wait_online(['dummy98:degraded', 'macsec99:routable'])
1033
1034 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macsec99'], universal_newlines=True).rstrip()
1035 print(output)
1036 self.assertRegex(output, 'macsec99@dummy98')
1037 self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
1038 self.assertRegex(output, 'encrypt on')
1039
1040 output = subprocess.check_output(['ip', 'macsec', 'show', 'macsec99'], universal_newlines=True).rstrip()
1041 print(output)
1042 self.assertRegex(output, 'encrypt on')
1043 self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
1044 self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000')
1045 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000')
1046 self.assertRegex(output, 'RXSC: c619528fe6a00100, state on')
1047 self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000')
1048 self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000')
1049 self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000')
1050 self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000')
1051 self.assertNotRegex(output, 'key 02030405067080900000000000000000')
1052 self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on')
1053 self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000')
1054
1055 def test_nlmon(self):
1056 self.copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network')
1057 self.start_networkd()
1058
1059 self.wait_online(['nlmon99:carrier'])
1060
1061 class NetworkdL2TPTests(unittest.TestCase, Utilities):
1062
1063 links =[
1064 'l2tp-ses1',
1065 'l2tp-ses2',
1066 'l2tp-ses3',
1067 'l2tp-ses4',
1068 'test1']
1069
1070 units = [
1071 '11-dummy.netdev',
1072 '25-l2tp-dummy.network',
1073 '25-l2tp-ip.netdev',
1074 '25-l2tp-udp.netdev']
1075
1076 l2tp_tunnel_ids = [ '10' ]
1077
1078 def setUp(self):
1079 self.l2tp_tunnel_remove(self.l2tp_tunnel_ids)
1080 self.remove_links(self.links)
1081
1082 def tearDown(self):
1083 self.l2tp_tunnel_remove(self.l2tp_tunnel_ids)
1084 self.remove_links(self.links)
1085 self.remove_unit_from_networkd_path(self.units)
1086
1087 @expectedFailureIfModuleIsNotAvailable('l2tp_eth')
1088 def test_l2tp_udp(self):
1089 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', '25-l2tp-udp.netdev')
1090 self.start_networkd(0)
1091
1092 self.wait_online(['test1:routable', 'l2tp-ses1:off', 'l2tp-ses2:off'])
1093
1094 output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10'], universal_newlines=True).rstrip()
1095 print(output)
1096 self.assertRegex(output, "Tunnel 10, encap UDP")
1097 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1098 self.assertRegex(output, "Peer tunnel 11")
1099 self.assertRegex(output, "UDP source / dest ports: 3000/4000")
1100 self.assertRegex(output, "UDP checksum: enabled")
1101
1102 output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '15'], universal_newlines=True).rstrip()
1103 print(output)
1104 self.assertRegex(output, "Session 15 in tunnel 10")
1105 self.assertRegex(output, "Peer session 16, tunnel 11")
1106 self.assertRegex(output, "interface name: l2tp-ses1")
1107
1108 output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '17'], universal_newlines=True).rstrip()
1109 print(output)
1110 self.assertRegex(output, "Session 17 in tunnel 10")
1111 self.assertRegex(output, "Peer session 18, tunnel 11")
1112 self.assertRegex(output, "interface name: l2tp-ses2")
1113
1114 @expectedFailureIfModuleIsNotAvailable('l2tp_ip')
1115 def test_l2tp_ip(self):
1116 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', '25-l2tp-ip.netdev')
1117 self.start_networkd(0)
1118
1119 self.wait_online(['test1:routable', 'l2tp-ses3:off', 'l2tp-ses4:off'])
1120
1121 output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10'], universal_newlines=True).rstrip()
1122 print(output)
1123 self.assertRegex(output, "Tunnel 10, encap IP")
1124 self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
1125 self.assertRegex(output, "Peer tunnel 12")
1126
1127 output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '25'], universal_newlines=True).rstrip()
1128 print(output)
1129 self.assertRegex(output, "Session 25 in tunnel 10")
1130 self.assertRegex(output, "Peer session 26, tunnel 12")
1131 self.assertRegex(output, "interface name: l2tp-ses3")
1132
1133 output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '27'], universal_newlines=True).rstrip()
1134 print(output)
1135 self.assertRegex(output, "Session 27 in tunnel 10")
1136 self.assertRegex(output, "Peer session 28, tunnel 12")
1137 self.assertRegex(output, "interface name: l2tp-ses4")
1138
1139 class NetworkdNetworkTests(unittest.TestCase, Utilities):
1140 links = [
1141 'bond199',
1142 'dummy98',
1143 'dummy99',
1144 'test1']
1145
1146 units = [
1147 '11-dummy.netdev',
1148 '12-dummy.netdev',
1149 '23-active-slave.network',
1150 '24-search-domain.network',
1151 '25-address-link-section.network',
1152 '25-address-preferred-lifetime-zero-ipv6.network',
1153 '25-address-static.network',
1154 '25-bind-carrier.network',
1155 '25-bond-active-backup-slave.netdev',
1156 '25-fibrule-invert.network',
1157 '25-fibrule-port-range.network',
1158 '25-ipv6-address-label-section.network',
1159 '25-neighbor-section.network',
1160 '25-link-local-addressing-no.network',
1161 '25-link-local-addressing-yes.network',
1162 '25-link-section-unmanaged.network',
1163 '25-route-ipv6-src.network',
1164 '25-route-static.network',
1165 '25-sysctl-disable-ipv6.network',
1166 '25-sysctl.network',
1167 'configure-without-carrier.network',
1168 'routing-policy-rule-dummy98.network',
1169 'routing-policy-rule-test1.network']
1170
1171 routing_policy_rule_tables = ['7', '8']
1172 routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
1173
1174 def setUp(self):
1175 self.remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1176 self.remove_routes(self.routes)
1177 self.remove_links(self.links)
1178
1179 def tearDown(self):
1180 self.remove_routing_policy_rule_tables(self.routing_policy_rule_tables)
1181 self.remove_routes(self.routes)
1182 self.remove_links(self.links)
1183 self.remove_unit_from_networkd_path(self.units)
1184
1185 def test_address_static(self):
1186 self.copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
1187 self.start_networkd(0)
1188
1189 self.wait_online(['dummy98:routable'])
1190
1191 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
1192 print(output)
1193 self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
1194 self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
1195 self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
1196
1197 # invalid sections
1198 self.assertNotRegex(output, '10.10.0.1/16')
1199 self.assertNotRegex(output, '10.10.0.2/16')
1200
1201 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '32'], universal_newlines=True).rstrip()
1202 self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
1203
1204 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '33'], universal_newlines=True).rstrip()
1205 self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
1206
1207 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '34'], universal_newlines=True).rstrip()
1208 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
1209
1210 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '35'], universal_newlines=True).rstrip()
1211 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
1212
1213 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
1214 print(output)
1215 self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
1216 self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
1217 self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global')
1218 self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global')
1219 self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global')
1220 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
1221
1222 def test_address_preferred_lifetime_zero_ipv6(self):
1223 self.copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero-ipv6.network', '12-dummy.netdev')
1224 self.start_networkd()
1225
1226 self.check_link_exists('dummy98')
1227
1228 self.check_operstate('dummy98', 'routable', setup_state='configuring')
1229
1230 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
1231 print(output)
1232 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
1233 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
1234
1235 def test_configure_without_carrier(self):
1236 self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
1237 self.start_networkd()
1238
1239 self.check_link_exists('test1')
1240
1241 output = subprocess.check_output(networkctl_cmd + ['status', 'test1'], universal_newlines=True, env=env).rstrip()
1242 print(output)
1243 self.assertRegex(output, '192.168.0.15')
1244 self.assertRegex(output, '192.168.0.1')
1245 self.assertRegex(output, 'routable')
1246
1247 def test_routing_policy_rule(self):
1248 self.copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
1249
1250 self.start_networkd()
1251
1252 self.check_link_exists('test1')
1253
1254 output = subprocess.check_output(['ip', 'rule'], universal_newlines=True).rstrip()
1255 print(output)
1256 self.assertRegex(output, '111')
1257 self.assertRegex(output, 'from 192.168.100.18')
1258 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
1259 self.assertRegex(output, 'iif test1')
1260 self.assertRegex(output, 'oif test1')
1261 self.assertRegex(output, 'lookup 7')
1262
1263 def test_routing_policy_rule_issue_11280(self):
1264 self.copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
1265 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
1266
1267 for trial in range(3):
1268 # Remove state files only first time
1269 self.start_networkd(remove_state_files=(trial == 0))
1270
1271 self.check_link_exists('test1')
1272 self.check_link_exists('dummy98')
1273
1274 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '7'], universal_newlines=True).rstrip()
1275 print(output)
1276 self.assertRegex(output, '111: from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
1277
1278 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '8'], universal_newlines=True).rstrip()
1279 print(output)
1280 self.assertRegex(output, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
1281
1282 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
1283 def test_routing_policy_rule_port_range(self):
1284 self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
1285
1286 self.start_networkd()
1287
1288 self.check_link_exists('test1')
1289
1290 output = subprocess.check_output(['ip', 'rule'], universal_newlines=True).rstrip()
1291 print(output)
1292 self.assertRegex(output, '111')
1293 self.assertRegex(output, 'from 192.168.100.18')
1294 self.assertRegex(output, '1123-1150')
1295 self.assertRegex(output, '3224-3290')
1296 self.assertRegex(output, 'tcp')
1297 self.assertRegex(output, 'lookup 7')
1298
1299 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
1300 def test_routing_policy_rule_invert(self):
1301 self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
1302
1303 self.start_networkd()
1304
1305 self.check_link_exists('test1')
1306
1307 output = subprocess.check_output(['ip', 'rule'], universal_newlines=True).rstrip()
1308 print(output)
1309 self.assertRegex(output, '111')
1310 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
1311 self.assertRegex(output, 'tcp')
1312 self.assertRegex(output, 'lookup 7')
1313
1314 def test_route_static(self):
1315 self.copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
1316 self.start_networkd(0)
1317
1318 self.wait_online(['dummy98:routable'])
1319
1320 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
1321 print(output)
1322 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
1323 self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
1324
1325 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98', 'default'], universal_newlines=True).rstrip()
1326 self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
1327
1328 output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
1329 print(output)
1330 self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
1331 self.assertRegex(output, '149.10.124.64 proto static scope link')
1332 self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
1333 self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
1334 self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
1335
1336 output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98', 'default'], universal_newlines=True).rstrip()
1337 self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
1338 self.assertRegex(output, 'default via 149.10.124.64 proto static')
1339 self.assertRegex(output, 'default proto static')
1340
1341 output = subprocess.check_output(['ip', 'route', 'show', 'type', 'blackhole'], universal_newlines=True).rstrip()
1342 print(output)
1343 self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
1344
1345 output = subprocess.check_output(['ip', 'route', 'show', 'type', 'unreachable'], universal_newlines=True).rstrip()
1346 print(output)
1347 self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
1348
1349 output = subprocess.check_output(['ip', 'route', 'show', 'type', 'prohibit'], universal_newlines=True).rstrip()
1350 print(output)
1351 self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
1352
1353 def test_ip_route_ipv6_src_route(self):
1354 # a dummy device does not make the addresses go through tentative state, so we
1355 # reuse a bond from an earlier test, which does make the addresses go through
1356 # tentative state, and do our test on that
1357 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1358 self.start_networkd()
1359
1360 self.check_link_exists('dummy98')
1361 self.check_link_exists('bond199')
1362
1363 output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199'], universal_newlines=True).rstrip()
1364 print(output)
1365 self.assertRegex(output, 'abcd::/16')
1366 self.assertRegex(output, 'src')
1367 self.assertRegex(output, '2001:1234:56:8f63::2')
1368
1369 def test_ip_link_mac_address(self):
1370 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
1371 self.start_networkd()
1372
1373 self.check_link_exists('dummy98')
1374
1375 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
1376 print(output)
1377 self.assertRegex(output, '00:01:02:aa:bb:cc')
1378
1379 def test_ip_link_unmanaged(self):
1380 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
1381 self.start_networkd()
1382
1383 self.check_link_exists('dummy98')
1384
1385 output = subprocess.check_output(networkctl_cmd + ['status', 'dummy98'], universal_newlines=True, env=env).rstrip()
1386 print(output)
1387 self.assertRegex(output, 'unmanaged')
1388
1389 def test_ipv6_address_label(self):
1390 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
1391 self.start_networkd()
1392
1393 self.check_link_exists('dummy98')
1394
1395 output = subprocess.check_output(['ip', 'addrlabel', 'list'], universal_newlines=True).rstrip()
1396 print(output)
1397 self.assertRegex(output, '2004:da8:1::/64')
1398
1399 def test_ipv6_neighbor(self):
1400 self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
1401 self.start_networkd()
1402
1403 self.check_link_exists('dummy98')
1404
1405 output = subprocess.check_output(['ip', 'neigh', 'list'], universal_newlines=True).rstrip()
1406 print(output)
1407 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
1408 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
1409
1410 def test_link_local_addressing(self):
1411 self.copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
1412 '25-link-local-addressing-no.network', '12-dummy.netdev')
1413 self.start_networkd(0)
1414 self.wait_online(['test1:degraded', 'dummy98:carrier'])
1415
1416 self.check_link_exists('test1')
1417 self.check_link_exists('dummy98')
1418
1419 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1'], universal_newlines=True).rstrip()
1420 print(output)
1421 self.assertRegex(output, 'inet .* scope link')
1422 self.assertRegex(output, 'inet6 .* scope link')
1423
1424 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
1425 print(output)
1426 self.assertNotRegex(output, 'inet6* .* scope link')
1427
1428 self.check_operstate('test1', 'degraded')
1429 self.check_operstate('dummy98', 'carrier')
1430
1431 '''
1432 Documentation/networking/ip-sysctl.txt
1433
1434 addr_gen_mode - INTEGER
1435 Defines how link-local and autoconf addresses are generated.
1436
1437 0: generate address based on EUI64 (default)
1438 1: do no generate a link-local address, use EUI64 for addresses generated
1439 from autoconf
1440 2: generate stable privacy addresses, using the secret from
1441 stable_secret (RFC7217)
1442 3: generate stable privacy addresses, using a random secret if unset
1443 '''
1444
1445 test1_addr_gen_mode = ''
1446 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
1447 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
1448 try:
1449 f.readline()
1450 except IOError:
1451 # if stable_secret is unset, then EIO is returned
1452 test1_addr_gen_mode = '0'
1453 else:
1454 test1_addr_gen_mode = '2'
1455 else:
1456 test1_addr_gen_mode = '0'
1457
1458 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
1459 self.assertEqual(self.read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
1460
1461 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
1462 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1463
1464 def test_sysctl(self):
1465 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1466 self.start_networkd(0)
1467 self.wait_online(['dummy98:degraded'])
1468
1469 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1470 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1471 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1472 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1473 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1474 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1475 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1476
1477 def test_sysctl_disable_ipv6(self):
1478 self.copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1479
1480 print('## Disable ipv6')
1481 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=1']), 0)
1482 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=1']), 0)
1483
1484 self.start_networkd(0)
1485 self.wait_online(['dummy98:routable'])
1486
1487 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
1488 print(output)
1489 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1490 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
1491 print(output)
1492 self.assertEqual(output, '')
1493 self.check_operstate('dummy98', 'routable')
1494
1495 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1496
1497 print('## Enable ipv6')
1498 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=0']), 0)
1499 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=0']), 0)
1500
1501 self.start_networkd(0)
1502 self.wait_online(['dummy98:routable'])
1503
1504 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
1505 print(output)
1506 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1507 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
1508 print(output)
1509 self.assertRegex(output, 'inet6 .* scope link')
1510 self.check_operstate('dummy98', 'routable')
1511
1512 def test_bind_carrier(self):
1513 self.copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1514 self.start_networkd()
1515
1516 self.check_link_exists('test1')
1517
1518 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1519 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1520 time.sleep(2)
1521 output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
1522 print(output)
1523 self.assertRegex(output, 'UP,LOWER_UP')
1524 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1525 self.check_operstate('test1', 'routable')
1526
1527 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy99', 'type', 'dummy']), 0)
1528 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy99', 'up']), 0)
1529 time.sleep(2)
1530 output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
1531 print(output)
1532 self.assertRegex(output, 'UP,LOWER_UP')
1533 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1534 self.check_operstate('test1', 'routable')
1535
1536 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1537 time.sleep(2)
1538 output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
1539 print(output)
1540 self.assertRegex(output, 'UP,LOWER_UP')
1541 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1542 self.check_operstate('test1', 'routable')
1543
1544 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy99']), 0)
1545 time.sleep(2)
1546 output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
1547 print(output)
1548 self.assertNotRegex(output, 'UP,LOWER_UP')
1549 self.assertRegex(output, 'DOWN')
1550 self.assertNotRegex(output, '192.168.10')
1551 self.check_operstate('test1', 'off')
1552
1553 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1554 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1555 time.sleep(2)
1556 output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
1557 print(output)
1558 self.assertRegex(output, 'UP,LOWER_UP')
1559 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1560 self.check_operstate('test1', 'routable')
1561
1562 def test_domain(self):
1563 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1564 self.start_networkd(0)
1565 self.wait_online(['dummy98:routable'])
1566
1567 output = subprocess.check_output(networkctl_cmd + ['status', 'dummy98'], universal_newlines=True, env=env).rstrip()
1568 print(output)
1569 self.assertRegex(output, 'Address: 192.168.42.100')
1570 self.assertRegex(output, 'DNS: 192.168.42.1')
1571 self.assertRegex(output, 'Search Domains: one')
1572
1573 class NetworkdBondTests(unittest.TestCase, Utilities):
1574 links = [
1575 'bond199',
1576 'bond99',
1577 'dummy98',
1578 'test1']
1579
1580 units = [
1581 '11-dummy.netdev',
1582 '12-dummy.netdev',
1583 '23-active-slave.network',
1584 '23-bond199.network',
1585 '23-primary-slave.network',
1586 '23-test1-bond199.network',
1587 '25-bond-active-backup-slave.netdev',
1588 '25-bond.netdev',
1589 'bond99.network',
1590 'bond-slave.network']
1591
1592 def setUp(self):
1593 self.remove_links(self.links)
1594
1595 def tearDown(self):
1596 self.remove_links(self.links)
1597 self.remove_unit_from_networkd_path(self.units)
1598
1599 def test_bond_active_slave(self):
1600 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
1601 self.start_networkd()
1602
1603 self.check_link_exists('dummy98')
1604 self.check_link_exists('bond199')
1605
1606 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199'], universal_newlines=True).rstrip()
1607 print(output)
1608 self.assertRegex(output, 'active_slave dummy98')
1609
1610 def test_bond_primary_slave(self):
1611 self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
1612 self.start_networkd()
1613
1614 self.check_link_exists('test1')
1615 self.check_link_exists('bond199')
1616
1617 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199'], universal_newlines=True).rstrip()
1618 print(output)
1619 self.assertRegex(output, 'primary test1')
1620
1621 def test_bond_operstate(self):
1622 self.copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
1623 'bond99.network','bond-slave.network')
1624 self.start_networkd()
1625
1626 self.check_link_exists('bond99')
1627 self.check_link_exists('dummy98')
1628 self.check_link_exists('test1')
1629
1630 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
1631 print(output)
1632 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1633
1634 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
1635 print(output)
1636 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1637
1638 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond99'], universal_newlines=True).rstrip()
1639 print(output)
1640 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
1641
1642 self.check_operstate('dummy98', 'enslaved')
1643 self.check_operstate('test1', 'enslaved')
1644 self.check_operstate('bond99', 'routable')
1645
1646 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
1647 time.sleep(2)
1648
1649 self.check_operstate('dummy98', 'off')
1650 self.check_operstate('test1', 'enslaved')
1651 self.check_operstate('bond99', 'degraded-carrier')
1652
1653 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1654 time.sleep(2)
1655
1656 self.check_operstate('dummy98', 'enslaved')
1657 self.check_operstate('test1', 'enslaved')
1658 self.check_operstate('bond99', 'routable')
1659
1660 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
1661 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'test1', 'down']), 0)
1662 time.sleep(2)
1663
1664 self.check_operstate('dummy98', 'off')
1665 self.check_operstate('test1', 'off')
1666
1667 for trial in range(30):
1668 if trial > 0:
1669 time.sleep(1)
1670 output = subprocess.check_output(['ip', 'address', 'show', 'bond99'], universal_newlines=True).rstrip()
1671 print(output)
1672 if self.get_operstate('bond99') == 'no-carrier':
1673 break
1674 else:
1675 # Huh? Kernel does not recognize that all slave interfaces are down?
1676 # Let's confirm that networkd's operstate is consistent with ip's result.
1677 self.assertNotRegex(output, 'NO-CARRIER')
1678
1679 class NetworkdBridgeTests(unittest.TestCase, Utilities):
1680 links = [
1681 'bridge99',
1682 'dummy98',
1683 'test1']
1684
1685 units = [
1686 '11-dummy.netdev',
1687 '12-dummy.netdev',
1688 '26-bridge.netdev',
1689 '26-bridge-slave-interface-1.network',
1690 '26-bridge-slave-interface-2.network',
1691 'bridge99-ignore-carrier-loss.network',
1692 'bridge99.network']
1693
1694 def setUp(self):
1695 self.remove_links(self.links)
1696
1697 def tearDown(self):
1698 self.remove_links(self.links)
1699 self.remove_unit_from_networkd_path(self.units)
1700
1701 def test_bridge_property(self):
1702 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1703 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1704 'bridge99.network')
1705 self.start_networkd()
1706
1707 self.check_link_exists('dummy98')
1708 self.check_link_exists('test1')
1709 self.check_link_exists('bridge99')
1710
1711 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
1712 print(output)
1713 self.assertRegex(output, 'master')
1714 self.assertRegex(output, 'bridge')
1715
1716 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
1717 print(output)
1718 self.assertRegex(output, 'master')
1719 self.assertRegex(output, 'bridge')
1720
1721 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99'], universal_newlines=True).rstrip()
1722 print(output)
1723 self.assertRegex(output, '192.168.0.15/24')
1724
1725 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
1726 print(output)
1727 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
1728 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
1729 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
1730 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0')
1731 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
1732 if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')):
1733 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1')
1734 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0')
1735
1736 # CONFIG_BRIDGE_IGMP_SNOOPING=y
1737 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
1738 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1739
1740 self.check_operstate('test1', 'enslaved')
1741 self.check_operstate('dummy98', 'enslaved')
1742 self.check_operstate('bridge99', 'routable')
1743
1744 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1745 time.sleep(1)
1746
1747 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99'], universal_newlines=True).rstrip()
1748 print(output)
1749 self.assertRegex(output, '192.168.0.16/24')
1750
1751 self.check_operstate('bridge99', 'routable')
1752
1753 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1754 time.sleep(3)
1755
1756 self.check_operstate('bridge99', 'degraded-carrier')
1757
1758 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1759 time.sleep(3)
1760
1761 self.check_operstate('bridge99', 'no-carrier')
1762
1763 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99'], universal_newlines=True).rstrip()
1764 print(output)
1765 self.assertRegex(output, 'NO-CARRIER')
1766 self.assertNotRegex(output, '192.168.0.15/24')
1767 self.assertNotRegex(output, '192.168.0.16/24')
1768
1769 def test_bridge_ignore_carrier_loss(self):
1770 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1771 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1772 'bridge99-ignore-carrier-loss.network')
1773
1774 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1775
1776 self.start_networkd()
1777
1778 self.check_link_exists('dummy98')
1779 self.check_link_exists('test1')
1780 self.check_link_exists('bridge99')
1781
1782 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1783 time.sleep(1)
1784
1785 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1786 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1787 time.sleep(3)
1788
1789 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99'], universal_newlines=True).rstrip()
1790 print(output)
1791 self.assertRegex(output, 'NO-CARRIER')
1792 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1793 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
1794
1795 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1796
1797 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
1798 self.copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
1799 'bridge99-ignore-carrier-loss.network')
1800
1801 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1802
1803 self.start_networkd()
1804
1805 self.check_link_exists('bridge99')
1806
1807 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1808 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1809 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1810
1811 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1812 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1813 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1814
1815 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1816 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1817 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1818
1819 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1820 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1821
1822 for trial in range(30):
1823 if trial > 0:
1824 time.sleep(1)
1825 if self.get_operstate('bridge99') == 'routable' and self.get_operstate('dummy98') == 'enslaved':
1826 break
1827 else:
1828 self.assertTrue(False)
1829
1830 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99'], universal_newlines=True).rstrip()
1831 print(output)
1832 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1833
1834 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '100'], universal_newlines=True).rstrip()
1835 print(output)
1836 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
1837
1838 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1839
1840 class NetworkdLLDPTests(unittest.TestCase, Utilities):
1841 links = ['veth99']
1842
1843 units = [
1844 '23-emit-lldp.network',
1845 '24-lldp.network',
1846 '25-veth.netdev']
1847
1848 def setUp(self):
1849 self.remove_links(self.links)
1850
1851 def tearDown(self):
1852 self.remove_links(self.links)
1853 self.remove_unit_from_networkd_path(self.units)
1854
1855 def test_lldp(self):
1856 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
1857 self.start_networkd(0)
1858 self.wait_online(['veth99:degraded', 'veth-peer:degraded'])
1859
1860 output = subprocess.check_output(networkctl_cmd + ['lldp'], universal_newlines=True, env=env).rstrip()
1861 print(output)
1862 self.assertRegex(output, 'veth-peer')
1863 self.assertRegex(output, 'veth99')
1864
1865 class NetworkdRATests(unittest.TestCase, Utilities):
1866 links = ['veth99']
1867
1868 units = [
1869 '25-veth.netdev',
1870 'ipv6-prefix.network',
1871 'ipv6-prefix-veth.network']
1872
1873 def setUp(self):
1874 self.remove_links(self.links)
1875
1876 def tearDown(self):
1877 self.remove_links(self.links)
1878 self.remove_unit_from_networkd_path(self.units)
1879
1880 def test_ipv6_prefix_delegation(self):
1881 self.warn_about_firewalld()
1882 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1883 self.start_networkd(0)
1884 self.wait_online(['veth99:routable', 'veth-peer:degraded'])
1885
1886 output = subprocess.check_output(networkctl_cmd + ['status', 'veth99'], universal_newlines=True, env=env).rstrip()
1887 print(output)
1888 self.assertRegex(output, '2002:da8:1:0')
1889
1890 class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
1891 links = ['veth99']
1892
1893 units = [
1894 '25-veth.netdev',
1895 'dhcp-client.network',
1896 'dhcp-client-timezone-router.network',
1897 'dhcp-server.network',
1898 'dhcp-server-timezone-router.network']
1899
1900 def setUp(self):
1901 self.remove_links(self.links)
1902
1903 def tearDown(self):
1904 self.remove_links(self.links)
1905 self.remove_unit_from_networkd_path(self.units)
1906
1907 def test_dhcp_server(self):
1908 self.warn_about_firewalld()
1909 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
1910 self.start_networkd(0)
1911 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1912
1913 output = subprocess.check_output(networkctl_cmd + ['status', 'veth99'], universal_newlines=True, env=env).rstrip()
1914 print(output)
1915 self.assertRegex(output, '192.168.5.*')
1916 self.assertRegex(output, 'Gateway: 192.168.5.1')
1917 self.assertRegex(output, 'DNS: 192.168.5.1')
1918 self.assertRegex(output, 'NTP: 192.168.5.1')
1919
1920 def test_emit_router_timezone(self):
1921 self.warn_about_firewalld()
1922 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
1923 self.start_networkd(0)
1924 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1925
1926 output = subprocess.check_output(networkctl_cmd + ['status', 'veth99'], universal_newlines=True, env=env).rstrip()
1927 print(output)
1928 self.assertRegex(output, 'Gateway: 192.168.5.*')
1929 self.assertRegex(output, '192.168.5.*')
1930 self.assertRegex(output, 'Europe/Berlin')
1931
1932 class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
1933 links = [
1934 'veth99',
1935 'vrf99']
1936
1937 units = [
1938 '25-veth.netdev',
1939 '25-vrf.netdev',
1940 '25-vrf.network',
1941 'dhcp-client-anonymize.network',
1942 'dhcp-client-critical-connection.network',
1943 'dhcp-client-gateway-onlink-implicit.network',
1944 'dhcp-client-ipv4-dhcp-settings.network',
1945 'dhcp-client-ipv4-only-ipv6-disabled.network',
1946 'dhcp-client-ipv4-only.network',
1947 'dhcp-client-ipv6-only.network',
1948 'dhcp-client-ipv6-rapid-commit.network',
1949 'dhcp-client-listen-port.network',
1950 'dhcp-client-route-metric.network',
1951 'dhcp-client-route-table.network',
1952 'dhcp-client-vrf.network',
1953 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network',
1954 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network',
1955 'dhcp-client.network',
1956 'dhcp-server-veth-peer.network',
1957 'dhcp-v4-server-veth-peer.network',
1958 'static.network']
1959
1960 def setUp(self):
1961 self.stop_dnsmasq(dnsmasq_pid_file)
1962 self.remove_links(self.links)
1963
1964 def tearDown(self):
1965 self.stop_dnsmasq(dnsmasq_pid_file)
1966 self.remove_lease_file()
1967 self.remove_log_file()
1968 self.remove_links(self.links)
1969 self.remove_unit_from_networkd_path(self.units)
1970
1971 def test_dhcp_client_ipv6_only(self):
1972 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1973
1974 self.start_networkd(0)
1975 self.wait_online(['veth-peer:carrier'])
1976 self.start_dnsmasq()
1977 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1978
1979 output = subprocess.check_output(networkctl_cmd + ['status', 'veth99'], universal_newlines=True, env=env).rstrip()
1980 print(output)
1981 self.assertRegex(output, '2600::')
1982 self.assertNotRegex(output, '192.168.5')
1983
1984 # Confirm that ipv6 token is not set in the kernel
1985 output = subprocess.check_output(['ip', 'token', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
1986 print(output)
1987 self.assertRegex(output, 'token :: dev veth99')
1988
1989 def test_dhcp_client_ipv4_only(self):
1990 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1991
1992 self.start_networkd(0)
1993 self.wait_online(['veth-peer:carrier'])
1994 self.start_dnsmasq()
1995 self.wait_online(['veth99:routable', 'veth-peer:routable'])
1996
1997 output = subprocess.check_output(networkctl_cmd + ['status', 'veth99'], universal_newlines=True, env=env).rstrip()
1998 print(output)
1999 self.assertNotRegex(output, '2600::')
2000 self.assertRegex(output, '192.168.5')
2001
2002 def test_dhcp_client_ipv4_ipv6(self):
2003 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
2004 'dhcp-client-ipv4-only.network')
2005 self.start_networkd(0)
2006 self.wait_online(['veth-peer:carrier'])
2007 self.start_dnsmasq()
2008 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2009
2010 # link become 'routable' when at least one protocol provide an valid address.
2011 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255', ipv='-4')
2012 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128', ipv='-6')
2013
2014 output = subprocess.check_output(networkctl_cmd + ['status', 'veth99'], universal_newlines=True, env=env).rstrip()
2015 print(output)
2016 self.assertRegex(output, '2600::')
2017 self.assertRegex(output, '192.168.5')
2018
2019 def test_dhcp_client_settings(self):
2020 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
2021
2022 self.start_networkd(0)
2023 self.wait_online(['veth-peer:carrier'])
2024 self.start_dnsmasq()
2025 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2026
2027 print('## ip address show dev veth99')
2028 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2029 print(output)
2030 self.assertRegex(output, '12:34:56:78:9a:bc')
2031 self.assertRegex(output, '192.168.5')
2032 self.assertRegex(output, '1492')
2033
2034 # issue #8726
2035 print('## ip route show table main dev veth99')
2036 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99'], universal_newlines=True).rstrip()
2037 print(output)
2038 self.assertNotRegex(output, 'proto dhcp')
2039
2040 print('## ip route show table 211 dev veth99')
2041 output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99'], universal_newlines=True).rstrip()
2042 print(output)
2043 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
2044 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
2045 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
2046
2047 print('## dnsmasq log')
2048 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
2049 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
2050 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
2051 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
2052
2053 def test_dhcp6_client_settings_rapidcommit_true(self):
2054 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
2055 self.start_networkd(0)
2056 self.wait_online(['veth-peer:carrier'])
2057 self.start_dnsmasq()
2058 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2059
2060 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2061 print(output)
2062 self.assertRegex(output, '12:34:56:78:9a:bc')
2063 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
2064
2065 def test_dhcp6_client_settings_rapidcommit_false(self):
2066 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
2067 self.start_networkd(0)
2068 self.wait_online(['veth-peer:carrier'])
2069 self.start_dnsmasq()
2070 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2071
2072 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2073 print(output)
2074 self.assertRegex(output, '12:34:56:78:9a:bc')
2075 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
2076
2077 def test_dhcp_client_settings_anonymize(self):
2078 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
2079 self.start_networkd(0)
2080 self.wait_online(['veth-peer:carrier'])
2081 self.start_dnsmasq()
2082 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2083
2084 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
2085 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
2086 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
2087
2088 def test_dhcp_client_listen_port(self):
2089 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
2090 self.start_networkd(0)
2091 self.wait_online(['veth-peer:carrier'])
2092 self.start_dnsmasq('--dhcp-alternate-port=67,5555')
2093 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2094
2095 # link become 'routable' when at least one protocol provide an valid address.
2096 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255', ipv='-4')
2097 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128', ipv='-6')
2098
2099 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2100 print(output)
2101 self.assertRegex(output, '192.168.5.* dynamic')
2102
2103 def test_dhcp_route_table_id(self):
2104 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
2105 self.start_networkd(0)
2106 self.wait_online(['veth-peer:carrier'])
2107 self.start_dnsmasq()
2108 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2109
2110 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12'], universal_newlines=True).rstrip()
2111 print(output)
2112 self.assertRegex(output, 'veth99 proto dhcp')
2113 self.assertRegex(output, '192.168.5.1')
2114
2115 def test_dhcp_route_metric(self):
2116 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
2117 self.start_networkd(0)
2118 self.wait_online(['veth-peer:carrier'])
2119 self.start_dnsmasq()
2120 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2121
2122 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2123 print(output)
2124 self.assertRegex(output, 'metric 24')
2125
2126 def test_dhcp_route_criticalconnection_true(self):
2127 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
2128 self.start_networkd(0)
2129 self.wait_online(['veth-peer:carrier'])
2130 self.start_dnsmasq()
2131 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2132
2133 output = subprocess.check_output(networkctl_cmd + ['status', 'veth99'], universal_newlines=True, env=env).rstrip()
2134 print(output)
2135 self.assertRegex(output, '192.168.5.*')
2136
2137 # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease.
2138 self.stop_dnsmasq(dnsmasq_pid_file)
2139
2140 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
2141 time.sleep(125)
2142
2143 output = subprocess.check_output(networkctl_cmd + ['status', 'veth99'], universal_newlines=True, env=env).rstrip()
2144 print(output)
2145 self.assertRegex(output, '192.168.5.*')
2146
2147 def test_dhcp_client_reuse_address_as_static(self):
2148 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
2149 self.start_networkd(0)
2150 self.wait_online(['veth-peer:carrier'])
2151 self.start_dnsmasq()
2152 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2153
2154 # link become 'routable' when at least one protocol provide an valid address.
2155 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255', ipv='-4')
2156 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128', ipv='-6')
2157
2158 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global'], universal_newlines=True).rstrip()
2159 print(output)
2160 self.assertRegex(output, '192.168.5')
2161 self.assertRegex(output, '2600::')
2162
2163 ipv4_address = re.search(r'192.168.5.[0-9]*/24', output)
2164 ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output)
2165 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
2166 print(static_network)
2167
2168 self.remove_unit_from_networkd_path(['dhcp-client.network'])
2169
2170 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
2171 f.write(static_network)
2172
2173 # When networkd started, the links are already configured, so let's wait for 5 seconds
2174 # the links to be re-configured.
2175 self.start_networkd(5)
2176 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2177
2178 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global'], universal_newlines=True).rstrip()
2179 print(output)
2180 self.assertRegex(output, '192.168.5')
2181 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2182
2183 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global'], universal_newlines=True).rstrip()
2184 print(output)
2185 self.assertRegex(output, '2600::')
2186 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
2187
2188 @expectedFailureIfModuleIsNotAvailable('vrf')
2189 def test_dhcp_client_vrf(self):
2190 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
2191 '25-vrf.netdev', '25-vrf.network')
2192 self.start_networkd(0)
2193 self.wait_online(['veth-peer:carrier'])
2194 self.start_dnsmasq()
2195 self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier'])
2196
2197 # link become 'routable' when at least one protocol provide an valid address.
2198 self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255', ipv='-4')
2199 self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128', ipv='-6')
2200
2201 print('## ip -d link show dev vrf99')
2202 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99'], universal_newlines=True).rstrip()
2203 print(output)
2204 self.assertRegex(output, 'vrf table 42')
2205
2206 print('## ip address show vrf vrf99')
2207 output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99'], universal_newlines=True).rstrip()
2208 print(output_ip_vrf)
2209
2210 print('## ip address show dev veth99')
2211 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2212 print(output)
2213 self.assertEqual(output, output_ip_vrf)
2214 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
2215 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2216 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic noprefixroute')
2217 self.assertRegex(output, 'inet6 .* scope link')
2218
2219 print('## ip route show vrf vrf99')
2220 output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99'], universal_newlines=True).rstrip()
2221 print(output)
2222 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
2223 self.assertRegex(output, 'default dev veth99 proto static scope link')
2224 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
2225 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
2226 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
2227 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
2228
2229 print('## ip route show table main dev veth99')
2230 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99'], universal_newlines=True).rstrip()
2231 print(output)
2232 self.assertEqual(output, '')
2233
2234 self.check_operstate('vrf99', 'carrier')
2235 self.check_operstate('veth99', 'routable')
2236
2237 def test_dhcp_client_gateway_onlink_implicit(self):
2238 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2239 'dhcp-client-gateway-onlink-implicit.network')
2240 self.start_networkd(0)
2241 self.wait_online(['veth-peer:carrier'])
2242 self.start_dnsmasq()
2243 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2244
2245 output = subprocess.check_output(networkctl_cmd + ['status', 'veth99'], universal_newlines=True, env=env).rstrip()
2246 print(output)
2247 self.assertRegex(output, '192.168.5')
2248
2249 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '10.0.0.0/8'], universal_newlines=True).rstrip()
2250 print(output)
2251 self.assertRegex(output, 'onlink')
2252 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '192.168.100.0/24'], universal_newlines=True).rstrip()
2253 print(output)
2254 self.assertRegex(output, 'onlink')
2255
2256 def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self):
2257 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2258 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network')
2259 self.start_networkd(0)
2260 self.wait_online(['veth-peer:carrier'])
2261 self.start_dnsmasq(lease_time='2m')
2262 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2263
2264 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2265 print(output)
2266
2267 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
2268 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
2269 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
2270 self.assertRegex(output, 'inet6 .* scope link')
2271 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
2272 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2273 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
2274 self.assertNotRegex(output, 'inet .* scope link')
2275
2276 print('Wait for the dynamic address to be expired')
2277 time.sleep(130)
2278
2279 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2280 print(output)
2281
2282 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
2283 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
2284 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
2285 self.assertRegex(output, 'inet6 .* scope link')
2286 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
2287 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2288 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
2289 self.assertNotRegex(output, 'inet .* scope link')
2290
2291 self.search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
2292
2293 def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self):
2294 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2295 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network')
2296 self.start_networkd(0)
2297 self.wait_online(['veth99:degraded', 'veth-peer:routable'])
2298
2299 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2300 print(output)
2301
2302 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
2303 self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
2304 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
2305 self.assertRegex(output, 'inet6 .* scope link')
2306 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
2307 self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2308 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
2309 self.assertRegex(output, 'inet .* scope link')
2310
2311 def test_dhcp_client_route_remove_on_renew(self):
2312 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
2313 'dhcp-client-ipv4-only-ipv6-disabled.network')
2314 self.start_networkd(0)
2315 self.wait_online(['veth-peer:carrier'])
2316 self.start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m')
2317 self.wait_online(['veth99:routable', 'veth-peer:routable'])
2318
2319 # test for issue #12490
2320
2321 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
2322 print(output)
2323 self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2324 address1=None
2325 for line in output.splitlines():
2326 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
2327 address1 = line.split()[1].split('/')[0]
2328 break
2329
2330 output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2331 print(output)
2332 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
2333 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
2334
2335 self.stop_dnsmasq(dnsmasq_pid_file)
2336 self.start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m')
2337
2338 print('Wait for the dynamic address to be expired')
2339 time.sleep(130)
2340
2341 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
2342 print(output)
2343 self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
2344 address2=None
2345 for line in output.splitlines():
2346 if 'brd 192.168.5.255 scope global dynamic veth99' in line:
2347 address2 = line.split()[1].split('/')[0]
2348 break
2349
2350 self.assertNotEqual(address1, address2)
2351
2352 output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
2353 print(output)
2354 self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024')
2355 self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024')
2356 self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024')
2357 self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024')
2358
2359 if __name__ == '__main__':
2360 parser = argparse.ArgumentParser()
2361 parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir')
2362 parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin')
2363 parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin')
2364 parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin')
2365 parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind)
2366 parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug)
2367 parser.add_argument('--asan-options', help='ASAN options', dest='asan_options')
2368 parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options')
2369 parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options')
2370 ns, args = parser.parse_known_args(namespace=unittest)
2371
2372 if ns.build_dir:
2373 if ns.networkd_bin or ns.wait_online_bin or ns.networkctl_bin:
2374 print('WARNING: --networkd, --wait-online, or --networkctl options are ignored when --build-dir is specified.')
2375 networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd')
2376 wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online')
2377 networkctl_bin = os.path.join(ns.build_dir, 'networkctl')
2378 else:
2379 if ns.networkd_bin:
2380 networkd_bin = ns.networkd_bin
2381 if ns.wait_online_bin:
2382 wait_online_bin = ns.wait_online_bin
2383 if ns.networkctl_bin:
2384 networkctl_bin = ns.networkctl_bin
2385
2386 use_valgrind = ns.use_valgrind
2387 enable_debug = ns.enable_debug
2388 asan_options = ns.asan_options
2389 lsan_options = ns.lsan_options
2390 ubsan_options = ns.ubsan_options
2391
2392 if use_valgrind:
2393 networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin]
2394 wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin]
2395 else:
2396 networkctl_cmd = [networkctl_bin]
2397 wait_online_cmd = [wait_online_bin]
2398
2399 if enable_debug:
2400 env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' })
2401 if asan_options:
2402 env.update({ 'ASAN_OPTIONS' : asan_options })
2403 if lsan_options:
2404 env.update({ 'LSAN_OPTIONS' : lsan_options })
2405 if ubsan_options:
2406 env.update({ 'UBSAN_OPTIONS' : ubsan_options })
2407
2408 sys.argv[1:] = args
2409 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
2410 verbosity=3))