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