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