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