]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
machinectl: do not format size if freed disk space is "-1"
[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):
ecdd0392 120 print()
1f0e3109
SS
121 for unit in units:
122 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
013c8dc9
YW
123 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
124 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
1f0e3109
SS
125
126 def remove_unit_from_networkd_path(self, units):
127 for unit in units:
128 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
129 os.remove(os.path.join(network_unit_file_path, unit))
013c8dc9
YW
130 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
131 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
1f0e3109 132
b412fce8
YW
133 def start_dnsmasq(self, additional_options=''):
134 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
135 subprocess.check_call(dnsmasq_command, shell=True)
1f0e3109
SS
136
137 time.sleep(10)
138
139 def stop_dnsmasq(self, pid_file):
140 if os.path.exists(pid_file):
141 with open(pid_file, 'r') as f:
142 pid = f.read().rstrip(' \t\r\n\0')
143 os.kill(int(pid), signal.SIGTERM)
144
145 os.remove(pid_file)
146
131717cb 147 def search_words_in_dnsmasq_log(self, words, show_all=False):
1f0e3109
SS
148 if os.path.exists(dnsmasq_log_file):
149 with open (dnsmasq_log_file) as in_file:
150 contents = in_file.read()
131717cb
YW
151 if show_all:
152 print(contents)
153 for line in contents.split('\n'):
154 if words in line:
1f0e3109 155 in_file.close()
131717cb 156 print("%s, %s" % (words, line))
1f0e3109
SS
157 return True
158 return False
159
160 def remove_lease_file(self):
161 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
162 os.remove(os.path.join(networkd_ci_path, 'lease'))
163
164 def remove_log_file(self):
165 if os.path.exists(dnsmasq_log_file):
166 os.remove(dnsmasq_log_file)
167
b677774d
YW
168 def start_networkd(self, remove_state_files=True):
169 if (remove_state_files and
170 os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
bad4969b
YW
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
SS
176 time.sleep(5)
177
1f0e3109
SS
178class NetworkdNetDevTests(unittest.TestCase, Utilities):
179
09ea6724
YW
180 links =[
181 '6rdtun99',
182 'bond99',
183 'bridge99',
184 'dropin-test',
185 'dummy98',
186 'erspan-test',
187 'geneve99',
188 'gretap99',
189 'gretun99',
190 'ip6gretap99',
191 'ip6tnl99',
192 'ipiptun99',
193 'ipvlan99',
194 'isataptun99',
195 'macvlan99',
196 'macvtap99',
197 'sittun99',
198 'tap99',
199 'test1',
200 'tun99',
201 'vcan99',
202 'veth99',
203 'vlan99',
204 'vrf99',
205 'vti6tun99',
206 'vtitun99',
207 'vxlan99',
da44fb8a 208 'wg98',
09ea6724
YW
209 'wg99']
210
211 units = [
212 '10-dropin-test.netdev',
213 '11-dummy.netdev',
214 '12-dummy.netdev',
215 '21-macvlan.netdev',
216 '21-macvtap.netdev',
217 '21-vlan.netdev',
218 '21-vlan.network',
219 '25-6rd-tunnel.netdev',
220 '25-bond.netdev',
fde60a42 221 '25-bond-balanced-tlb.netdev',
09ea6724
YW
222 '25-bridge.netdev',
223 '25-erspan-tunnel.netdev',
224 '25-geneve.netdev',
225 '25-gretap-tunnel.netdev',
226 '25-gre-tunnel.netdev',
227 '25-ip6gre-tunnel.netdev',
228 '25-ip6tnl-tunnel.netdev',
229 '25-ipip-tunnel-independent.netdev',
230 '25-ipip-tunnel.netdev',
231 '25-ipvlan.netdev',
232 '25-isatap-tunnel.netdev',
233 '25-sit-tunnel.netdev',
234 '25-tap.netdev',
235 '25-tun.netdev',
236 '25-vcan.netdev',
237 '25-veth.netdev',
238 '25-vrf.netdev',
239 '25-vti6-tunnel.netdev',
240 '25-vti-tunnel.netdev',
241 '25-vxlan.netdev',
da44fb8a
YW
242 '25-wireguard-23-peers.netdev',
243 '25-wireguard-23-peers.network',
09ea6724
YW
244 '25-wireguard.netdev',
245 '6rd.network',
246 'gre.network',
247 'gretap.network',
248 'gretun.network',
249 'ip6gretap.network',
250 'ip6tnl.network',
251 'ipip.network',
252 'ipvlan.network',
253 'isatap.network',
254 'macvlan.network',
255 'macvtap.network',
256 'sit.network',
257 'vti6.network',
258 'vti.network',
259 'vxlan.network']
1f0e3109
SS
260
261 def setUp(self):
262 self.link_remove(self.links)
263
264 def tearDown(self):
265 self.link_remove(self.links)
266 self.remove_unit_from_networkd_path(self.units)
267
d80734f7
YW
268 def test_dropin(self):
269 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
d80734f7
YW
270 self.start_networkd()
271
272 self.assertTrue(self.link_exits('dropin-test'))
273
274 output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
275 print(output)
276 self.assertRegex(output, '00:50:56:c0:00:28')
277
308ae89c
YW
278 output = subprocess.check_output(['networkctl', 'list']).rstrip().decode('utf-8')
279 self.assertRegex(output, '1 lo ')
280 self.assertRegex(output, 'dropin-test')
281
282 output = subprocess.check_output(['networkctl', 'list', 'dropin-test']).rstrip().decode('utf-8')
283 self.assertNotRegex(output, '1 lo ')
284 self.assertRegex(output, 'dropin-test')
285
286 output = subprocess.check_output(['networkctl', 'list', 'dropin-*']).rstrip().decode('utf-8')
287 self.assertNotRegex(output, '1 lo ')
288 self.assertRegex(output, 'dropin-test')
289
96fb7dc3 290 output = subprocess.check_output(['networkctl', 'status', 'dropin-*']).rstrip().decode('utf-8')
fde66c21 291 self.assertNotRegex(output, '1: lo ')
96fb7dc3 292 self.assertRegex(output, 'dropin-test')
232152bc
YW
293
294 ret = subprocess.run(['ethtool', '--driver', 'dropin-test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
295 print(ret.stdout.rstrip().decode('utf-8'))
296 if ret.returncode == 0 and re.search('driver: dummy', ret.stdout.rstrip().decode('utf-8')) != None:
297 self.assertRegex(output, 'Driver: dummy')
298 else:
299 print('ethtool does not support driver field at least for dummy interfaces, skipping test for Driver field of networkctl.')
96fb7dc3 300
1f0e3109
SS
301 def test_bridge(self):
302 self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
303 self.start_networkd()
304
305 self.assertTrue(self.link_exits('bridge99'))
306
307 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'hello_time'))
308 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'max_age'))
309 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','forward_delay'))
310 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','ageing_time'))
311 self.assertEqual('9', self.read_link_attr('bridge99', 'bridge','priority'))
312 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_querier'))
313 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_snooping'))
314 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','stp_state'))
315
316 def test_bond(self):
317 self.copy_unit_to_networkd_unit_path('25-bond.netdev')
318 self.start_networkd()
319
320 self.assertTrue(self.link_exits('bond99'))
321
99f68ef0
TJ
322 self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode'))
323 self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
324 self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon'))
325 self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate'))
326 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay'))
327 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay'))
328 self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp'))
329 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links'))
330 self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
331 self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
332 self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
1f0e3109 333
fde60a42
SS
334 def test_bond_balanced_tlb(self):
335 self.copy_unit_to_networkd_unit_path('25-bond-balanced-tlb.netdev')
336 self.start_networkd()
337
338 self.assertTrue(self.link_exits('bond99'))
339
340 self.assertEqual('balance-tlb 5', self.read_link_attr('bond99', 'bonding', 'mode'))
341 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
342
1f0e3109
SS
343 def test_vlan(self):
344 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
1f0e3109
SS
345 self.start_networkd()
346
72b7f1b9 347 self.assertTrue(self.link_exits('test1'))
1f0e3109
SS
348 self.assertTrue(self.link_exits('vlan99'))
349
72b7f1b9
YW
350 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
351 print(output)
352 self.assertTrue(output, ' mtu 2004 ')
353
1f0e3109 354 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
14ecd604 355 print(output)
72b7f1b9 356 self.assertTrue(output, ' mtu 2000 ')
1f0e3109
SS
357 self.assertTrue(output, 'REORDER_HDR')
358 self.assertTrue(output, 'LOOSE_BINDING')
359 self.assertTrue(output, 'GVRP')
360 self.assertTrue(output, 'MVRP')
72b7f1b9 361 self.assertTrue(output, ' id 99 ')
1f0e3109
SS
362
363 def test_macvtap(self):
364 self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
1f0e3109
SS
365 self.start_networkd()
366
367 self.assertTrue(self.link_exits('macvtap99'))
368
369 def test_macvlan(self):
370 self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
1f0e3109
SS
371 self.start_networkd()
372
72b7f1b9 373 self.assertTrue(self.link_exits('test1'))
1f0e3109
SS
374 self.assertTrue(self.link_exits('macvlan99'))
375
72b7f1b9
YW
376 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
377 print(output)
378 self.assertTrue(output, ' mtu 2000 ')
379
380 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macvlan99']).rstrip().decode('utf-8')
381 print(output)
382 self.assertTrue(output, ' mtu 2000 ')
383
7a0a37b2 384 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109
SS
385 def test_ipvlan(self):
386 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
1f0e3109
SS
387 self.start_networkd()
388
389 self.assertTrue(self.link_exits('ipvlan99'))
390
391 def test_veth(self):
392 self.copy_unit_to_networkd_unit_path('25-veth.netdev')
1f0e3109
SS
393 self.start_networkd()
394
395 self.assertTrue(self.link_exits('veth99'))
396
397 def test_dummy(self):
398 self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
1f0e3109
SS
399 self.start_networkd()
400
401 self.assertTrue(self.link_exits('test1'))
402
403 def test_tun(self):
404 self.copy_unit_to_networkd_unit_path('25-tun.netdev')
1f0e3109
SS
405 self.start_networkd()
406
407 self.assertTrue(self.link_exits('tun99'))
408
409 def test_tap(self):
410 self.copy_unit_to_networkd_unit_path('25-tap.netdev')
1f0e3109
SS
411 self.start_networkd()
412
413 self.assertTrue(self.link_exits('tap99'))
414
7a0a37b2 415 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109
SS
416 def test_vrf(self):
417 self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
1f0e3109
SS
418 self.start_networkd()
419
420 self.assertTrue(self.link_exits('vrf99'))
421
7a0a37b2 422 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109
SS
423 def test_vcan(self):
424 self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
1f0e3109
SS
425 self.start_networkd()
426
427 self.assertTrue(self.link_exits('vcan99'))
428
7a3bc5a8
EV
429 @expectedFailureIfModuleIsNotAvailable('wireguard')
430 def test_wireguard(self):
431 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
7a3bc5a8
EV
432 self.start_networkd()
433
434 if shutil.which('wg'):
435 subprocess.call('wg')
16ab043b
YW
436 output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
437 self.assertTrue(output, '51820')
438 output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
439 self.assertTrue(output, '0x4d2')
440 output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
441 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
442 output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
443 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20')
444 output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
445 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820')
7a3bc5a8
EV
446
447 self.assertTrue(self.link_exits('wg99'))
448
da44fb8a
YW
449 @expectedFailureIfModuleIsNotAvailable('wireguard')
450 def test_wireguard_23_peers(self):
451 self.copy_unit_to_networkd_unit_path('25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network')
452 self.start_networkd()
453
454 if shutil.which('wg'):
455 subprocess.call('wg')
456
457 self.assertTrue(self.link_exits('wg98'))
458
1f0e3109
SS
459 def test_geneve(self):
460 self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
1f0e3109
SS
461 self.start_networkd()
462
463 self.assertTrue(self.link_exits('geneve99'))
464
465 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
14ecd604 466 print(output)
1f0e3109
SS
467 self.assertTrue(output, '192.168.22.1')
468 self.assertTrue(output, '6082')
469 self.assertTrue(output, 'udpcsum')
470 self.assertTrue(output, 'udp6zerocsumrx')
471
472 def test_ipip_tunnel(self):
473 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network')
474 self.start_networkd()
475
476 self.assertTrue(self.link_exits('dummy98'))
477 self.assertTrue(self.link_exits('ipiptun99'))
478
479 def test_gre_tunnel(self):
480 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network')
481 self.start_networkd()
482
483 self.assertTrue(self.link_exits('dummy98'))
484 self.assertTrue(self.link_exits('gretun99'))
485
486 def test_gretap_tunnel(self):
487 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network')
488 self.start_networkd()
489
490 self.assertTrue(self.link_exits('dummy98'))
491 self.assertTrue(self.link_exits('gretap99'))
492
493 def test_ip6gretap_tunnel(self):
494 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretap.network')
495 self.start_networkd()
496
497 self.assertTrue(self.link_exits('dummy98'))
498 self.assertTrue(self.link_exits('ip6gretap99'))
499
500 def test_vti_tunnel(self):
501 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network')
502 self.start_networkd()
503
504 self.assertTrue(self.link_exits('dummy98'))
505 self.assertTrue(self.link_exits('vtitun99'))
506
507 def test_vti6_tunnel(self):
508 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network')
509 self.start_networkd()
510
511 self.assertTrue(self.link_exits('dummy98'))
512 self.assertTrue(self.link_exits('vti6tun99'))
513
514 def test_ip6tnl_tunnel(self):
515 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network')
516 self.start_networkd()
517
518 self.assertTrue(self.link_exits('dummy98'))
519 self.assertTrue(self.link_exits('ip6tnl99'))
520
521 def test_sit_tunnel(self):
522 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network')
523 self.start_networkd()
524
525 self.assertTrue(self.link_exits('dummy98'))
526 self.assertTrue(self.link_exits('sittun99'))
527
d0e728b6
SS
528 def test_isatap_tunnel(self):
529 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
530 self.start_networkd()
531
532 self.assertTrue(self.link_exits('dummy98'))
533 self.assertTrue(self.link_exits('isataptun99'))
e40a58b5 534
d0e728b6 535 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
14ecd604 536 print(output)
d0e728b6
SS
537 self.assertRegex(output, "isatap ")
538
d29dc4f1
DA
539 def test_6rd_tunnel(self):
540 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
541 self.start_networkd()
542
543 self.assertTrue(self.link_exits('dummy98'))
544 self.assertTrue(self.link_exits('sittun99'))
545
7bea7f9b 546 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b
SS
547 def test_erspan_tunnel(self):
548 self.copy_unit_to_networkd_unit_path('25-erspan-tunnel.netdev')
549 self.start_networkd()
550
551 self.assertTrue(self.link_exits('erspan-test'))
552
553 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan-test']).rstrip().decode('utf-8')
554 print(output)
555 self.assertTrue(output, '172.16.1.200')
556 self.assertTrue(output, '172.16.1.100')
557 self.assertTrue(output, '101')
558
1f0e3109
SS
559 def test_tunnel_independent(self):
560 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
1f0e3109 561 self.start_networkd()
e40a58b5 562
1f0e3109
SS
563 self.assertTrue(self.link_exits('ipiptun99'))
564
565 def test_vxlan(self):
566 self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network','11-dummy.netdev')
1f0e3109
SS
567 self.start_networkd()
568
569 self.assertTrue(self.link_exits('vxlan99'))
570
571 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
14ecd604 572 print(output)
1f0e3109
SS
573 self.assertRegex(output, "999")
574 self.assertRegex(output, '5555')
575 self.assertRegex(output, 'l2miss')
576 self.assertRegex(output, 'l3miss')
577 self.assertRegex(output, 'udpcsum')
578 self.assertRegex(output, 'udp6zerocsumtx')
579 self.assertRegex(output, 'udp6zerocsumrx')
580 self.assertRegex(output, 'remcsumtx')
581 self.assertRegex(output, 'remcsumrx')
582 self.assertRegex(output, 'gbp')
583
584class NetworkdNetWorkTests(unittest.TestCase, Utilities):
09ea6724
YW
585 links = [
586 'bond199',
587 'dummy98',
cd65d067 588 'dummy99',
09ea6724
YW
589 'test1']
590
591 units = [
592 '11-dummy.netdev',
593 '12-dummy.netdev',
594 '23-active-slave.network',
595 '23-bond199.network',
596 '23-primary-slave.network',
597 '23-test1-bond199.network',
598 '25-address-link-section.network',
599 '25-address-section-miscellaneous.network',
600 '25-address-section.network',
cd65d067 601 '25-bind-carrier.network',
09ea6724
YW
602 '25-bond-active-backup-slave.netdev',
603 '25-fibrule-invert.network',
604 '25-fibrule-port-range.network',
605 '25-ipv6-address-label-section.network',
e4a71bf3 606 '25-neighbor-section.network',
05514ae1
YW
607 '25-link-local-addressing-no.network',
608 '25-link-local-addressing-yes.network',
09ea6724
YW
609 '25-link-section-unmanaged.network',
610 '25-route-gateway.network',
611 '25-route-gateway-on-link.network',
20ca06a6 612 '25-route-ipv6-src.network',
09ea6724
YW
613 '25-route-reverse-order.network',
614 '25-route-section.network',
615 '25-route-tcp-window-settings.network',
616 '25-route-type.network',
4da33154 617 '25-sysctl-disable-ipv6.network',
09ea6724
YW
618 '25-sysctl.network',
619 'configure-without-carrier.network',
b677774d
YW
620 'routing-policy-rule-dummy98.network',
621 'routing-policy-rule-test1.network',
09ea6724 622 'test-static.network']
1f0e3109
SS
623
624 def setUp(self):
625 self.link_remove(self.links)
626
627 def tearDown(self):
628 self.link_remove(self.links)
629 self.remove_unit_from_networkd_path(self.units)
630
631 def test_static_address(self):
632 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'test-static.network')
633 self.start_networkd()
634
635 self.assertTrue(self.link_exits('dummy98'))
e40a58b5 636
1f0e3109
SS
637 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
638 print(output)
639 self.assertRegex(output, '192.168.0.15')
640 self.assertRegex(output, '192.168.0.1')
641 self.assertRegex(output, 'routable')
642
643 def test_configure_without_carrier(self):
644 self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
645 self.start_networkd()
646
647 self.assertTrue(self.link_exits('test1'))
e40a58b5 648
1f0e3109
SS
649 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
650 print(output)
651 self.assertRegex(output, '192.168.0.15')
652 self.assertRegex(output, '192.168.0.1')
653 self.assertRegex(output, 'routable')
654
655 def test_bond_active_slave(self):
656 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
657 self.start_networkd()
658
659 self.assertTrue(self.link_exits('dummy98'))
660 self.assertTrue(self.link_exits('bond199'))
e40a58b5 661
1f0e3109
SS
662 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
663 print(output)
664 self.assertRegex(output, 'active_slave dummy98')
665
666 def test_bond_primary_slave(self):
667 self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
668 self.start_networkd()
669
670 self.assertTrue(self.link_exits('test1'))
671 self.assertTrue(self.link_exits('bond199'))
e40a58b5 672
1f0e3109
SS
673 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
674 print(output)
675 self.assertRegex(output, 'primary test1')
676
677 def test_routing_policy_rule(self):
b677774d 678 self.copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev')
703bc7a2
YW
679
680 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
681
1f0e3109
SS
682 self.start_networkd()
683
684 self.assertTrue(self.link_exits('test1'))
e40a58b5 685
1f0e3109
SS
686 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
687 print(output)
688 self.assertRegex(output, '111')
689 self.assertRegex(output, 'from 192.168.100.18')
f7bdd562 690 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
1f0e3109
SS
691 self.assertRegex(output, 'iif test1')
692 self.assertRegex(output, 'oif test1')
693 self.assertRegex(output, 'lookup 7')
694
e4eacdb0
YW
695 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
696
b677774d
YW
697 def test_routing_policy_rule_issue_11280(self):
698 self.copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev',
699 'routing-policy-rule-dummy98.network', '12-dummy.netdev')
700
701 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
702 subprocess.call(['ip', 'rule', 'del', 'table', '8'])
703
704 for trial in range(3):
705 # Remove state files only first time
706 self.start_networkd(trial == 0)
707
708 self.assertTrue(self.link_exits('test1'))
709 self.assertTrue(self.link_exits('dummy98'))
710
711 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '7']).rstrip().decode('utf-8')
712 print(output)
713 self.assertRegex(output, '111: from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
714
715 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '8']).rstrip().decode('utf-8')
716 print(output)
717 self.assertRegex(output, '112: from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
718
719 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
720 subprocess.call(['ip', 'rule', 'del', 'table', '8'])
721
d586a2c3 722 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0
SS
723 def test_routing_policy_rule_port_range(self):
724 self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
703bc7a2
YW
725
726 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
727
926062f0
SS
728 self.start_networkd()
729
730 self.assertTrue(self.link_exits('test1'))
e40a58b5 731
926062f0
SS
732 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
733 print(output)
734 self.assertRegex(output, '111')
735 self.assertRegex(output, 'from 192.168.100.18')
736 self.assertRegex(output, '1123-1150')
737 self.assertRegex(output, '3224-3290')
738 self.assertRegex(output, 'tcp')
739 self.assertRegex(output, 'lookup 7')
1f0e3109 740
e4eacdb0
YW
741 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
742
d586a2c3 743 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd
SS
744 def test_routing_policy_rule_invert(self):
745 self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
703bc7a2
YW
746
747 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
748
efecf9cd
SS
749 self.start_networkd()
750
751 self.assertTrue(self.link_exits('test1'))
e40a58b5 752
efecf9cd
SS
753 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
754 print(output)
efecf9cd
SS
755 self.assertRegex(output, '111')
756 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
757 self.assertRegex(output, 'tcp')
758 self.assertRegex(output, 'lookup 7')
759
e4eacdb0
YW
760 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
761
ac60877f
YW
762 def test_address_peer(self):
763 self.copy_unit_to_networkd_unit_path('25-address-section.network', '12-dummy.netdev')
764 self.start_networkd()
765
766 self.assertTrue(self.link_exits('dummy98'))
767
26bf9c30
YW
768 # This also tests address pool
769
770 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '32']).rstrip().decode('utf-8')
ac60877f
YW
771 print(output)
772 self.assertRegex(output, 'inet 10.2.3.4 peer 10.2.3.5/16 scope global 32')
26bf9c30
YW
773
774 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '33']).rstrip().decode('utf-8')
775 print(output)
ac60877f 776 self.assertRegex(output, 'inet 10.6.7.8/16 brd 10.6.255.255 scope global 33')
26bf9c30
YW
777
778 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '34']).rstrip().decode('utf-8')
779 print(output)
780 self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
781
782 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98', 'label', '35']).rstrip().decode('utf-8')
783 print(output)
784 self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
785
786 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
787 print(output)
7e663619 788 self.assertRegex(output, 'inet6 2001:db8::20 peer 2001:db8::10/128 scope global')
26bf9c30 789 self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global')
ac60877f
YW
790
791 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
792 print(output)
793 self.assertRegex(output, 'State: routable \(configured\)')
794
1f0e3109
SS
795 def test_address_preferred_lifetime_zero_ipv6(self):
796 self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev')
797 self.start_networkd()
798
799 self.assertTrue(self.link_exits('dummy98'))
800
801 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
802 print(output)
803 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
804 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
805
806 def test_ip_route(self):
807 self.copy_unit_to_networkd_unit_path('25-route-section.network', '12-dummy.netdev')
808 self.start_networkd()
809
810 self.assertTrue(self.link_exits('dummy98'))
811
812 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98']).rstrip().decode('utf-8')
813 print(output)
814 self.assertRegex(output, '192.168.0.1')
815 self.assertRegex(output, 'static')
816 self.assertRegex(output, '192.168.0.0/24')
817
0d34228f
SS
818 def test_ip_route_reverse(self):
819 self.copy_unit_to_networkd_unit_path('25-route-reverse-order.network', '12-dummy.netdev')
820 self.start_networkd()
821
822 self.assertTrue(self.link_exits('dummy98'))
823
824 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
825 print(output)
826 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff')
827 self.assertRegex(output, '2001:1234:5:8f63::1')
828
1f0e3109
SS
829 def test_ip_route_blackhole_unreachable_prohibit(self):
830 self.copy_unit_to_networkd_unit_path('25-route-type.network', '12-dummy.netdev')
831 self.start_networkd()
832
833 self.assertTrue(self.link_exits('dummy98'))
834
835 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
836 print(output)
837 self.assertRegex(output, 'blackhole')
838 self.assertRegex(output, 'unreachable')
839 self.assertRegex(output, 'prohibit')
840
841 subprocess.call(['ip', 'route', 'del', 'blackhole', '202.54.1.2'])
842 subprocess.call(['ip', 'route', 'del', 'unreachable', '202.54.1.3'])
843 subprocess.call(['ip', 'route', 'del', 'prohibit', '202.54.1.4'])
844
845 def test_ip_route_tcp_window(self):
846 self.copy_unit_to_networkd_unit_path('25-route-tcp-window-settings.network', '11-dummy.netdev')
847 self.start_networkd()
848
849 self.assertTrue(self.link_exits('test1'))
850
851 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
852 print(output)
853 self.assertRegex(output, 'initcwnd 20')
854 self.assertRegex(output, 'initrwnd 30')
855
f5050e48
YW
856 def test_ip_route_gateway(self):
857 self.copy_unit_to_networkd_unit_path('25-route-gateway.network', '12-dummy.netdev')
858 self.start_networkd()
859
860 self.assertTrue(self.link_exits('dummy98'))
861
862 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
863 print(output)
864 self.assertRegex(output, 'default')
865 self.assertRegex(output, 'via')
866 self.assertRegex(output, '149.10.124.64')
867 self.assertRegex(output, 'proto')
868 self.assertRegex(output, 'static')
869
870 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
871 print(output)
872 self.assertRegex(output, '149.10.124.48/28')
873 self.assertRegex(output, 'proto')
874 self.assertRegex(output, 'kernel')
875 self.assertRegex(output, 'scope')
876 self.assertRegex(output, 'link')
877
878 def test_ip_route_gateway_on_link(self):
879 self.copy_unit_to_networkd_unit_path('25-route-gateway-on-link.network', '12-dummy.netdev')
880 self.start_networkd()
881
882 self.assertTrue(self.link_exits('dummy98'))
883
884 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
885 print(output)
886 self.assertRegex(output, 'default')
887 self.assertRegex(output, 'via')
888 self.assertRegex(output, '149.10.125.65')
889 self.assertRegex(output, 'proto')
890 self.assertRegex(output, 'static')
891 self.assertRegex(output, 'onlink')
892
893 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
894 print(output)
895 self.assertRegex(output, '149.10.124.48/28')
896 self.assertRegex(output, 'proto')
897 self.assertRegex(output, 'kernel')
898 self.assertRegex(output, 'scope')
899 self.assertRegex(output, 'link')
900
20ca06a6
DA
901 def test_ip_route_ipv6_src_route(self):
902 # a dummy device does not make the addresses go through tentative state, so we
903 # reuse a bond from an earlier test, which does make the addresses go through
904 # tentative state, and do our test on that
905 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')
906 self.start_networkd()
907
908 self.assertTrue(self.link_exits('dummy98'))
909 self.assertTrue(self.link_exits('bond199'))
910
911 output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8')
912 print(output)
913 self.assertRegex(output, 'abcd::/16')
914 self.assertRegex(output, 'src')
915 self.assertRegex(output, '2001:1234:56:8f63::2')
916
1f0e3109
SS
917 def test_ip_link_mac_address(self):
918 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
919 self.start_networkd()
920
921 self.assertTrue(self.link_exits('dummy98'))
922
923 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
924 print(output)
925 self.assertRegex(output, '00:01:02:aa:bb:cc')
926
927 def test_ip_link_unmanaged(self):
928 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
929 self.start_networkd()
930
931 self.assertTrue(self.link_exits('dummy98'))
932
933 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
934 print(output)
935 self.assertRegex(output, 'unmanaged')
936
937 def test_ipv6_address_label(self):
938 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
939 self.start_networkd()
940
941 self.assertTrue(self.link_exits('dummy98'))
942
943 output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
944 print(output)
945 self.assertRegex(output, '2004:da8:1::/64')
946
e4a71bf3
WKI
947 def test_ipv6_neighbor(self):
948 self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
949 self.start_networkd()
950
951 self.assertTrue(self.link_exits('dummy98'))
952
953 output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
954 print(output)
955 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 956 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 957
05514ae1
YW
958 def test_link_local_addressing(self):
959 self.copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
960 '25-link-local-addressing-no.network', '12-dummy.netdev')
961 self.start_networkd()
962
963 self.assertTrue(self.link_exits('test1'))
964 self.assertTrue(self.link_exits('dummy98'))
965
966 time.sleep(10)
967
968 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
969 print(output)
970 self.assertRegex(output, 'inet .* scope link')
971 self.assertRegex(output, 'inet6 .* scope link')
972
973 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
974 print(output)
975 self.assertNotRegex(output, 'inet6* .* scope link')
976
977 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
978 print(output)
979 self.assertRegex(output, 'State: degraded \(configured\)')
980
981 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
982 print(output)
983 self.assertRegex(output, 'State: carrier \(configured\)')
984
985 '''
986 Documentation/networking/ip-sysctl.txt
987
988 addr_gen_mode - INTEGER
989 Defines how link-local and autoconf addresses are generated.
990
991 0: generate address based on EUI64 (default)
992 1: do no generate a link-local address, use EUI64 for addresses generated
993 from autoconf
994 2: generate stable privacy addresses, using the secret from
995 stable_secret (RFC7217)
996 3: generate stable privacy addresses, using a random secret if unset
997 '''
998
999 test1_addr_gen_mode = ''
1000 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
1001 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
1002 try:
1003 f.readline()
1004 except IOError:
1005 # if stable_secret is unset, then EIO is returned
1006 test1_addr_gen_mode = '0'
1007 else:
1008 test1_addr_gen_mode = '2'
1009 else:
1010 test1_addr_gen_mode = '0'
1011
1012 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
1013 self.assertEqual(self.read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '0')
1014
1015 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
1016 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1017
1f0e3109
SS
1018 def test_sysctl(self):
1019 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1020 self.start_networkd()
1021
1022 self.assertTrue(self.link_exits('dummy98'))
1023
1024 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1025 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1026 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1027 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1028 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1029 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1030 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1031
4da33154
YW
1032 def test_sysctl_disable_ipv6(self):
1033 self.copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1034
1035 print('## Disable ipv6')
1036 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=1']), 0)
1037 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=1']), 0)
1038
1039 self.start_networkd()
1040
1041 self.assertTrue(self.link_exits('dummy98'))
1042
1043 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1044 print(output)
1045 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1046 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1047 print(output)
1048 self.assertEqual(output, '')
1049 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1050 self.assertRegex(output, 'State: routable \(configured\)')
1051
1052 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1053
1054 print('## Enable ipv6')
1055 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=0']), 0)
1056 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=0']), 0)
1057
1058 self.start_networkd()
1059
1060 self.assertTrue(self.link_exits('dummy98'))
1061
1062 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1063 print(output)
1064 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1065 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1066 print(output)
1067 self.assertRegex(output, 'inet6 .* scope link')
1068 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1069 self.assertRegex(output, 'State: routable \(configured\)')
1070
cd65d067
YW
1071 def test_bind_carrier(self):
1072 self.copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1073 self.start_networkd()
1074
1075 self.assertTrue(self.link_exits('test1'))
1076
cd65d067
YW
1077 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1078 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
b117044c 1079 time.sleep(2)
cd65d067
YW
1080 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1081 print(output)
1082 self.assertRegex(output, 'UP,LOWER_UP')
1083 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1084 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1085 self.assertRegex(output, 'State: routable \(configured\)')
1086
1087 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy99', 'type', 'dummy']), 0)
1088 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy99', 'up']), 0)
b117044c 1089 time.sleep(2)
cd65d067
YW
1090 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1091 print(output)
1092 self.assertRegex(output, 'UP,LOWER_UP')
1093 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1094 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1095 self.assertRegex(output, 'State: routable \(configured\)')
1096
1097 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
b117044c 1098 time.sleep(2)
cd65d067
YW
1099 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1100 print(output)
1101 self.assertRegex(output, 'UP,LOWER_UP')
1102 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1103 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1104 self.assertRegex(output, 'State: routable \(configured\)')
1105
1106 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy99']), 0)
b117044c 1107 time.sleep(2)
cd65d067
YW
1108 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1109 print(output)
1110 self.assertNotRegex(output, 'UP,LOWER_UP')
1111 self.assertRegex(output, 'DOWN')
1112 self.assertNotRegex(output, '192.168.10')
1113 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1114 self.assertRegex(output, 'State: off \(configured\)')
1115
1116 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1117 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
b117044c 1118 time.sleep(2)
cd65d067
YW
1119 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1120 print(output)
1121 self.assertRegex(output, 'UP,LOWER_UP')
1122 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1123 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1124 self.assertRegex(output, 'State: routable \(configured\)')
1125
c3a8853f
YW
1126class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
1127 links = [
1128 'bond99',
cc3e488c
YW
1129 'dummy98',
1130 'test1']
c3a8853f
YW
1131
1132 units = [
cc3e488c
YW
1133 '11-dummy.netdev',
1134 '12-dummy.netdev',
c3a8853f 1135 '25-bond.netdev',
c3a8853f 1136 'bond99.network',
cc3e488c 1137 'bond-slave.network']
c3a8853f
YW
1138
1139 def setUp(self):
1140 self.link_remove(self.links)
1141
1142 def tearDown(self):
1143 self.link_remove(self.links)
1144 self.remove_unit_from_networkd_path(self.units)
1145
cc3e488c
YW
1146 def test_bond_operstate(self):
1147 self.copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
1148 'bond99.network','bond-slave.network')
c3a8853f
YW
1149 self.start_networkd()
1150
1151 self.assertTrue(self.link_exits('bond99'))
cc3e488c
YW
1152 self.assertTrue(self.link_exits('dummy98'))
1153 self.assertTrue(self.link_exits('test1'))
c3a8853f 1154
cc3e488c 1155 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
c3a8853f 1156 print(output)
cc3e488c 1157 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 1158
cc3e488c 1159 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
c3a8853f
YW
1160 print(output)
1161 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1162
1163 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond99']).rstrip().decode('utf-8')
1164 print(output)
1165 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
1166
cc3e488c 1167 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
c3a8853f 1168 print(output)
cc3e488c 1169 self.assertRegex(output, 'State: enslaved \(configured\)')
c3a8853f 1170
cc3e488c 1171 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
c3a8853f
YW
1172 print(output)
1173 self.assertRegex(output, 'State: enslaved \(configured\)')
1174
1175 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1176 print(output)
1177 self.assertRegex(output, 'State: routable \(configured\)')
1178
cc3e488c 1179 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
c3a8853f
YW
1180 time.sleep(2)
1181
cc3e488c 1182 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
c3a8853f
YW
1183 print(output)
1184 self.assertRegex(output, 'State: off \(configured\)')
1185
cc3e488c
YW
1186 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1187 print(output)
1188 self.assertRegex(output, 'State: enslaved \(configured\)')
1189
c3a8853f
YW
1190 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1191 print(output)
1192 self.assertRegex(output, 'State: degraded \(configured\)')
1193
cc3e488c 1194 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
c3a8853f
YW
1195 time.sleep(2)
1196
cc3e488c
YW
1197 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1198 print(output)
1199 self.assertRegex(output, 'State: enslaved \(configured\)')
1200
1201 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
c3a8853f
YW
1202 print(output)
1203 self.assertRegex(output, 'State: enslaved \(configured\)')
1204
1205 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1206 print(output)
1207 self.assertRegex(output, 'State: routable \(configured\)')
1208
cc3e488c
YW
1209 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
1210 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'test1', 'down']), 0)
1211 time.sleep(2)
1212
1213 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1214 print(output)
1215 self.assertRegex(output, 'State: off \(configured\)')
1216
1217 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1218 print(output)
1219 self.assertRegex(output, 'State: off \(configured\)')
1220
1221 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1222 print(output)
1223 self.assertRegex(output, 'State: degraded \(configured\)')
1224
14dc0335 1225class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
1226 links = [
1227 'bridge99',
1228 'dummy98',
1229 'test1']
1230
1231 units = [
1232 '11-dummy.netdev',
1233 '12-dummy.netdev',
1234 '26-bridge.netdev',
1235 '26-bridge-slave-interface-1.network',
1236 '26-bridge-slave-interface-2.network',
804b6cd2 1237 'bridge99-ignore-carrier-loss.network',
09ea6724 1238 'bridge99.network']
1f0e3109
SS
1239
1240 def setUp(self):
1241 self.link_remove(self.links)
1242
1243 def tearDown(self):
1244 self.link_remove(self.links)
1245 self.remove_unit_from_networkd_path(self.units)
1246
1247 def test_bridge_property(self):
1248 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1249 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1250 'bridge99.network')
1251 self.start_networkd()
1252
1253 self.assertTrue(self.link_exits('dummy98'))
1254 self.assertTrue(self.link_exits('test1'))
1255 self.assertTrue(self.link_exits('bridge99'))
1256
1257 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
1258 print(output)
1259 self.assertRegex(output, 'master')
1260 self.assertRegex(output, 'bridge')
1261
1262 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1263 print(output)
1264 self.assertRegex(output, 'master')
1265 self.assertRegex(output, 'bridge')
1266
1267 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
1268 print(output)
2be6c5d2 1269 self.assertRegex(output, '192.168.0.15/24')
1f0e3109
SS
1270
1271 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1272 print(output)
4d7ed14f
SS
1273 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
1274 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
1275 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
1276 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
1277
1278 # CONFIG_BRIDGE_IGMP_SNOOPING=y
1279 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
1280 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1f0e3109 1281
2be6c5d2
YW
1282 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1283 self.assertRegex(output, 'State: enslaved \(configured\)')
1284
1285 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1286 self.assertRegex(output, 'State: enslaved \(configured\)')
1287
1288 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1289 self.assertRegex(output, 'State: routable \(configured\)')
1290
804b6cd2
YW
1291 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1292 time.sleep(1)
1293
2be6c5d2
YW
1294 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
1295 print(output)
1296 self.assertRegex(output, '192.168.0.16/24')
1297
1298 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1299 self.assertRegex(output, 'State: routable \(configured\)')
1300
804b6cd2 1301 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
2be6c5d2
YW
1302 time.sleep(3)
1303
1304 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1305 self.assertRegex(output, 'State: degraded \(configured\)')
1306
804b6cd2
YW
1307 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1308 time.sleep(3)
1309
2be6c5d2
YW
1310 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1311 self.assertRegex(output, 'State: no-carrier \(configured\)')
1312
804b6cd2
YW
1313 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1314 print(output)
1315 self.assertRegex(output, 'NO-CARRIER')
1316 self.assertNotRegex(output, '192.168.0.15/24')
1317 self.assertNotRegex(output, '192.168.0.16/24')
1318
1319 def test_bridge_ignore_carrier_loss(self):
1320 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1321 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1322 'bridge99-ignore-carrier-loss.network')
703bc7a2
YW
1323
1324 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1325
804b6cd2
YW
1326 self.start_networkd()
1327
1328 self.assertTrue(self.link_exits('dummy98'))
1329 self.assertTrue(self.link_exits('test1'))
1330 self.assertTrue(self.link_exits('bridge99'))
1331
1332 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1333 time.sleep(1)
1334
1335 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1336 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1337 time.sleep(3)
1338
1339 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1340 print(output)
1341 self.assertRegex(output, 'NO-CARRIER')
1342 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1343 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
1344
6609924c
YW
1345 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1346
1347 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
1348 self.copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
1349 'bridge99-ignore-carrier-loss.network')
703bc7a2
YW
1350
1351 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1352
6609924c
YW
1353 self.start_networkd()
1354
1355 self.assertTrue(self.link_exits('bridge99'))
1356
1357 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1358 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1359 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1360
1361 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1362 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1363 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1364
1365 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1366 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1367 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1368
1369 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1370 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1371
1372 time.sleep(3)
1373
1374 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1375 print(output)
1376 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1377
1378 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1379 self.assertRegex(output, 'State: routable \(configured\)')
1380
1381 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1382 self.assertRegex(output, 'State: enslaved \(configured\)')
1383
1384 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '100']).rstrip().decode('utf-8')
1385 print(output)
1386 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
1387
1388 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1389
1f0e3109
SS
1390class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
1391 links = ['veth99']
1392
09ea6724
YW
1393 units = [
1394 '23-emit-lldp.network',
1395 '24-lldp.network',
1396 '25-veth.netdev']
1f0e3109
SS
1397
1398 def setUp(self):
1399 self.link_remove(self.links)
1400
1401 def tearDown(self):
1402 self.link_remove(self.links)
1403 self.remove_unit_from_networkd_path(self.units)
1404
1405 def test_lldp(self):
1406 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
1407 self.start_networkd()
1408
1409 self.assertTrue(self.link_exits('veth99'))
1410
1411 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
1412 print(output)
1413 self.assertRegex(output, 'veth-peer')
1414 self.assertRegex(output, 'veth99')
1415
1416class NetworkdNetworkRATests(unittest.TestCase, Utilities):
1417 links = ['veth99']
1418
09ea6724
YW
1419 units = [
1420 '25-veth.netdev',
1421 'ipv6-prefix.network',
1422 'ipv6-prefix-veth.network']
1f0e3109
SS
1423
1424 def setUp(self):
1425 self.link_remove(self.links)
1426
1427 def tearDown(self):
1428 self.link_remove(self.links)
1429 self.remove_unit_from_networkd_path(self.units)
1430
1431 def test_ipv6_prefix_delegation(self):
1432 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1433 self.start_networkd()
1434
1435 self.assertTrue(self.link_exits('veth99'))
1436
1437 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1438 print(output)
1439 self.assertRegex(output, '2002:da8:1:0')
1440
1441class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
09ea6724
YW
1442 links = [
1443 'dummy98',
1444 'veth99']
1445
1446 units = [
1447 '12-dummy.netdev',
1448 '24-search-domain.network',
1449 '25-veth.netdev',
1450 'dhcp-client.network',
1451 'dhcp-client-timezone-router.network',
1452 'dhcp-server.network',
1453 'dhcp-server-timezone-router.network']
1f0e3109
SS
1454
1455 def setUp(self):
1456 self.link_remove(self.links)
1457
1458 def tearDown(self):
1459 self.link_remove(self.links)
1460 self.remove_unit_from_networkd_path(self.units)
1461
1462 def test_dhcp_server(self):
1463 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
1464 self.start_networkd()
1465
1466 self.assertTrue(self.link_exits('veth99'))
1467
1f0e3109
SS
1468 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1469 print(output)
1470 self.assertRegex(output, '192.168.5.*')
1471 self.assertRegex(output, 'Gateway: 192.168.5.1')
1472 self.assertRegex(output, 'DNS: 192.168.5.1')
1473 self.assertRegex(output, 'NTP: 192.168.5.1')
1474
1475 def test_domain(self):
f5d191a9 1476 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1f0e3109
SS
1477 self.start_networkd()
1478
1479 self.assertTrue(self.link_exits('dummy98'))
1480
1481 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1482 print(output)
1483 self.assertRegex(output, 'Address: 192.168.42.100')
1484 self.assertRegex(output, 'DNS: 192.168.42.1')
1485 self.assertRegex(output, 'Search Domains: one')
1486
1487 def test_emit_router_timezone(self):
1488 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
1489 self.start_networkd()
1490
1491 self.assertTrue(self.link_exits('veth99'))
1492
1493 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1494 print(output)
1495 self.assertRegex(output, 'Gateway: 192.168.5.*')
1496 self.assertRegex(output, '192.168.5.*')
1497 self.assertRegex(output, 'Europe/Berlin')
1498
1499class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
09ea6724
YW
1500 links = [
1501 'dummy98',
18c613dc
YW
1502 'veth99',
1503 'vrf99']
09ea6724
YW
1504
1505 units = [
1506 '25-veth.netdev',
18c613dc
YW
1507 '25-vrf.netdev',
1508 '25-vrf.network',
09ea6724
YW
1509 'dhcp-client-anonymize.network',
1510 'dhcp-client-critical-connection.network',
af3b1498 1511 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
1512 'dhcp-client-ipv4-dhcp-settings.network',
1513 'dhcp-client-ipv4-only-ipv6-disabled.network',
1514 'dhcp-client-ipv4-only.network',
1515 'dhcp-client-ipv6-only.network',
1516 'dhcp-client-ipv6-rapid-commit.network',
1517 'dhcp-client-listen-port.network',
1518 'dhcp-client-route-metric.network',
1519 'dhcp-client-route-table.network',
18c613dc 1520 'dhcp-client-vrf.network',
3e9d5552 1521 'dhcp-client.network',
09ea6724 1522 'dhcp-server-veth-peer.network',
30d3b54e
YW
1523 'dhcp-v4-server-veth-peer.network',
1524 'static.network']
1f0e3109
SS
1525
1526 def setUp(self):
1527 self.link_remove(self.links)
1528 self.stop_dnsmasq(dnsmasq_pid_file)
1529
1530 def tearDown(self):
1531 self.link_remove(self.links)
1532 self.remove_unit_from_networkd_path(self.units)
1533 self.stop_dnsmasq(dnsmasq_pid_file)
1534 self.remove_lease_file()
1535 self.remove_log_file()
1536
1537 def test_dhcp_client_ipv6_only(self):
f5d191a9 1538 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109
SS
1539 self.start_networkd()
1540
1541 self.assertTrue(self.link_exits('veth99'))
1542
1543 self.start_dnsmasq()
1544
1545 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1546 print(output)
1547 self.assertRegex(output, '2600::')
1548 self.assertNotRegex(output, '192.168.5')
1549
1550 def test_dhcp_client_ipv4_only(self):
f5d191a9 1551 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109
SS
1552 self.start_networkd()
1553
1554 self.assertTrue(self.link_exits('veth99'))
1555
1556 self.start_dnsmasq()
1557
1558 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1559 print(output)
1560 self.assertNotRegex(output, '2600::')
1561 self.assertRegex(output, '192.168.5')
1562
1563 def test_dhcp_client_ipv4_ipv6(self):
1564 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
1565 'dhcp-client-ipv4-only.network')
1566 self.start_networkd()
1567
1568 self.assertTrue(self.link_exits('veth99'))
1569
1570 self.start_dnsmasq()
1571
1572 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1573 print(output)
1574 self.assertRegex(output, '2600::')
1575 self.assertRegex(output, '192.168.5')
1576
1577 def test_dhcp_client_settings(self):
1578 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1579 self.start_networkd()
1580
1581 self.assertTrue(self.link_exits('veth99'))
1582
1583 self.start_dnsmasq()
1584
0ae7a66d 1585 print('## ip address show dev veth99')
1f0e3109
SS
1586 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1587 print(output)
1588 self.assertRegex(output, '12:34:56:78:9a:bc')
1589 self.assertRegex(output, '192.168.5')
1590 self.assertRegex(output, '1492')
1591
0ae7a66d
YW
1592 # issue #8726
1593 print('## ip route show table main dev veth99')
1594 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
1f0e3109 1595 print(output)
0ae7a66d 1596 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 1597
0ae7a66d
YW
1598 print('## ip route show table 211 dev veth99')
1599 output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99']).rstrip().decode('utf-8')
1600 print(output)
1601 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
1602 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
1603 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
1604
1605 print('## dnsmasq log')
131717cb
YW
1606 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
1607 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
1608 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
1609 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1610
1611 def test_dhcp6_client_settings_rapidcommit_true(self):
1612 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1613 self.start_networkd()
1614
1615 self.assertTrue(self.link_exits('veth99'))
1616
1617 self.start_dnsmasq()
1618
1619 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1620 print(output)
1621 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1622 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1623
1624 def test_dhcp6_client_settings_rapidcommit_false(self):
1625 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
1626 self.start_networkd()
1627
1628 self.assertTrue(self.link_exits('veth99'))
1629
1630 self.start_dnsmasq()
1631
1632 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1633 print(output)
1634 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1635 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1636
1637 def test_dhcp_client_settings_anonymize(self):
1638 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
1639 self.start_networkd()
1640
1641 self.assertTrue(self.link_exits('veth99'))
1642
1643 self.start_dnsmasq()
e40a58b5 1644
131717cb
YW
1645 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
1646 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
1647 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1648
1649 def test_dhcp_client_listen_port(self):
1650 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
1f0e3109
SS
1651 self.start_networkd()
1652
1653 self.assertTrue(self.link_exits('veth99'))
1654
b412fce8 1655 self.start_dnsmasq('--dhcp-alternate-port=67,5555')
1f0e3109 1656
b412fce8
YW
1657 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1658 print(output)
1659 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109
SS
1660
1661 def test_dhcp_route_table_id(self):
1662 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
1663 self.start_networkd()
1f0e3109
SS
1664
1665 self.assertTrue(self.link_exits('veth99'))
1666
e40a58b5
YW
1667 self.start_dnsmasq()
1668
1f0e3109
SS
1669 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
1670 print(output)
1f0e3109
SS
1671 self.assertRegex(output, 'veth99 proto dhcp')
1672 self.assertRegex(output, '192.168.5.1')
1673
1674 def test_dhcp_route_metric(self):
1675 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
1676 self.start_networkd()
1f0e3109
SS
1677
1678 self.assertTrue(self.link_exits('veth99'))
1679
e40a58b5
YW
1680 self.start_dnsmasq()
1681
1f0e3109
SS
1682 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1683 print(output)
1f0e3109
SS
1684 self.assertRegex(output, 'metric 24')
1685
1686 def test_dhcp_route_criticalconnection_true(self):
1687 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
1688 self.start_networkd()
1f0e3109
SS
1689
1690 self.assertTrue(self.link_exits('veth99'))
1691
e40a58b5
YW
1692 self.start_dnsmasq()
1693
1f0e3109
SS
1694 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1695 print(output)
1f0e3109 1696 self.assertRegex(output, '192.168.5.*')
e40a58b5 1697
1f0e3109
SS
1698 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
1699 self.stop_dnsmasq(dnsmasq_pid_file)
1700
1701 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1702 time.sleep(125)
1703
1704 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1705 print(output)
1706 self.assertRegex(output, '192.168.5.*')
1707
30d3b54e
YW
1708 def test_dhcp_client_reuse_address_as_static(self):
1709 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
1710 self.start_networkd()
1711
1712 self.assertTrue(self.link_exits('veth99'))
1713
1714 self.start_dnsmasq()
1715
1716 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1717 print(output)
1718 self.assertRegex(output, '192.168.5')
1719 self.assertRegex(output, '2600::')
1720
1721 ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
1722 ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
1723 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
1724 print(static_network)
1725
1726 self.remove_unit_from_networkd_path(['dhcp-client.network'])
1727
1728 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
1729 f.write(static_network)
1730
1731 self.start_networkd()
1732
1733 self.assertTrue(self.link_exits('veth99'))
1734
1735 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1736 print(output)
1737 self.assertRegex(output, '192.168.5')
1738 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1739
1740 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1741 print(output)
1742 self.assertRegex(output, '2600::')
1743 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1744
18c613dc
YW
1745 @expectedFailureIfModuleIsNotAvailable('vrf')
1746 def test_dhcp_client_vrf(self):
1747 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
1748 '25-vrf.netdev', '25-vrf.network')
1749 self.start_networkd()
1750
1751 self.assertTrue(self.link_exits('veth99'))
1752 self.assertTrue(self.link_exits('vrf99'))
1753
1754 self.start_dnsmasq()
1755
1756 print('## ip -d link show dev vrf99')
1757 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99']).rstrip().decode('utf-8')
1758 print(output)
1759 self.assertRegex(output, 'vrf table 42')
1760
1761 print('## ip address show vrf vrf99')
1762 output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
1763 print(output_ip_vrf)
1764
1765 print('## ip address show dev veth99')
1766 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1767 print(output)
1768 self.assertEqual(output, output_ip_vrf)
1769 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
1770 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
1771 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic noprefixroute')
1772 self.assertRegex(output, 'inet6 .* scope link')
1773
1774 print('## ip route show vrf vrf99')
1775 output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
1776 print(output)
1777 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
1778 self.assertRegex(output, 'default dev veth99 proto static scope link')
1779 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
1780 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
1781 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
1782 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
1783
1784 print('## ip route show table main dev veth99')
1785 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
1786 print(output)
1787 self.assertEqual(output, '')
1788
1789 output = subprocess.check_output(['networkctl', 'status', 'vrf99']).rstrip().decode('utf-8')
1790 print(output)
1791 self.assertRegex(output, 'State: carrier \(configured\)')
1792
1793 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1794 print(output)
1795 self.assertRegex(output, 'State: routable \(configured\)')
1796
af3b1498
YW
1797 def test_dhcp_client_gateway_onlink_implicit(self):
1798 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
1799 'dhcp-client-gateway-onlink-implicit.network')
1800 self.start_networkd()
1801
1802 self.assertTrue(self.link_exits('veth99'))
1803
1804 self.start_dnsmasq()
1805
1806 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1807 print(output)
1808 self.assertRegex(output, '192.168.5')
1809
1810 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '10.0.0.0/8']).rstrip().decode('utf-8')
1811 print(output)
1812 self.assertRegex(output, 'onlink')
1813 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '192.168.100.0/24']).rstrip().decode('utf-8')
1814 print(output)
1815 self.assertRegex(output, 'onlink')
1816
1f0e3109
SS
1817if __name__ == '__main__':
1818 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
1819 verbosity=3))