]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
test: add a testcase for #11458
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
CommitLineData
1f0e3109
SS
1#!/usr/bin/env python3
2# SPDX-License-Identifier: LGPL-2.1+
3# systemd-networkd tests
4
5import os
201bf07f 6import re
1f0e3109
SS
7import shutil
8import signal
9import socket
a9bc5e37
YW
10import subprocess
11import sys
1f0e3109 12import threading
a9bc5e37
YW
13import time
14import unittest
1f0e3109
SS
15from shutil import copytree
16
d486a2d0 17network_unit_file_path='/run/systemd/network'
bad4969b 18networkd_runtime_directory='/run/systemd/netif'
d486a2d0 19networkd_ci_path='/run/networkd-ci'
1f0e3109
SS
20network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
21network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
22
d486a2d0
YW
23dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
24dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
1f0e3109 25
7a0a37b2 26def is_module_available(module_name):
201bf07f
EV
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])
7a0a37b2
EV
30
31def 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
1f0e3109
SS
39def 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)
6aea9276 45 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
1f0e3109 46
c0bf6733
YW
47 subprocess.check_call('systemctl stop systemd-networkd.socket', shell=True)
48
1f0e3109
SS
49def tearDownModule():
50 shutil.rmtree(networkd_ci_path)
51
c0bf6733
YW
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
1f0e3109
SS
56class 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
4d7ed14f
SS
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
1f0e3109
SS
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])
9a4720a9 79 time.sleep(1)
1f0e3109
SS
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)
013c8dc9
YW
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'))
1f0e3109
SS
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))
013c8dc9
YW
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'))
1f0e3109
SS
101
102 def start_dnsmasq(self):
6f783ce5 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)
1f0e3109
SS
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
131717cb 115 def search_words_in_dnsmasq_log(self, words, show_all=False):
1f0e3109
SS
116 if os.path.exists(dnsmasq_log_file):
117 with open (dnsmasq_log_file) as in_file:
118 contents = in_file.read()
131717cb
YW
119 if show_all:
120 print(contents)
121 for line in contents.split('\n'):
122 if words in line:
1f0e3109 123 in_file.close()
131717cb 124 print("%s, %s" % (words, line))
1f0e3109
SS
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):
bad4969b
YW
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)
1f0e3109 143 time.sleep(5)
fa7cd602 144 print()
1f0e3109
SS
145
146global ip
147global port
148
149class 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
173class NetworkdNetDevTests(unittest.TestCase, Utilities):
174
09ea6724
YW
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',
da44fb8a 203 'wg98',
09ea6724
YW
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',
fde60a42 216 '25-bond-balanced-tlb.netdev',
09ea6724
YW
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',
da44fb8a
YW
237 '25-wireguard-23-peers.netdev',
238 '25-wireguard-23-peers.network',
09ea6724
YW
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']
1f0e3109
SS
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
d80734f7
YW
263 def test_dropin(self):
264 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
d80734f7
YW
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
1f0e3109
SS
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
99f68ef0
TJ
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'))
1f0e3109 305
fde60a42
SS
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
1f0e3109
SS
315 def test_vlan(self):
316 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
1f0e3109
SS
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')
14ecd604 322 print(output)
1f0e3109
SS
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')
1f0e3109
SS
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')
1f0e3109
SS
337 self.start_networkd()
338
339 self.assertTrue(self.link_exits('macvlan99'))
340
7a0a37b2 341 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109
SS
342 def test_ipvlan(self):
343 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
1f0e3109
SS
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')
1f0e3109
SS
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')
1f0e3109
SS
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')
1f0e3109
SS
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')
1f0e3109
SS
368 self.start_networkd()
369
370 self.assertTrue(self.link_exits('tap99'))
371
7a0a37b2 372 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109
SS
373 def test_vrf(self):
374 self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
1f0e3109
SS
375 self.start_networkd()
376
377 self.assertTrue(self.link_exits('vrf99'))
378
7a0a37b2 379 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109
SS
380 def test_vcan(self):
381 self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
1f0e3109
SS
382 self.start_networkd()
383
384 self.assertTrue(self.link_exits('vcan99'))
385
7a3bc5a8
EV
386 @expectedFailureIfModuleIsNotAvailable('wireguard')
387 def test_wireguard(self):
388 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
7a3bc5a8
EV
389 self.start_networkd()
390
391 if shutil.which('wg'):
392 subprocess.call('wg')
393
394 self.assertTrue(self.link_exits('wg99'))
395
da44fb8a
YW
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
1f0e3109
SS
406 def test_geneve(self):
407 self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
1f0e3109
SS
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')
14ecd604 413 print(output)
1f0e3109
SS
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
d0e728b6
SS
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'))
e40a58b5 481
d0e728b6 482 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
14ecd604 483 print(output)
d0e728b6
SS
484 self.assertRegex(output, "isatap ")
485
d29dc4f1
DA
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
2266864b
SS
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
1f0e3109
SS
505 def test_tunnel_independent(self):
506 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
1f0e3109 507 self.start_networkd()
e40a58b5 508
1f0e3109
SS
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')
1f0e3109
SS
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')
14ecd604 518 print(output)
1f0e3109
SS
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
530class NetworkdNetWorkTests(unittest.TestCase, Utilities):
09ea6724
YW
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',
e4a71bf3 550 '25-neighbor-section.network',
09ea6724
YW
551 '25-link-section-unmanaged.network',
552 '25-route-gateway.network',
553 '25-route-gateway-on-link.network',
554 '25-route-reverse-order.network',
555 '25-route-section.network',
556 '25-route-tcp-window-settings.network',
557 '25-route-type.network',
558 '25-sysctl.network',
559 'configure-without-carrier.network',
560 'routing-policy-rule.network',
561 'test-static.network']
1f0e3109
SS
562
563 def setUp(self):
564 self.link_remove(self.links)
565
566 def tearDown(self):
567 self.link_remove(self.links)
568 self.remove_unit_from_networkd_path(self.units)
569
570 def test_static_address(self):
571 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'test-static.network')
572 self.start_networkd()
573
574 self.assertTrue(self.link_exits('dummy98'))
e40a58b5 575
1f0e3109
SS
576 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
577 print(output)
578 self.assertRegex(output, '192.168.0.15')
579 self.assertRegex(output, '192.168.0.1')
580 self.assertRegex(output, 'routable')
581
582 def test_configure_without_carrier(self):
583 self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
584 self.start_networkd()
585
586 self.assertTrue(self.link_exits('test1'))
e40a58b5 587
1f0e3109
SS
588 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
589 print(output)
590 self.assertRegex(output, '192.168.0.15')
591 self.assertRegex(output, '192.168.0.1')
592 self.assertRegex(output, 'routable')
593
594 def test_bond_active_slave(self):
595 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
596 self.start_networkd()
597
598 self.assertTrue(self.link_exits('dummy98'))
599 self.assertTrue(self.link_exits('bond199'))
e40a58b5 600
1f0e3109
SS
601 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
602 print(output)
603 self.assertRegex(output, 'active_slave dummy98')
604
605 def test_bond_primary_slave(self):
606 self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
607 self.start_networkd()
608
609 self.assertTrue(self.link_exits('test1'))
610 self.assertTrue(self.link_exits('bond199'))
e40a58b5 611
1f0e3109
SS
612 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
613 print(output)
614 self.assertRegex(output, 'primary test1')
615
616 def test_routing_policy_rule(self):
617 self.copy_unit_to_networkd_unit_path('routing-policy-rule.network', '11-dummy.netdev')
618 self.start_networkd()
619
620 self.assertTrue(self.link_exits('test1'))
e40a58b5 621
1f0e3109
SS
622 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
623 print(output)
624 self.assertRegex(output, '111')
625 self.assertRegex(output, 'from 192.168.100.18')
f7bdd562 626 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
1f0e3109
SS
627 self.assertRegex(output, 'iif test1')
628 self.assertRegex(output, 'oif test1')
629 self.assertRegex(output, 'lookup 7')
630
e4eacdb0
YW
631 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
632
926062f0
SS
633 def test_routing_policy_rule_port_range(self):
634 self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
635 self.start_networkd()
636
637 self.assertTrue(self.link_exits('test1'))
e40a58b5 638
926062f0
SS
639 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
640 print(output)
641 self.assertRegex(output, '111')
642 self.assertRegex(output, 'from 192.168.100.18')
643 self.assertRegex(output, '1123-1150')
644 self.assertRegex(output, '3224-3290')
645 self.assertRegex(output, 'tcp')
646 self.assertRegex(output, 'lookup 7')
1f0e3109 647
e4eacdb0
YW
648 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
649
efecf9cd
SS
650 def test_routing_policy_rule_invert(self):
651 self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
652 self.start_networkd()
653
654 self.assertTrue(self.link_exits('test1'))
e40a58b5 655
efecf9cd
SS
656 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
657 print(output)
efecf9cd
SS
658 self.assertRegex(output, '111')
659 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
660 self.assertRegex(output, 'tcp')
661 self.assertRegex(output, 'lookup 7')
662
e4eacdb0
YW
663 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
664
ac60877f
YW
665 def test_address_peer(self):
666 self.copy_unit_to_networkd_unit_path('25-address-section.network', '12-dummy.netdev')
667 self.start_networkd()
668
669 self.assertTrue(self.link_exits('dummy98'))
670
671 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
672 print(output)
673 self.assertRegex(output, 'inet 10.2.3.4 peer 10.2.3.5/16 scope global 32')
674 self.assertRegex(output, 'inet 10.6.7.8/16 brd 10.6.255.255 scope global 33')
7e663619 675 self.assertRegex(output, 'inet6 2001:db8::20 peer 2001:db8::10/128 scope global')
ac60877f
YW
676
677 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
678 print(output)
679 self.assertRegex(output, 'State: routable \(configured\)')
680
1f0e3109
SS
681 def test_address_preferred_lifetime_zero_ipv6(self):
682 self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev')
683 self.start_networkd()
684
685 self.assertTrue(self.link_exits('dummy98'))
686
687 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
688 print(output)
689 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
690 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
691
692 def test_ip_route(self):
693 self.copy_unit_to_networkd_unit_path('25-route-section.network', '12-dummy.netdev')
694 self.start_networkd()
695
696 self.assertTrue(self.link_exits('dummy98'))
697
698 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98']).rstrip().decode('utf-8')
699 print(output)
700 self.assertRegex(output, '192.168.0.1')
701 self.assertRegex(output, 'static')
702 self.assertRegex(output, '192.168.0.0/24')
703
0d34228f
SS
704 def test_ip_route_reverse(self):
705 self.copy_unit_to_networkd_unit_path('25-route-reverse-order.network', '12-dummy.netdev')
706 self.start_networkd()
707
708 self.assertTrue(self.link_exits('dummy98'))
709
710 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
711 print(output)
712 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff')
713 self.assertRegex(output, '2001:1234:5:8f63::1')
714
1f0e3109
SS
715 def test_ip_route_blackhole_unreachable_prohibit(self):
716 self.copy_unit_to_networkd_unit_path('25-route-type.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']).rstrip().decode('utf-8')
722 print(output)
723 self.assertRegex(output, 'blackhole')
724 self.assertRegex(output, 'unreachable')
725 self.assertRegex(output, 'prohibit')
726
727 subprocess.call(['ip', 'route', 'del', 'blackhole', '202.54.1.2'])
728 subprocess.call(['ip', 'route', 'del', 'unreachable', '202.54.1.3'])
729 subprocess.call(['ip', 'route', 'del', 'prohibit', '202.54.1.4'])
730
731 def test_ip_route_tcp_window(self):
732 self.copy_unit_to_networkd_unit_path('25-route-tcp-window-settings.network', '11-dummy.netdev')
733 self.start_networkd()
734
735 self.assertTrue(self.link_exits('test1'))
736
737 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
738 print(output)
739 self.assertRegex(output, 'initcwnd 20')
740 self.assertRegex(output, 'initrwnd 30')
741
f5050e48
YW
742 def test_ip_route_gateway(self):
743 self.copy_unit_to_networkd_unit_path('25-route-gateway.network', '12-dummy.netdev')
744 self.start_networkd()
745
746 self.assertTrue(self.link_exits('dummy98'))
747
748 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
749 print(output)
750 self.assertRegex(output, 'default')
751 self.assertRegex(output, 'via')
752 self.assertRegex(output, '149.10.124.64')
753 self.assertRegex(output, 'proto')
754 self.assertRegex(output, 'static')
755
756 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
757 print(output)
758 self.assertRegex(output, '149.10.124.48/28')
759 self.assertRegex(output, 'proto')
760 self.assertRegex(output, 'kernel')
761 self.assertRegex(output, 'scope')
762 self.assertRegex(output, 'link')
763
764 def test_ip_route_gateway_on_link(self):
765 self.copy_unit_to_networkd_unit_path('25-route-gateway-on-link.network', '12-dummy.netdev')
766 self.start_networkd()
767
768 self.assertTrue(self.link_exits('dummy98'))
769
770 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
771 print(output)
772 self.assertRegex(output, 'default')
773 self.assertRegex(output, 'via')
774 self.assertRegex(output, '149.10.125.65')
775 self.assertRegex(output, 'proto')
776 self.assertRegex(output, 'static')
777 self.assertRegex(output, 'onlink')
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
1f0e3109
SS
787 def test_ip_link_mac_address(self):
788 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
789 self.start_networkd()
790
791 self.assertTrue(self.link_exits('dummy98'))
792
793 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
794 print(output)
795 self.assertRegex(output, '00:01:02:aa:bb:cc')
796
797 def test_ip_link_unmanaged(self):
798 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
799 self.start_networkd()
800
801 self.assertTrue(self.link_exits('dummy98'))
802
803 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
804 print(output)
805 self.assertRegex(output, 'unmanaged')
806
807 def test_ipv6_address_label(self):
808 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
809 self.start_networkd()
810
811 self.assertTrue(self.link_exits('dummy98'))
812
813 output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
814 print(output)
815 self.assertRegex(output, '2004:da8:1::/64')
816
e4a71bf3
WKI
817 def test_ipv6_neighbor(self):
818 self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
819 self.start_networkd()
820
821 self.assertTrue(self.link_exits('dummy98'))
822
823 output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
824 print(output)
825 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 826 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 827
1f0e3109
SS
828 def test_sysctl(self):
829 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
830 self.start_networkd()
831
832 self.assertTrue(self.link_exits('dummy98'))
833
834 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
835 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
836 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
837 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
838 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
839 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
840 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
841
14dc0335 842class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
843 links = [
844 'bridge99',
845 'dummy98',
846 'test1']
847
848 units = [
849 '11-dummy.netdev',
850 '12-dummy.netdev',
851 '26-bridge.netdev',
852 '26-bridge-slave-interface-1.network',
853 '26-bridge-slave-interface-2.network',
854 'bridge99.network']
1f0e3109
SS
855
856 def setUp(self):
857 self.link_remove(self.links)
858
859 def tearDown(self):
860 self.link_remove(self.links)
861 self.remove_unit_from_networkd_path(self.units)
862
863 def test_bridge_property(self):
864 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
865 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
866 'bridge99.network')
867 self.start_networkd()
868
869 self.assertTrue(self.link_exits('dummy98'))
870 self.assertTrue(self.link_exits('test1'))
871 self.assertTrue(self.link_exits('bridge99'))
872
873 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
874 print(output)
875 self.assertRegex(output, 'master')
876 self.assertRegex(output, 'bridge')
877
878 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
879 print(output)
880 self.assertRegex(output, 'master')
881 self.assertRegex(output, 'bridge')
882
883 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
884 print(output)
885 self.assertRegex(output, '192.168.0.15')
886 self.assertRegex(output, '192.168.0.1')
887
888 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
889 print(output)
4d7ed14f
SS
890 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
891 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
892 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
893 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
894
895 # CONFIG_BRIDGE_IGMP_SNOOPING=y
896 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
897 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1f0e3109
SS
898
899class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
900 links = ['veth99']
901
09ea6724
YW
902 units = [
903 '23-emit-lldp.network',
904 '24-lldp.network',
905 '25-veth.netdev']
1f0e3109
SS
906
907 def setUp(self):
908 self.link_remove(self.links)
909
910 def tearDown(self):
911 self.link_remove(self.links)
912 self.remove_unit_from_networkd_path(self.units)
913
914 def test_lldp(self):
915 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
916 self.start_networkd()
917
918 self.assertTrue(self.link_exits('veth99'))
919
920 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
921 print(output)
922 self.assertRegex(output, 'veth-peer')
923 self.assertRegex(output, 'veth99')
924
925class NetworkdNetworkRATests(unittest.TestCase, Utilities):
926 links = ['veth99']
927
09ea6724
YW
928 units = [
929 '25-veth.netdev',
930 'ipv6-prefix.network',
931 'ipv6-prefix-veth.network']
1f0e3109
SS
932
933 def setUp(self):
934 self.link_remove(self.links)
935
936 def tearDown(self):
937 self.link_remove(self.links)
938 self.remove_unit_from_networkd_path(self.units)
939
940 def test_ipv6_prefix_delegation(self):
941 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
942 self.start_networkd()
943
944 self.assertTrue(self.link_exits('veth99'))
945
946 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
947 print(output)
948 self.assertRegex(output, '2002:da8:1:0')
949
950class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
09ea6724
YW
951 links = [
952 'dummy98',
953 'veth99']
954
955 units = [
956 '12-dummy.netdev',
957 '24-search-domain.network',
958 '25-veth.netdev',
959 'dhcp-client.network',
960 'dhcp-client-timezone-router.network',
961 'dhcp-server.network',
962 'dhcp-server-timezone-router.network']
1f0e3109
SS
963
964 def setUp(self):
965 self.link_remove(self.links)
966
967 def tearDown(self):
968 self.link_remove(self.links)
969 self.remove_unit_from_networkd_path(self.units)
970
971 def test_dhcp_server(self):
972 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
973 self.start_networkd()
974
975 self.assertTrue(self.link_exits('veth99'))
976
1f0e3109
SS
977 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
978 print(output)
979 self.assertRegex(output, '192.168.5.*')
980 self.assertRegex(output, 'Gateway: 192.168.5.1')
981 self.assertRegex(output, 'DNS: 192.168.5.1')
982 self.assertRegex(output, 'NTP: 192.168.5.1')
983
984 def test_domain(self):
985 self.copy_unit_to_networkd_unit_path( '12-dummy.netdev', '24-search-domain.network')
986 self.start_networkd()
987
988 self.assertTrue(self.link_exits('dummy98'))
989
990 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
991 print(output)
992 self.assertRegex(output, 'Address: 192.168.42.100')
993 self.assertRegex(output, 'DNS: 192.168.42.1')
994 self.assertRegex(output, 'Search Domains: one')
995
996 def test_emit_router_timezone(self):
997 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
998 self.start_networkd()
999
1000 self.assertTrue(self.link_exits('veth99'))
1001
1002 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1003 print(output)
1004 self.assertRegex(output, 'Gateway: 192.168.5.*')
1005 self.assertRegex(output, '192.168.5.*')
1006 self.assertRegex(output, 'Europe/Berlin')
1007
1008class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
09ea6724
YW
1009 links = [
1010 'dummy98',
1011 'veth99']
1012
1013 units = [
1014 '25-veth.netdev',
1015 'dhcp-client-anonymize.network',
1016 'dhcp-client-critical-connection.network',
1017 'dhcp-client-ipv4-dhcp-settings.network',
1018 'dhcp-client-ipv4-only-ipv6-disabled.network',
1019 'dhcp-client-ipv4-only.network',
1020 'dhcp-client-ipv6-only.network',
1021 'dhcp-client-ipv6-rapid-commit.network',
1022 'dhcp-client-listen-port.network',
1023 'dhcp-client-route-metric.network',
1024 'dhcp-client-route-table.network',
30d3b54e 1025 'dhcp-client.network'
09ea6724 1026 'dhcp-server-veth-peer.network',
30d3b54e
YW
1027 'dhcp-v4-server-veth-peer.network',
1028 'static.network']
1f0e3109
SS
1029
1030 def setUp(self):
1031 self.link_remove(self.links)
1032 self.stop_dnsmasq(dnsmasq_pid_file)
1033
1034 def tearDown(self):
1035 self.link_remove(self.links)
1036 self.remove_unit_from_networkd_path(self.units)
1037 self.stop_dnsmasq(dnsmasq_pid_file)
1038 self.remove_lease_file()
1039 self.remove_log_file()
1040
1041 def test_dhcp_client_ipv6_only(self):
1042 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network','dhcp-client-ipv6-only.network')
1043 self.start_networkd()
1044
1045 self.assertTrue(self.link_exits('veth99'))
1046
1047 self.start_dnsmasq()
1048
1049 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1050 print(output)
1051 self.assertRegex(output, '2600::')
1052 self.assertNotRegex(output, '192.168.5')
1053
1054 def test_dhcp_client_ipv4_only(self):
1055 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network','dhcp-client-ipv4-only-ipv6-disabled.network')
1056 self.start_networkd()
1057
1058 self.assertTrue(self.link_exits('veth99'))
1059
1060 self.start_dnsmasq()
1061
1062 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1063 print(output)
1064 self.assertNotRegex(output, '2600::')
1065 self.assertRegex(output, '192.168.5')
1066
1067 def test_dhcp_client_ipv4_ipv6(self):
1068 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
1069 'dhcp-client-ipv4-only.network')
1070 self.start_networkd()
1071
1072 self.assertTrue(self.link_exits('veth99'))
1073
1074 self.start_dnsmasq()
1075
1076 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1077 print(output)
1078 self.assertRegex(output, '2600::')
1079 self.assertRegex(output, '192.168.5')
1080
1081 def test_dhcp_client_settings(self):
1082 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1083 self.start_networkd()
1084
1085 self.assertTrue(self.link_exits('veth99'))
1086
1087 self.start_dnsmasq()
1088
1089 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1090 print(output)
1091 self.assertRegex(output, '12:34:56:78:9a:bc')
1092 self.assertRegex(output, '192.168.5')
1093 self.assertRegex(output, '1492')
1094
1095 output = subprocess.check_output(['ip', 'route']).rstrip().decode('utf-8')
1096 print(output)
1097 self.assertRegex(output, 'default.*dev veth99 proto dhcp')
1098
131717cb
YW
1099 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
1100 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
1101 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
1102 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1103
1104 def test_dhcp6_client_settings_rapidcommit_true(self):
1105 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1106 self.start_networkd()
1107
1108 self.assertTrue(self.link_exits('veth99'))
1109
1110 self.start_dnsmasq()
1111
1112 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1113 print(output)
1114 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1115 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1116
1117 def test_dhcp6_client_settings_rapidcommit_false(self):
1118 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
1119 self.start_networkd()
1120
1121 self.assertTrue(self.link_exits('veth99'))
1122
1123 self.start_dnsmasq()
1124
1125 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1126 print(output)
1127 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1128 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1129
1130 def test_dhcp_client_settings_anonymize(self):
1131 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
1132 self.start_networkd()
1133
1134 self.assertTrue(self.link_exits('veth99'))
1135
1136 self.start_dnsmasq()
e40a58b5 1137
131717cb
YW
1138 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
1139 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
1140 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1141
1142 def test_dhcp_client_listen_port(self):
1143 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
e40a58b5 1144
1f0e3109
SS
1145 dh_server = DHCPServer("dhcp_server")
1146 dh_server.start()
1147
1148 self.start_networkd()
1149
1150 self.assertTrue(self.link_exits('veth99'))
1151
1152 global port
1153 global ip
1154
1155 self.assertRegex(str(port), '5555')
1156 self.assertRegex(str(ip), '0.0.0.0')
1157
1158 dh_server.join()
1159
1160 def test_dhcp_route_table_id(self):
1161 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
1162 self.start_networkd()
1f0e3109
SS
1163
1164 self.assertTrue(self.link_exits('veth99'))
1165
e40a58b5
YW
1166 self.start_dnsmasq()
1167
1f0e3109
SS
1168 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
1169 print(output)
1f0e3109
SS
1170 self.assertRegex(output, 'veth99 proto dhcp')
1171 self.assertRegex(output, '192.168.5.1')
1172
1173 def test_dhcp_route_metric(self):
1174 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
1175 self.start_networkd()
1f0e3109
SS
1176
1177 self.assertTrue(self.link_exits('veth99'))
1178
e40a58b5
YW
1179 self.start_dnsmasq()
1180
1f0e3109
SS
1181 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1182 print(output)
1f0e3109
SS
1183 self.assertRegex(output, 'metric 24')
1184
1185 def test_dhcp_route_criticalconnection_true(self):
1186 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
1187 self.start_networkd()
1f0e3109
SS
1188
1189 self.assertTrue(self.link_exits('veth99'))
1190
e40a58b5
YW
1191 self.start_dnsmasq()
1192
1f0e3109
SS
1193 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1194 print(output)
1f0e3109 1195 self.assertRegex(output, '192.168.5.*')
e40a58b5 1196
1f0e3109
SS
1197 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
1198 self.stop_dnsmasq(dnsmasq_pid_file)
1199
1200 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1201 time.sleep(125)
1202
1203 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1204 print(output)
1205 self.assertRegex(output, '192.168.5.*')
1206
30d3b54e
YW
1207 def test_dhcp_client_reuse_address_as_static(self):
1208 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
1209 self.start_networkd()
1210
1211 self.assertTrue(self.link_exits('veth99'))
1212
1213 self.start_dnsmasq()
1214
1215 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1216 print(output)
1217 self.assertRegex(output, '192.168.5')
1218 self.assertRegex(output, '2600::')
1219
1220 ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
1221 ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
1222 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
1223 print(static_network)
1224
1225 self.remove_unit_from_networkd_path(['dhcp-client.network'])
1226
1227 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
1228 f.write(static_network)
1229
1230 self.start_networkd()
1231
1232 self.assertTrue(self.link_exits('veth99'))
1233
1234 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1235 print(output)
1236 self.assertRegex(output, '192.168.5')
1237 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1238
1239 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1240 print(output)
1241 self.assertRegex(output, '2600::')
1242 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1243
1f0e3109
SS
1244if __name__ == '__main__':
1245 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
1246 verbosity=3))