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