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