]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
test-network: drop unused variable
[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 88class Utilities():
1f0e3109
SS
89 def read_link_attr(self, link, dev, attribute):
90 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
91 return f.readline().strip()
92
4d7ed14f
SS
93 def read_bridge_port_attr(self, bridge, link, attribute):
94
95 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
96 path_port = 'lower_' + link + '/brport'
97 path = os.path.join(path_bridge, path_port)
98
99 with open(os.path.join(path, attribute)) as f:
100 return f.readline().strip()
101
1f0e3109
SS
102 def link_exits(self, link):
103 return os.path.exists(os.path.join('/sys/class/net', link))
104
105 def link_remove(self, links):
106 for link in links:
107 if os.path.exists(os.path.join('/sys/class/net', link)):
108 subprocess.call(['ip', 'link', 'del', 'dev', link])
9a4720a9 109 time.sleep(1)
1f0e3109
SS
110
111 def read_ipv6_sysctl_attr(self, link, attribute):
112 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
113 return f.readline().strip()
114
115 def read_ipv4_sysctl_attr(self, link, attribute):
116 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
117 return f.readline().strip()
118
119 def copy_unit_to_networkd_unit_path(self, *units):
120 for unit in units:
121 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
013c8dc9
YW
122 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
123 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
1f0e3109
SS
124
125 def remove_unit_from_networkd_path(self, units):
126 for unit in units:
127 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
128 os.remove(os.path.join(network_unit_file_path, unit))
013c8dc9
YW
129 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
130 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
1f0e3109 131
b412fce8
YW
132 def start_dnsmasq(self, additional_options=''):
133 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
134 subprocess.check_call(dnsmasq_command, shell=True)
1f0e3109
SS
135
136 time.sleep(10)
137
138 def stop_dnsmasq(self, pid_file):
139 if os.path.exists(pid_file):
140 with open(pid_file, 'r') as f:
141 pid = f.read().rstrip(' \t\r\n\0')
142 os.kill(int(pid), signal.SIGTERM)
143
144 os.remove(pid_file)
145
131717cb 146 def search_words_in_dnsmasq_log(self, words, show_all=False):
1f0e3109
SS
147 if os.path.exists(dnsmasq_log_file):
148 with open (dnsmasq_log_file) as in_file:
149 contents = in_file.read()
131717cb
YW
150 if show_all:
151 print(contents)
152 for line in contents.split('\n'):
153 if words in line:
1f0e3109 154 in_file.close()
131717cb 155 print("%s, %s" % (words, line))
1f0e3109
SS
156 return True
157 return False
158
159 def remove_lease_file(self):
160 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
161 os.remove(os.path.join(networkd_ci_path, 'lease'))
162
163 def remove_log_file(self):
164 if os.path.exists(dnsmasq_log_file):
165 os.remove(dnsmasq_log_file)
166
167 def start_networkd(self):
bad4969b
YW
168 if (os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
169 subprocess.check_call('systemctl stop systemd-networkd', shell=True)
170 os.remove(os.path.join(networkd_runtime_directory, 'state'))
171 subprocess.check_call('systemctl start systemd-networkd', shell=True)
172 else:
173 subprocess.check_call('systemctl restart systemd-networkd', shell=True)
1f0e3109 174 time.sleep(5)
fa7cd602 175 print()
1f0e3109 176
1f0e3109
SS
177class NetworkdNetDevTests(unittest.TestCase, Utilities):
178
09ea6724
YW
179 links =[
180 '6rdtun99',
181 'bond99',
182 'bridge99',
183 'dropin-test',
184 'dummy98',
185 'erspan-test',
186 'geneve99',
187 'gretap99',
188 'gretun99',
189 'ip6gretap99',
190 'ip6tnl99',
191 'ipiptun99',
192 'ipvlan99',
193 'isataptun99',
194 'macvlan99',
195 'macvtap99',
196 'sittun99',
197 'tap99',
198 'test1',
199 'tun99',
200 'vcan99',
201 'veth99',
202 'vlan99',
203 'vrf99',
204 'vti6tun99',
205 'vtitun99',
206 'vxlan99',
da44fb8a 207 'wg98',
09ea6724
YW
208 'wg99']
209
210 units = [
211 '10-dropin-test.netdev',
212 '11-dummy.netdev',
213 '12-dummy.netdev',
214 '21-macvlan.netdev',
215 '21-macvtap.netdev',
216 '21-vlan.netdev',
217 '21-vlan.network',
218 '25-6rd-tunnel.netdev',
219 '25-bond.netdev',
fde60a42 220 '25-bond-balanced-tlb.netdev',
09ea6724
YW
221 '25-bridge.netdev',
222 '25-erspan-tunnel.netdev',
223 '25-geneve.netdev',
224 '25-gretap-tunnel.netdev',
225 '25-gre-tunnel.netdev',
226 '25-ip6gre-tunnel.netdev',
227 '25-ip6tnl-tunnel.netdev',
228 '25-ipip-tunnel-independent.netdev',
229 '25-ipip-tunnel.netdev',
230 '25-ipvlan.netdev',
231 '25-isatap-tunnel.netdev',
232 '25-sit-tunnel.netdev',
233 '25-tap.netdev',
234 '25-tun.netdev',
235 '25-vcan.netdev',
236 '25-veth.netdev',
237 '25-vrf.netdev',
238 '25-vti6-tunnel.netdev',
239 '25-vti-tunnel.netdev',
240 '25-vxlan.netdev',
da44fb8a
YW
241 '25-wireguard-23-peers.netdev',
242 '25-wireguard-23-peers.network',
09ea6724
YW
243 '25-wireguard.netdev',
244 '6rd.network',
245 'gre.network',
246 'gretap.network',
247 'gretun.network',
248 'ip6gretap.network',
249 'ip6tnl.network',
250 'ipip.network',
251 'ipvlan.network',
252 'isatap.network',
253 'macvlan.network',
254 'macvtap.network',
255 'sit.network',
256 'vti6.network',
257 'vti.network',
258 'vxlan.network']
1f0e3109
SS
259
260 def setUp(self):
261 self.link_remove(self.links)
262
263 def tearDown(self):
264 self.link_remove(self.links)
265 self.remove_unit_from_networkd_path(self.units)
266
d80734f7
YW
267 def test_dropin(self):
268 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
d80734f7
YW
269 self.start_networkd()
270
271 self.assertTrue(self.link_exits('dropin-test'))
272
273 output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
274 print(output)
275 self.assertRegex(output, '00:50:56:c0:00:28')
276
1f0e3109
SS
277 def test_bridge(self):
278 self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
279 self.start_networkd()
280
281 self.assertTrue(self.link_exits('bridge99'))
282
283 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'hello_time'))
284 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'max_age'))
285 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','forward_delay'))
286 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','ageing_time'))
287 self.assertEqual('9', self.read_link_attr('bridge99', 'bridge','priority'))
288 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_querier'))
289 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_snooping'))
290 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','stp_state'))
291
292 def test_bond(self):
293 self.copy_unit_to_networkd_unit_path('25-bond.netdev')
294 self.start_networkd()
295
296 self.assertTrue(self.link_exits('bond99'))
297
99f68ef0
TJ
298 self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode'))
299 self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
300 self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon'))
301 self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate'))
302 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay'))
303 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay'))
304 self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp'))
305 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links'))
306 self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
307 self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
308 self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
1f0e3109 309
fde60a42
SS
310 def test_bond_balanced_tlb(self):
311 self.copy_unit_to_networkd_unit_path('25-bond-balanced-tlb.netdev')
312 self.start_networkd()
313
314 self.assertTrue(self.link_exits('bond99'))
315
316 self.assertEqual('balance-tlb 5', self.read_link_attr('bond99', 'bonding', 'mode'))
317 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
318
1f0e3109
SS
319 def test_vlan(self):
320 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
1f0e3109
SS
321 self.start_networkd()
322
323 self.assertTrue(self.link_exits('vlan99'))
324
325 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
14ecd604 326 print(output)
1f0e3109
SS
327 self.assertTrue(output, 'REORDER_HDR')
328 self.assertTrue(output, 'LOOSE_BINDING')
329 self.assertTrue(output, 'GVRP')
330 self.assertTrue(output, 'MVRP')
331 self.assertTrue(output, '99')
332
333 def test_macvtap(self):
334 self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
1f0e3109
SS
335 self.start_networkd()
336
337 self.assertTrue(self.link_exits('macvtap99'))
338
339 def test_macvlan(self):
340 self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
1f0e3109
SS
341 self.start_networkd()
342
343 self.assertTrue(self.link_exits('macvlan99'))
344
7a0a37b2 345 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109
SS
346 def test_ipvlan(self):
347 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
1f0e3109
SS
348 self.start_networkd()
349
350 self.assertTrue(self.link_exits('ipvlan99'))
351
352 def test_veth(self):
353 self.copy_unit_to_networkd_unit_path('25-veth.netdev')
1f0e3109
SS
354 self.start_networkd()
355
356 self.assertTrue(self.link_exits('veth99'))
357
358 def test_dummy(self):
359 self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
1f0e3109
SS
360 self.start_networkd()
361
362 self.assertTrue(self.link_exits('test1'))
363
364 def test_tun(self):
365 self.copy_unit_to_networkd_unit_path('25-tun.netdev')
1f0e3109
SS
366 self.start_networkd()
367
368 self.assertTrue(self.link_exits('tun99'))
369
370 def test_tap(self):
371 self.copy_unit_to_networkd_unit_path('25-tap.netdev')
1f0e3109
SS
372 self.start_networkd()
373
374 self.assertTrue(self.link_exits('tap99'))
375
7a0a37b2 376 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109
SS
377 def test_vrf(self):
378 self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
1f0e3109
SS
379 self.start_networkd()
380
381 self.assertTrue(self.link_exits('vrf99'))
382
7a0a37b2 383 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109
SS
384 def test_vcan(self):
385 self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
1f0e3109
SS
386 self.start_networkd()
387
388 self.assertTrue(self.link_exits('vcan99'))
389
7a3bc5a8
EV
390 @expectedFailureIfModuleIsNotAvailable('wireguard')
391 def test_wireguard(self):
392 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
7a3bc5a8
EV
393 self.start_networkd()
394
395 if shutil.which('wg'):
396 subprocess.call('wg')
16ab043b
YW
397 output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
398 self.assertTrue(output, '51820')
399 output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
400 self.assertTrue(output, '0x4d2')
401 output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
402 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
403 output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
404 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20')
405 output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
406 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820')
7a3bc5a8
EV
407
408 self.assertTrue(self.link_exits('wg99'))
409
da44fb8a
YW
410 @expectedFailureIfModuleIsNotAvailable('wireguard')
411 def test_wireguard_23_peers(self):
412 self.copy_unit_to_networkd_unit_path('25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network')
413 self.start_networkd()
414
415 if shutil.which('wg'):
416 subprocess.call('wg')
417
418 self.assertTrue(self.link_exits('wg98'))
419
1f0e3109
SS
420 def test_geneve(self):
421 self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
1f0e3109
SS
422 self.start_networkd()
423
424 self.assertTrue(self.link_exits('geneve99'))
425
426 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
14ecd604 427 print(output)
1f0e3109
SS
428 self.assertTrue(output, '192.168.22.1')
429 self.assertTrue(output, '6082')
430 self.assertTrue(output, 'udpcsum')
431 self.assertTrue(output, 'udp6zerocsumrx')
432
433 def test_ipip_tunnel(self):
434 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network')
435 self.start_networkd()
436
437 self.assertTrue(self.link_exits('dummy98'))
438 self.assertTrue(self.link_exits('ipiptun99'))
439
440 def test_gre_tunnel(self):
441 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network')
442 self.start_networkd()
443
444 self.assertTrue(self.link_exits('dummy98'))
445 self.assertTrue(self.link_exits('gretun99'))
446
447 def test_gretap_tunnel(self):
448 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network')
449 self.start_networkd()
450
451 self.assertTrue(self.link_exits('dummy98'))
452 self.assertTrue(self.link_exits('gretap99'))
453
454 def test_ip6gretap_tunnel(self):
455 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretap.network')
456 self.start_networkd()
457
458 self.assertTrue(self.link_exits('dummy98'))
459 self.assertTrue(self.link_exits('ip6gretap99'))
460
461 def test_vti_tunnel(self):
462 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network')
463 self.start_networkd()
464
465 self.assertTrue(self.link_exits('dummy98'))
466 self.assertTrue(self.link_exits('vtitun99'))
467
468 def test_vti6_tunnel(self):
469 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network')
470 self.start_networkd()
471
472 self.assertTrue(self.link_exits('dummy98'))
473 self.assertTrue(self.link_exits('vti6tun99'))
474
475 def test_ip6tnl_tunnel(self):
476 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network')
477 self.start_networkd()
478
479 self.assertTrue(self.link_exits('dummy98'))
480 self.assertTrue(self.link_exits('ip6tnl99'))
481
482 def test_sit_tunnel(self):
483 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network')
484 self.start_networkd()
485
486 self.assertTrue(self.link_exits('dummy98'))
487 self.assertTrue(self.link_exits('sittun99'))
488
d0e728b6
SS
489 def test_isatap_tunnel(self):
490 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
491 self.start_networkd()
492
493 self.assertTrue(self.link_exits('dummy98'))
494 self.assertTrue(self.link_exits('isataptun99'))
e40a58b5 495
d0e728b6 496 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
14ecd604 497 print(output)
d0e728b6
SS
498 self.assertRegex(output, "isatap ")
499
d29dc4f1
DA
500 def test_6rd_tunnel(self):
501 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
502 self.start_networkd()
503
504 self.assertTrue(self.link_exits('dummy98'))
505 self.assertTrue(self.link_exits('sittun99'))
506
7bea7f9b 507 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b
SS
508 def test_erspan_tunnel(self):
509 self.copy_unit_to_networkd_unit_path('25-erspan-tunnel.netdev')
510 self.start_networkd()
511
512 self.assertTrue(self.link_exits('erspan-test'))
513
514 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan-test']).rstrip().decode('utf-8')
515 print(output)
516 self.assertTrue(output, '172.16.1.200')
517 self.assertTrue(output, '172.16.1.100')
518 self.assertTrue(output, '101')
519
1f0e3109
SS
520 def test_tunnel_independent(self):
521 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
1f0e3109 522 self.start_networkd()
e40a58b5 523
1f0e3109
SS
524 self.assertTrue(self.link_exits('ipiptun99'))
525
526 def test_vxlan(self):
527 self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network','11-dummy.netdev')
1f0e3109
SS
528 self.start_networkd()
529
530 self.assertTrue(self.link_exits('vxlan99'))
531
532 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
14ecd604 533 print(output)
1f0e3109
SS
534 self.assertRegex(output, "999")
535 self.assertRegex(output, '5555')
536 self.assertRegex(output, 'l2miss')
537 self.assertRegex(output, 'l3miss')
538 self.assertRegex(output, 'udpcsum')
539 self.assertRegex(output, 'udp6zerocsumtx')
540 self.assertRegex(output, 'udp6zerocsumrx')
541 self.assertRegex(output, 'remcsumtx')
542 self.assertRegex(output, 'remcsumrx')
543 self.assertRegex(output, 'gbp')
544
545class NetworkdNetWorkTests(unittest.TestCase, Utilities):
09ea6724
YW
546 links = [
547 'bond199',
548 'dummy98',
549 'test1']
550
551 units = [
552 '11-dummy.netdev',
553 '12-dummy.netdev',
554 '23-active-slave.network',
555 '23-bond199.network',
556 '23-primary-slave.network',
557 '23-test1-bond199.network',
558 '25-address-link-section.network',
559 '25-address-section-miscellaneous.network',
560 '25-address-section.network',
561 '25-bond-active-backup-slave.netdev',
562 '25-fibrule-invert.network',
563 '25-fibrule-port-range.network',
564 '25-ipv6-address-label-section.network',
e4a71bf3 565 '25-neighbor-section.network',
05514ae1
YW
566 '25-link-local-addressing-no.network',
567 '25-link-local-addressing-yes.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
05514ae1
YW
864 def test_link_local_addressing(self):
865 self.copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
866 '25-link-local-addressing-no.network', '12-dummy.netdev')
867 self.start_networkd()
868
869 self.assertTrue(self.link_exits('test1'))
870 self.assertTrue(self.link_exits('dummy98'))
871
872 time.sleep(10)
873
874 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
875 print(output)
876 self.assertRegex(output, 'inet .* scope link')
877 self.assertRegex(output, 'inet6 .* scope link')
878
879 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
880 print(output)
881 self.assertNotRegex(output, 'inet6* .* scope link')
882
883 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
884 print(output)
885 self.assertRegex(output, 'State: degraded \(configured\)')
886
887 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
888 print(output)
889 self.assertRegex(output, 'State: carrier \(configured\)')
890
891 '''
892 Documentation/networking/ip-sysctl.txt
893
894 addr_gen_mode - INTEGER
895 Defines how link-local and autoconf addresses are generated.
896
897 0: generate address based on EUI64 (default)
898 1: do no generate a link-local address, use EUI64 for addresses generated
899 from autoconf
900 2: generate stable privacy addresses, using the secret from
901 stable_secret (RFC7217)
902 3: generate stable privacy addresses, using a random secret if unset
903 '''
904
905 test1_addr_gen_mode = ''
906 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
907 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
908 try:
909 f.readline()
910 except IOError:
911 # if stable_secret is unset, then EIO is returned
912 test1_addr_gen_mode = '0'
913 else:
914 test1_addr_gen_mode = '2'
915 else:
916 test1_addr_gen_mode = '0'
917
918 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
919 self.assertEqual(self.read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '0')
920
921 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
922 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
923
1f0e3109
SS
924 def test_sysctl(self):
925 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
926 self.start_networkd()
927
928 self.assertTrue(self.link_exits('dummy98'))
929
930 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
931 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
932 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
933 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
934 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
935 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
936 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
937
14dc0335 938class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
939 links = [
940 'bridge99',
941 'dummy98',
942 'test1']
943
944 units = [
945 '11-dummy.netdev',
946 '12-dummy.netdev',
947 '26-bridge.netdev',
948 '26-bridge-slave-interface-1.network',
949 '26-bridge-slave-interface-2.network',
950 'bridge99.network']
1f0e3109
SS
951
952 def setUp(self):
953 self.link_remove(self.links)
954
955 def tearDown(self):
956 self.link_remove(self.links)
957 self.remove_unit_from_networkd_path(self.units)
958
959 def test_bridge_property(self):
960 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
961 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
962 'bridge99.network')
963 self.start_networkd()
964
965 self.assertTrue(self.link_exits('dummy98'))
966 self.assertTrue(self.link_exits('test1'))
967 self.assertTrue(self.link_exits('bridge99'))
968
969 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
970 print(output)
971 self.assertRegex(output, 'master')
972 self.assertRegex(output, 'bridge')
973
974 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
975 print(output)
976 self.assertRegex(output, 'master')
977 self.assertRegex(output, 'bridge')
978
979 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
980 print(output)
981 self.assertRegex(output, '192.168.0.15')
982 self.assertRegex(output, '192.168.0.1')
983
984 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
985 print(output)
4d7ed14f
SS
986 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
987 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
988 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
989 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
990
991 # CONFIG_BRIDGE_IGMP_SNOOPING=y
992 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
993 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1f0e3109
SS
994
995class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
996 links = ['veth99']
997
09ea6724
YW
998 units = [
999 '23-emit-lldp.network',
1000 '24-lldp.network',
1001 '25-veth.netdev']
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_lldp(self):
1011 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
1012 self.start_networkd()
1013
1014 self.assertTrue(self.link_exits('veth99'))
1015
1016 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
1017 print(output)
1018 self.assertRegex(output, 'veth-peer')
1019 self.assertRegex(output, 'veth99')
1020
1021class NetworkdNetworkRATests(unittest.TestCase, Utilities):
1022 links = ['veth99']
1023
09ea6724
YW
1024 units = [
1025 '25-veth.netdev',
1026 'ipv6-prefix.network',
1027 'ipv6-prefix-veth.network']
1f0e3109
SS
1028
1029 def setUp(self):
1030 self.link_remove(self.links)
1031
1032 def tearDown(self):
1033 self.link_remove(self.links)
1034 self.remove_unit_from_networkd_path(self.units)
1035
1036 def test_ipv6_prefix_delegation(self):
1037 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1038 self.start_networkd()
1039
1040 self.assertTrue(self.link_exits('veth99'))
1041
1042 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1043 print(output)
1044 self.assertRegex(output, '2002:da8:1:0')
1045
1046class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
09ea6724
YW
1047 links = [
1048 'dummy98',
1049 'veth99']
1050
1051 units = [
1052 '12-dummy.netdev',
1053 '24-search-domain.network',
1054 '25-veth.netdev',
1055 'dhcp-client.network',
1056 'dhcp-client-timezone-router.network',
1057 'dhcp-server.network',
1058 'dhcp-server-timezone-router.network']
1f0e3109
SS
1059
1060 def setUp(self):
1061 self.link_remove(self.links)
1062
1063 def tearDown(self):
1064 self.link_remove(self.links)
1065 self.remove_unit_from_networkd_path(self.units)
1066
1067 def test_dhcp_server(self):
1068 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
1069 self.start_networkd()
1070
1071 self.assertTrue(self.link_exits('veth99'))
1072
1f0e3109
SS
1073 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1074 print(output)
1075 self.assertRegex(output, '192.168.5.*')
1076 self.assertRegex(output, 'Gateway: 192.168.5.1')
1077 self.assertRegex(output, 'DNS: 192.168.5.1')
1078 self.assertRegex(output, 'NTP: 192.168.5.1')
1079
1080 def test_domain(self):
f5d191a9 1081 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1f0e3109
SS
1082 self.start_networkd()
1083
1084 self.assertTrue(self.link_exits('dummy98'))
1085
1086 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1087 print(output)
1088 self.assertRegex(output, 'Address: 192.168.42.100')
1089 self.assertRegex(output, 'DNS: 192.168.42.1')
1090 self.assertRegex(output, 'Search Domains: one')
1091
1092 def test_emit_router_timezone(self):
1093 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
1094 self.start_networkd()
1095
1096 self.assertTrue(self.link_exits('veth99'))
1097
1098 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1099 print(output)
1100 self.assertRegex(output, 'Gateway: 192.168.5.*')
1101 self.assertRegex(output, '192.168.5.*')
1102 self.assertRegex(output, 'Europe/Berlin')
1103
1104class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
09ea6724
YW
1105 links = [
1106 'dummy98',
1107 'veth99']
1108
1109 units = [
1110 '25-veth.netdev',
1111 'dhcp-client-anonymize.network',
1112 'dhcp-client-critical-connection.network',
1113 'dhcp-client-ipv4-dhcp-settings.network',
1114 'dhcp-client-ipv4-only-ipv6-disabled.network',
1115 'dhcp-client-ipv4-only.network',
1116 'dhcp-client-ipv6-only.network',
1117 'dhcp-client-ipv6-rapid-commit.network',
1118 'dhcp-client-listen-port.network',
1119 'dhcp-client-route-metric.network',
1120 'dhcp-client-route-table.network',
3e9d5552 1121 'dhcp-client.network',
09ea6724 1122 'dhcp-server-veth-peer.network',
30d3b54e
YW
1123 'dhcp-v4-server-veth-peer.network',
1124 'static.network']
1f0e3109
SS
1125
1126 def setUp(self):
1127 self.link_remove(self.links)
1128 self.stop_dnsmasq(dnsmasq_pid_file)
1129
1130 def tearDown(self):
1131 self.link_remove(self.links)
1132 self.remove_unit_from_networkd_path(self.units)
1133 self.stop_dnsmasq(dnsmasq_pid_file)
1134 self.remove_lease_file()
1135 self.remove_log_file()
1136
1137 def test_dhcp_client_ipv6_only(self):
f5d191a9 1138 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109
SS
1139 self.start_networkd()
1140
1141 self.assertTrue(self.link_exits('veth99'))
1142
1143 self.start_dnsmasq()
1144
1145 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1146 print(output)
1147 self.assertRegex(output, '2600::')
1148 self.assertNotRegex(output, '192.168.5')
1149
1150 def test_dhcp_client_ipv4_only(self):
f5d191a9 1151 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109
SS
1152 self.start_networkd()
1153
1154 self.assertTrue(self.link_exits('veth99'))
1155
1156 self.start_dnsmasq()
1157
1158 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1159 print(output)
1160 self.assertNotRegex(output, '2600::')
1161 self.assertRegex(output, '192.168.5')
1162
1163 def test_dhcp_client_ipv4_ipv6(self):
1164 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
1165 'dhcp-client-ipv4-only.network')
1166 self.start_networkd()
1167
1168 self.assertTrue(self.link_exits('veth99'))
1169
1170 self.start_dnsmasq()
1171
1172 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1173 print(output)
1174 self.assertRegex(output, '2600::')
1175 self.assertRegex(output, '192.168.5')
1176
1177 def test_dhcp_client_settings(self):
1178 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1179 self.start_networkd()
1180
1181 self.assertTrue(self.link_exits('veth99'))
1182
1183 self.start_dnsmasq()
1184
1185 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1186 print(output)
1187 self.assertRegex(output, '12:34:56:78:9a:bc')
1188 self.assertRegex(output, '192.168.5')
1189 self.assertRegex(output, '1492')
1190
1191 output = subprocess.check_output(['ip', 'route']).rstrip().decode('utf-8')
1192 print(output)
1193 self.assertRegex(output, 'default.*dev veth99 proto dhcp')
1194
131717cb
YW
1195 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
1196 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
1197 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
1198 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1199
1200 def test_dhcp6_client_settings_rapidcommit_true(self):
1201 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1202 self.start_networkd()
1203
1204 self.assertTrue(self.link_exits('veth99'))
1205
1206 self.start_dnsmasq()
1207
1208 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1209 print(output)
1210 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1211 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1212
1213 def test_dhcp6_client_settings_rapidcommit_false(self):
1214 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
1215 self.start_networkd()
1216
1217 self.assertTrue(self.link_exits('veth99'))
1218
1219 self.start_dnsmasq()
1220
1221 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1222 print(output)
1223 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1224 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1225
1226 def test_dhcp_client_settings_anonymize(self):
1227 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
1228 self.start_networkd()
1229
1230 self.assertTrue(self.link_exits('veth99'))
1231
1232 self.start_dnsmasq()
e40a58b5 1233
131717cb
YW
1234 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
1235 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
1236 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1237
1238 def test_dhcp_client_listen_port(self):
1239 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
1f0e3109
SS
1240 self.start_networkd()
1241
1242 self.assertTrue(self.link_exits('veth99'))
1243
b412fce8 1244 self.start_dnsmasq('--dhcp-alternate-port=67,5555')
1f0e3109 1245
b412fce8
YW
1246 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1247 print(output)
1248 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109
SS
1249
1250 def test_dhcp_route_table_id(self):
1251 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
1252 self.start_networkd()
1f0e3109
SS
1253
1254 self.assertTrue(self.link_exits('veth99'))
1255
e40a58b5
YW
1256 self.start_dnsmasq()
1257
1f0e3109
SS
1258 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
1259 print(output)
1f0e3109
SS
1260 self.assertRegex(output, 'veth99 proto dhcp')
1261 self.assertRegex(output, '192.168.5.1')
1262
1263 def test_dhcp_route_metric(self):
1264 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
1265 self.start_networkd()
1f0e3109
SS
1266
1267 self.assertTrue(self.link_exits('veth99'))
1268
e40a58b5
YW
1269 self.start_dnsmasq()
1270
1f0e3109
SS
1271 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1272 print(output)
1f0e3109
SS
1273 self.assertRegex(output, 'metric 24')
1274
1275 def test_dhcp_route_criticalconnection_true(self):
1276 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
1277 self.start_networkd()
1f0e3109
SS
1278
1279 self.assertTrue(self.link_exits('veth99'))
1280
e40a58b5
YW
1281 self.start_dnsmasq()
1282
1f0e3109
SS
1283 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1284 print(output)
1f0e3109 1285 self.assertRegex(output, '192.168.5.*')
e40a58b5 1286
1f0e3109
SS
1287 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
1288 self.stop_dnsmasq(dnsmasq_pid_file)
1289
1290 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1291 time.sleep(125)
1292
1293 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1294 print(output)
1295 self.assertRegex(output, '192.168.5.*')
1296
30d3b54e
YW
1297 def test_dhcp_client_reuse_address_as_static(self):
1298 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
1299 self.start_networkd()
1300
1301 self.assertTrue(self.link_exits('veth99'))
1302
1303 self.start_dnsmasq()
1304
1305 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1306 print(output)
1307 self.assertRegex(output, '192.168.5')
1308 self.assertRegex(output, '2600::')
1309
1310 ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
1311 ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
1312 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
1313 print(static_network)
1314
1315 self.remove_unit_from_networkd_path(['dhcp-client.network'])
1316
1317 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
1318 f.write(static_network)
1319
1320 self.start_networkd()
1321
1322 self.assertTrue(self.link_exits('veth99'))
1323
1324 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1325 print(output)
1326 self.assertRegex(output, '192.168.5')
1327 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1328
1329 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1330 print(output)
1331 self.assertRegex(output, '2600::')
1332 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1333
1f0e3109
SS
1334if __name__ == '__main__':
1335 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
1336 verbosity=3))