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