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