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