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