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