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