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