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