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