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