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