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