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