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