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