]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
Merge pull request #11919 from poettering/login-simplify
[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')
816
817 def test_ip_route(self):
818 self.copy_unit_to_networkd_unit_path('25-route-section.network', '12-dummy.netdev')
819 self.start_networkd()
820
821 self.assertTrue(self.link_exits('dummy98'))
822
823 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98']).rstrip().decode('utf-8')
824 print(output)
825 self.assertRegex(output, '192.168.0.1')
826 self.assertRegex(output, 'static')
827 self.assertRegex(output, '192.168.0.0/24')
828
0d34228f
SS
829 def test_ip_route_reverse(self):
830 self.copy_unit_to_networkd_unit_path('25-route-reverse-order.network', '12-dummy.netdev')
831 self.start_networkd()
832
833 self.assertTrue(self.link_exits('dummy98'))
834
835 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
836 print(output)
837 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff')
838 self.assertRegex(output, '2001:1234:5:8f63::1')
839
1f0e3109
SS
840 def test_ip_route_blackhole_unreachable_prohibit(self):
841 self.copy_unit_to_networkd_unit_path('25-route-type.network', '12-dummy.netdev')
842 self.start_networkd()
843
844 self.assertTrue(self.link_exits('dummy98'))
845
846 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
847 print(output)
848 self.assertRegex(output, 'blackhole')
849 self.assertRegex(output, 'unreachable')
850 self.assertRegex(output, 'prohibit')
851
852 subprocess.call(['ip', 'route', 'del', 'blackhole', '202.54.1.2'])
853 subprocess.call(['ip', 'route', 'del', 'unreachable', '202.54.1.3'])
854 subprocess.call(['ip', 'route', 'del', 'prohibit', '202.54.1.4'])
855
856 def test_ip_route_tcp_window(self):
857 self.copy_unit_to_networkd_unit_path('25-route-tcp-window-settings.network', '11-dummy.netdev')
858 self.start_networkd()
859
860 self.assertTrue(self.link_exits('test1'))
861
862 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
863 print(output)
864 self.assertRegex(output, 'initcwnd 20')
865 self.assertRegex(output, 'initrwnd 30')
866
f5050e48
YW
867 def test_ip_route_gateway(self):
868 self.copy_unit_to_networkd_unit_path('25-route-gateway.network', '12-dummy.netdev')
869 self.start_networkd()
870
871 self.assertTrue(self.link_exits('dummy98'))
872
873 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
874 print(output)
875 self.assertRegex(output, 'default')
876 self.assertRegex(output, 'via')
877 self.assertRegex(output, '149.10.124.64')
878 self.assertRegex(output, 'proto')
879 self.assertRegex(output, 'static')
880
881 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
882 print(output)
883 self.assertRegex(output, '149.10.124.48/28')
884 self.assertRegex(output, 'proto')
885 self.assertRegex(output, 'kernel')
886 self.assertRegex(output, 'scope')
887 self.assertRegex(output, 'link')
888
889 def test_ip_route_gateway_on_link(self):
890 self.copy_unit_to_networkd_unit_path('25-route-gateway-on-link.network', '12-dummy.netdev')
891 self.start_networkd()
892
893 self.assertTrue(self.link_exits('dummy98'))
894
895 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
896 print(output)
897 self.assertRegex(output, 'default')
898 self.assertRegex(output, 'via')
899 self.assertRegex(output, '149.10.125.65')
900 self.assertRegex(output, 'proto')
901 self.assertRegex(output, 'static')
902 self.assertRegex(output, 'onlink')
903
904 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
905 print(output)
906 self.assertRegex(output, '149.10.124.48/28')
907 self.assertRegex(output, 'proto')
908 self.assertRegex(output, 'kernel')
909 self.assertRegex(output, 'scope')
910 self.assertRegex(output, 'link')
911
20ca06a6
DA
912 def test_ip_route_ipv6_src_route(self):
913 # a dummy device does not make the addresses go through tentative state, so we
914 # reuse a bond from an earlier test, which does make the addresses go through
915 # tentative state, and do our test on that
916 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')
917 self.start_networkd()
918
919 self.assertTrue(self.link_exits('dummy98'))
920 self.assertTrue(self.link_exits('bond199'))
921
922 output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8')
923 print(output)
924 self.assertRegex(output, 'abcd::/16')
925 self.assertRegex(output, 'src')
926 self.assertRegex(output, '2001:1234:56:8f63::2')
927
1f0e3109
SS
928 def test_ip_link_mac_address(self):
929 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
930 self.start_networkd()
931
932 self.assertTrue(self.link_exits('dummy98'))
933
934 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
935 print(output)
936 self.assertRegex(output, '00:01:02:aa:bb:cc')
937
938 def test_ip_link_unmanaged(self):
939 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
940 self.start_networkd()
941
942 self.assertTrue(self.link_exits('dummy98'))
943
944 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
945 print(output)
946 self.assertRegex(output, 'unmanaged')
947
948 def test_ipv6_address_label(self):
949 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
950 self.start_networkd()
951
952 self.assertTrue(self.link_exits('dummy98'))
953
954 output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
955 print(output)
956 self.assertRegex(output, '2004:da8:1::/64')
957
e4a71bf3
WKI
958 def test_ipv6_neighbor(self):
959 self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
960 self.start_networkd()
961
962 self.assertTrue(self.link_exits('dummy98'))
963
964 output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
965 print(output)
966 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 967 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 968
05514ae1
YW
969 def test_link_local_addressing(self):
970 self.copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
971 '25-link-local-addressing-no.network', '12-dummy.netdev')
972 self.start_networkd()
973
974 self.assertTrue(self.link_exits('test1'))
975 self.assertTrue(self.link_exits('dummy98'))
976
977 time.sleep(10)
978
979 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
980 print(output)
981 self.assertRegex(output, 'inet .* scope link')
982 self.assertRegex(output, 'inet6 .* scope link')
983
984 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
985 print(output)
986 self.assertNotRegex(output, 'inet6* .* scope link')
987
988 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
989 print(output)
990 self.assertRegex(output, 'State: degraded \(configured\)')
991
992 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
993 print(output)
994 self.assertRegex(output, 'State: carrier \(configured\)')
995
996 '''
997 Documentation/networking/ip-sysctl.txt
998
999 addr_gen_mode - INTEGER
1000 Defines how link-local and autoconf addresses are generated.
1001
1002 0: generate address based on EUI64 (default)
1003 1: do no generate a link-local address, use EUI64 for addresses generated
1004 from autoconf
1005 2: generate stable privacy addresses, using the secret from
1006 stable_secret (RFC7217)
1007 3: generate stable privacy addresses, using a random secret if unset
1008 '''
1009
1010 test1_addr_gen_mode = ''
1011 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
1012 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
1013 try:
1014 f.readline()
1015 except IOError:
1016 # if stable_secret is unset, then EIO is returned
1017 test1_addr_gen_mode = '0'
1018 else:
1019 test1_addr_gen_mode = '2'
1020 else:
1021 test1_addr_gen_mode = '0'
1022
1023 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
1024 self.assertEqual(self.read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '0')
1025
1026 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
1027 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
1028
1f0e3109
SS
1029 def test_sysctl(self):
1030 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
1031 self.start_networkd()
1032
1033 self.assertTrue(self.link_exits('dummy98'))
1034
1035 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
1036 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
1037 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
1038 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
1039 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
1040 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
1041 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
1042
4da33154
YW
1043 def test_sysctl_disable_ipv6(self):
1044 self.copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
1045
1046 print('## Disable ipv6')
1047 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=1']), 0)
1048 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=1']), 0)
1049
1050 self.start_networkd()
1051
1052 self.assertTrue(self.link_exits('dummy98'))
1053
1054 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1055 print(output)
1056 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1057 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1058 print(output)
1059 self.assertEqual(output, '')
1060 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1061 self.assertRegex(output, 'State: routable \(configured\)')
1062
1063 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1064
1065 print('## Enable ipv6')
1066 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=0']), 0)
1067 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=0']), 0)
1068
1069 self.start_networkd()
1070
1071 self.assertTrue(self.link_exits('dummy98'))
1072
1073 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1074 print(output)
1075 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
1076 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
1077 print(output)
1078 self.assertRegex(output, 'inet6 .* scope link')
1079 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1080 self.assertRegex(output, 'State: routable \(configured\)')
1081
cd65d067
YW
1082 def test_bind_carrier(self):
1083 self.copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1084 self.start_networkd()
1085
1086 self.assertTrue(self.link_exits('test1'))
1087
cd65d067
YW
1088 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1089 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
b117044c 1090 time.sleep(2)
cd65d067
YW
1091 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1092 print(output)
1093 self.assertRegex(output, 'UP,LOWER_UP')
1094 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1095 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1096 self.assertRegex(output, 'State: routable \(configured\)')
1097
1098 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy99', 'type', 'dummy']), 0)
1099 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy99', 'up']), 0)
b117044c 1100 time.sleep(2)
cd65d067
YW
1101 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1102 print(output)
1103 self.assertRegex(output, 'UP,LOWER_UP')
1104 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1105 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1106 self.assertRegex(output, 'State: routable \(configured\)')
1107
1108 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
b117044c 1109 time.sleep(2)
cd65d067
YW
1110 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1111 print(output)
1112 self.assertRegex(output, 'UP,LOWER_UP')
1113 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1114 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1115 self.assertRegex(output, 'State: routable \(configured\)')
1116
1117 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy99']), 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.assertNotRegex(output, 'UP,LOWER_UP')
1122 self.assertRegex(output, 'DOWN')
1123 self.assertNotRegex(output, '192.168.10')
1124 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1125 self.assertRegex(output, 'State: off \(configured\)')
1126
1127 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1128 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
b117044c 1129 time.sleep(2)
cd65d067
YW
1130 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1131 print(output)
1132 self.assertRegex(output, 'UP,LOWER_UP')
1133 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1134 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1135 self.assertRegex(output, 'State: routable \(configured\)')
1136
c3a8853f
YW
1137class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
1138 links = [
1139 'bond99',
cc3e488c
YW
1140 'dummy98',
1141 'test1']
c3a8853f
YW
1142
1143 units = [
cc3e488c
YW
1144 '11-dummy.netdev',
1145 '12-dummy.netdev',
c3a8853f 1146 '25-bond.netdev',
c3a8853f 1147 'bond99.network',
cc3e488c 1148 'bond-slave.network']
c3a8853f
YW
1149
1150 def setUp(self):
1151 self.link_remove(self.links)
1152
1153 def tearDown(self):
1154 self.link_remove(self.links)
1155 self.remove_unit_from_networkd_path(self.units)
1156
cc3e488c
YW
1157 def test_bond_operstate(self):
1158 self.copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
1159 'bond99.network','bond-slave.network')
c3a8853f
YW
1160 self.start_networkd()
1161
1162 self.assertTrue(self.link_exits('bond99'))
cc3e488c
YW
1163 self.assertTrue(self.link_exits('dummy98'))
1164 self.assertTrue(self.link_exits('test1'))
c3a8853f 1165
cc3e488c 1166 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
c3a8853f 1167 print(output)
cc3e488c 1168 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
c3a8853f 1169
cc3e488c 1170 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
c3a8853f
YW
1171 print(output)
1172 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1173
1174 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond99']).rstrip().decode('utf-8')
1175 print(output)
1176 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
1177
cc3e488c 1178 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
c3a8853f 1179 print(output)
cc3e488c 1180 self.assertRegex(output, 'State: enslaved \(configured\)')
c3a8853f 1181
cc3e488c 1182 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
c3a8853f
YW
1183 print(output)
1184 self.assertRegex(output, 'State: enslaved \(configured\)')
1185
1186 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1187 print(output)
1188 self.assertRegex(output, 'State: routable \(configured\)')
1189
cc3e488c 1190 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
c3a8853f
YW
1191 time.sleep(2)
1192
cc3e488c 1193 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
c3a8853f
YW
1194 print(output)
1195 self.assertRegex(output, 'State: off \(configured\)')
1196
cc3e488c
YW
1197 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1198 print(output)
1199 self.assertRegex(output, 'State: enslaved \(configured\)')
1200
c3a8853f
YW
1201 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1202 print(output)
1203 self.assertRegex(output, 'State: degraded \(configured\)')
1204
cc3e488c 1205 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
c3a8853f
YW
1206 time.sleep(2)
1207
cc3e488c
YW
1208 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1209 print(output)
1210 self.assertRegex(output, 'State: enslaved \(configured\)')
1211
1212 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
c3a8853f
YW
1213 print(output)
1214 self.assertRegex(output, 'State: enslaved \(configured\)')
1215
1216 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1217 print(output)
1218 self.assertRegex(output, 'State: routable \(configured\)')
1219
cc3e488c
YW
1220 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
1221 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'test1', 'down']), 0)
1222 time.sleep(2)
1223
1224 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1225 print(output)
1226 self.assertRegex(output, 'State: off \(configured\)')
1227
1228 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1229 print(output)
1230 self.assertRegex(output, 'State: off \(configured\)')
1231
1232 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1233 print(output)
1234 self.assertRegex(output, 'State: degraded \(configured\)')
1235
14dc0335 1236class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
1237 links = [
1238 'bridge99',
1239 'dummy98',
1240 'test1']
1241
1242 units = [
1243 '11-dummy.netdev',
1244 '12-dummy.netdev',
1245 '26-bridge.netdev',
1246 '26-bridge-slave-interface-1.network',
1247 '26-bridge-slave-interface-2.network',
804b6cd2 1248 'bridge99-ignore-carrier-loss.network',
09ea6724 1249 'bridge99.network']
1f0e3109
SS
1250
1251 def setUp(self):
1252 self.link_remove(self.links)
1253
1254 def tearDown(self):
1255 self.link_remove(self.links)
1256 self.remove_unit_from_networkd_path(self.units)
1257
1258 def test_bridge_property(self):
1259 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1260 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1261 'bridge99.network')
1262 self.start_networkd()
1263
1264 self.assertTrue(self.link_exits('dummy98'))
1265 self.assertTrue(self.link_exits('test1'))
1266 self.assertTrue(self.link_exits('bridge99'))
1267
1268 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
1269 print(output)
1270 self.assertRegex(output, 'master')
1271 self.assertRegex(output, 'bridge')
1272
1273 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1274 print(output)
1275 self.assertRegex(output, 'master')
1276 self.assertRegex(output, 'bridge')
1277
1278 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
1279 print(output)
2be6c5d2 1280 self.assertRegex(output, '192.168.0.15/24')
1f0e3109
SS
1281
1282 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1283 print(output)
4d7ed14f
SS
1284 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
1285 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
1286 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
1287 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
1288
1289 # CONFIG_BRIDGE_IGMP_SNOOPING=y
1290 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
1291 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1f0e3109 1292
2be6c5d2
YW
1293 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1294 self.assertRegex(output, 'State: enslaved \(configured\)')
1295
1296 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1297 self.assertRegex(output, 'State: enslaved \(configured\)')
1298
1299 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1300 self.assertRegex(output, 'State: routable \(configured\)')
1301
804b6cd2
YW
1302 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1303 time.sleep(1)
1304
2be6c5d2
YW
1305 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
1306 print(output)
1307 self.assertRegex(output, '192.168.0.16/24')
1308
1309 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1310 self.assertRegex(output, 'State: routable \(configured\)')
1311
804b6cd2 1312 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
2be6c5d2
YW
1313 time.sleep(3)
1314
1315 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1316 self.assertRegex(output, 'State: degraded \(configured\)')
1317
804b6cd2
YW
1318 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1319 time.sleep(3)
1320
2be6c5d2
YW
1321 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1322 self.assertRegex(output, 'State: no-carrier \(configured\)')
1323
804b6cd2
YW
1324 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1325 print(output)
1326 self.assertRegex(output, 'NO-CARRIER')
1327 self.assertNotRegex(output, '192.168.0.15/24')
1328 self.assertNotRegex(output, '192.168.0.16/24')
1329
1330 def test_bridge_ignore_carrier_loss(self):
1331 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1332 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1333 'bridge99-ignore-carrier-loss.network')
703bc7a2
YW
1334
1335 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1336
804b6cd2
YW
1337 self.start_networkd()
1338
1339 self.assertTrue(self.link_exits('dummy98'))
1340 self.assertTrue(self.link_exits('test1'))
1341 self.assertTrue(self.link_exits('bridge99'))
1342
1343 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1344 time.sleep(1)
1345
1346 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1347 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1348 time.sleep(3)
1349
1350 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1351 print(output)
1352 self.assertRegex(output, 'NO-CARRIER')
1353 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1354 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
1355
6609924c
YW
1356 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1357
1358 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
1359 self.copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
1360 'bridge99-ignore-carrier-loss.network')
703bc7a2
YW
1361
1362 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1363
6609924c
YW
1364 self.start_networkd()
1365
1366 self.assertTrue(self.link_exits('bridge99'))
1367
1368 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1369 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1370 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1371
1372 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1373 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1374 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1375
1376 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1377 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1378 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1379
1380 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1381 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1382
1383 time.sleep(3)
1384
1385 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1386 print(output)
1387 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1388
1389 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1390 self.assertRegex(output, 'State: routable \(configured\)')
1391
1392 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1393 self.assertRegex(output, 'State: enslaved \(configured\)')
1394
1395 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '100']).rstrip().decode('utf-8')
1396 print(output)
1397 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
1398
1399 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1400
1f0e3109
SS
1401class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
1402 links = ['veth99']
1403
09ea6724
YW
1404 units = [
1405 '23-emit-lldp.network',
1406 '24-lldp.network',
1407 '25-veth.netdev']
1f0e3109
SS
1408
1409 def setUp(self):
1410 self.link_remove(self.links)
1411
1412 def tearDown(self):
1413 self.link_remove(self.links)
1414 self.remove_unit_from_networkd_path(self.units)
1415
1416 def test_lldp(self):
1417 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
1418 self.start_networkd()
1419
1420 self.assertTrue(self.link_exits('veth99'))
1421
1422 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
1423 print(output)
1424 self.assertRegex(output, 'veth-peer')
1425 self.assertRegex(output, 'veth99')
1426
1427class NetworkdNetworkRATests(unittest.TestCase, Utilities):
1428 links = ['veth99']
1429
09ea6724
YW
1430 units = [
1431 '25-veth.netdev',
1432 'ipv6-prefix.network',
1433 'ipv6-prefix-veth.network']
1f0e3109
SS
1434
1435 def setUp(self):
1436 self.link_remove(self.links)
1437
1438 def tearDown(self):
1439 self.link_remove(self.links)
1440 self.remove_unit_from_networkd_path(self.units)
1441
1442 def test_ipv6_prefix_delegation(self):
1443 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1444 self.start_networkd()
1445
1446 self.assertTrue(self.link_exits('veth99'))
1447
1448 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1449 print(output)
1450 self.assertRegex(output, '2002:da8:1:0')
1451
1452class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
09ea6724
YW
1453 links = [
1454 'dummy98',
1455 'veth99']
1456
1457 units = [
1458 '12-dummy.netdev',
1459 '24-search-domain.network',
1460 '25-veth.netdev',
1461 'dhcp-client.network',
1462 'dhcp-client-timezone-router.network',
1463 'dhcp-server.network',
1464 'dhcp-server-timezone-router.network']
1f0e3109
SS
1465
1466 def setUp(self):
1467 self.link_remove(self.links)
1468
1469 def tearDown(self):
1470 self.link_remove(self.links)
1471 self.remove_unit_from_networkd_path(self.units)
1472
1473 def test_dhcp_server(self):
1474 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
1475 self.start_networkd()
1476
1477 self.assertTrue(self.link_exits('veth99'))
1478
1f0e3109
SS
1479 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1480 print(output)
1481 self.assertRegex(output, '192.168.5.*')
1482 self.assertRegex(output, 'Gateway: 192.168.5.1')
1483 self.assertRegex(output, 'DNS: 192.168.5.1')
1484 self.assertRegex(output, 'NTP: 192.168.5.1')
1485
1486 def test_domain(self):
f5d191a9 1487 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1f0e3109
SS
1488 self.start_networkd()
1489
1490 self.assertTrue(self.link_exits('dummy98'))
1491
1492 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1493 print(output)
1494 self.assertRegex(output, 'Address: 192.168.42.100')
1495 self.assertRegex(output, 'DNS: 192.168.42.1')
1496 self.assertRegex(output, 'Search Domains: one')
1497
1498 def test_emit_router_timezone(self):
1499 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
1500 self.start_networkd()
1501
1502 self.assertTrue(self.link_exits('veth99'))
1503
1504 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1505 print(output)
1506 self.assertRegex(output, 'Gateway: 192.168.5.*')
1507 self.assertRegex(output, '192.168.5.*')
1508 self.assertRegex(output, 'Europe/Berlin')
1509
1510class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
09ea6724
YW
1511 links = [
1512 'dummy98',
18c613dc
YW
1513 'veth99',
1514 'vrf99']
09ea6724
YW
1515
1516 units = [
1517 '25-veth.netdev',
18c613dc
YW
1518 '25-vrf.netdev',
1519 '25-vrf.network',
09ea6724
YW
1520 'dhcp-client-anonymize.network',
1521 'dhcp-client-critical-connection.network',
af3b1498 1522 'dhcp-client-gateway-onlink-implicit.network',
09ea6724
YW
1523 'dhcp-client-ipv4-dhcp-settings.network',
1524 'dhcp-client-ipv4-only-ipv6-disabled.network',
1525 'dhcp-client-ipv4-only.network',
1526 'dhcp-client-ipv6-only.network',
1527 'dhcp-client-ipv6-rapid-commit.network',
1528 'dhcp-client-listen-port.network',
1529 'dhcp-client-route-metric.network',
1530 'dhcp-client-route-table.network',
18c613dc 1531 'dhcp-client-vrf.network',
3e9d5552 1532 'dhcp-client.network',
09ea6724 1533 'dhcp-server-veth-peer.network',
30d3b54e
YW
1534 'dhcp-v4-server-veth-peer.network',
1535 'static.network']
1f0e3109
SS
1536
1537 def setUp(self):
1538 self.link_remove(self.links)
1539 self.stop_dnsmasq(dnsmasq_pid_file)
1540
1541 def tearDown(self):
1542 self.link_remove(self.links)
1543 self.remove_unit_from_networkd_path(self.units)
1544 self.stop_dnsmasq(dnsmasq_pid_file)
1545 self.remove_lease_file()
1546 self.remove_log_file()
1547
1548 def test_dhcp_client_ipv6_only(self):
f5d191a9 1549 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109
SS
1550 self.start_networkd()
1551
1552 self.assertTrue(self.link_exits('veth99'))
1553
1554 self.start_dnsmasq()
1555
1556 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1557 print(output)
1558 self.assertRegex(output, '2600::')
1559 self.assertNotRegex(output, '192.168.5')
1560
1561 def test_dhcp_client_ipv4_only(self):
f5d191a9 1562 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109
SS
1563 self.start_networkd()
1564
1565 self.assertTrue(self.link_exits('veth99'))
1566
1567 self.start_dnsmasq()
1568
1569 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1570 print(output)
1571 self.assertNotRegex(output, '2600::')
1572 self.assertRegex(output, '192.168.5')
1573
1574 def test_dhcp_client_ipv4_ipv6(self):
1575 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
1576 'dhcp-client-ipv4-only.network')
1577 self.start_networkd()
1578
1579 self.assertTrue(self.link_exits('veth99'))
1580
1581 self.start_dnsmasq()
1582
1583 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1584 print(output)
1585 self.assertRegex(output, '2600::')
1586 self.assertRegex(output, '192.168.5')
1587
1588 def test_dhcp_client_settings(self):
1589 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1590 self.start_networkd()
1591
1592 self.assertTrue(self.link_exits('veth99'))
1593
1594 self.start_dnsmasq()
1595
0ae7a66d 1596 print('## ip address show dev veth99')
1f0e3109
SS
1597 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1598 print(output)
1599 self.assertRegex(output, '12:34:56:78:9a:bc')
1600 self.assertRegex(output, '192.168.5')
1601 self.assertRegex(output, '1492')
1602
0ae7a66d
YW
1603 # issue #8726
1604 print('## ip route show table main dev veth99')
1605 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
1f0e3109 1606 print(output)
0ae7a66d 1607 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 1608
0ae7a66d
YW
1609 print('## ip route show table 211 dev veth99')
1610 output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99']).rstrip().decode('utf-8')
1611 print(output)
1612 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
1613 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
1614 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
1615
1616 print('## dnsmasq log')
131717cb
YW
1617 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
1618 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
1619 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
1620 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1621
1622 def test_dhcp6_client_settings_rapidcommit_true(self):
1623 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1624 self.start_networkd()
1625
1626 self.assertTrue(self.link_exits('veth99'))
1627
1628 self.start_dnsmasq()
1629
1630 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1631 print(output)
1632 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1633 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1634
1635 def test_dhcp6_client_settings_rapidcommit_false(self):
1636 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
1637 self.start_networkd()
1638
1639 self.assertTrue(self.link_exits('veth99'))
1640
1641 self.start_dnsmasq()
1642
1643 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1644 print(output)
1645 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1646 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1647
1648 def test_dhcp_client_settings_anonymize(self):
1649 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
1650 self.start_networkd()
1651
1652 self.assertTrue(self.link_exits('veth99'))
1653
1654 self.start_dnsmasq()
e40a58b5 1655
131717cb
YW
1656 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
1657 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
1658 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1659
1660 def test_dhcp_client_listen_port(self):
1661 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
1f0e3109
SS
1662 self.start_networkd()
1663
1664 self.assertTrue(self.link_exits('veth99'))
1665
b412fce8 1666 self.start_dnsmasq('--dhcp-alternate-port=67,5555')
1f0e3109 1667
b412fce8
YW
1668 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1669 print(output)
1670 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109
SS
1671
1672 def test_dhcp_route_table_id(self):
1673 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
1674 self.start_networkd()
1f0e3109
SS
1675
1676 self.assertTrue(self.link_exits('veth99'))
1677
e40a58b5
YW
1678 self.start_dnsmasq()
1679
1f0e3109
SS
1680 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
1681 print(output)
1f0e3109
SS
1682 self.assertRegex(output, 'veth99 proto dhcp')
1683 self.assertRegex(output, '192.168.5.1')
1684
1685 def test_dhcp_route_metric(self):
1686 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
1687 self.start_networkd()
1f0e3109
SS
1688
1689 self.assertTrue(self.link_exits('veth99'))
1690
e40a58b5
YW
1691 self.start_dnsmasq()
1692
1f0e3109
SS
1693 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1694 print(output)
1f0e3109
SS
1695 self.assertRegex(output, 'metric 24')
1696
1697 def test_dhcp_route_criticalconnection_true(self):
1698 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
1699 self.start_networkd()
1f0e3109
SS
1700
1701 self.assertTrue(self.link_exits('veth99'))
1702
e40a58b5
YW
1703 self.start_dnsmasq()
1704
1f0e3109
SS
1705 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1706 print(output)
1f0e3109 1707 self.assertRegex(output, '192.168.5.*')
e40a58b5 1708
1f0e3109
SS
1709 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
1710 self.stop_dnsmasq(dnsmasq_pid_file)
1711
1712 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1713 time.sleep(125)
1714
1715 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1716 print(output)
1717 self.assertRegex(output, '192.168.5.*')
1718
30d3b54e
YW
1719 def test_dhcp_client_reuse_address_as_static(self):
1720 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
1721 self.start_networkd()
1722
1723 self.assertTrue(self.link_exits('veth99'))
1724
1725 self.start_dnsmasq()
1726
1727 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1728 print(output)
1729 self.assertRegex(output, '192.168.5')
1730 self.assertRegex(output, '2600::')
1731
1732 ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
1733 ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
1734 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
1735 print(static_network)
1736
1737 self.remove_unit_from_networkd_path(['dhcp-client.network'])
1738
1739 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
1740 f.write(static_network)
1741
1742 self.start_networkd()
1743
1744 self.assertTrue(self.link_exits('veth99'))
1745
1746 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1747 print(output)
1748 self.assertRegex(output, '192.168.5')
1749 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1750
1751 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1752 print(output)
1753 self.assertRegex(output, '2600::')
1754 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1755
18c613dc
YW
1756 @expectedFailureIfModuleIsNotAvailable('vrf')
1757 def test_dhcp_client_vrf(self):
1758 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
1759 '25-vrf.netdev', '25-vrf.network')
1760 self.start_networkd()
1761
1762 self.assertTrue(self.link_exits('veth99'))
1763 self.assertTrue(self.link_exits('vrf99'))
1764
1765 self.start_dnsmasq()
1766
1767 print('## ip -d link show dev vrf99')
1768 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99']).rstrip().decode('utf-8')
1769 print(output)
1770 self.assertRegex(output, 'vrf table 42')
1771
1772 print('## ip address show vrf vrf99')
1773 output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
1774 print(output_ip_vrf)
1775
1776 print('## ip address show dev veth99')
1777 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1778 print(output)
1779 self.assertEqual(output, output_ip_vrf)
1780 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
1781 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
1782 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic noprefixroute')
1783 self.assertRegex(output, 'inet6 .* scope link')
1784
1785 print('## ip route show vrf vrf99')
1786 output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
1787 print(output)
1788 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
1789 self.assertRegex(output, 'default dev veth99 proto static scope link')
1790 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
1791 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
1792 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
1793 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
1794
1795 print('## ip route show table main dev veth99')
1796 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
1797 print(output)
1798 self.assertEqual(output, '')
1799
1800 output = subprocess.check_output(['networkctl', 'status', 'vrf99']).rstrip().decode('utf-8')
1801 print(output)
1802 self.assertRegex(output, 'State: carrier \(configured\)')
1803
1804 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1805 print(output)
1806 self.assertRegex(output, 'State: routable \(configured\)')
1807
af3b1498
YW
1808 def test_dhcp_client_gateway_onlink_implicit(self):
1809 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
1810 'dhcp-client-gateway-onlink-implicit.network')
1811 self.start_networkd()
1812
1813 self.assertTrue(self.link_exits('veth99'))
1814
1815 self.start_dnsmasq()
1816
1817 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1818 print(output)
1819 self.assertRegex(output, '192.168.5')
1820
1821 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '10.0.0.0/8']).rstrip().decode('utf-8')
1822 print(output)
1823 self.assertRegex(output, 'onlink')
1824 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '192.168.100.0/24']).rstrip().decode('utf-8')
1825 print(output)
1826 self.assertRegex(output, 'onlink')
1827
1f0e3109
SS
1828if __name__ == '__main__':
1829 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
1830 verbosity=3))