]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
test-network: increase sleep time in test_bind_carrier()
[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 dhcp_server_data = []
90
91 def read_link_attr(self, link, dev, attribute):
92 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
93 return f.readline().strip()
94
95 def read_bridge_port_attr(self, bridge, link, attribute):
96
97 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
98 path_port = 'lower_' + link + '/brport'
99 path = os.path.join(path_bridge, path_port)
100
101 with open(os.path.join(path, attribute)) as f:
102 return f.readline().strip()
103
104 def link_exits(self, link):
105 return os.path.exists(os.path.join('/sys/class/net', link))
106
107 def link_remove(self, links):
108 for link in links:
109 if os.path.exists(os.path.join('/sys/class/net', link)):
110 subprocess.call(['ip', 'link', 'del', 'dev', link])
111 time.sleep(1)
112
113 def read_ipv6_sysctl_attr(self, link, attribute):
114 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
115 return f.readline().strip()
116
117 def read_ipv4_sysctl_attr(self, link, attribute):
118 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
119 return f.readline().strip()
120
121 def copy_unit_to_networkd_unit_path(self, *units):
122 for unit in units:
123 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
124 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
125 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
126
127 def remove_unit_from_networkd_path(self, units):
128 for unit in units:
129 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
130 os.remove(os.path.join(network_unit_file_path, unit))
131 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
132 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
133
134 def start_dnsmasq(self, additional_options=''):
135 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
136 subprocess.check_call(dnsmasq_command, shell=True)
137
138 time.sleep(10)
139
140 def stop_dnsmasq(self, pid_file):
141 if os.path.exists(pid_file):
142 with open(pid_file, 'r') as f:
143 pid = f.read().rstrip(' \t\r\n\0')
144 os.kill(int(pid), signal.SIGTERM)
145
146 os.remove(pid_file)
147
148 def search_words_in_dnsmasq_log(self, words, show_all=False):
149 if os.path.exists(dnsmasq_log_file):
150 with open (dnsmasq_log_file) as in_file:
151 contents = in_file.read()
152 if show_all:
153 print(contents)
154 for line in contents.split('\n'):
155 if words in line:
156 in_file.close()
157 print("%s, %s" % (words, line))
158 return True
159 return False
160
161 def remove_lease_file(self):
162 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
163 os.remove(os.path.join(networkd_ci_path, 'lease'))
164
165 def remove_log_file(self):
166 if os.path.exists(dnsmasq_log_file):
167 os.remove(dnsmasq_log_file)
168
169 def start_networkd(self):
170 if (os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
171 subprocess.check_call('systemctl stop systemd-networkd', shell=True)
172 os.remove(os.path.join(networkd_runtime_directory, 'state'))
173 subprocess.check_call('systemctl start systemd-networkd', shell=True)
174 else:
175 subprocess.check_call('systemctl restart systemd-networkd', shell=True)
176 time.sleep(5)
177 print()
178
179 class NetworkdNetDevTests(unittest.TestCase, Utilities):
180
181 links =[
182 '6rdtun99',
183 'bond99',
184 'bridge99',
185 'dropin-test',
186 'dummy98',
187 'erspan-test',
188 'geneve99',
189 'gretap99',
190 'gretun99',
191 'ip6gretap99',
192 'ip6tnl99',
193 'ipiptun99',
194 'ipvlan99',
195 'isataptun99',
196 'macvlan99',
197 'macvtap99',
198 'sittun99',
199 'tap99',
200 'test1',
201 'tun99',
202 'vcan99',
203 'veth99',
204 'vlan99',
205 'vrf99',
206 'vti6tun99',
207 'vtitun99',
208 'vxlan99',
209 'wg98',
210 'wg99']
211
212 units = [
213 '10-dropin-test.netdev',
214 '11-dummy.netdev',
215 '12-dummy.netdev',
216 '21-macvlan.netdev',
217 '21-macvtap.netdev',
218 '21-vlan.netdev',
219 '21-vlan.network',
220 '25-6rd-tunnel.netdev',
221 '25-bond.netdev',
222 '25-bond-balanced-tlb.netdev',
223 '25-bridge.netdev',
224 '25-erspan-tunnel.netdev',
225 '25-geneve.netdev',
226 '25-gretap-tunnel.netdev',
227 '25-gre-tunnel.netdev',
228 '25-ip6gre-tunnel.netdev',
229 '25-ip6tnl-tunnel.netdev',
230 '25-ipip-tunnel-independent.netdev',
231 '25-ipip-tunnel.netdev',
232 '25-ipvlan.netdev',
233 '25-isatap-tunnel.netdev',
234 '25-sit-tunnel.netdev',
235 '25-tap.netdev',
236 '25-tun.netdev',
237 '25-vcan.netdev',
238 '25-veth.netdev',
239 '25-vrf.netdev',
240 '25-vti6-tunnel.netdev',
241 '25-vti-tunnel.netdev',
242 '25-vxlan.netdev',
243 '25-wireguard-23-peers.netdev',
244 '25-wireguard-23-peers.network',
245 '25-wireguard.netdev',
246 '6rd.network',
247 'gre.network',
248 'gretap.network',
249 'gretun.network',
250 'ip6gretap.network',
251 'ip6tnl.network',
252 'ipip.network',
253 'ipvlan.network',
254 'isatap.network',
255 'macvlan.network',
256 'macvtap.network',
257 'sit.network',
258 'vti6.network',
259 'vti.network',
260 'vxlan.network']
261
262 def setUp(self):
263 self.link_remove(self.links)
264
265 def tearDown(self):
266 self.link_remove(self.links)
267 self.remove_unit_from_networkd_path(self.units)
268
269 def test_dropin(self):
270 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
271 self.start_networkd()
272
273 self.assertTrue(self.link_exits('dropin-test'))
274
275 output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
276 print(output)
277 self.assertRegex(output, '00:50:56:c0:00:28')
278
279 output = subprocess.check_output(['networkctl', 'list']).rstrip().decode('utf-8')
280 self.assertRegex(output, '1 lo ')
281 self.assertRegex(output, 'dropin-test')
282
283 output = subprocess.check_output(['networkctl', 'list', 'dropin-test']).rstrip().decode('utf-8')
284 self.assertNotRegex(output, '1 lo ')
285 self.assertRegex(output, 'dropin-test')
286
287 output = subprocess.check_output(['networkctl', 'list', 'dropin-*']).rstrip().decode('utf-8')
288 self.assertNotRegex(output, '1 lo ')
289 self.assertRegex(output, 'dropin-test')
290
291 def test_bridge(self):
292 self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
293 self.start_networkd()
294
295 self.assertTrue(self.link_exits('bridge99'))
296
297 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'hello_time'))
298 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'max_age'))
299 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','forward_delay'))
300 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','ageing_time'))
301 self.assertEqual('9', self.read_link_attr('bridge99', 'bridge','priority'))
302 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_querier'))
303 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_snooping'))
304 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','stp_state'))
305
306 def test_bond(self):
307 self.copy_unit_to_networkd_unit_path('25-bond.netdev')
308 self.start_networkd()
309
310 self.assertTrue(self.link_exits('bond99'))
311
312 self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode'))
313 self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
314 self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon'))
315 self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate'))
316 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay'))
317 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay'))
318 self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp'))
319 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links'))
320 self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
321 self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
322 self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
323
324 def test_bond_balanced_tlb(self):
325 self.copy_unit_to_networkd_unit_path('25-bond-balanced-tlb.netdev')
326 self.start_networkd()
327
328 self.assertTrue(self.link_exits('bond99'))
329
330 self.assertEqual('balance-tlb 5', self.read_link_attr('bond99', 'bonding', 'mode'))
331 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
332
333 def test_vlan(self):
334 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
335 self.start_networkd()
336
337 self.assertTrue(self.link_exits('vlan99'))
338
339 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
340 print(output)
341 self.assertTrue(output, 'REORDER_HDR')
342 self.assertTrue(output, 'LOOSE_BINDING')
343 self.assertTrue(output, 'GVRP')
344 self.assertTrue(output, 'MVRP')
345 self.assertTrue(output, '99')
346
347 def test_macvtap(self):
348 self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
349 self.start_networkd()
350
351 self.assertTrue(self.link_exits('macvtap99'))
352
353 def test_macvlan(self):
354 self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
355 self.start_networkd()
356
357 self.assertTrue(self.link_exits('macvlan99'))
358
359 @expectedFailureIfModuleIsNotAvailable('ipvlan')
360 def test_ipvlan(self):
361 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
362 self.start_networkd()
363
364 self.assertTrue(self.link_exits('ipvlan99'))
365
366 def test_veth(self):
367 self.copy_unit_to_networkd_unit_path('25-veth.netdev')
368 self.start_networkd()
369
370 self.assertTrue(self.link_exits('veth99'))
371
372 def test_dummy(self):
373 self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
374 self.start_networkd()
375
376 self.assertTrue(self.link_exits('test1'))
377
378 def test_tun(self):
379 self.copy_unit_to_networkd_unit_path('25-tun.netdev')
380 self.start_networkd()
381
382 self.assertTrue(self.link_exits('tun99'))
383
384 def test_tap(self):
385 self.copy_unit_to_networkd_unit_path('25-tap.netdev')
386 self.start_networkd()
387
388 self.assertTrue(self.link_exits('tap99'))
389
390 @expectedFailureIfModuleIsNotAvailable('vrf')
391 def test_vrf(self):
392 self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
393 self.start_networkd()
394
395 self.assertTrue(self.link_exits('vrf99'))
396
397 @expectedFailureIfModuleIsNotAvailable('vcan')
398 def test_vcan(self):
399 self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
400 self.start_networkd()
401
402 self.assertTrue(self.link_exits('vcan99'))
403
404 @expectedFailureIfModuleIsNotAvailable('wireguard')
405 def test_wireguard(self):
406 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
407 self.start_networkd()
408
409 if shutil.which('wg'):
410 subprocess.call('wg')
411 output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
412 self.assertTrue(output, '51820')
413 output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
414 self.assertTrue(output, '0x4d2')
415 output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
416 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
417 output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
418 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20')
419 output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
420 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820')
421
422 self.assertTrue(self.link_exits('wg99'))
423
424 @expectedFailureIfModuleIsNotAvailable('wireguard')
425 def test_wireguard_23_peers(self):
426 self.copy_unit_to_networkd_unit_path('25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network')
427 self.start_networkd()
428
429 if shutil.which('wg'):
430 subprocess.call('wg')
431
432 self.assertTrue(self.link_exits('wg98'))
433
434 def test_geneve(self):
435 self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
436 self.start_networkd()
437
438 self.assertTrue(self.link_exits('geneve99'))
439
440 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
441 print(output)
442 self.assertTrue(output, '192.168.22.1')
443 self.assertTrue(output, '6082')
444 self.assertTrue(output, 'udpcsum')
445 self.assertTrue(output, 'udp6zerocsumrx')
446
447 def test_ipip_tunnel(self):
448 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network')
449 self.start_networkd()
450
451 self.assertTrue(self.link_exits('dummy98'))
452 self.assertTrue(self.link_exits('ipiptun99'))
453
454 def test_gre_tunnel(self):
455 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network')
456 self.start_networkd()
457
458 self.assertTrue(self.link_exits('dummy98'))
459 self.assertTrue(self.link_exits('gretun99'))
460
461 def test_gretap_tunnel(self):
462 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network')
463 self.start_networkd()
464
465 self.assertTrue(self.link_exits('dummy98'))
466 self.assertTrue(self.link_exits('gretap99'))
467
468 def test_ip6gretap_tunnel(self):
469 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretap.network')
470 self.start_networkd()
471
472 self.assertTrue(self.link_exits('dummy98'))
473 self.assertTrue(self.link_exits('ip6gretap99'))
474
475 def test_vti_tunnel(self):
476 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network')
477 self.start_networkd()
478
479 self.assertTrue(self.link_exits('dummy98'))
480 self.assertTrue(self.link_exits('vtitun99'))
481
482 def test_vti6_tunnel(self):
483 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network')
484 self.start_networkd()
485
486 self.assertTrue(self.link_exits('dummy98'))
487 self.assertTrue(self.link_exits('vti6tun99'))
488
489 def test_ip6tnl_tunnel(self):
490 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network')
491 self.start_networkd()
492
493 self.assertTrue(self.link_exits('dummy98'))
494 self.assertTrue(self.link_exits('ip6tnl99'))
495
496 def test_sit_tunnel(self):
497 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network')
498 self.start_networkd()
499
500 self.assertTrue(self.link_exits('dummy98'))
501 self.assertTrue(self.link_exits('sittun99'))
502
503 def test_isatap_tunnel(self):
504 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
505 self.start_networkd()
506
507 self.assertTrue(self.link_exits('dummy98'))
508 self.assertTrue(self.link_exits('isataptun99'))
509
510 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
511 print(output)
512 self.assertRegex(output, "isatap ")
513
514 def test_6rd_tunnel(self):
515 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
516 self.start_networkd()
517
518 self.assertTrue(self.link_exits('dummy98'))
519 self.assertTrue(self.link_exits('sittun99'))
520
521 @expectedFailureIfERSPANModuleIsNotAvailable()
522 def test_erspan_tunnel(self):
523 self.copy_unit_to_networkd_unit_path('25-erspan-tunnel.netdev')
524 self.start_networkd()
525
526 self.assertTrue(self.link_exits('erspan-test'))
527
528 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan-test']).rstrip().decode('utf-8')
529 print(output)
530 self.assertTrue(output, '172.16.1.200')
531 self.assertTrue(output, '172.16.1.100')
532 self.assertTrue(output, '101')
533
534 def test_tunnel_independent(self):
535 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
536 self.start_networkd()
537
538 self.assertTrue(self.link_exits('ipiptun99'))
539
540 def test_vxlan(self):
541 self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network','11-dummy.netdev')
542 self.start_networkd()
543
544 self.assertTrue(self.link_exits('vxlan99'))
545
546 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
547 print(output)
548 self.assertRegex(output, "999")
549 self.assertRegex(output, '5555')
550 self.assertRegex(output, 'l2miss')
551 self.assertRegex(output, 'l3miss')
552 self.assertRegex(output, 'udpcsum')
553 self.assertRegex(output, 'udp6zerocsumtx')
554 self.assertRegex(output, 'udp6zerocsumrx')
555 self.assertRegex(output, 'remcsumtx')
556 self.assertRegex(output, 'remcsumrx')
557 self.assertRegex(output, 'gbp')
558
559 class NetworkdNetWorkTests(unittest.TestCase, Utilities):
560 links = [
561 'bond199',
562 'dummy98',
563 'dummy99',
564 'test1']
565
566 units = [
567 '11-dummy.netdev',
568 '12-dummy.netdev',
569 '23-active-slave.network',
570 '23-bond199.network',
571 '23-primary-slave.network',
572 '23-test1-bond199.network',
573 '25-address-link-section.network',
574 '25-address-section-miscellaneous.network',
575 '25-address-section.network',
576 '25-bind-carrier.network',
577 '25-bond-active-backup-slave.netdev',
578 '25-fibrule-invert.network',
579 '25-fibrule-port-range.network',
580 '25-ipv6-address-label-section.network',
581 '25-neighbor-section.network',
582 '25-link-local-addressing-no.network',
583 '25-link-local-addressing-yes.network',
584 '25-link-section-unmanaged.network',
585 '25-route-gateway.network',
586 '25-route-gateway-on-link.network',
587 '25-route-ipv6-src.network',
588 '25-route-reverse-order.network',
589 '25-route-section.network',
590 '25-route-tcp-window-settings.network',
591 '25-route-type.network',
592 '25-sysctl.network',
593 'configure-without-carrier.network',
594 'routing-policy-rule.network',
595 'test-static.network']
596
597 def setUp(self):
598 self.link_remove(self.links)
599
600 def tearDown(self):
601 self.link_remove(self.links)
602 self.remove_unit_from_networkd_path(self.units)
603
604 def test_static_address(self):
605 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'test-static.network')
606 self.start_networkd()
607
608 self.assertTrue(self.link_exits('dummy98'))
609
610 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
611 print(output)
612 self.assertRegex(output, '192.168.0.15')
613 self.assertRegex(output, '192.168.0.1')
614 self.assertRegex(output, 'routable')
615
616 def test_configure_without_carrier(self):
617 self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
618 self.start_networkd()
619
620 self.assertTrue(self.link_exits('test1'))
621
622 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
623 print(output)
624 self.assertRegex(output, '192.168.0.15')
625 self.assertRegex(output, '192.168.0.1')
626 self.assertRegex(output, 'routable')
627
628 def test_bond_active_slave(self):
629 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
630 self.start_networkd()
631
632 self.assertTrue(self.link_exits('dummy98'))
633 self.assertTrue(self.link_exits('bond199'))
634
635 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
636 print(output)
637 self.assertRegex(output, 'active_slave dummy98')
638
639 def test_bond_primary_slave(self):
640 self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
641 self.start_networkd()
642
643 self.assertTrue(self.link_exits('test1'))
644 self.assertTrue(self.link_exits('bond199'))
645
646 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
647 print(output)
648 self.assertRegex(output, 'primary test1')
649
650 def test_routing_policy_rule(self):
651 self.copy_unit_to_networkd_unit_path('routing-policy-rule.network', '11-dummy.netdev')
652 self.start_networkd()
653
654 self.assertTrue(self.link_exits('test1'))
655
656 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
657 print(output)
658 self.assertRegex(output, '111')
659 self.assertRegex(output, 'from 192.168.100.18')
660 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
661 self.assertRegex(output, 'iif test1')
662 self.assertRegex(output, 'oif test1')
663 self.assertRegex(output, 'lookup 7')
664
665 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
666
667 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
668 def test_routing_policy_rule_port_range(self):
669 self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
670 self.start_networkd()
671
672 self.assertTrue(self.link_exits('test1'))
673
674 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
675 print(output)
676 self.assertRegex(output, '111')
677 self.assertRegex(output, 'from 192.168.100.18')
678 self.assertRegex(output, '1123-1150')
679 self.assertRegex(output, '3224-3290')
680 self.assertRegex(output, 'tcp')
681 self.assertRegex(output, 'lookup 7')
682
683 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
684
685 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
686 def test_routing_policy_rule_invert(self):
687 self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
688 self.start_networkd()
689
690 self.assertTrue(self.link_exits('test1'))
691
692 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
693 print(output)
694 self.assertRegex(output, '111')
695 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
696 self.assertRegex(output, 'tcp')
697 self.assertRegex(output, 'lookup 7')
698
699 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
700
701 def test_address_peer(self):
702 self.copy_unit_to_networkd_unit_path('25-address-section.network', '12-dummy.netdev')
703 self.start_networkd()
704
705 self.assertTrue(self.link_exits('dummy98'))
706
707 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
708 print(output)
709 self.assertRegex(output, 'inet 10.2.3.4 peer 10.2.3.5/16 scope global 32')
710 self.assertRegex(output, 'inet 10.6.7.8/16 brd 10.6.255.255 scope global 33')
711 self.assertRegex(output, 'inet6 2001:db8::20 peer 2001:db8::10/128 scope global')
712
713 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
714 print(output)
715 self.assertRegex(output, 'State: routable \(configured\)')
716
717 def test_address_preferred_lifetime_zero_ipv6(self):
718 self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev')
719 self.start_networkd()
720
721 self.assertTrue(self.link_exits('dummy98'))
722
723 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
724 print(output)
725 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
726 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
727
728 def test_ip_route(self):
729 self.copy_unit_to_networkd_unit_path('25-route-section.network', '12-dummy.netdev')
730 self.start_networkd()
731
732 self.assertTrue(self.link_exits('dummy98'))
733
734 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98']).rstrip().decode('utf-8')
735 print(output)
736 self.assertRegex(output, '192.168.0.1')
737 self.assertRegex(output, 'static')
738 self.assertRegex(output, '192.168.0.0/24')
739
740 def test_ip_route_reverse(self):
741 self.copy_unit_to_networkd_unit_path('25-route-reverse-order.network', '12-dummy.netdev')
742 self.start_networkd()
743
744 self.assertTrue(self.link_exits('dummy98'))
745
746 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
747 print(output)
748 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff')
749 self.assertRegex(output, '2001:1234:5:8f63::1')
750
751 def test_ip_route_blackhole_unreachable_prohibit(self):
752 self.copy_unit_to_networkd_unit_path('25-route-type.network', '12-dummy.netdev')
753 self.start_networkd()
754
755 self.assertTrue(self.link_exits('dummy98'))
756
757 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
758 print(output)
759 self.assertRegex(output, 'blackhole')
760 self.assertRegex(output, 'unreachable')
761 self.assertRegex(output, 'prohibit')
762
763 subprocess.call(['ip', 'route', 'del', 'blackhole', '202.54.1.2'])
764 subprocess.call(['ip', 'route', 'del', 'unreachable', '202.54.1.3'])
765 subprocess.call(['ip', 'route', 'del', 'prohibit', '202.54.1.4'])
766
767 def test_ip_route_tcp_window(self):
768 self.copy_unit_to_networkd_unit_path('25-route-tcp-window-settings.network', '11-dummy.netdev')
769 self.start_networkd()
770
771 self.assertTrue(self.link_exits('test1'))
772
773 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
774 print(output)
775 self.assertRegex(output, 'initcwnd 20')
776 self.assertRegex(output, 'initrwnd 30')
777
778 def test_ip_route_gateway(self):
779 self.copy_unit_to_networkd_unit_path('25-route-gateway.network', '12-dummy.netdev')
780 self.start_networkd()
781
782 self.assertTrue(self.link_exits('dummy98'))
783
784 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
785 print(output)
786 self.assertRegex(output, 'default')
787 self.assertRegex(output, 'via')
788 self.assertRegex(output, '149.10.124.64')
789 self.assertRegex(output, 'proto')
790 self.assertRegex(output, 'static')
791
792 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
793 print(output)
794 self.assertRegex(output, '149.10.124.48/28')
795 self.assertRegex(output, 'proto')
796 self.assertRegex(output, 'kernel')
797 self.assertRegex(output, 'scope')
798 self.assertRegex(output, 'link')
799
800 def test_ip_route_gateway_on_link(self):
801 self.copy_unit_to_networkd_unit_path('25-route-gateway-on-link.network', '12-dummy.netdev')
802 self.start_networkd()
803
804 self.assertTrue(self.link_exits('dummy98'))
805
806 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
807 print(output)
808 self.assertRegex(output, 'default')
809 self.assertRegex(output, 'via')
810 self.assertRegex(output, '149.10.125.65')
811 self.assertRegex(output, 'proto')
812 self.assertRegex(output, 'static')
813 self.assertRegex(output, 'onlink')
814
815 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
816 print(output)
817 self.assertRegex(output, '149.10.124.48/28')
818 self.assertRegex(output, 'proto')
819 self.assertRegex(output, 'kernel')
820 self.assertRegex(output, 'scope')
821 self.assertRegex(output, 'link')
822
823 def test_ip_route_ipv6_src_route(self):
824 # a dummy device does not make the addresses go through tentative state, so we
825 # reuse a bond from an earlier test, which does make the addresses go through
826 # tentative state, and do our test on that
827 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')
828 self.start_networkd()
829
830 self.assertTrue(self.link_exits('dummy98'))
831 self.assertTrue(self.link_exits('bond199'))
832
833 output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8')
834 print(output)
835 self.assertRegex(output, 'abcd::/16')
836 self.assertRegex(output, 'src')
837 self.assertRegex(output, '2001:1234:56:8f63::2')
838
839 def test_ip_link_mac_address(self):
840 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
841 self.start_networkd()
842
843 self.assertTrue(self.link_exits('dummy98'))
844
845 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
846 print(output)
847 self.assertRegex(output, '00:01:02:aa:bb:cc')
848
849 def test_ip_link_unmanaged(self):
850 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
851 self.start_networkd()
852
853 self.assertTrue(self.link_exits('dummy98'))
854
855 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
856 print(output)
857 self.assertRegex(output, 'unmanaged')
858
859 def test_ipv6_address_label(self):
860 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
861 self.start_networkd()
862
863 self.assertTrue(self.link_exits('dummy98'))
864
865 output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
866 print(output)
867 self.assertRegex(output, '2004:da8:1::/64')
868
869 def test_ipv6_neighbor(self):
870 self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
871 self.start_networkd()
872
873 self.assertTrue(self.link_exits('dummy98'))
874
875 output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
876 print(output)
877 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
878 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
879
880 def test_link_local_addressing(self):
881 self.copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
882 '25-link-local-addressing-no.network', '12-dummy.netdev')
883 self.start_networkd()
884
885 self.assertTrue(self.link_exits('test1'))
886 self.assertTrue(self.link_exits('dummy98'))
887
888 time.sleep(10)
889
890 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
891 print(output)
892 self.assertRegex(output, 'inet .* scope link')
893 self.assertRegex(output, 'inet6 .* scope link')
894
895 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
896 print(output)
897 self.assertNotRegex(output, 'inet6* .* scope link')
898
899 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
900 print(output)
901 self.assertRegex(output, 'State: degraded \(configured\)')
902
903 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
904 print(output)
905 self.assertRegex(output, 'State: carrier \(configured\)')
906
907 '''
908 Documentation/networking/ip-sysctl.txt
909
910 addr_gen_mode - INTEGER
911 Defines how link-local and autoconf addresses are generated.
912
913 0: generate address based on EUI64 (default)
914 1: do no generate a link-local address, use EUI64 for addresses generated
915 from autoconf
916 2: generate stable privacy addresses, using the secret from
917 stable_secret (RFC7217)
918 3: generate stable privacy addresses, using a random secret if unset
919 '''
920
921 test1_addr_gen_mode = ''
922 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
923 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
924 try:
925 f.readline()
926 except IOError:
927 # if stable_secret is unset, then EIO is returned
928 test1_addr_gen_mode = '0'
929 else:
930 test1_addr_gen_mode = '2'
931 else:
932 test1_addr_gen_mode = '0'
933
934 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
935 self.assertEqual(self.read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '0')
936
937 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
938 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
939
940 def test_sysctl(self):
941 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
942 self.start_networkd()
943
944 self.assertTrue(self.link_exits('dummy98'))
945
946 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
947 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
948 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
949 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
950 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
951 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
952 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
953
954 def test_bind_carrier(self):
955 self.copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
956 self.start_networkd()
957
958 self.assertTrue(self.link_exits('test1'))
959
960 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
961 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
962 time.sleep(4)
963 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
964 print(output)
965 self.assertRegex(output, 'UP,LOWER_UP')
966 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
967 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
968 self.assertRegex(output, 'State: routable \(configured\)')
969
970 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy99', 'type', 'dummy']), 0)
971 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy99', 'up']), 0)
972 time.sleep(4)
973 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
974 print(output)
975 self.assertRegex(output, 'UP,LOWER_UP')
976 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
977 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
978 self.assertRegex(output, 'State: routable \(configured\)')
979
980 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
981 time.sleep(4)
982 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
983 print(output)
984 self.assertRegex(output, 'UP,LOWER_UP')
985 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
986 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
987 self.assertRegex(output, 'State: routable \(configured\)')
988
989 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy99']), 0)
990 time.sleep(4)
991 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
992 print(output)
993 self.assertNotRegex(output, 'UP,LOWER_UP')
994 self.assertRegex(output, 'DOWN')
995 self.assertNotRegex(output, '192.168.10')
996 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
997 self.assertRegex(output, 'State: off \(configured\)')
998
999 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1000 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1001 time.sleep(4)
1002 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1003 print(output)
1004 self.assertRegex(output, 'UP,LOWER_UP')
1005 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1006 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1007 self.assertRegex(output, 'State: routable \(configured\)')
1008
1009 class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
1010 links = [
1011 'bridge99',
1012 'dummy98',
1013 'test1']
1014
1015 units = [
1016 '11-dummy.netdev',
1017 '12-dummy.netdev',
1018 '26-bridge.netdev',
1019 '26-bridge-slave-interface-1.network',
1020 '26-bridge-slave-interface-2.network',
1021 'bridge99-ignore-carrier-loss.network',
1022 'bridge99.network']
1023
1024 def setUp(self):
1025 self.link_remove(self.links)
1026
1027 def tearDown(self):
1028 self.link_remove(self.links)
1029 self.remove_unit_from_networkd_path(self.units)
1030
1031 def test_bridge_property(self):
1032 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1033 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1034 'bridge99.network')
1035 self.start_networkd()
1036
1037 self.assertTrue(self.link_exits('dummy98'))
1038 self.assertTrue(self.link_exits('test1'))
1039 self.assertTrue(self.link_exits('bridge99'))
1040
1041 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
1042 print(output)
1043 self.assertRegex(output, 'master')
1044 self.assertRegex(output, 'bridge')
1045
1046 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1047 print(output)
1048 self.assertRegex(output, 'master')
1049 self.assertRegex(output, 'bridge')
1050
1051 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
1052 print(output)
1053 self.assertRegex(output, '192.168.0.15')
1054 self.assertRegex(output, '192.168.0.1')
1055
1056 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1057 print(output)
1058 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
1059 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
1060 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
1061 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
1062
1063 # CONFIG_BRIDGE_IGMP_SNOOPING=y
1064 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
1065 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1066
1067 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1068 time.sleep(1)
1069
1070 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1071 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1072 time.sleep(3)
1073
1074 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1075 print(output)
1076 self.assertRegex(output, 'NO-CARRIER')
1077 self.assertNotRegex(output, '192.168.0.15/24')
1078 self.assertNotRegex(output, '192.168.0.16/24')
1079
1080 def test_bridge_ignore_carrier_loss(self):
1081 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1082 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1083 'bridge99-ignore-carrier-loss.network')
1084 self.start_networkd()
1085
1086 self.assertTrue(self.link_exits('dummy98'))
1087 self.assertTrue(self.link_exits('test1'))
1088 self.assertTrue(self.link_exits('bridge99'))
1089
1090 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1091 time.sleep(1)
1092
1093 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1094 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1095 time.sleep(3)
1096
1097 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1098 print(output)
1099 self.assertRegex(output, 'NO-CARRIER')
1100 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1101 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
1102
1103 class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
1104 links = ['veth99']
1105
1106 units = [
1107 '23-emit-lldp.network',
1108 '24-lldp.network',
1109 '25-veth.netdev']
1110
1111 def setUp(self):
1112 self.link_remove(self.links)
1113
1114 def tearDown(self):
1115 self.link_remove(self.links)
1116 self.remove_unit_from_networkd_path(self.units)
1117
1118 def test_lldp(self):
1119 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
1120 self.start_networkd()
1121
1122 self.assertTrue(self.link_exits('veth99'))
1123
1124 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
1125 print(output)
1126 self.assertRegex(output, 'veth-peer')
1127 self.assertRegex(output, 'veth99')
1128
1129 class NetworkdNetworkRATests(unittest.TestCase, Utilities):
1130 links = ['veth99']
1131
1132 units = [
1133 '25-veth.netdev',
1134 'ipv6-prefix.network',
1135 'ipv6-prefix-veth.network']
1136
1137 def setUp(self):
1138 self.link_remove(self.links)
1139
1140 def tearDown(self):
1141 self.link_remove(self.links)
1142 self.remove_unit_from_networkd_path(self.units)
1143
1144 def test_ipv6_prefix_delegation(self):
1145 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1146 self.start_networkd()
1147
1148 self.assertTrue(self.link_exits('veth99'))
1149
1150 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1151 print(output)
1152 self.assertRegex(output, '2002:da8:1:0')
1153
1154 class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
1155 links = [
1156 'dummy98',
1157 'veth99']
1158
1159 units = [
1160 '12-dummy.netdev',
1161 '24-search-domain.network',
1162 '25-veth.netdev',
1163 'dhcp-client.network',
1164 'dhcp-client-timezone-router.network',
1165 'dhcp-server.network',
1166 'dhcp-server-timezone-router.network']
1167
1168 def setUp(self):
1169 self.link_remove(self.links)
1170
1171 def tearDown(self):
1172 self.link_remove(self.links)
1173 self.remove_unit_from_networkd_path(self.units)
1174
1175 def test_dhcp_server(self):
1176 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
1177 self.start_networkd()
1178
1179 self.assertTrue(self.link_exits('veth99'))
1180
1181 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1182 print(output)
1183 self.assertRegex(output, '192.168.5.*')
1184 self.assertRegex(output, 'Gateway: 192.168.5.1')
1185 self.assertRegex(output, 'DNS: 192.168.5.1')
1186 self.assertRegex(output, 'NTP: 192.168.5.1')
1187
1188 def test_domain(self):
1189 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1190 self.start_networkd()
1191
1192 self.assertTrue(self.link_exits('dummy98'))
1193
1194 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1195 print(output)
1196 self.assertRegex(output, 'Address: 192.168.42.100')
1197 self.assertRegex(output, 'DNS: 192.168.42.1')
1198 self.assertRegex(output, 'Search Domains: one')
1199
1200 def test_emit_router_timezone(self):
1201 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
1202 self.start_networkd()
1203
1204 self.assertTrue(self.link_exits('veth99'))
1205
1206 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1207 print(output)
1208 self.assertRegex(output, 'Gateway: 192.168.5.*')
1209 self.assertRegex(output, '192.168.5.*')
1210 self.assertRegex(output, 'Europe/Berlin')
1211
1212 class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
1213 links = [
1214 'dummy98',
1215 'veth99']
1216
1217 units = [
1218 '25-veth.netdev',
1219 'dhcp-client-anonymize.network',
1220 'dhcp-client-critical-connection.network',
1221 'dhcp-client-ipv4-dhcp-settings.network',
1222 'dhcp-client-ipv4-only-ipv6-disabled.network',
1223 'dhcp-client-ipv4-only.network',
1224 'dhcp-client-ipv6-only.network',
1225 'dhcp-client-ipv6-rapid-commit.network',
1226 'dhcp-client-listen-port.network',
1227 'dhcp-client-route-metric.network',
1228 'dhcp-client-route-table.network',
1229 'dhcp-client.network',
1230 'dhcp-server-veth-peer.network',
1231 'dhcp-v4-server-veth-peer.network',
1232 'static.network']
1233
1234 def setUp(self):
1235 self.link_remove(self.links)
1236 self.stop_dnsmasq(dnsmasq_pid_file)
1237
1238 def tearDown(self):
1239 self.link_remove(self.links)
1240 self.remove_unit_from_networkd_path(self.units)
1241 self.stop_dnsmasq(dnsmasq_pid_file)
1242 self.remove_lease_file()
1243 self.remove_log_file()
1244
1245 def test_dhcp_client_ipv6_only(self):
1246 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1247 self.start_networkd()
1248
1249 self.assertTrue(self.link_exits('veth99'))
1250
1251 self.start_dnsmasq()
1252
1253 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1254 print(output)
1255 self.assertRegex(output, '2600::')
1256 self.assertNotRegex(output, '192.168.5')
1257
1258 def test_dhcp_client_ipv4_only(self):
1259 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1260 self.start_networkd()
1261
1262 self.assertTrue(self.link_exits('veth99'))
1263
1264 self.start_dnsmasq()
1265
1266 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1267 print(output)
1268 self.assertNotRegex(output, '2600::')
1269 self.assertRegex(output, '192.168.5')
1270
1271 def test_dhcp_client_ipv4_ipv6(self):
1272 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
1273 'dhcp-client-ipv4-only.network')
1274 self.start_networkd()
1275
1276 self.assertTrue(self.link_exits('veth99'))
1277
1278 self.start_dnsmasq()
1279
1280 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1281 print(output)
1282 self.assertRegex(output, '2600::')
1283 self.assertRegex(output, '192.168.5')
1284
1285 def test_dhcp_client_settings(self):
1286 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1287 self.start_networkd()
1288
1289 self.assertTrue(self.link_exits('veth99'))
1290
1291 self.start_dnsmasq()
1292
1293 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1294 print(output)
1295 self.assertRegex(output, '12:34:56:78:9a:bc')
1296 self.assertRegex(output, '192.168.5')
1297 self.assertRegex(output, '1492')
1298
1299 output = subprocess.check_output(['ip', 'route']).rstrip().decode('utf-8')
1300 print(output)
1301 self.assertRegex(output, 'default.*dev veth99 proto dhcp')
1302
1303 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
1304 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
1305 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
1306 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
1307
1308 def test_dhcp6_client_settings_rapidcommit_true(self):
1309 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1310 self.start_networkd()
1311
1312 self.assertTrue(self.link_exits('veth99'))
1313
1314 self.start_dnsmasq()
1315
1316 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1317 print(output)
1318 self.assertRegex(output, '12:34:56:78:9a:bc')
1319 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1320
1321 def test_dhcp6_client_settings_rapidcommit_false(self):
1322 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
1323 self.start_networkd()
1324
1325 self.assertTrue(self.link_exits('veth99'))
1326
1327 self.start_dnsmasq()
1328
1329 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1330 print(output)
1331 self.assertRegex(output, '12:34:56:78:9a:bc')
1332 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1333
1334 def test_dhcp_client_settings_anonymize(self):
1335 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
1336 self.start_networkd()
1337
1338 self.assertTrue(self.link_exits('veth99'))
1339
1340 self.start_dnsmasq()
1341
1342 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
1343 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
1344 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
1345
1346 def test_dhcp_client_listen_port(self):
1347 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
1348 self.start_networkd()
1349
1350 self.assertTrue(self.link_exits('veth99'))
1351
1352 self.start_dnsmasq('--dhcp-alternate-port=67,5555')
1353
1354 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1355 print(output)
1356 self.assertRegex(output, '192.168.5.* dynamic')
1357
1358 def test_dhcp_route_table_id(self):
1359 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
1360 self.start_networkd()
1361
1362 self.assertTrue(self.link_exits('veth99'))
1363
1364 self.start_dnsmasq()
1365
1366 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
1367 print(output)
1368 self.assertRegex(output, 'veth99 proto dhcp')
1369 self.assertRegex(output, '192.168.5.1')
1370
1371 def test_dhcp_route_metric(self):
1372 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
1373 self.start_networkd()
1374
1375 self.assertTrue(self.link_exits('veth99'))
1376
1377 self.start_dnsmasq()
1378
1379 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1380 print(output)
1381 self.assertRegex(output, 'metric 24')
1382
1383 def test_dhcp_route_criticalconnection_true(self):
1384 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
1385 self.start_networkd()
1386
1387 self.assertTrue(self.link_exits('veth99'))
1388
1389 self.start_dnsmasq()
1390
1391 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1392 print(output)
1393 self.assertRegex(output, '192.168.5.*')
1394
1395 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
1396 self.stop_dnsmasq(dnsmasq_pid_file)
1397
1398 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1399 time.sleep(125)
1400
1401 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1402 print(output)
1403 self.assertRegex(output, '192.168.5.*')
1404
1405 def test_dhcp_client_reuse_address_as_static(self):
1406 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
1407 self.start_networkd()
1408
1409 self.assertTrue(self.link_exits('veth99'))
1410
1411 self.start_dnsmasq()
1412
1413 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1414 print(output)
1415 self.assertRegex(output, '192.168.5')
1416 self.assertRegex(output, '2600::')
1417
1418 ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
1419 ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
1420 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
1421 print(static_network)
1422
1423 self.remove_unit_from_networkd_path(['dhcp-client.network'])
1424
1425 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
1426 f.write(static_network)
1427
1428 self.start_networkd()
1429
1430 self.assertTrue(self.link_exits('veth99'))
1431
1432 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1433 print(output)
1434 self.assertRegex(output, '192.168.5')
1435 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1436
1437 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1438 print(output)
1439 self.assertRegex(output, '2600::')
1440 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1441
1442 if __name__ == '__main__':
1443 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
1444 verbosity=3))