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