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