]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
test-network: add or drop whitespace
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: LGPL-2.1+
3 # systemd-networkd tests
4
5 import os
6 import re
7 import shutil
8 import signal
9 import socket
10 import subprocess
11 import sys
12 import threading
13 import time
14 import unittest
15 from shutil import copytree
16
17 network_unit_file_path='/run/systemd/network'
18 networkd_runtime_directory='/run/systemd/netif'
19 networkd_ci_path='/run/networkd-ci'
20 network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
21 network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
22
23 dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
24 dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
25
26 def is_module_available(module_name):
27 lsmod_output = subprocess.check_output('lsmod', universal_newlines=True)
28 module_re = re.compile(r'^{0}\b'.format(re.escape(module_name)), re.MULTILINE)
29 return module_re.search(lsmod_output) or not subprocess.call(["modprobe", module_name])
30
31 def expectedFailureIfModuleIsNotAvailable(module_name):
32 def f(func):
33 if not is_module_available(module_name):
34 return unittest.expectedFailure(func)
35 return func
36
37 return f
38
39 def expectedFailureIfERSPANModuleIsNotAvailable():
40 def f(func):
41 rc = subprocess.call(['ip', 'link', 'add', 'dev', 'erspan99', 'type', 'erspan', 'seq', 'key', '30', 'local', '192.168.1.4', 'remote', '192.168.1.1', 'erspan_ver', '1', 'erspan', '123'])
42 if rc == 0:
43 subprocess.call(['ip', 'link', 'del', 'erspan99'])
44 return func
45 else:
46 return unittest.expectedFailure(func)
47
48 return f
49
50 def setUpModule():
51
52 os.makedirs(network_unit_file_path, exist_ok=True)
53 os.makedirs(networkd_ci_path, exist_ok=True)
54
55 shutil.rmtree(networkd_ci_path)
56 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
57
58 subprocess.check_call('systemctl stop systemd-networkd.socket', shell=True)
59
60 def tearDownModule():
61 shutil.rmtree(networkd_ci_path)
62
63 subprocess.check_call('systemctl stop systemd-networkd.service', shell=True)
64 subprocess.check_call('systemctl start systemd-networkd.socket', shell=True)
65 subprocess.check_call('systemctl start systemd-networkd.service', shell=True)
66
67 class Utilities():
68 dhcp_server_data = []
69
70 def read_link_attr(self, link, dev, attribute):
71 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
72 return f.readline().strip()
73
74 def read_bridge_port_attr(self, bridge, link, attribute):
75
76 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
77 path_port = 'lower_' + link + '/brport'
78 path = os.path.join(path_bridge, path_port)
79
80 with open(os.path.join(path, attribute)) as f:
81 return f.readline().strip()
82
83 def link_exits(self, link):
84 return os.path.exists(os.path.join('/sys/class/net', link))
85
86 def link_remove(self, links):
87 for link in links:
88 if os.path.exists(os.path.join('/sys/class/net', link)):
89 subprocess.call(['ip', 'link', 'del', 'dev', link])
90 time.sleep(1)
91
92 def read_ipv6_sysctl_attr(self, link, attribute):
93 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
94 return f.readline().strip()
95
96 def read_ipv4_sysctl_attr(self, link, attribute):
97 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
98 return f.readline().strip()
99
100 def copy_unit_to_networkd_unit_path(self, *units):
101 for unit in units:
102 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
103 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
104 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
105
106 def remove_unit_from_networkd_path(self, units):
107 for unit in units:
108 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
109 os.remove(os.path.join(network_unit_file_path, unit))
110 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
111 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
112
113 def start_dnsmasq(self):
114 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 --port=0', shell=True)
115
116 time.sleep(10)
117
118 def stop_dnsmasq(self, pid_file):
119 if os.path.exists(pid_file):
120 with open(pid_file, 'r') as f:
121 pid = f.read().rstrip(' \t\r\n\0')
122 os.kill(int(pid), signal.SIGTERM)
123
124 os.remove(pid_file)
125
126 def search_words_in_dnsmasq_log(self, words, show_all=False):
127 if os.path.exists(dnsmasq_log_file):
128 with open (dnsmasq_log_file) as in_file:
129 contents = in_file.read()
130 if show_all:
131 print(contents)
132 for line in contents.split('\n'):
133 if words in line:
134 in_file.close()
135 print("%s, %s" % (words, line))
136 return True
137 return False
138
139 def remove_lease_file(self):
140 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
141 os.remove(os.path.join(networkd_ci_path, 'lease'))
142
143 def remove_log_file(self):
144 if os.path.exists(dnsmasq_log_file):
145 os.remove(dnsmasq_log_file)
146
147 def start_networkd(self):
148 if (os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
149 subprocess.check_call('systemctl stop systemd-networkd', shell=True)
150 os.remove(os.path.join(networkd_runtime_directory, 'state'))
151 subprocess.check_call('systemctl start systemd-networkd', shell=True)
152 else:
153 subprocess.check_call('systemctl restart systemd-networkd', shell=True)
154 time.sleep(5)
155 print()
156
157 global ip
158 global port
159
160 class DHCPServer(threading.Thread):
161 def __init__(self, name):
162 threading.Thread.__init__(self)
163 self.name = name
164
165 def run(self):
166 self.start_dhcp_server()
167
168 def start_dhcp_server(self):
169 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
170
171 server_address = ('0.0.0.0', 67)
172 sock.bind(server_address)
173
174 print('Starting DHCP Server ...\n')
175 data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
176
177 global ip
178 ip = addr[0]
179
180 global port
181 port = addr[1]
182 sock.close()
183
184 class NetworkdNetDevTests(unittest.TestCase, Utilities):
185
186 links =[
187 '6rdtun99',
188 'bond99',
189 'bridge99',
190 'dropin-test',
191 'dummy98',
192 'erspan-test',
193 'geneve99',
194 'gretap99',
195 'gretun99',
196 'ip6gretap99',
197 'ip6tnl99',
198 'ipiptun99',
199 'ipvlan99',
200 'isataptun99',
201 'macvlan99',
202 'macvtap99',
203 'sittun99',
204 'tap99',
205 'test1',
206 'tun99',
207 'vcan99',
208 'veth99',
209 'vlan99',
210 'vrf99',
211 'vti6tun99',
212 'vtitun99',
213 'vxlan99',
214 'wg98',
215 'wg99']
216
217 units = [
218 '10-dropin-test.netdev',
219 '11-dummy.netdev',
220 '12-dummy.netdev',
221 '21-macvlan.netdev',
222 '21-macvtap.netdev',
223 '21-vlan.netdev',
224 '21-vlan.network',
225 '25-6rd-tunnel.netdev',
226 '25-bond.netdev',
227 '25-bond-balanced-tlb.netdev',
228 '25-bridge.netdev',
229 '25-erspan-tunnel.netdev',
230 '25-geneve.netdev',
231 '25-gretap-tunnel.netdev',
232 '25-gre-tunnel.netdev',
233 '25-ip6gre-tunnel.netdev',
234 '25-ip6tnl-tunnel.netdev',
235 '25-ipip-tunnel-independent.netdev',
236 '25-ipip-tunnel.netdev',
237 '25-ipvlan.netdev',
238 '25-isatap-tunnel.netdev',
239 '25-sit-tunnel.netdev',
240 '25-tap.netdev',
241 '25-tun.netdev',
242 '25-vcan.netdev',
243 '25-veth.netdev',
244 '25-vrf.netdev',
245 '25-vti6-tunnel.netdev',
246 '25-vti-tunnel.netdev',
247 '25-vxlan.netdev',
248 '25-wireguard-23-peers.netdev',
249 '25-wireguard-23-peers.network',
250 '25-wireguard.netdev',
251 '6rd.network',
252 'gre.network',
253 'gretap.network',
254 'gretun.network',
255 'ip6gretap.network',
256 'ip6tnl.network',
257 'ipip.network',
258 'ipvlan.network',
259 'isatap.network',
260 'macvlan.network',
261 'macvtap.network',
262 'sit.network',
263 'vti6.network',
264 'vti.network',
265 'vxlan.network']
266
267 def setUp(self):
268 self.link_remove(self.links)
269
270 def tearDown(self):
271 self.link_remove(self.links)
272 self.remove_unit_from_networkd_path(self.units)
273
274 def test_dropin(self):
275 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
276 self.start_networkd()
277
278 self.assertTrue(self.link_exits('dropin-test'))
279
280 output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
281 print(output)
282 self.assertRegex(output, '00:50:56:c0:00:28')
283
284 def test_bridge(self):
285 self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
286 self.start_networkd()
287
288 self.assertTrue(self.link_exits('bridge99'))
289
290 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'hello_time'))
291 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'max_age'))
292 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','forward_delay'))
293 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','ageing_time'))
294 self.assertEqual('9', self.read_link_attr('bridge99', 'bridge','priority'))
295 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_querier'))
296 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_snooping'))
297 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','stp_state'))
298
299 def test_bond(self):
300 self.copy_unit_to_networkd_unit_path('25-bond.netdev')
301 self.start_networkd()
302
303 self.assertTrue(self.link_exits('bond99'))
304
305 self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode'))
306 self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
307 self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon'))
308 self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate'))
309 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay'))
310 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay'))
311 self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp'))
312 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links'))
313 self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
314 self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
315 self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
316
317 def test_bond_balanced_tlb(self):
318 self.copy_unit_to_networkd_unit_path('25-bond-balanced-tlb.netdev')
319 self.start_networkd()
320
321 self.assertTrue(self.link_exits('bond99'))
322
323 self.assertEqual('balance-tlb 5', self.read_link_attr('bond99', 'bonding', 'mode'))
324 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
325
326 def test_vlan(self):
327 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
328 self.start_networkd()
329
330 self.assertTrue(self.link_exits('vlan99'))
331
332 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
333 print(output)
334 self.assertTrue(output, 'REORDER_HDR')
335 self.assertTrue(output, 'LOOSE_BINDING')
336 self.assertTrue(output, 'GVRP')
337 self.assertTrue(output, 'MVRP')
338 self.assertTrue(output, '99')
339
340 def test_macvtap(self):
341 self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
342 self.start_networkd()
343
344 self.assertTrue(self.link_exits('macvtap99'))
345
346 def test_macvlan(self):
347 self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
348 self.start_networkd()
349
350 self.assertTrue(self.link_exits('macvlan99'))
351
352 @expectedFailureIfModuleIsNotAvailable('ipvlan')
353 def test_ipvlan(self):
354 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
355 self.start_networkd()
356
357 self.assertTrue(self.link_exits('ipvlan99'))
358
359 def test_veth(self):
360 self.copy_unit_to_networkd_unit_path('25-veth.netdev')
361 self.start_networkd()
362
363 self.assertTrue(self.link_exits('veth99'))
364
365 def test_dummy(self):
366 self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
367 self.start_networkd()
368
369 self.assertTrue(self.link_exits('test1'))
370
371 def test_tun(self):
372 self.copy_unit_to_networkd_unit_path('25-tun.netdev')
373 self.start_networkd()
374
375 self.assertTrue(self.link_exits('tun99'))
376
377 def test_tap(self):
378 self.copy_unit_to_networkd_unit_path('25-tap.netdev')
379 self.start_networkd()
380
381 self.assertTrue(self.link_exits('tap99'))
382
383 @expectedFailureIfModuleIsNotAvailable('vrf')
384 def test_vrf(self):
385 self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
386 self.start_networkd()
387
388 self.assertTrue(self.link_exits('vrf99'))
389
390 @expectedFailureIfModuleIsNotAvailable('vcan')
391 def test_vcan(self):
392 self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
393 self.start_networkd()
394
395 self.assertTrue(self.link_exits('vcan99'))
396
397 @expectedFailureIfModuleIsNotAvailable('wireguard')
398 def test_wireguard(self):
399 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
400 self.start_networkd()
401
402 if shutil.which('wg'):
403 subprocess.call('wg')
404 output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
405 self.assertTrue(output, '51820')
406 output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
407 self.assertTrue(output, '0x4d2')
408 output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
409 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
410 output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
411 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20')
412 output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
413 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820')
414
415 self.assertTrue(self.link_exits('wg99'))
416
417 @expectedFailureIfModuleIsNotAvailable('wireguard')
418 def test_wireguard_23_peers(self):
419 self.copy_unit_to_networkd_unit_path('25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network')
420 self.start_networkd()
421
422 if shutil.which('wg'):
423 subprocess.call('wg')
424
425 self.assertTrue(self.link_exits('wg98'))
426
427 def test_geneve(self):
428 self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
429 self.start_networkd()
430
431 self.assertTrue(self.link_exits('geneve99'))
432
433 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
434 print(output)
435 self.assertTrue(output, '192.168.22.1')
436 self.assertTrue(output, '6082')
437 self.assertTrue(output, 'udpcsum')
438 self.assertTrue(output, 'udp6zerocsumrx')
439
440 def test_ipip_tunnel(self):
441 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network')
442 self.start_networkd()
443
444 self.assertTrue(self.link_exits('dummy98'))
445 self.assertTrue(self.link_exits('ipiptun99'))
446
447 def test_gre_tunnel(self):
448 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network')
449 self.start_networkd()
450
451 self.assertTrue(self.link_exits('dummy98'))
452 self.assertTrue(self.link_exits('gretun99'))
453
454 def test_gretap_tunnel(self):
455 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network')
456 self.start_networkd()
457
458 self.assertTrue(self.link_exits('dummy98'))
459 self.assertTrue(self.link_exits('gretap99'))
460
461 def test_ip6gretap_tunnel(self):
462 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretap.network')
463 self.start_networkd()
464
465 self.assertTrue(self.link_exits('dummy98'))
466 self.assertTrue(self.link_exits('ip6gretap99'))
467
468 def test_vti_tunnel(self):
469 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network')
470 self.start_networkd()
471
472 self.assertTrue(self.link_exits('dummy98'))
473 self.assertTrue(self.link_exits('vtitun99'))
474
475 def test_vti6_tunnel(self):
476 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network')
477 self.start_networkd()
478
479 self.assertTrue(self.link_exits('dummy98'))
480 self.assertTrue(self.link_exits('vti6tun99'))
481
482 def test_ip6tnl_tunnel(self):
483 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network')
484 self.start_networkd()
485
486 self.assertTrue(self.link_exits('dummy98'))
487 self.assertTrue(self.link_exits('ip6tnl99'))
488
489 def test_sit_tunnel(self):
490 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network')
491 self.start_networkd()
492
493 self.assertTrue(self.link_exits('dummy98'))
494 self.assertTrue(self.link_exits('sittun99'))
495
496 def test_isatap_tunnel(self):
497 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
498 self.start_networkd()
499
500 self.assertTrue(self.link_exits('dummy98'))
501 self.assertTrue(self.link_exits('isataptun99'))
502
503 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
504 print(output)
505 self.assertRegex(output, "isatap ")
506
507 def test_6rd_tunnel(self):
508 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
509 self.start_networkd()
510
511 self.assertTrue(self.link_exits('dummy98'))
512 self.assertTrue(self.link_exits('sittun99'))
513
514 @expectedFailureIfERSPANModuleIsNotAvailable()
515 def test_erspan_tunnel(self):
516 self.copy_unit_to_networkd_unit_path('25-erspan-tunnel.netdev')
517 self.start_networkd()
518
519 self.assertTrue(self.link_exits('erspan-test'))
520
521 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan-test']).rstrip().decode('utf-8')
522 print(output)
523 self.assertTrue(output, '172.16.1.200')
524 self.assertTrue(output, '172.16.1.100')
525 self.assertTrue(output, '101')
526
527 def test_tunnel_independent(self):
528 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
529 self.start_networkd()
530
531 self.assertTrue(self.link_exits('ipiptun99'))
532
533 def test_vxlan(self):
534 self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network','11-dummy.netdev')
535 self.start_networkd()
536
537 self.assertTrue(self.link_exits('vxlan99'))
538
539 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
540 print(output)
541 self.assertRegex(output, "999")
542 self.assertRegex(output, '5555')
543 self.assertRegex(output, 'l2miss')
544 self.assertRegex(output, 'l3miss')
545 self.assertRegex(output, 'udpcsum')
546 self.assertRegex(output, 'udp6zerocsumtx')
547 self.assertRegex(output, 'udp6zerocsumrx')
548 self.assertRegex(output, 'remcsumtx')
549 self.assertRegex(output, 'remcsumrx')
550 self.assertRegex(output, 'gbp')
551
552 class NetworkdNetWorkTests(unittest.TestCase, Utilities):
553 links = [
554 'bond199',
555 'dummy98',
556 'test1']
557
558 units = [
559 '11-dummy.netdev',
560 '12-dummy.netdev',
561 '23-active-slave.network',
562 '23-bond199.network',
563 '23-primary-slave.network',
564 '23-test1-bond199.network',
565 '25-address-link-section.network',
566 '25-address-section-miscellaneous.network',
567 '25-address-section.network',
568 '25-bond-active-backup-slave.netdev',
569 '25-fibrule-invert.network',
570 '25-fibrule-port-range.network',
571 '25-ipv6-address-label-section.network',
572 '25-neighbor-section.network',
573 '25-link-section-unmanaged.network',
574 '25-route-gateway.network',
575 '25-route-gateway-on-link.network',
576 '25-route-ipv6-src.network',
577 '25-route-reverse-order.network',
578 '25-route-section.network',
579 '25-route-tcp-window-settings.network',
580 '25-route-type.network',
581 '25-sysctl.network',
582 'configure-without-carrier.network',
583 'routing-policy-rule.network',
584 'test-static.network']
585
586 def setUp(self):
587 self.link_remove(self.links)
588
589 def tearDown(self):
590 self.link_remove(self.links)
591 self.remove_unit_from_networkd_path(self.units)
592
593 def test_static_address(self):
594 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'test-static.network')
595 self.start_networkd()
596
597 self.assertTrue(self.link_exits('dummy98'))
598
599 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
600 print(output)
601 self.assertRegex(output, '192.168.0.15')
602 self.assertRegex(output, '192.168.0.1')
603 self.assertRegex(output, 'routable')
604
605 def test_configure_without_carrier(self):
606 self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
607 self.start_networkd()
608
609 self.assertTrue(self.link_exits('test1'))
610
611 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
612 print(output)
613 self.assertRegex(output, '192.168.0.15')
614 self.assertRegex(output, '192.168.0.1')
615 self.assertRegex(output, 'routable')
616
617 def test_bond_active_slave(self):
618 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
619 self.start_networkd()
620
621 self.assertTrue(self.link_exits('dummy98'))
622 self.assertTrue(self.link_exits('bond199'))
623
624 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
625 print(output)
626 self.assertRegex(output, 'active_slave dummy98')
627
628 def test_bond_primary_slave(self):
629 self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
630 self.start_networkd()
631
632 self.assertTrue(self.link_exits('test1'))
633 self.assertTrue(self.link_exits('bond199'))
634
635 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
636 print(output)
637 self.assertRegex(output, 'primary test1')
638
639 def test_routing_policy_rule(self):
640 self.copy_unit_to_networkd_unit_path('routing-policy-rule.network', '11-dummy.netdev')
641 self.start_networkd()
642
643 self.assertTrue(self.link_exits('test1'))
644
645 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
646 print(output)
647 self.assertRegex(output, '111')
648 self.assertRegex(output, 'from 192.168.100.18')
649 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
650 self.assertRegex(output, 'iif test1')
651 self.assertRegex(output, 'oif test1')
652 self.assertRegex(output, 'lookup 7')
653
654 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
655
656 def test_routing_policy_rule_port_range(self):
657 self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
658 self.start_networkd()
659
660 self.assertTrue(self.link_exits('test1'))
661
662 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
663 print(output)
664 self.assertRegex(output, '111')
665 self.assertRegex(output, 'from 192.168.100.18')
666 self.assertRegex(output, '1123-1150')
667 self.assertRegex(output, '3224-3290')
668 self.assertRegex(output, 'tcp')
669 self.assertRegex(output, 'lookup 7')
670
671 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
672
673 def test_routing_policy_rule_invert(self):
674 self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
675 self.start_networkd()
676
677 self.assertTrue(self.link_exits('test1'))
678
679 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
680 print(output)
681 self.assertRegex(output, '111')
682 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
683 self.assertRegex(output, 'tcp')
684 self.assertRegex(output, 'lookup 7')
685
686 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
687
688 def test_address_peer(self):
689 self.copy_unit_to_networkd_unit_path('25-address-section.network', '12-dummy.netdev')
690 self.start_networkd()
691
692 self.assertTrue(self.link_exits('dummy98'))
693
694 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
695 print(output)
696 self.assertRegex(output, 'inet 10.2.3.4 peer 10.2.3.5/16 scope global 32')
697 self.assertRegex(output, 'inet 10.6.7.8/16 brd 10.6.255.255 scope global 33')
698 self.assertRegex(output, 'inet6 2001:db8::20 peer 2001:db8::10/128 scope global')
699
700 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
701 print(output)
702 self.assertRegex(output, 'State: routable \(configured\)')
703
704 def test_address_preferred_lifetime_zero_ipv6(self):
705 self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev')
706 self.start_networkd()
707
708 self.assertTrue(self.link_exits('dummy98'))
709
710 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
711 print(output)
712 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
713 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
714
715 def test_ip_route(self):
716 self.copy_unit_to_networkd_unit_path('25-route-section.network', '12-dummy.netdev')
717 self.start_networkd()
718
719 self.assertTrue(self.link_exits('dummy98'))
720
721 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98']).rstrip().decode('utf-8')
722 print(output)
723 self.assertRegex(output, '192.168.0.1')
724 self.assertRegex(output, 'static')
725 self.assertRegex(output, '192.168.0.0/24')
726
727 def test_ip_route_reverse(self):
728 self.copy_unit_to_networkd_unit_path('25-route-reverse-order.network', '12-dummy.netdev')
729 self.start_networkd()
730
731 self.assertTrue(self.link_exits('dummy98'))
732
733 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
734 print(output)
735 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff')
736 self.assertRegex(output, '2001:1234:5:8f63::1')
737
738 def test_ip_route_blackhole_unreachable_prohibit(self):
739 self.copy_unit_to_networkd_unit_path('25-route-type.network', '12-dummy.netdev')
740 self.start_networkd()
741
742 self.assertTrue(self.link_exits('dummy98'))
743
744 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
745 print(output)
746 self.assertRegex(output, 'blackhole')
747 self.assertRegex(output, 'unreachable')
748 self.assertRegex(output, 'prohibit')
749
750 subprocess.call(['ip', 'route', 'del', 'blackhole', '202.54.1.2'])
751 subprocess.call(['ip', 'route', 'del', 'unreachable', '202.54.1.3'])
752 subprocess.call(['ip', 'route', 'del', 'prohibit', '202.54.1.4'])
753
754 def test_ip_route_tcp_window(self):
755 self.copy_unit_to_networkd_unit_path('25-route-tcp-window-settings.network', '11-dummy.netdev')
756 self.start_networkd()
757
758 self.assertTrue(self.link_exits('test1'))
759
760 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
761 print(output)
762 self.assertRegex(output, 'initcwnd 20')
763 self.assertRegex(output, 'initrwnd 30')
764
765 def test_ip_route_gateway(self):
766 self.copy_unit_to_networkd_unit_path('25-route-gateway.network', '12-dummy.netdev')
767 self.start_networkd()
768
769 self.assertTrue(self.link_exits('dummy98'))
770
771 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
772 print(output)
773 self.assertRegex(output, 'default')
774 self.assertRegex(output, 'via')
775 self.assertRegex(output, '149.10.124.64')
776 self.assertRegex(output, 'proto')
777 self.assertRegex(output, 'static')
778
779 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
780 print(output)
781 self.assertRegex(output, '149.10.124.48/28')
782 self.assertRegex(output, 'proto')
783 self.assertRegex(output, 'kernel')
784 self.assertRegex(output, 'scope')
785 self.assertRegex(output, 'link')
786
787 def test_ip_route_gateway_on_link(self):
788 self.copy_unit_to_networkd_unit_path('25-route-gateway-on-link.network', '12-dummy.netdev')
789 self.start_networkd()
790
791 self.assertTrue(self.link_exits('dummy98'))
792
793 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
794 print(output)
795 self.assertRegex(output, 'default')
796 self.assertRegex(output, 'via')
797 self.assertRegex(output, '149.10.125.65')
798 self.assertRegex(output, 'proto')
799 self.assertRegex(output, 'static')
800 self.assertRegex(output, 'onlink')
801
802 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
803 print(output)
804 self.assertRegex(output, '149.10.124.48/28')
805 self.assertRegex(output, 'proto')
806 self.assertRegex(output, 'kernel')
807 self.assertRegex(output, 'scope')
808 self.assertRegex(output, 'link')
809
810 def test_ip_route_ipv6_src_route(self):
811 # a dummy device does not make the addresses go through tentative state, so we
812 # reuse a bond from an earlier test, which does make the addresses go through
813 # tentative state, and do our test on that
814 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
815 self.start_networkd()
816
817 self.assertTrue(self.link_exits('dummy98'))
818 self.assertTrue(self.link_exits('bond199'))
819
820 output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8')
821 print(output)
822 self.assertRegex(output, 'abcd::/16')
823 self.assertRegex(output, 'src')
824 self.assertRegex(output, '2001:1234:56:8f63::2')
825
826 def test_ip_link_mac_address(self):
827 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
828 self.start_networkd()
829
830 self.assertTrue(self.link_exits('dummy98'))
831
832 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
833 print(output)
834 self.assertRegex(output, '00:01:02:aa:bb:cc')
835
836 def test_ip_link_unmanaged(self):
837 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
838 self.start_networkd()
839
840 self.assertTrue(self.link_exits('dummy98'))
841
842 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
843 print(output)
844 self.assertRegex(output, 'unmanaged')
845
846 def test_ipv6_address_label(self):
847 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
848 self.start_networkd()
849
850 self.assertTrue(self.link_exits('dummy98'))
851
852 output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
853 print(output)
854 self.assertRegex(output, '2004:da8:1::/64')
855
856 def test_ipv6_neighbor(self):
857 self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
858 self.start_networkd()
859
860 self.assertTrue(self.link_exits('dummy98'))
861
862 output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
863 print(output)
864 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
865 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
866
867 def test_sysctl(self):
868 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
869 self.start_networkd()
870
871 self.assertTrue(self.link_exits('dummy98'))
872
873 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
874 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
875 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
876 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
877 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
878 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
879 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
880
881 class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
882 links = [
883 'bridge99',
884 'dummy98',
885 'test1']
886
887 units = [
888 '11-dummy.netdev',
889 '12-dummy.netdev',
890 '26-bridge.netdev',
891 '26-bridge-slave-interface-1.network',
892 '26-bridge-slave-interface-2.network',
893 'bridge99.network']
894
895 def setUp(self):
896 self.link_remove(self.links)
897
898 def tearDown(self):
899 self.link_remove(self.links)
900 self.remove_unit_from_networkd_path(self.units)
901
902 def test_bridge_property(self):
903 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
904 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
905 'bridge99.network')
906 self.start_networkd()
907
908 self.assertTrue(self.link_exits('dummy98'))
909 self.assertTrue(self.link_exits('test1'))
910 self.assertTrue(self.link_exits('bridge99'))
911
912 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
913 print(output)
914 self.assertRegex(output, 'master')
915 self.assertRegex(output, 'bridge')
916
917 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
918 print(output)
919 self.assertRegex(output, 'master')
920 self.assertRegex(output, 'bridge')
921
922 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
923 print(output)
924 self.assertRegex(output, '192.168.0.15')
925 self.assertRegex(output, '192.168.0.1')
926
927 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
928 print(output)
929 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
930 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
931 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
932 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
933
934 # CONFIG_BRIDGE_IGMP_SNOOPING=y
935 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
936 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
937
938 class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
939 links = ['veth99']
940
941 units = [
942 '23-emit-lldp.network',
943 '24-lldp.network',
944 '25-veth.netdev']
945
946 def setUp(self):
947 self.link_remove(self.links)
948
949 def tearDown(self):
950 self.link_remove(self.links)
951 self.remove_unit_from_networkd_path(self.units)
952
953 def test_lldp(self):
954 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
955 self.start_networkd()
956
957 self.assertTrue(self.link_exits('veth99'))
958
959 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
960 print(output)
961 self.assertRegex(output, 'veth-peer')
962 self.assertRegex(output, 'veth99')
963
964 class NetworkdNetworkRATests(unittest.TestCase, Utilities):
965 links = ['veth99']
966
967 units = [
968 '25-veth.netdev',
969 'ipv6-prefix.network',
970 'ipv6-prefix-veth.network']
971
972 def setUp(self):
973 self.link_remove(self.links)
974
975 def tearDown(self):
976 self.link_remove(self.links)
977 self.remove_unit_from_networkd_path(self.units)
978
979 def test_ipv6_prefix_delegation(self):
980 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
981 self.start_networkd()
982
983 self.assertTrue(self.link_exits('veth99'))
984
985 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
986 print(output)
987 self.assertRegex(output, '2002:da8:1:0')
988
989 class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
990 links = [
991 'dummy98',
992 'veth99']
993
994 units = [
995 '12-dummy.netdev',
996 '24-search-domain.network',
997 '25-veth.netdev',
998 'dhcp-client.network',
999 'dhcp-client-timezone-router.network',
1000 'dhcp-server.network',
1001 'dhcp-server-timezone-router.network']
1002
1003 def setUp(self):
1004 self.link_remove(self.links)
1005
1006 def tearDown(self):
1007 self.link_remove(self.links)
1008 self.remove_unit_from_networkd_path(self.units)
1009
1010 def test_dhcp_server(self):
1011 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
1012 self.start_networkd()
1013
1014 self.assertTrue(self.link_exits('veth99'))
1015
1016 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1017 print(output)
1018 self.assertRegex(output, '192.168.5.*')
1019 self.assertRegex(output, 'Gateway: 192.168.5.1')
1020 self.assertRegex(output, 'DNS: 192.168.5.1')
1021 self.assertRegex(output, 'NTP: 192.168.5.1')
1022
1023 def test_domain(self):
1024 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1025 self.start_networkd()
1026
1027 self.assertTrue(self.link_exits('dummy98'))
1028
1029 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1030 print(output)
1031 self.assertRegex(output, 'Address: 192.168.42.100')
1032 self.assertRegex(output, 'DNS: 192.168.42.1')
1033 self.assertRegex(output, 'Search Domains: one')
1034
1035 def test_emit_router_timezone(self):
1036 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
1037 self.start_networkd()
1038
1039 self.assertTrue(self.link_exits('veth99'))
1040
1041 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1042 print(output)
1043 self.assertRegex(output, 'Gateway: 192.168.5.*')
1044 self.assertRegex(output, '192.168.5.*')
1045 self.assertRegex(output, 'Europe/Berlin')
1046
1047 class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
1048 links = [
1049 'dummy98',
1050 'veth99']
1051
1052 units = [
1053 '25-veth.netdev',
1054 'dhcp-client-anonymize.network',
1055 'dhcp-client-critical-connection.network',
1056 'dhcp-client-ipv4-dhcp-settings.network',
1057 'dhcp-client-ipv4-only-ipv6-disabled.network',
1058 'dhcp-client-ipv4-only.network',
1059 'dhcp-client-ipv6-only.network',
1060 'dhcp-client-ipv6-rapid-commit.network',
1061 'dhcp-client-listen-port.network',
1062 'dhcp-client-route-metric.network',
1063 'dhcp-client-route-table.network',
1064 'dhcp-client.network',
1065 'dhcp-server-veth-peer.network',
1066 'dhcp-v4-server-veth-peer.network',
1067 'static.network']
1068
1069 def setUp(self):
1070 self.link_remove(self.links)
1071 self.stop_dnsmasq(dnsmasq_pid_file)
1072
1073 def tearDown(self):
1074 self.link_remove(self.links)
1075 self.remove_unit_from_networkd_path(self.units)
1076 self.stop_dnsmasq(dnsmasq_pid_file)
1077 self.remove_lease_file()
1078 self.remove_log_file()
1079
1080 def test_dhcp_client_ipv6_only(self):
1081 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1082 self.start_networkd()
1083
1084 self.assertTrue(self.link_exits('veth99'))
1085
1086 self.start_dnsmasq()
1087
1088 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1089 print(output)
1090 self.assertRegex(output, '2600::')
1091 self.assertNotRegex(output, '192.168.5')
1092
1093 def test_dhcp_client_ipv4_only(self):
1094 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1095 self.start_networkd()
1096
1097 self.assertTrue(self.link_exits('veth99'))
1098
1099 self.start_dnsmasq()
1100
1101 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1102 print(output)
1103 self.assertNotRegex(output, '2600::')
1104 self.assertRegex(output, '192.168.5')
1105
1106 def test_dhcp_client_ipv4_ipv6(self):
1107 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
1108 'dhcp-client-ipv4-only.network')
1109 self.start_networkd()
1110
1111 self.assertTrue(self.link_exits('veth99'))
1112
1113 self.start_dnsmasq()
1114
1115 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1116 print(output)
1117 self.assertRegex(output, '2600::')
1118 self.assertRegex(output, '192.168.5')
1119
1120 def test_dhcp_client_settings(self):
1121 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1122 self.start_networkd()
1123
1124 self.assertTrue(self.link_exits('veth99'))
1125
1126 self.start_dnsmasq()
1127
1128 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1129 print(output)
1130 self.assertRegex(output, '12:34:56:78:9a:bc')
1131 self.assertRegex(output, '192.168.5')
1132 self.assertRegex(output, '1492')
1133
1134 output = subprocess.check_output(['ip', 'route']).rstrip().decode('utf-8')
1135 print(output)
1136 self.assertRegex(output, 'default.*dev veth99 proto dhcp')
1137
1138 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
1139 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
1140 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
1141 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
1142
1143 def test_dhcp6_client_settings_rapidcommit_true(self):
1144 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1145 self.start_networkd()
1146
1147 self.assertTrue(self.link_exits('veth99'))
1148
1149 self.start_dnsmasq()
1150
1151 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1152 print(output)
1153 self.assertRegex(output, '12:34:56:78:9a:bc')
1154 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1155
1156 def test_dhcp6_client_settings_rapidcommit_false(self):
1157 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
1158 self.start_networkd()
1159
1160 self.assertTrue(self.link_exits('veth99'))
1161
1162 self.start_dnsmasq()
1163
1164 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1165 print(output)
1166 self.assertRegex(output, '12:34:56:78:9a:bc')
1167 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1168
1169 def test_dhcp_client_settings_anonymize(self):
1170 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
1171 self.start_networkd()
1172
1173 self.assertTrue(self.link_exits('veth99'))
1174
1175 self.start_dnsmasq()
1176
1177 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
1178 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
1179 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
1180
1181 def test_dhcp_client_listen_port(self):
1182 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
1183
1184 dh_server = DHCPServer("dhcp_server")
1185 dh_server.start()
1186
1187 self.start_networkd()
1188
1189 self.assertTrue(self.link_exits('veth99'))
1190
1191 global port
1192 global ip
1193
1194 self.assertRegex(str(port), '5555')
1195 self.assertRegex(str(ip), '0.0.0.0')
1196
1197 dh_server.join()
1198
1199 def test_dhcp_route_table_id(self):
1200 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
1201 self.start_networkd()
1202
1203 self.assertTrue(self.link_exits('veth99'))
1204
1205 self.start_dnsmasq()
1206
1207 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
1208 print(output)
1209 self.assertRegex(output, 'veth99 proto dhcp')
1210 self.assertRegex(output, '192.168.5.1')
1211
1212 def test_dhcp_route_metric(self):
1213 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
1214 self.start_networkd()
1215
1216 self.assertTrue(self.link_exits('veth99'))
1217
1218 self.start_dnsmasq()
1219
1220 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1221 print(output)
1222 self.assertRegex(output, 'metric 24')
1223
1224 def test_dhcp_route_criticalconnection_true(self):
1225 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
1226 self.start_networkd()
1227
1228 self.assertTrue(self.link_exits('veth99'))
1229
1230 self.start_dnsmasq()
1231
1232 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1233 print(output)
1234 self.assertRegex(output, '192.168.5.*')
1235
1236 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
1237 self.stop_dnsmasq(dnsmasq_pid_file)
1238
1239 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1240 time.sleep(125)
1241
1242 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1243 print(output)
1244 self.assertRegex(output, '192.168.5.*')
1245
1246 def test_dhcp_client_reuse_address_as_static(self):
1247 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
1248 self.start_networkd()
1249
1250 self.assertTrue(self.link_exits('veth99'))
1251
1252 self.start_dnsmasq()
1253
1254 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1255 print(output)
1256 self.assertRegex(output, '192.168.5')
1257 self.assertRegex(output, '2600::')
1258
1259 ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
1260 ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
1261 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
1262 print(static_network)
1263
1264 self.remove_unit_from_networkd_path(['dhcp-client.network'])
1265
1266 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
1267 f.write(static_network)
1268
1269 self.start_networkd()
1270
1271 self.assertTrue(self.link_exits('veth99'))
1272
1273 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1274 print(output)
1275 self.assertRegex(output, '192.168.5')
1276 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1277
1278 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1279 print(output)
1280 self.assertRegex(output, '2600::')
1281 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1282
1283 if __name__ == '__main__':
1284 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
1285 verbosity=3))