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