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