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