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