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