]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/test-network/systemd-networkd-tests.py
test-network: update cosmetic workaround
[thirdparty/systemd.git] / test / test-network / systemd-networkd-tests.py
CommitLineData
1f0e3109
SS
1#!/usr/bin/env python3
2# SPDX-License-Identifier: LGPL-2.1+
3# systemd-networkd tests
4
5import os
201bf07f 6import re
1f0e3109
SS
7import shutil
8import signal
9import socket
a9bc5e37
YW
10import subprocess
11import sys
a9bc5e37
YW
12import time
13import unittest
1f0e3109
SS
14from shutil import copytree
15
d486a2d0 16network_unit_file_path='/run/systemd/network'
bad4969b 17networkd_runtime_directory='/run/systemd/netif'
d486a2d0 18networkd_ci_path='/run/networkd-ci'
1f0e3109
SS
19network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
20network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
21
d486a2d0
YW
22dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
23dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
1f0e3109 24
7a0a37b2 25def is_module_available(module_name):
201bf07f
EV
26 lsmod_output = subprocess.check_output('lsmod', universal_newlines=True)
27 module_re = re.compile(r'^{0}\b'.format(re.escape(module_name)), re.MULTILINE)
28 return module_re.search(lsmod_output) or not subprocess.call(["modprobe", module_name])
7a0a37b2
EV
29
30def expectedFailureIfModuleIsNotAvailable(module_name):
31 def f(func):
32 if not is_module_available(module_name):
33 return unittest.expectedFailure(func)
34 return func
35
36 return f
37
7bea7f9b
SS
38def expectedFailureIfERSPANModuleIsNotAvailable():
39 def f(func):
40 rc = subprocess.call(['ip', 'link', 'add', 'dev', 'erspan99', 'type', 'erspan', 'seq', 'key', '30', 'local', '192.168.1.4', 'remote', '192.168.1.1', 'erspan_ver', '1', 'erspan', '123'])
41 if rc == 0:
42 subprocess.call(['ip', 'link', 'del', 'erspan99'])
43 return func
44 else:
45 return unittest.expectedFailure(func)
46
47 return f
48
d586a2c3
YW
49def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
50 def f(func):
51 rc = subprocess.call(['ip', 'rule', 'add', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7'])
52 if rc == 0:
53 subprocess.call(['ip', 'rule', 'del', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7'])
54 return func
55 else:
56 return unittest.expectedFailure(func)
57
58 return f
59
60def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
61 def f(func):
62 rc = subprocess.call(['ip', 'rule', 'add', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7'])
63 if rc == 0:
64 subprocess.call(['ip', 'rule', 'del', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7'])
65 return func
66 else:
67 return unittest.expectedFailure(func)
68
69 return f
70
1f0e3109
SS
71def setUpModule():
72
73 os.makedirs(network_unit_file_path, exist_ok=True)
74 os.makedirs(networkd_ci_path, exist_ok=True)
75
76 shutil.rmtree(networkd_ci_path)
6aea9276 77 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
1f0e3109 78
c0bf6733
YW
79 subprocess.check_call('systemctl stop systemd-networkd.socket', shell=True)
80
1f0e3109
SS
81def tearDownModule():
82 shutil.rmtree(networkd_ci_path)
83
c0bf6733
YW
84 subprocess.check_call('systemctl stop systemd-networkd.service', shell=True)
85 subprocess.check_call('systemctl start systemd-networkd.socket', shell=True)
86 subprocess.check_call('systemctl start systemd-networkd.service', shell=True)
87
1f0e3109 88class Utilities():
1f0e3109
SS
89 def read_link_attr(self, link, dev, attribute):
90 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
91 return f.readline().strip()
92
4d7ed14f
SS
93 def read_bridge_port_attr(self, bridge, link, attribute):
94
95 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
96 path_port = 'lower_' + link + '/brport'
97 path = os.path.join(path_bridge, path_port)
98
99 with open(os.path.join(path, attribute)) as f:
100 return f.readline().strip()
101
1f0e3109
SS
102 def link_exits(self, link):
103 return os.path.exists(os.path.join('/sys/class/net', link))
104
105 def link_remove(self, links):
106 for link in links:
107 if os.path.exists(os.path.join('/sys/class/net', link)):
108 subprocess.call(['ip', 'link', 'del', 'dev', link])
9a4720a9 109 time.sleep(1)
1f0e3109
SS
110
111 def read_ipv6_sysctl_attr(self, link, attribute):
112 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
113 return f.readline().strip()
114
115 def read_ipv4_sysctl_attr(self, link, attribute):
116 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
117 return f.readline().strip()
118
119 def copy_unit_to_networkd_unit_path(self, *units):
ecdd0392 120 print()
1f0e3109
SS
121 for unit in units:
122 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
013c8dc9
YW
123 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
124 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
1f0e3109
SS
125
126 def remove_unit_from_networkd_path(self, units):
127 for unit in units:
128 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
129 os.remove(os.path.join(network_unit_file_path, unit))
013c8dc9
YW
130 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
131 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
1f0e3109 132
b412fce8
YW
133 def start_dnsmasq(self, additional_options=''):
134 dnsmasq_command = 'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range=2600::10,2600::20 --dhcp-range=192.168.5.10,192.168.5.200 -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
135 subprocess.check_call(dnsmasq_command, shell=True)
1f0e3109
SS
136
137 time.sleep(10)
138
139 def stop_dnsmasq(self, pid_file):
140 if os.path.exists(pid_file):
141 with open(pid_file, 'r') as f:
142 pid = f.read().rstrip(' \t\r\n\0')
143 os.kill(int(pid), signal.SIGTERM)
144
145 os.remove(pid_file)
146
131717cb 147 def search_words_in_dnsmasq_log(self, words, show_all=False):
1f0e3109
SS
148 if os.path.exists(dnsmasq_log_file):
149 with open (dnsmasq_log_file) as in_file:
150 contents = in_file.read()
131717cb
YW
151 if show_all:
152 print(contents)
153 for line in contents.split('\n'):
154 if words in line:
1f0e3109 155 in_file.close()
131717cb 156 print("%s, %s" % (words, line))
1f0e3109
SS
157 return True
158 return False
159
160 def remove_lease_file(self):
161 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
162 os.remove(os.path.join(networkd_ci_path, 'lease'))
163
164 def remove_log_file(self):
165 if os.path.exists(dnsmasq_log_file):
166 os.remove(dnsmasq_log_file)
167
168 def start_networkd(self):
bad4969b
YW
169 if (os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
170 subprocess.check_call('systemctl stop systemd-networkd', shell=True)
171 os.remove(os.path.join(networkd_runtime_directory, 'state'))
172 subprocess.check_call('systemctl start systemd-networkd', shell=True)
173 else:
174 subprocess.check_call('systemctl restart systemd-networkd', shell=True)
1f0e3109
SS
175 time.sleep(5)
176
1f0e3109
SS
177class NetworkdNetDevTests(unittest.TestCase, Utilities):
178
09ea6724
YW
179 links =[
180 '6rdtun99',
181 'bond99',
182 'bridge99',
183 'dropin-test',
184 'dummy98',
185 'erspan-test',
186 'geneve99',
187 'gretap99',
188 'gretun99',
189 'ip6gretap99',
190 'ip6tnl99',
191 'ipiptun99',
192 'ipvlan99',
193 'isataptun99',
194 'macvlan99',
195 'macvtap99',
196 'sittun99',
197 'tap99',
198 'test1',
199 'tun99',
200 'vcan99',
201 'veth99',
202 'vlan99',
203 'vrf99',
204 'vti6tun99',
205 'vtitun99',
206 'vxlan99',
da44fb8a 207 'wg98',
09ea6724
YW
208 'wg99']
209
210 units = [
211 '10-dropin-test.netdev',
212 '11-dummy.netdev',
213 '12-dummy.netdev',
214 '21-macvlan.netdev',
215 '21-macvtap.netdev',
216 '21-vlan.netdev',
217 '21-vlan.network',
218 '25-6rd-tunnel.netdev',
219 '25-bond.netdev',
fde60a42 220 '25-bond-balanced-tlb.netdev',
09ea6724
YW
221 '25-bridge.netdev',
222 '25-erspan-tunnel.netdev',
223 '25-geneve.netdev',
224 '25-gretap-tunnel.netdev',
225 '25-gre-tunnel.netdev',
226 '25-ip6gre-tunnel.netdev',
227 '25-ip6tnl-tunnel.netdev',
228 '25-ipip-tunnel-independent.netdev',
229 '25-ipip-tunnel.netdev',
230 '25-ipvlan.netdev',
231 '25-isatap-tunnel.netdev',
232 '25-sit-tunnel.netdev',
233 '25-tap.netdev',
234 '25-tun.netdev',
235 '25-vcan.netdev',
236 '25-veth.netdev',
237 '25-vrf.netdev',
238 '25-vti6-tunnel.netdev',
239 '25-vti-tunnel.netdev',
240 '25-vxlan.netdev',
da44fb8a
YW
241 '25-wireguard-23-peers.netdev',
242 '25-wireguard-23-peers.network',
09ea6724
YW
243 '25-wireguard.netdev',
244 '6rd.network',
245 'gre.network',
246 'gretap.network',
247 'gretun.network',
248 'ip6gretap.network',
249 'ip6tnl.network',
250 'ipip.network',
251 'ipvlan.network',
252 'isatap.network',
253 'macvlan.network',
254 'macvtap.network',
255 'sit.network',
256 'vti6.network',
257 'vti.network',
258 'vxlan.network']
1f0e3109
SS
259
260 def setUp(self):
261 self.link_remove(self.links)
262
263 def tearDown(self):
264 self.link_remove(self.links)
265 self.remove_unit_from_networkd_path(self.units)
266
d80734f7
YW
267 def test_dropin(self):
268 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
d80734f7
YW
269 self.start_networkd()
270
271 self.assertTrue(self.link_exits('dropin-test'))
272
273 output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
274 print(output)
275 self.assertRegex(output, '00:50:56:c0:00:28')
276
308ae89c
YW
277 output = subprocess.check_output(['networkctl', 'list']).rstrip().decode('utf-8')
278 self.assertRegex(output, '1 lo ')
279 self.assertRegex(output, 'dropin-test')
280
281 output = subprocess.check_output(['networkctl', 'list', 'dropin-test']).rstrip().decode('utf-8')
282 self.assertNotRegex(output, '1 lo ')
283 self.assertRegex(output, 'dropin-test')
284
285 output = subprocess.check_output(['networkctl', 'list', 'dropin-*']).rstrip().decode('utf-8')
286 self.assertNotRegex(output, '1 lo ')
287 self.assertRegex(output, 'dropin-test')
288
96fb7dc3 289 output = subprocess.check_output(['networkctl', 'status', 'dropin-*']).rstrip().decode('utf-8')
fde66c21 290 self.assertNotRegex(output, '1: lo ')
96fb7dc3 291 self.assertRegex(output, 'dropin-test')
232152bc
YW
292
293 ret = subprocess.run(['ethtool', '--driver', 'dropin-test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
294 print(ret.stdout.rstrip().decode('utf-8'))
295 if ret.returncode == 0 and re.search('driver: dummy', ret.stdout.rstrip().decode('utf-8')) != None:
296 self.assertRegex(output, 'Driver: dummy')
297 else:
298 print('ethtool does not support driver field at least for dummy interfaces, skipping test for Driver field of networkctl.')
96fb7dc3 299
1f0e3109
SS
300 def test_bridge(self):
301 self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
302 self.start_networkd()
303
304 self.assertTrue(self.link_exits('bridge99'))
305
306 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'hello_time'))
307 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'max_age'))
308 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','forward_delay'))
309 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','ageing_time'))
310 self.assertEqual('9', self.read_link_attr('bridge99', 'bridge','priority'))
311 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_querier'))
312 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_snooping'))
313 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','stp_state'))
314
315 def test_bond(self):
316 self.copy_unit_to_networkd_unit_path('25-bond.netdev')
317 self.start_networkd()
318
319 self.assertTrue(self.link_exits('bond99'))
320
99f68ef0
TJ
321 self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode'))
322 self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
323 self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon'))
324 self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate'))
325 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay'))
326 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay'))
327 self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp'))
328 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links'))
329 self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
330 self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
331 self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
1f0e3109 332
fde60a42
SS
333 def test_bond_balanced_tlb(self):
334 self.copy_unit_to_networkd_unit_path('25-bond-balanced-tlb.netdev')
335 self.start_networkd()
336
337 self.assertTrue(self.link_exits('bond99'))
338
339 self.assertEqual('balance-tlb 5', self.read_link_attr('bond99', 'bonding', 'mode'))
340 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
341
1f0e3109
SS
342 def test_vlan(self):
343 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
1f0e3109
SS
344 self.start_networkd()
345
346 self.assertTrue(self.link_exits('vlan99'))
347
348 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
14ecd604 349 print(output)
1f0e3109
SS
350 self.assertTrue(output, 'REORDER_HDR')
351 self.assertTrue(output, 'LOOSE_BINDING')
352 self.assertTrue(output, 'GVRP')
353 self.assertTrue(output, 'MVRP')
354 self.assertTrue(output, '99')
355
356 def test_macvtap(self):
357 self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
1f0e3109
SS
358 self.start_networkd()
359
360 self.assertTrue(self.link_exits('macvtap99'))
361
362 def test_macvlan(self):
363 self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
1f0e3109
SS
364 self.start_networkd()
365
366 self.assertTrue(self.link_exits('macvlan99'))
367
7a0a37b2 368 @expectedFailureIfModuleIsNotAvailable('ipvlan')
1f0e3109
SS
369 def test_ipvlan(self):
370 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
1f0e3109
SS
371 self.start_networkd()
372
373 self.assertTrue(self.link_exits('ipvlan99'))
374
375 def test_veth(self):
376 self.copy_unit_to_networkd_unit_path('25-veth.netdev')
1f0e3109
SS
377 self.start_networkd()
378
379 self.assertTrue(self.link_exits('veth99'))
380
381 def test_dummy(self):
382 self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
1f0e3109
SS
383 self.start_networkd()
384
385 self.assertTrue(self.link_exits('test1'))
386
387 def test_tun(self):
388 self.copy_unit_to_networkd_unit_path('25-tun.netdev')
1f0e3109
SS
389 self.start_networkd()
390
391 self.assertTrue(self.link_exits('tun99'))
392
393 def test_tap(self):
394 self.copy_unit_to_networkd_unit_path('25-tap.netdev')
1f0e3109
SS
395 self.start_networkd()
396
397 self.assertTrue(self.link_exits('tap99'))
398
7a0a37b2 399 @expectedFailureIfModuleIsNotAvailable('vrf')
1f0e3109
SS
400 def test_vrf(self):
401 self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
1f0e3109
SS
402 self.start_networkd()
403
404 self.assertTrue(self.link_exits('vrf99'))
405
7a0a37b2 406 @expectedFailureIfModuleIsNotAvailable('vcan')
1f0e3109
SS
407 def test_vcan(self):
408 self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
1f0e3109
SS
409 self.start_networkd()
410
411 self.assertTrue(self.link_exits('vcan99'))
412
7a3bc5a8
EV
413 @expectedFailureIfModuleIsNotAvailable('wireguard')
414 def test_wireguard(self):
415 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
7a3bc5a8
EV
416 self.start_networkd()
417
418 if shutil.which('wg'):
419 subprocess.call('wg')
16ab043b
YW
420 output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
421 self.assertTrue(output, '51820')
422 output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
423 self.assertTrue(output, '0x4d2')
424 output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
425 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
426 output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
427 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20')
428 output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
429 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820')
7a3bc5a8
EV
430
431 self.assertTrue(self.link_exits('wg99'))
432
da44fb8a
YW
433 @expectedFailureIfModuleIsNotAvailable('wireguard')
434 def test_wireguard_23_peers(self):
435 self.copy_unit_to_networkd_unit_path('25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network')
436 self.start_networkd()
437
438 if shutil.which('wg'):
439 subprocess.call('wg')
440
441 self.assertTrue(self.link_exits('wg98'))
442
1f0e3109
SS
443 def test_geneve(self):
444 self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
1f0e3109
SS
445 self.start_networkd()
446
447 self.assertTrue(self.link_exits('geneve99'))
448
449 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
14ecd604 450 print(output)
1f0e3109
SS
451 self.assertTrue(output, '192.168.22.1')
452 self.assertTrue(output, '6082')
453 self.assertTrue(output, 'udpcsum')
454 self.assertTrue(output, 'udp6zerocsumrx')
455
456 def test_ipip_tunnel(self):
457 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network')
458 self.start_networkd()
459
460 self.assertTrue(self.link_exits('dummy98'))
461 self.assertTrue(self.link_exits('ipiptun99'))
462
463 def test_gre_tunnel(self):
464 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network')
465 self.start_networkd()
466
467 self.assertTrue(self.link_exits('dummy98'))
468 self.assertTrue(self.link_exits('gretun99'))
469
470 def test_gretap_tunnel(self):
471 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network')
472 self.start_networkd()
473
474 self.assertTrue(self.link_exits('dummy98'))
475 self.assertTrue(self.link_exits('gretap99'))
476
477 def test_ip6gretap_tunnel(self):
478 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretap.network')
479 self.start_networkd()
480
481 self.assertTrue(self.link_exits('dummy98'))
482 self.assertTrue(self.link_exits('ip6gretap99'))
483
484 def test_vti_tunnel(self):
485 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network')
486 self.start_networkd()
487
488 self.assertTrue(self.link_exits('dummy98'))
489 self.assertTrue(self.link_exits('vtitun99'))
490
491 def test_vti6_tunnel(self):
492 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network')
493 self.start_networkd()
494
495 self.assertTrue(self.link_exits('dummy98'))
496 self.assertTrue(self.link_exits('vti6tun99'))
497
498 def test_ip6tnl_tunnel(self):
499 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network')
500 self.start_networkd()
501
502 self.assertTrue(self.link_exits('dummy98'))
503 self.assertTrue(self.link_exits('ip6tnl99'))
504
505 def test_sit_tunnel(self):
506 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network')
507 self.start_networkd()
508
509 self.assertTrue(self.link_exits('dummy98'))
510 self.assertTrue(self.link_exits('sittun99'))
511
d0e728b6
SS
512 def test_isatap_tunnel(self):
513 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
514 self.start_networkd()
515
516 self.assertTrue(self.link_exits('dummy98'))
517 self.assertTrue(self.link_exits('isataptun99'))
e40a58b5 518
d0e728b6 519 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
14ecd604 520 print(output)
d0e728b6
SS
521 self.assertRegex(output, "isatap ")
522
d29dc4f1
DA
523 def test_6rd_tunnel(self):
524 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
525 self.start_networkd()
526
527 self.assertTrue(self.link_exits('dummy98'))
528 self.assertTrue(self.link_exits('sittun99'))
529
7bea7f9b 530 @expectedFailureIfERSPANModuleIsNotAvailable()
2266864b
SS
531 def test_erspan_tunnel(self):
532 self.copy_unit_to_networkd_unit_path('25-erspan-tunnel.netdev')
533 self.start_networkd()
534
535 self.assertTrue(self.link_exits('erspan-test'))
536
537 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan-test']).rstrip().decode('utf-8')
538 print(output)
539 self.assertTrue(output, '172.16.1.200')
540 self.assertTrue(output, '172.16.1.100')
541 self.assertTrue(output, '101')
542
1f0e3109
SS
543 def test_tunnel_independent(self):
544 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
1f0e3109 545 self.start_networkd()
e40a58b5 546
1f0e3109
SS
547 self.assertTrue(self.link_exits('ipiptun99'))
548
549 def test_vxlan(self):
550 self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network','11-dummy.netdev')
1f0e3109
SS
551 self.start_networkd()
552
553 self.assertTrue(self.link_exits('vxlan99'))
554
555 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
14ecd604 556 print(output)
1f0e3109
SS
557 self.assertRegex(output, "999")
558 self.assertRegex(output, '5555')
559 self.assertRegex(output, 'l2miss')
560 self.assertRegex(output, 'l3miss')
561 self.assertRegex(output, 'udpcsum')
562 self.assertRegex(output, 'udp6zerocsumtx')
563 self.assertRegex(output, 'udp6zerocsumrx')
564 self.assertRegex(output, 'remcsumtx')
565 self.assertRegex(output, 'remcsumrx')
566 self.assertRegex(output, 'gbp')
567
568class NetworkdNetWorkTests(unittest.TestCase, Utilities):
09ea6724
YW
569 links = [
570 'bond199',
571 'dummy98',
cd65d067 572 'dummy99',
09ea6724
YW
573 'test1']
574
575 units = [
576 '11-dummy.netdev',
577 '12-dummy.netdev',
578 '23-active-slave.network',
579 '23-bond199.network',
580 '23-primary-slave.network',
581 '23-test1-bond199.network',
582 '25-address-link-section.network',
583 '25-address-section-miscellaneous.network',
584 '25-address-section.network',
cd65d067 585 '25-bind-carrier.network',
09ea6724
YW
586 '25-bond-active-backup-slave.netdev',
587 '25-fibrule-invert.network',
588 '25-fibrule-port-range.network',
589 '25-ipv6-address-label-section.network',
e4a71bf3 590 '25-neighbor-section.network',
05514ae1
YW
591 '25-link-local-addressing-no.network',
592 '25-link-local-addressing-yes.network',
09ea6724
YW
593 '25-link-section-unmanaged.network',
594 '25-route-gateway.network',
595 '25-route-gateway-on-link.network',
20ca06a6 596 '25-route-ipv6-src.network',
09ea6724
YW
597 '25-route-reverse-order.network',
598 '25-route-section.network',
599 '25-route-tcp-window-settings.network',
600 '25-route-type.network',
601 '25-sysctl.network',
602 'configure-without-carrier.network',
603 'routing-policy-rule.network',
604 'test-static.network']
1f0e3109
SS
605
606 def setUp(self):
607 self.link_remove(self.links)
608
609 def tearDown(self):
610 self.link_remove(self.links)
611 self.remove_unit_from_networkd_path(self.units)
612
613 def test_static_address(self):
614 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'test-static.network')
615 self.start_networkd()
616
617 self.assertTrue(self.link_exits('dummy98'))
e40a58b5 618
1f0e3109
SS
619 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
620 print(output)
621 self.assertRegex(output, '192.168.0.15')
622 self.assertRegex(output, '192.168.0.1')
623 self.assertRegex(output, 'routable')
624
625 def test_configure_without_carrier(self):
626 self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
627 self.start_networkd()
628
629 self.assertTrue(self.link_exits('test1'))
e40a58b5 630
1f0e3109
SS
631 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
632 print(output)
633 self.assertRegex(output, '192.168.0.15')
634 self.assertRegex(output, '192.168.0.1')
635 self.assertRegex(output, 'routable')
636
637 def test_bond_active_slave(self):
638 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
639 self.start_networkd()
640
641 self.assertTrue(self.link_exits('dummy98'))
642 self.assertTrue(self.link_exits('bond199'))
e40a58b5 643
1f0e3109
SS
644 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
645 print(output)
646 self.assertRegex(output, 'active_slave dummy98')
647
648 def test_bond_primary_slave(self):
649 self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
650 self.start_networkd()
651
652 self.assertTrue(self.link_exits('test1'))
653 self.assertTrue(self.link_exits('bond199'))
e40a58b5 654
1f0e3109
SS
655 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
656 print(output)
657 self.assertRegex(output, 'primary test1')
658
659 def test_routing_policy_rule(self):
660 self.copy_unit_to_networkd_unit_path('routing-policy-rule.network', '11-dummy.netdev')
661 self.start_networkd()
662
663 self.assertTrue(self.link_exits('test1'))
e40a58b5 664
1f0e3109
SS
665 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
666 print(output)
667 self.assertRegex(output, '111')
668 self.assertRegex(output, 'from 192.168.100.18')
f7bdd562 669 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
1f0e3109
SS
670 self.assertRegex(output, 'iif test1')
671 self.assertRegex(output, 'oif test1')
672 self.assertRegex(output, 'lookup 7')
673
e4eacdb0
YW
674 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
675
d586a2c3 676 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
926062f0
SS
677 def test_routing_policy_rule_port_range(self):
678 self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
679 self.start_networkd()
680
681 self.assertTrue(self.link_exits('test1'))
e40a58b5 682
926062f0
SS
683 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
684 print(output)
685 self.assertRegex(output, '111')
686 self.assertRegex(output, 'from 192.168.100.18')
687 self.assertRegex(output, '1123-1150')
688 self.assertRegex(output, '3224-3290')
689 self.assertRegex(output, 'tcp')
690 self.assertRegex(output, 'lookup 7')
1f0e3109 691
e4eacdb0
YW
692 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
693
d586a2c3 694 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
efecf9cd
SS
695 def test_routing_policy_rule_invert(self):
696 self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
697 self.start_networkd()
698
699 self.assertTrue(self.link_exits('test1'))
e40a58b5 700
efecf9cd
SS
701 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
702 print(output)
efecf9cd
SS
703 self.assertRegex(output, '111')
704 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
705 self.assertRegex(output, 'tcp')
706 self.assertRegex(output, 'lookup 7')
707
e4eacdb0
YW
708 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
709
ac60877f
YW
710 def test_address_peer(self):
711 self.copy_unit_to_networkd_unit_path('25-address-section.network', '12-dummy.netdev')
712 self.start_networkd()
713
714 self.assertTrue(self.link_exits('dummy98'))
715
716 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
717 print(output)
718 self.assertRegex(output, 'inet 10.2.3.4 peer 10.2.3.5/16 scope global 32')
719 self.assertRegex(output, 'inet 10.6.7.8/16 brd 10.6.255.255 scope global 33')
7e663619 720 self.assertRegex(output, 'inet6 2001:db8::20 peer 2001:db8::10/128 scope global')
ac60877f
YW
721
722 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
723 print(output)
724 self.assertRegex(output, 'State: routable \(configured\)')
725
1f0e3109
SS
726 def test_address_preferred_lifetime_zero_ipv6(self):
727 self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev')
728 self.start_networkd()
729
730 self.assertTrue(self.link_exits('dummy98'))
731
732 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
733 print(output)
734 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
735 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
736
737 def test_ip_route(self):
738 self.copy_unit_to_networkd_unit_path('25-route-section.network', '12-dummy.netdev')
739 self.start_networkd()
740
741 self.assertTrue(self.link_exits('dummy98'))
742
743 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98']).rstrip().decode('utf-8')
744 print(output)
745 self.assertRegex(output, '192.168.0.1')
746 self.assertRegex(output, 'static')
747 self.assertRegex(output, '192.168.0.0/24')
748
0d34228f
SS
749 def test_ip_route_reverse(self):
750 self.copy_unit_to_networkd_unit_path('25-route-reverse-order.network', '12-dummy.netdev')
751 self.start_networkd()
752
753 self.assertTrue(self.link_exits('dummy98'))
754
755 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
756 print(output)
757 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff')
758 self.assertRegex(output, '2001:1234:5:8f63::1')
759
1f0e3109
SS
760 def test_ip_route_blackhole_unreachable_prohibit(self):
761 self.copy_unit_to_networkd_unit_path('25-route-type.network', '12-dummy.netdev')
762 self.start_networkd()
763
764 self.assertTrue(self.link_exits('dummy98'))
765
766 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
767 print(output)
768 self.assertRegex(output, 'blackhole')
769 self.assertRegex(output, 'unreachable')
770 self.assertRegex(output, 'prohibit')
771
772 subprocess.call(['ip', 'route', 'del', 'blackhole', '202.54.1.2'])
773 subprocess.call(['ip', 'route', 'del', 'unreachable', '202.54.1.3'])
774 subprocess.call(['ip', 'route', 'del', 'prohibit', '202.54.1.4'])
775
776 def test_ip_route_tcp_window(self):
777 self.copy_unit_to_networkd_unit_path('25-route-tcp-window-settings.network', '11-dummy.netdev')
778 self.start_networkd()
779
780 self.assertTrue(self.link_exits('test1'))
781
782 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
783 print(output)
784 self.assertRegex(output, 'initcwnd 20')
785 self.assertRegex(output, 'initrwnd 30')
786
f5050e48
YW
787 def test_ip_route_gateway(self):
788 self.copy_unit_to_networkd_unit_path('25-route-gateway.network', '12-dummy.netdev')
789 self.start_networkd()
790
791 self.assertTrue(self.link_exits('dummy98'))
792
793 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
794 print(output)
795 self.assertRegex(output, 'default')
796 self.assertRegex(output, 'via')
797 self.assertRegex(output, '149.10.124.64')
798 self.assertRegex(output, 'proto')
799 self.assertRegex(output, 'static')
800
801 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
802 print(output)
803 self.assertRegex(output, '149.10.124.48/28')
804 self.assertRegex(output, 'proto')
805 self.assertRegex(output, 'kernel')
806 self.assertRegex(output, 'scope')
807 self.assertRegex(output, 'link')
808
809 def test_ip_route_gateway_on_link(self):
810 self.copy_unit_to_networkd_unit_path('25-route-gateway-on-link.network', '12-dummy.netdev')
811 self.start_networkd()
812
813 self.assertTrue(self.link_exits('dummy98'))
814
815 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
816 print(output)
817 self.assertRegex(output, 'default')
818 self.assertRegex(output, 'via')
819 self.assertRegex(output, '149.10.125.65')
820 self.assertRegex(output, 'proto')
821 self.assertRegex(output, 'static')
822 self.assertRegex(output, 'onlink')
823
824 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
825 print(output)
826 self.assertRegex(output, '149.10.124.48/28')
827 self.assertRegex(output, 'proto')
828 self.assertRegex(output, 'kernel')
829 self.assertRegex(output, 'scope')
830 self.assertRegex(output, 'link')
831
20ca06a6
DA
832 def test_ip_route_ipv6_src_route(self):
833 # a dummy device does not make the addresses go through tentative state, so we
834 # reuse a bond from an earlier test, which does make the addresses go through
835 # tentative state, and do our test on that
836 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')
837 self.start_networkd()
838
839 self.assertTrue(self.link_exits('dummy98'))
840 self.assertTrue(self.link_exits('bond199'))
841
842 output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8')
843 print(output)
844 self.assertRegex(output, 'abcd::/16')
845 self.assertRegex(output, 'src')
846 self.assertRegex(output, '2001:1234:56:8f63::2')
847
1f0e3109
SS
848 def test_ip_link_mac_address(self):
849 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
850 self.start_networkd()
851
852 self.assertTrue(self.link_exits('dummy98'))
853
854 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
855 print(output)
856 self.assertRegex(output, '00:01:02:aa:bb:cc')
857
858 def test_ip_link_unmanaged(self):
859 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
860 self.start_networkd()
861
862 self.assertTrue(self.link_exits('dummy98'))
863
864 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
865 print(output)
866 self.assertRegex(output, 'unmanaged')
867
868 def test_ipv6_address_label(self):
869 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
870 self.start_networkd()
871
872 self.assertTrue(self.link_exits('dummy98'))
873
874 output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
875 print(output)
876 self.assertRegex(output, '2004:da8:1::/64')
877
e4a71bf3
WKI
878 def test_ipv6_neighbor(self):
879 self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
880 self.start_networkd()
881
882 self.assertTrue(self.link_exits('dummy98'))
883
884 output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
885 print(output)
886 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
094b5479 887 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
e4a71bf3 888
05514ae1
YW
889 def test_link_local_addressing(self):
890 self.copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
891 '25-link-local-addressing-no.network', '12-dummy.netdev')
892 self.start_networkd()
893
894 self.assertTrue(self.link_exits('test1'))
895 self.assertTrue(self.link_exits('dummy98'))
896
897 time.sleep(10)
898
899 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
900 print(output)
901 self.assertRegex(output, 'inet .* scope link')
902 self.assertRegex(output, 'inet6 .* scope link')
903
904 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
905 print(output)
906 self.assertNotRegex(output, 'inet6* .* scope link')
907
908 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
909 print(output)
910 self.assertRegex(output, 'State: degraded \(configured\)')
911
912 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
913 print(output)
914 self.assertRegex(output, 'State: carrier \(configured\)')
915
916 '''
917 Documentation/networking/ip-sysctl.txt
918
919 addr_gen_mode - INTEGER
920 Defines how link-local and autoconf addresses are generated.
921
922 0: generate address based on EUI64 (default)
923 1: do no generate a link-local address, use EUI64 for addresses generated
924 from autoconf
925 2: generate stable privacy addresses, using the secret from
926 stable_secret (RFC7217)
927 3: generate stable privacy addresses, using a random secret if unset
928 '''
929
930 test1_addr_gen_mode = ''
931 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
932 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
933 try:
934 f.readline()
935 except IOError:
936 # if stable_secret is unset, then EIO is returned
937 test1_addr_gen_mode = '0'
938 else:
939 test1_addr_gen_mode = '2'
940 else:
941 test1_addr_gen_mode = '0'
942
943 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
944 self.assertEqual(self.read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '0')
945
946 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
947 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
948
1f0e3109
SS
949 def test_sysctl(self):
950 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
951 self.start_networkd()
952
953 self.assertTrue(self.link_exits('dummy98'))
954
955 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
956 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
957 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
958 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
959 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
960 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
961 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
962
cd65d067
YW
963 def test_bind_carrier(self):
964 self.copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
965 self.start_networkd()
966
967 self.assertTrue(self.link_exits('test1'))
968
cd65d067
YW
969 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
970 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
b117044c 971 time.sleep(2)
cd65d067
YW
972 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
973 print(output)
974 self.assertRegex(output, 'UP,LOWER_UP')
975 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
976 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
977 self.assertRegex(output, 'State: routable \(configured\)')
978
979 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy99', 'type', 'dummy']), 0)
980 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy99', 'up']), 0)
b117044c 981 time.sleep(2)
cd65d067
YW
982 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
983 print(output)
984 self.assertRegex(output, 'UP,LOWER_UP')
985 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
986 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
987 self.assertRegex(output, 'State: routable \(configured\)')
988
989 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
b117044c 990 time.sleep(2)
cd65d067
YW
991 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
992 print(output)
993 self.assertRegex(output, 'UP,LOWER_UP')
994 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
995 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
996 self.assertRegex(output, 'State: routable \(configured\)')
997
998 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy99']), 0)
b117044c 999 time.sleep(2)
cd65d067
YW
1000 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1001 print(output)
1002 self.assertNotRegex(output, 'UP,LOWER_UP')
1003 self.assertRegex(output, 'DOWN')
1004 self.assertNotRegex(output, '192.168.10')
1005 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1006 self.assertRegex(output, 'State: off \(configured\)')
1007
1008 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1009 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
b117044c 1010 time.sleep(2)
cd65d067
YW
1011 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1012 print(output)
1013 self.assertRegex(output, 'UP,LOWER_UP')
1014 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1015 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1016 self.assertRegex(output, 'State: routable \(configured\)')
1017
c3a8853f
YW
1018class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
1019 links = [
1020 'bond99',
1021 'veth99']
1022
1023 units = [
1024 '25-bond.netdev',
1025 '25-veth.netdev',
1026 'bond99.network',
1027 'dhcp-server.network',
1028 'veth-bond.network']
1029
1030 def setUp(self):
1031 self.link_remove(self.links)
1032
1033 def tearDown(self):
1034 self.link_remove(self.links)
1035 self.remove_unit_from_networkd_path(self.units)
1036
1037 def test_bridge_property(self):
1038 self.copy_unit_to_networkd_unit_path('25-bond.netdev', '25-veth.netdev', 'bond99.network',
1039 'dhcp-server.network', 'veth-bond.network')
1040 self.start_networkd()
1041
1042 self.assertTrue(self.link_exits('bond99'))
1043 self.assertTrue(self.link_exits('veth99'))
1044 self.assertTrue(self.link_exits('veth-peer'))
1045
1046 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'veth-peer']).rstrip().decode('utf-8')
1047 print(output)
1048 self.assertRegex(output, 'UP,LOWER_UP')
1049
1050 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'veth99']).rstrip().decode('utf-8')
1051 print(output)
1052 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1053
1054 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond99']).rstrip().decode('utf-8')
1055 print(output)
1056 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
1057
1058 output = subprocess.check_output(['networkctl', 'status', 'veth-peer']).rstrip().decode('utf-8')
1059 print(output)
1060 self.assertRegex(output, 'State: routable \(configured\)')
1061
1062 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1063 print(output)
1064 self.assertRegex(output, 'State: enslaved \(configured\)')
1065
1066 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1067 print(output)
1068 self.assertRegex(output, 'State: routable \(configured\)')
1069
1070 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'veth99', 'down']), 0)
1071 time.sleep(2)
1072
1073 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1074 print(output)
1075 self.assertRegex(output, 'State: off \(configured\)')
1076
1077 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1078 print(output)
1079 self.assertRegex(output, 'State: degraded \(configured\)')
1080
1081 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'veth99', 'up']), 0)
1082 time.sleep(2)
1083
1084 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1085 print(output)
1086 self.assertRegex(output, 'State: enslaved \(configured\)')
1087
1088 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1089 print(output)
1090 self.assertRegex(output, 'State: routable \(configured\)')
1091
14dc0335 1092class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
09ea6724
YW
1093 links = [
1094 'bridge99',
1095 'dummy98',
1096 'test1']
1097
1098 units = [
1099 '11-dummy.netdev',
1100 '12-dummy.netdev',
1101 '26-bridge.netdev',
1102 '26-bridge-slave-interface-1.network',
1103 '26-bridge-slave-interface-2.network',
804b6cd2 1104 'bridge99-ignore-carrier-loss.network',
09ea6724 1105 'bridge99.network']
1f0e3109
SS
1106
1107 def setUp(self):
1108 self.link_remove(self.links)
1109
1110 def tearDown(self):
1111 self.link_remove(self.links)
1112 self.remove_unit_from_networkd_path(self.units)
1113
1114 def test_bridge_property(self):
1115 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1116 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1117 'bridge99.network')
1118 self.start_networkd()
1119
1120 self.assertTrue(self.link_exits('dummy98'))
1121 self.assertTrue(self.link_exits('test1'))
1122 self.assertTrue(self.link_exits('bridge99'))
1123
1124 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
1125 print(output)
1126 self.assertRegex(output, 'master')
1127 self.assertRegex(output, 'bridge')
1128
1129 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1130 print(output)
1131 self.assertRegex(output, 'master')
1132 self.assertRegex(output, 'bridge')
1133
1134 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
1135 print(output)
1136 self.assertRegex(output, '192.168.0.15')
1137 self.assertRegex(output, '192.168.0.1')
1138
1139 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1140 print(output)
4d7ed14f
SS
1141 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
1142 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
1143 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
1144 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
1145
1146 # CONFIG_BRIDGE_IGMP_SNOOPING=y
1147 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
1148 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1f0e3109 1149
804b6cd2
YW
1150 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1151 time.sleep(1)
1152
1153 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1154 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1155 time.sleep(3)
1156
1157 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1158 print(output)
1159 self.assertRegex(output, 'NO-CARRIER')
1160 self.assertNotRegex(output, '192.168.0.15/24')
1161 self.assertNotRegex(output, '192.168.0.16/24')
1162
1163 def test_bridge_ignore_carrier_loss(self):
1164 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1165 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1166 'bridge99-ignore-carrier-loss.network')
1167 self.start_networkd()
1168
1169 self.assertTrue(self.link_exits('dummy98'))
1170 self.assertTrue(self.link_exits('test1'))
1171 self.assertTrue(self.link_exits('bridge99'))
1172
1173 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1174 time.sleep(1)
1175
1176 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1177 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1178 time.sleep(3)
1179
1180 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1181 print(output)
1182 self.assertRegex(output, 'NO-CARRIER')
1183 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1184 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
1185
1f0e3109
SS
1186class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
1187 links = ['veth99']
1188
09ea6724
YW
1189 units = [
1190 '23-emit-lldp.network',
1191 '24-lldp.network',
1192 '25-veth.netdev']
1f0e3109
SS
1193
1194 def setUp(self):
1195 self.link_remove(self.links)
1196
1197 def tearDown(self):
1198 self.link_remove(self.links)
1199 self.remove_unit_from_networkd_path(self.units)
1200
1201 def test_lldp(self):
1202 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
1203 self.start_networkd()
1204
1205 self.assertTrue(self.link_exits('veth99'))
1206
1207 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
1208 print(output)
1209 self.assertRegex(output, 'veth-peer')
1210 self.assertRegex(output, 'veth99')
1211
1212class NetworkdNetworkRATests(unittest.TestCase, Utilities):
1213 links = ['veth99']
1214
09ea6724
YW
1215 units = [
1216 '25-veth.netdev',
1217 'ipv6-prefix.network',
1218 'ipv6-prefix-veth.network']
1f0e3109
SS
1219
1220 def setUp(self):
1221 self.link_remove(self.links)
1222
1223 def tearDown(self):
1224 self.link_remove(self.links)
1225 self.remove_unit_from_networkd_path(self.units)
1226
1227 def test_ipv6_prefix_delegation(self):
1228 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1229 self.start_networkd()
1230
1231 self.assertTrue(self.link_exits('veth99'))
1232
1233 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1234 print(output)
1235 self.assertRegex(output, '2002:da8:1:0')
1236
1237class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
09ea6724
YW
1238 links = [
1239 'dummy98',
1240 'veth99']
1241
1242 units = [
1243 '12-dummy.netdev',
1244 '24-search-domain.network',
1245 '25-veth.netdev',
1246 'dhcp-client.network',
1247 'dhcp-client-timezone-router.network',
1248 'dhcp-server.network',
1249 'dhcp-server-timezone-router.network']
1f0e3109
SS
1250
1251 def setUp(self):
1252 self.link_remove(self.links)
1253
1254 def tearDown(self):
1255 self.link_remove(self.links)
1256 self.remove_unit_from_networkd_path(self.units)
1257
1258 def test_dhcp_server(self):
1259 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
1260 self.start_networkd()
1261
1262 self.assertTrue(self.link_exits('veth99'))
1263
1f0e3109
SS
1264 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1265 print(output)
1266 self.assertRegex(output, '192.168.5.*')
1267 self.assertRegex(output, 'Gateway: 192.168.5.1')
1268 self.assertRegex(output, 'DNS: 192.168.5.1')
1269 self.assertRegex(output, 'NTP: 192.168.5.1')
1270
1271 def test_domain(self):
f5d191a9 1272 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1f0e3109
SS
1273 self.start_networkd()
1274
1275 self.assertTrue(self.link_exits('dummy98'))
1276
1277 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1278 print(output)
1279 self.assertRegex(output, 'Address: 192.168.42.100')
1280 self.assertRegex(output, 'DNS: 192.168.42.1')
1281 self.assertRegex(output, 'Search Domains: one')
1282
1283 def test_emit_router_timezone(self):
1284 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
1285 self.start_networkd()
1286
1287 self.assertTrue(self.link_exits('veth99'))
1288
1289 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1290 print(output)
1291 self.assertRegex(output, 'Gateway: 192.168.5.*')
1292 self.assertRegex(output, '192.168.5.*')
1293 self.assertRegex(output, 'Europe/Berlin')
1294
1295class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
09ea6724
YW
1296 links = [
1297 'dummy98',
18c613dc
YW
1298 'veth99',
1299 'vrf99']
09ea6724
YW
1300
1301 units = [
1302 '25-veth.netdev',
18c613dc
YW
1303 '25-vrf.netdev',
1304 '25-vrf.network',
09ea6724
YW
1305 'dhcp-client-anonymize.network',
1306 'dhcp-client-critical-connection.network',
1307 'dhcp-client-ipv4-dhcp-settings.network',
1308 'dhcp-client-ipv4-only-ipv6-disabled.network',
1309 'dhcp-client-ipv4-only.network',
1310 'dhcp-client-ipv6-only.network',
1311 'dhcp-client-ipv6-rapid-commit.network',
1312 'dhcp-client-listen-port.network',
1313 'dhcp-client-route-metric.network',
1314 'dhcp-client-route-table.network',
18c613dc 1315 'dhcp-client-vrf.network',
3e9d5552 1316 'dhcp-client.network',
09ea6724 1317 'dhcp-server-veth-peer.network',
30d3b54e
YW
1318 'dhcp-v4-server-veth-peer.network',
1319 'static.network']
1f0e3109
SS
1320
1321 def setUp(self):
1322 self.link_remove(self.links)
1323 self.stop_dnsmasq(dnsmasq_pid_file)
1324
1325 def tearDown(self):
1326 self.link_remove(self.links)
1327 self.remove_unit_from_networkd_path(self.units)
1328 self.stop_dnsmasq(dnsmasq_pid_file)
1329 self.remove_lease_file()
1330 self.remove_log_file()
1331
1332 def test_dhcp_client_ipv6_only(self):
f5d191a9 1333 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1f0e3109
SS
1334 self.start_networkd()
1335
1336 self.assertTrue(self.link_exits('veth99'))
1337
1338 self.start_dnsmasq()
1339
1340 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1341 print(output)
1342 self.assertRegex(output, '2600::')
1343 self.assertNotRegex(output, '192.168.5')
1344
1345 def test_dhcp_client_ipv4_only(self):
f5d191a9 1346 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1f0e3109
SS
1347 self.start_networkd()
1348
1349 self.assertTrue(self.link_exits('veth99'))
1350
1351 self.start_dnsmasq()
1352
1353 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1354 print(output)
1355 self.assertNotRegex(output, '2600::')
1356 self.assertRegex(output, '192.168.5')
1357
1358 def test_dhcp_client_ipv4_ipv6(self):
1359 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
1360 'dhcp-client-ipv4-only.network')
1361 self.start_networkd()
1362
1363 self.assertTrue(self.link_exits('veth99'))
1364
1365 self.start_dnsmasq()
1366
1367 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1368 print(output)
1369 self.assertRegex(output, '2600::')
1370 self.assertRegex(output, '192.168.5')
1371
1372 def test_dhcp_client_settings(self):
1373 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1374 self.start_networkd()
1375
1376 self.assertTrue(self.link_exits('veth99'))
1377
1378 self.start_dnsmasq()
1379
0ae7a66d 1380 print('## ip address show dev veth99')
1f0e3109
SS
1381 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1382 print(output)
1383 self.assertRegex(output, '12:34:56:78:9a:bc')
1384 self.assertRegex(output, '192.168.5')
1385 self.assertRegex(output, '1492')
1386
0ae7a66d
YW
1387 # issue #8726
1388 print('## ip route show table main dev veth99')
1389 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
1f0e3109 1390 print(output)
0ae7a66d 1391 self.assertNotRegex(output, 'proto dhcp')
1f0e3109 1392
0ae7a66d
YW
1393 print('## ip route show table 211 dev veth99')
1394 output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99']).rstrip().decode('utf-8')
1395 print(output)
1396 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
1397 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
1398 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
1399
1400 print('## dnsmasq log')
131717cb
YW
1401 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
1402 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
1403 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
1404 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1405
1406 def test_dhcp6_client_settings_rapidcommit_true(self):
1407 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1408 self.start_networkd()
1409
1410 self.assertTrue(self.link_exits('veth99'))
1411
1412 self.start_dnsmasq()
1413
1414 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1415 print(output)
1416 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1417 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1418
1419 def test_dhcp6_client_settings_rapidcommit_false(self):
1420 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
1421 self.start_networkd()
1422
1423 self.assertTrue(self.link_exits('veth99'))
1424
1425 self.start_dnsmasq()
1426
1427 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1428 print(output)
1429 self.assertRegex(output, '12:34:56:78:9a:bc')
131717cb 1430 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1f0e3109
SS
1431
1432 def test_dhcp_client_settings_anonymize(self):
1433 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
1434 self.start_networkd()
1435
1436 self.assertTrue(self.link_exits('veth99'))
1437
1438 self.start_dnsmasq()
e40a58b5 1439
131717cb
YW
1440 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
1441 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
1442 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
1f0e3109
SS
1443
1444 def test_dhcp_client_listen_port(self):
1445 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
1f0e3109
SS
1446 self.start_networkd()
1447
1448 self.assertTrue(self.link_exits('veth99'))
1449
b412fce8 1450 self.start_dnsmasq('--dhcp-alternate-port=67,5555')
1f0e3109 1451
b412fce8
YW
1452 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1453 print(output)
1454 self.assertRegex(output, '192.168.5.* dynamic')
1f0e3109
SS
1455
1456 def test_dhcp_route_table_id(self):
1457 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
1458 self.start_networkd()
1f0e3109
SS
1459
1460 self.assertTrue(self.link_exits('veth99'))
1461
e40a58b5
YW
1462 self.start_dnsmasq()
1463
1f0e3109
SS
1464 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
1465 print(output)
1f0e3109
SS
1466 self.assertRegex(output, 'veth99 proto dhcp')
1467 self.assertRegex(output, '192.168.5.1')
1468
1469 def test_dhcp_route_metric(self):
1470 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
1471 self.start_networkd()
1f0e3109
SS
1472
1473 self.assertTrue(self.link_exits('veth99'))
1474
e40a58b5
YW
1475 self.start_dnsmasq()
1476
1f0e3109
SS
1477 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1478 print(output)
1f0e3109
SS
1479 self.assertRegex(output, 'metric 24')
1480
1481 def test_dhcp_route_criticalconnection_true(self):
1482 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
1483 self.start_networkd()
1f0e3109
SS
1484
1485 self.assertTrue(self.link_exits('veth99'))
1486
e40a58b5
YW
1487 self.start_dnsmasq()
1488
1f0e3109
SS
1489 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1490 print(output)
1f0e3109 1491 self.assertRegex(output, '192.168.5.*')
e40a58b5 1492
1f0e3109
SS
1493 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
1494 self.stop_dnsmasq(dnsmasq_pid_file)
1495
1496 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1497 time.sleep(125)
1498
1499 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1500 print(output)
1501 self.assertRegex(output, '192.168.5.*')
1502
30d3b54e
YW
1503 def test_dhcp_client_reuse_address_as_static(self):
1504 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
1505 self.start_networkd()
1506
1507 self.assertTrue(self.link_exits('veth99'))
1508
1509 self.start_dnsmasq()
1510
1511 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1512 print(output)
1513 self.assertRegex(output, '192.168.5')
1514 self.assertRegex(output, '2600::')
1515
1516 ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
1517 ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
1518 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
1519 print(static_network)
1520
1521 self.remove_unit_from_networkd_path(['dhcp-client.network'])
1522
1523 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
1524 f.write(static_network)
1525
1526 self.start_networkd()
1527
1528 self.assertTrue(self.link_exits('veth99'))
1529
1530 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1531 print(output)
1532 self.assertRegex(output, '192.168.5')
1533 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1534
1535 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1536 print(output)
1537 self.assertRegex(output, '2600::')
1538 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1539
18c613dc
YW
1540 @expectedFailureIfModuleIsNotAvailable('vrf')
1541 def test_dhcp_client_vrf(self):
1542 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
1543 '25-vrf.netdev', '25-vrf.network')
1544 self.start_networkd()
1545
1546 self.assertTrue(self.link_exits('veth99'))
1547 self.assertTrue(self.link_exits('vrf99'))
1548
1549 self.start_dnsmasq()
1550
1551 print('## ip -d link show dev vrf99')
1552 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99']).rstrip().decode('utf-8')
1553 print(output)
1554 self.assertRegex(output, 'vrf table 42')
1555
1556 print('## ip address show vrf vrf99')
1557 output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
1558 print(output_ip_vrf)
1559
1560 print('## ip address show dev veth99')
1561 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1562 print(output)
1563 self.assertEqual(output, output_ip_vrf)
1564 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
1565 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
1566 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic noprefixroute')
1567 self.assertRegex(output, 'inet6 .* scope link')
1568
1569 print('## ip route show vrf vrf99')
1570 output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
1571 print(output)
1572 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
1573 self.assertRegex(output, 'default dev veth99 proto static scope link')
1574 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
1575 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
1576 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
1577 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
1578
1579 print('## ip route show table main dev veth99')
1580 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
1581 print(output)
1582 self.assertEqual(output, '')
1583
1584 output = subprocess.check_output(['networkctl', 'status', 'vrf99']).rstrip().decode('utf-8')
1585 print(output)
1586 self.assertRegex(output, 'State: carrier \(configured\)')
1587
1588 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1589 print(output)
1590 self.assertRegex(output, 'State: routable \(configured\)')
1591
1f0e3109
SS
1592if __name__ == '__main__':
1593 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
1594 verbosity=3))