]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
Merge pull request #10928 from yuwata/fix-9940
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
CommitLineData
1f0e3109
SS
1#!/usr/bin/env python3
2# SPDX-License-Identifier: LGPL-2.1+
3# systemd-networkd tests
4
5import os
6import sys
7import unittest
8import subprocess
9import time
201bf07f 10import re
1f0e3109
SS
11import shutil
12import signal
13import socket
14import threading
15from shutil import copytree
16
17network_unit_file_path='/var/run/systemd/network'
18networkd_ci_path='/var/run/networkd-ci'
19network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
20network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
21
22dnsmasq_config_file='/var/run/networkd-ci/test-dnsmasq.conf'
23dnsmasq_pid_file='/var/run/networkd-ci/test-test-dnsmasq.pid'
24dnsmasq_log_file='/var/run/networkd-ci/test-dnsmasq-log-file'
25
7a0a37b2 26def is_module_available(module_name):
201bf07f
EV
27 lsmod_output = subprocess.check_output('lsmod', universal_newlines=True)
28 module_re = re.compile(r'^{0}\b'.format(re.escape(module_name)), re.MULTILINE)
29 return module_re.search(lsmod_output) or not subprocess.call(["modprobe", module_name])
7a0a37b2
EV
30
31def expectedFailureIfModuleIsNotAvailable(module_name):
32 def f(func):
33 if not is_module_available(module_name):
34 return unittest.expectedFailure(func)
35 return func
36
37 return f
38
1f0e3109
SS
39def setUpModule():
40
41 os.makedirs(network_unit_file_path, exist_ok=True)
42 os.makedirs(networkd_ci_path, exist_ok=True)
43
44 shutil.rmtree(networkd_ci_path)
6aea9276 45 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
1f0e3109
SS
46
47def tearDownModule():
48 shutil.rmtree(networkd_ci_path)
49
50class Utilities():
51 dhcp_server_data = []
52
53 def read_link_attr(self, link, dev, attribute):
54 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
55 return f.readline().strip()
56
57 def link_exits(self, link):
58 return os.path.exists(os.path.join('/sys/class/net', link))
59
60 def link_remove(self, links):
61 for link in links:
62 if os.path.exists(os.path.join('/sys/class/net', link)):
63 subprocess.call(['ip', 'link', 'del', 'dev', link])
9a4720a9 64 time.sleep(1)
1f0e3109
SS
65
66 def read_ipv6_sysctl_attr(self, link, attribute):
67 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
68 return f.readline().strip()
69
70 def read_ipv4_sysctl_attr(self, link, attribute):
71 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
72 return f.readline().strip()
73
74 def copy_unit_to_networkd_unit_path(self, *units):
75 for unit in units:
76 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
013c8dc9
YW
77 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
78 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
1f0e3109
SS
79
80 def remove_unit_from_networkd_path(self, units):
81 for unit in units:
82 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
83 os.remove(os.path.join(network_unit_file_path, unit))
013c8dc9
YW
84 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
85 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
1f0e3109
SS
86
87 def start_dnsmasq(self):
88 subprocess.check_call('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', shell=True)
89
90 time.sleep(10)
91
92 def stop_dnsmasq(self, pid_file):
93 if os.path.exists(pid_file):
94 with open(pid_file, 'r') as f:
95 pid = f.read().rstrip(' \t\r\n\0')
96 os.kill(int(pid), signal.SIGTERM)
97
98 os.remove(pid_file)
99
100 def search_words_in_file(self, word):
101 if os.path.exists(dnsmasq_log_file):
102 with open (dnsmasq_log_file) as in_file:
103 contents = in_file.read()
104 print(contents)
105 for part in contents.split():
106 if word in part:
107 in_file.close()
108 print("%s, %s" % (word, part))
109 return True
110 return False
111
112 def remove_lease_file(self):
113 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
114 os.remove(os.path.join(networkd_ci_path, 'lease'))
115
116 def remove_log_file(self):
117 if os.path.exists(dnsmasq_log_file):
118 os.remove(dnsmasq_log_file)
119
120 def start_networkd(self):
ec6a4704 121 subprocess.check_call('systemctl restart systemd-networkd', shell=True)
1f0e3109
SS
122 time.sleep(5)
123
124global ip
125global port
126
127class DHCPServer(threading.Thread):
128 def __init__(self, name):
129 threading.Thread.__init__(self)
130 self.name = name
131
132 def run(self):
133 self.start_dhcp_server()
134
135 def start_dhcp_server(self):
136 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
137
138 server_address = ('0.0.0.0', 67)
139 sock.bind(server_address)
140
141 print('Starting DHCP Server ...\n')
142 data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
143
144 global ip
145 ip = addr[0]
146
147 global port
148 port = addr[1]
149 sock.close()
150
151class NetworkdNetDevTests(unittest.TestCase, Utilities):
152
153 links =['bridge99', 'bond99', 'bond99', 'vlan99', 'test1', 'macvtap99',
154 'macvlan99', 'ipvlan99', 'vxlan99', 'veth99', 'vrf99', 'tun99',
d29dc4f1 155 'tap99', 'vcan99', 'geneve99', 'dummy98', 'ipiptun99', 'sittun99', '6rdtun99',
d80734f7 156 'gretap99', 'vtitun99', 'vti6tun99','ip6tnl99', 'gretun99', 'ip6gretap99', 'wg99', 'dropin-test']
1f0e3109
SS
157
158 units = ['25-bridge.netdev', '25-bond.netdev', '21-vlan.netdev', '11-dummy.netdev', '21-vlan.network',
159 '21-macvtap.netdev', 'macvtap.network', '21-macvlan.netdev', 'macvlan.network', 'vxlan.network',
160 '25-vxlan.netdev', '25-ipvlan.netdev', 'ipvlan.network', '25-veth.netdev', '25-vrf.netdev',
161 '25-tun.netdev', '25-tun.netdev', '25-vcan.netdev', '25-geneve.netdev', '25-ipip-tunnel.netdev',
d29dc4f1
DA
162 '25-ip6tnl-tunnel.netdev', '25-ip6gre-tunnel.netdev','25-sit-tunnel.netdev', '25-6rd-tunnel.netdev',
163 '25-gre-tunnel.netdev', '25-gretap-tunnel.netdev', '25-vti-tunnel.netdev', '25-vti6-tunnel.netdev',
164 '12-dummy.netdev', 'gre.network', 'ipip.network', 'ip6gretap.network', 'gretun.network',
165 'ip6tnl.network', '25-tap.netdev', 'vti6.network', 'vti.network', 'gretap.network', 'sit.network',
d80734f7 166 '25-ipip-tunnel-independent.netdev', '25-wireguard.netdev', '6rd.network', '10-dropin-test.netdev']
1f0e3109
SS
167
168 def setUp(self):
169 self.link_remove(self.links)
170
171 def tearDown(self):
172 self.link_remove(self.links)
173 self.remove_unit_from_networkd_path(self.units)
174
d80734f7
YW
175 def test_dropin(self):
176 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
177
178 self.start_networkd()
179
180 self.assertTrue(self.link_exits('dropin-test'))
181
182 output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
183 print(output)
184 self.assertRegex(output, '00:50:56:c0:00:28')
185
1f0e3109
SS
186 def test_bridge(self):
187 self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
188 self.start_networkd()
189
190 self.assertTrue(self.link_exits('bridge99'))
191
192 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'hello_time'))
193 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'max_age'))
194 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','forward_delay'))
195 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','ageing_time'))
196 self.assertEqual('9', self.read_link_attr('bridge99', 'bridge','priority'))
197 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_querier'))
198 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_snooping'))
199 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','stp_state'))
200
201 def test_bond(self):
202 self.copy_unit_to_networkd_unit_path('25-bond.netdev')
203 self.start_networkd()
204
205 self.assertTrue(self.link_exits('bond99'))
206
99f68ef0
TJ
207 self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode'))
208 self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
209 self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon'))
210 self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate'))
211 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay'))
212 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay'))
213 self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp'))
214 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links'))
215 self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
216 self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
217 self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
1f0e3109
SS
218
219 def test_vlan(self):
220 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
221
222 self.start_networkd()
223
224 self.assertTrue(self.link_exits('vlan99'))
225
226 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
227 self.assertTrue(output, 'REORDER_HDR')
228 self.assertTrue(output, 'LOOSE_BINDING')
229 self.assertTrue(output, 'GVRP')
230 self.assertTrue(output, 'MVRP')
231 self.assertTrue(output, '99')
232
233 def test_macvtap(self):
234 self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
235
236 self.start_networkd()
237
238 self.assertTrue(self.link_exits('macvtap99'))
239
240 def test_macvlan(self):
241 self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
242
243 self.start_networkd()
244
245 self.assertTrue(self.link_exits('macvlan99'))
246
7a0a37b2 247 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109
SS
248 def test_ipvlan(self):
249 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
250
251 self.start_networkd()
252
253 self.assertTrue(self.link_exits('ipvlan99'))
254
255 def test_veth(self):
256 self.copy_unit_to_networkd_unit_path('25-veth.netdev')
257
258 self.start_networkd()
259
260 self.assertTrue(self.link_exits('veth99'))
261
262 def test_dummy(self):
263 self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
264
265 self.start_networkd()
266
267 self.assertTrue(self.link_exits('test1'))
268
269 def test_tun(self):
270 self.copy_unit_to_networkd_unit_path('25-tun.netdev')
271
272 self.start_networkd()
273
274 self.assertTrue(self.link_exits('tun99'))
275
276 def test_tap(self):
277 self.copy_unit_to_networkd_unit_path('25-tap.netdev')
278
279 self.start_networkd()
280
281 self.assertTrue(self.link_exits('tap99'))
282
7a0a37b2 283 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109
SS
284 def test_vrf(self):
285 self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
286
287 self.start_networkd()
288
289 self.assertTrue(self.link_exits('vrf99'))
290
7a0a37b2 291 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109
SS
292 def test_vcan(self):
293 self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
294
295 self.start_networkd()
296
297 self.assertTrue(self.link_exits('vcan99'))
298
7a3bc5a8
EV
299 @expectedFailureIfModuleIsNotAvailable('wireguard')
300 def test_wireguard(self):
301 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
302
303 self.start_networkd()
304
305 if shutil.which('wg'):
306 subprocess.call('wg')
307
308 self.assertTrue(self.link_exits('wg99'))
309
1f0e3109
SS
310 def test_geneve(self):
311 self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
312
313 self.start_networkd()
314
315 self.assertTrue(self.link_exits('geneve99'))
316
317 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
318 self.assertTrue(output, '192.168.22.1')
319 self.assertTrue(output, '6082')
320 self.assertTrue(output, 'udpcsum')
321 self.assertTrue(output, 'udp6zerocsumrx')
322
323 def test_ipip_tunnel(self):
324 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network')
325 self.start_networkd()
326
327 self.assertTrue(self.link_exits('dummy98'))
328 self.assertTrue(self.link_exits('ipiptun99'))
329
330 def test_gre_tunnel(self):
331 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network')
332 self.start_networkd()
333
334 self.assertTrue(self.link_exits('dummy98'))
335 self.assertTrue(self.link_exits('gretun99'))
336
337 def test_gretap_tunnel(self):
338 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network')
339 self.start_networkd()
340
341 self.assertTrue(self.link_exits('dummy98'))
342 self.assertTrue(self.link_exits('gretap99'))
343
344 def test_ip6gretap_tunnel(self):
345 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretap.network')
346 self.start_networkd()
347
348 self.assertTrue(self.link_exits('dummy98'))
349 self.assertTrue(self.link_exits('ip6gretap99'))
350
351 def test_vti_tunnel(self):
352 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network')
353 self.start_networkd()
354
355 self.assertTrue(self.link_exits('dummy98'))
356 self.assertTrue(self.link_exits('vtitun99'))
357
358 def test_vti6_tunnel(self):
359 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network')
360 self.start_networkd()
361
362 self.assertTrue(self.link_exits('dummy98'))
363 self.assertTrue(self.link_exits('vti6tun99'))
364
365 def test_ip6tnl_tunnel(self):
366 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network')
367 self.start_networkd()
368
369 self.assertTrue(self.link_exits('dummy98'))
370 self.assertTrue(self.link_exits('ip6tnl99'))
371
372 def test_sit_tunnel(self):
373 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network')
374 self.start_networkd()
375
376 self.assertTrue(self.link_exits('dummy98'))
377 self.assertTrue(self.link_exits('sittun99'))
378
d29dc4f1
DA
379 def test_6rd_tunnel(self):
380 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
381 self.start_networkd()
382
383 self.assertTrue(self.link_exits('dummy98'))
384 self.assertTrue(self.link_exits('sittun99'))
385
1f0e3109
SS
386 def test_tunnel_independent(self):
387 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
388
389 self.start_networkd()
390 self.assertTrue(self.link_exits('ipiptun99'))
391
392 def test_vxlan(self):
393 self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network','11-dummy.netdev')
394
395 self.start_networkd()
396
397 self.assertTrue(self.link_exits('vxlan99'))
398
399 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
400 self.assertRegex(output, "999")
401 self.assertRegex(output, '5555')
402 self.assertRegex(output, 'l2miss')
403 self.assertRegex(output, 'l3miss')
404 self.assertRegex(output, 'udpcsum')
405 self.assertRegex(output, 'udp6zerocsumtx')
406 self.assertRegex(output, 'udp6zerocsumrx')
407 self.assertRegex(output, 'remcsumtx')
408 self.assertRegex(output, 'remcsumrx')
409 self.assertRegex(output, 'gbp')
410
411class NetworkdNetWorkTests(unittest.TestCase, Utilities):
412 links = ['dummy98', 'test1', 'bond199']
413
414 units = ['12-dummy.netdev', 'test-static.network', 'configure-without-carrier.network', '11-dummy.netdev',
415 '23-primary-slave.network', '23-test1-bond199.network', '11-dummy.netdev', '23-bond199.network',
416 '25-bond-active-backup-slave.netdev', '12-dummy.netdev', '23-active-slave.network',
417 'routing-policy-rule.network', '25-address-section.network', '25-address-section-miscellaneous.network',
418 '25-route-section.network', '25-route-type.network', '25-route-tcp-window-settings.network',
419 '25-address-link-section.network', '25-ipv6-address-label-section.network', '25-link-section-unmanaged.network',
420 '25-sysctl.network']
421
422 def setUp(self):
423 self.link_remove(self.links)
424
425 def tearDown(self):
426 self.link_remove(self.links)
427 self.remove_unit_from_networkd_path(self.units)
428
429 def test_static_address(self):
430 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'test-static.network')
431 self.start_networkd()
432
433 self.assertTrue(self.link_exits('dummy98'))
434 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
435 print(output)
436 self.assertRegex(output, '192.168.0.15')
437 self.assertRegex(output, '192.168.0.1')
438 self.assertRegex(output, 'routable')
439
440 def test_configure_without_carrier(self):
441 self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
442 self.start_networkd()
443
444 self.assertTrue(self.link_exits('test1'))
445 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
446 print(output)
447 self.assertRegex(output, '192.168.0.15')
448 self.assertRegex(output, '192.168.0.1')
449 self.assertRegex(output, 'routable')
450
451 def test_bond_active_slave(self):
452 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
453 self.start_networkd()
454
455 self.assertTrue(self.link_exits('dummy98'))
456 self.assertTrue(self.link_exits('bond199'))
457 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
458 print(output)
459 self.assertRegex(output, 'active_slave dummy98')
460
461 def test_bond_primary_slave(self):
462 self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
463 self.start_networkd()
464
465 self.assertTrue(self.link_exits('test1'))
466 self.assertTrue(self.link_exits('bond199'))
467 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
468 print(output)
469 self.assertRegex(output, 'primary test1')
470
471 def test_routing_policy_rule(self):
472 self.copy_unit_to_networkd_unit_path('routing-policy-rule.network', '11-dummy.netdev')
473 self.start_networkd()
474
475 self.assertTrue(self.link_exits('test1'))
476 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
477 print(output)
478 self.assertRegex(output, '111')
479 self.assertRegex(output, 'from 192.168.100.18')
f7bdd562 480 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
1f0e3109
SS
481 self.assertRegex(output, 'iif test1')
482 self.assertRegex(output, 'oif test1')
483 self.assertRegex(output, 'lookup 7')
484
485 def test_address_preferred_lifetime_zero_ipv6(self):
486 self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev')
487 self.start_networkd()
488
489 self.assertTrue(self.link_exits('dummy98'))
490
491 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
492 print(output)
493 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
494 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
495
496 def test_ip_route(self):
497 self.copy_unit_to_networkd_unit_path('25-route-section.network', '12-dummy.netdev')
498 self.start_networkd()
499
500 self.assertTrue(self.link_exits('dummy98'))
501
502 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98']).rstrip().decode('utf-8')
503 print(output)
504 self.assertRegex(output, '192.168.0.1')
505 self.assertRegex(output, 'static')
506 self.assertRegex(output, '192.168.0.0/24')
507
508 def test_ip_route_blackhole_unreachable_prohibit(self):
509 self.copy_unit_to_networkd_unit_path('25-route-type.network', '12-dummy.netdev')
510 self.start_networkd()
511
512 self.assertTrue(self.link_exits('dummy98'))
513
514 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
515 print(output)
516 self.assertRegex(output, 'blackhole')
517 self.assertRegex(output, 'unreachable')
518 self.assertRegex(output, 'prohibit')
519
520 subprocess.call(['ip', 'route', 'del', 'blackhole', '202.54.1.2'])
521 subprocess.call(['ip', 'route', 'del', 'unreachable', '202.54.1.3'])
522 subprocess.call(['ip', 'route', 'del', 'prohibit', '202.54.1.4'])
523
524 def test_ip_route_tcp_window(self):
525 self.copy_unit_to_networkd_unit_path('25-route-tcp-window-settings.network', '11-dummy.netdev')
526 self.start_networkd()
527
528 self.assertTrue(self.link_exits('test1'))
529
530 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
531 print(output)
532 self.assertRegex(output, 'initcwnd 20')
533 self.assertRegex(output, 'initrwnd 30')
534
535 def test_ip_link_mac_address(self):
536 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
537 self.start_networkd()
538
539 self.assertTrue(self.link_exits('dummy98'))
540
541 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
542 print(output)
543 self.assertRegex(output, '00:01:02:aa:bb:cc')
544
545 def test_ip_link_unmanaged(self):
546 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
547 self.start_networkd()
548
549 self.assertTrue(self.link_exits('dummy98'))
550
551 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
552 print(output)
553 self.assertRegex(output, 'unmanaged')
554
555 def test_ipv6_address_label(self):
556 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
557 self.start_networkd()
558
559 self.assertTrue(self.link_exits('dummy98'))
560
561 output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
562 print(output)
563 self.assertRegex(output, '2004:da8:1::/64')
564
565 def test_sysctl(self):
566 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
567 self.start_networkd()
568
569 self.assertTrue(self.link_exits('dummy98'))
570
571 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
572 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
573 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
574 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
575 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
576 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
577 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
578
579class NetworkdNetWorkBrideTests(unittest.TestCase, Utilities):
580 links = ['dummy98', 'test1', 'bridge99']
581
582 units = ['11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', '26-bridge-slave-interface-1.network',
583 '26-bridge-slave-interface-2.network', 'bridge99.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_bridge_property(self):
593 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
594 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
595 'bridge99.network')
596 self.start_networkd()
597
598 self.assertTrue(self.link_exits('dummy98'))
599 self.assertTrue(self.link_exits('test1'))
600 self.assertTrue(self.link_exits('bridge99'))
601
602 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
603 print(output)
604 self.assertRegex(output, 'master')
605 self.assertRegex(output, 'bridge')
606
607 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
608 print(output)
609 self.assertRegex(output, 'master')
610 self.assertRegex(output, 'bridge')
611
612 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
613 print(output)
614 self.assertRegex(output, '192.168.0.15')
615 self.assertRegex(output, '192.168.0.1')
616
617 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
618 print(output)
619 self.assertRegex(output, 'cost 400')
620 self.assertRegex(output, 'hairpin on')
621 self.assertRegex(output, 'flood on')
622 self.assertRegex(output, 'fastleave on')
623
624class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
625 links = ['veth99']
626
627 units = ['23-emit-lldp.network', '24-lldp.network', '25-veth.netdev']
628
629 def setUp(self):
630 self.link_remove(self.links)
631
632 def tearDown(self):
633 self.link_remove(self.links)
634 self.remove_unit_from_networkd_path(self.units)
635
636 def test_lldp(self):
637 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
638 self.start_networkd()
639
640 self.assertTrue(self.link_exits('veth99'))
641
642 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
643 print(output)
644 self.assertRegex(output, 'veth-peer')
645 self.assertRegex(output, 'veth99')
646
647class NetworkdNetworkRATests(unittest.TestCase, Utilities):
648 links = ['veth99']
649
650 units = ['25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network']
651
652 def setUp(self):
653 self.link_remove(self.links)
654
655 def tearDown(self):
656 self.link_remove(self.links)
657 self.remove_unit_from_networkd_path(self.units)
658
659 def test_ipv6_prefix_delegation(self):
660 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
661 self.start_networkd()
662
663 self.assertTrue(self.link_exits('veth99'))
664
665 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
666 print(output)
667 self.assertRegex(output, '2002:da8:1:0')
668
669class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
670 links = ['veth99', 'dummy98']
671
672 units = ['25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network', '12-dummy.netdev', '24-search-domain.network',
673 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network']
674
675 def setUp(self):
676 self.link_remove(self.links)
677
678 def tearDown(self):
679 self.link_remove(self.links)
680 self.remove_unit_from_networkd_path(self.units)
681
682 def test_dhcp_server(self):
683 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
684 self.start_networkd()
685
686 self.assertTrue(self.link_exits('veth99'))
687
688 time.sleep(5)
689
690 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
691 print(output)
692 self.assertRegex(output, '192.168.5.*')
693 self.assertRegex(output, 'Gateway: 192.168.5.1')
694 self.assertRegex(output, 'DNS: 192.168.5.1')
695 self.assertRegex(output, 'NTP: 192.168.5.1')
696
697 def test_domain(self):
698 self.copy_unit_to_networkd_unit_path( '12-dummy.netdev', '24-search-domain.network')
699 self.start_networkd()
700
701 self.assertTrue(self.link_exits('dummy98'))
702
703 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
704 print(output)
705 self.assertRegex(output, 'Address: 192.168.42.100')
706 self.assertRegex(output, 'DNS: 192.168.42.1')
707 self.assertRegex(output, 'Search Domains: one')
708
709 def test_emit_router_timezone(self):
710 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
711 self.start_networkd()
712
713 self.assertTrue(self.link_exits('veth99'))
714
715 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
716 print(output)
717 self.assertRegex(output, 'Gateway: 192.168.5.*')
718 self.assertRegex(output, '192.168.5.*')
719 self.assertRegex(output, 'Europe/Berlin')
720
721class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
722 links = ['veth99', 'dummy98']
723
724 units = ['25-veth.netdev', 'dhcp-server-veth-peer.network','dhcp-client-ipv6-only.network',
725 'dhcp-client-ipv4-only-ipv6-disabled.network', 'dhcp-client-ipv4-only.network',
726 'dhcp-client-ipv4-dhcp-settings.network', 'dhcp-client-anonymize.network',
727 'dhcp-client-ipv6-rapid-commit.network', 'dhcp-client-route-table.network',
728 'dhcp-v4-server-veth-peer.network', 'dhcp-client-listen-port.network',
729 'dhcp-client-route-metric.network', 'dhcp-client-critical-connection.network']
730
731 def setUp(self):
732 self.link_remove(self.links)
733 self.stop_dnsmasq(dnsmasq_pid_file)
734
735 def tearDown(self):
736 self.link_remove(self.links)
737 self.remove_unit_from_networkd_path(self.units)
738 self.stop_dnsmasq(dnsmasq_pid_file)
739 self.remove_lease_file()
740 self.remove_log_file()
741
742 def test_dhcp_client_ipv6_only(self):
743 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network','dhcp-client-ipv6-only.network')
744 self.start_networkd()
745
746 self.assertTrue(self.link_exits('veth99'))
747
748 self.start_dnsmasq()
749
750 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
751 print(output)
752 self.assertRegex(output, '2600::')
753 self.assertNotRegex(output, '192.168.5')
754
755 def test_dhcp_client_ipv4_only(self):
756 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network','dhcp-client-ipv4-only-ipv6-disabled.network')
757 self.start_networkd()
758
759 self.assertTrue(self.link_exits('veth99'))
760
761 self.start_dnsmasq()
762
763 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
764 print(output)
765 self.assertNotRegex(output, '2600::')
766 self.assertRegex(output, '192.168.5')
767
768 def test_dhcp_client_ipv4_ipv6(self):
769 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
770 'dhcp-client-ipv4-only.network')
771 self.start_networkd()
772
773 self.assertTrue(self.link_exits('veth99'))
774
775 self.start_dnsmasq()
776
777 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
778 print(output)
779 self.assertRegex(output, '2600::')
780 self.assertRegex(output, '192.168.5')
781
782 def test_dhcp_client_settings(self):
783 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
784 self.start_networkd()
785
786 self.assertTrue(self.link_exits('veth99'))
787
788 self.start_dnsmasq()
789
790 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
791 print(output)
792 self.assertRegex(output, '12:34:56:78:9a:bc')
793 self.assertRegex(output, '192.168.5')
794 self.assertRegex(output, '1492')
795
796 output = subprocess.check_output(['ip', 'route']).rstrip().decode('utf-8')
797 print(output)
798 self.assertRegex(output, 'default.*dev veth99 proto dhcp')
799
800 self.search_words_in_file('vendor class: SusantVendorTest')
801 self.search_words_in_file('client MAC address: 12:34:56:78:9a:bc')
802 self.search_words_in_file('client provides name: test-hostname')
803 self.search_words_in_file('26:mtu')
804
805 def test_dhcp6_client_settings_rapidcommit_true(self):
806 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
807 self.start_networkd()
808
809 self.assertTrue(self.link_exits('veth99'))
810
811 self.start_dnsmasq()
812
813 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
814 print(output)
815 self.assertRegex(output, '12:34:56:78:9a:bc')
816
817 self.assertTrue(self.search_words_in_file('14:rapid-commit'))
818
819 def test_dhcp6_client_settings_rapidcommit_false(self):
820 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
821 self.start_networkd()
822
823 self.assertTrue(self.link_exits('veth99'))
824
825 self.start_dnsmasq()
826
827 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
828 print(output)
829 self.assertRegex(output, '12:34:56:78:9a:bc')
830
831 self.assertFalse(self.search_words_in_file('14:rapid-commit'))
832
833 def test_dhcp_client_settings_anonymize(self):
834 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
835 self.start_networkd()
836
837 self.assertTrue(self.link_exits('veth99'))
838
839 self.start_dnsmasq()
840 self.assertFalse(self.search_words_in_file('VendorClassIdentifier=SusantVendorTest'))
841 self.assertFalse(self.search_words_in_file('test-hostname'))
842 self.assertFalse(self.search_words_in_file('26:mtu'))
843
844 def test_dhcp_client_listen_port(self):
845 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
846 dh_server = DHCPServer("dhcp_server")
847 dh_server.start()
848
849 self.start_networkd()
850
851 self.assertTrue(self.link_exits('veth99'))
852
853 global port
854 global ip
855
856 self.assertRegex(str(port), '5555')
857 self.assertRegex(str(ip), '0.0.0.0')
858
859 dh_server.join()
860
861 def test_dhcp_route_table_id(self):
862 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
863 self.start_networkd()
864 self.start_dnsmasq()
865
866 self.assertTrue(self.link_exits('veth99'))
867
868 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
869 print(output)
870
871 self.assertRegex(output, 'veth99 proto dhcp')
872 self.assertRegex(output, '192.168.5.1')
873
874 def test_dhcp_route_metric(self):
875 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
876 self.start_networkd()
877 self.start_dnsmasq()
878
879 self.assertTrue(self.link_exits('veth99'))
880
881 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
882 print(output)
883
884 self.assertRegex(output, 'metric 24')
885
886 def test_dhcp_route_criticalconnection_true(self):
887 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
888 self.start_networkd()
889 self.start_dnsmasq()
890
891 self.assertTrue(self.link_exits('veth99'))
892
893 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
894 print(output)
895
896 self.assertRegex(output, '192.168.5.*')
897 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
898 self.stop_dnsmasq(dnsmasq_pid_file)
899
900 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
901 time.sleep(125)
902
903 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
904 print(output)
905 self.assertRegex(output, '192.168.5.*')
906
907if __name__ == '__main__':
908 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
909 verbosity=3))