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