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