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