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