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