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