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