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