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