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