]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
Merge pull request #11827 from keszybz/pkgconfig-variables
[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 def is_module_available(module_name):
26 lsmod_output = subprocess.check_output('lsmod', universal_newlines=True)
27 module_re = re.compile(r'^{0}\b'.format(re.escape(module_name)), re.MULTILINE)
28 return module_re.search(lsmod_output) or not subprocess.call(["modprobe", module_name])
29
30 def expectedFailureIfModuleIsNotAvailable(module_name):
31 def f(func):
32 if not is_module_available(module_name):
33 return unittest.expectedFailure(func)
34 return func
35
36 return f
37
38 def expectedFailureIfERSPANModuleIsNotAvailable():
39 def f(func):
40 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'])
41 if rc == 0:
42 subprocess.call(['ip', 'link', 'del', 'erspan99'])
43 return func
44 else:
45 return unittest.expectedFailure(func)
46
47 return f
48
49 def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
50 def f(func):
51 rc = subprocess.call(['ip', 'rule', 'add', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7'])
52 if rc == 0:
53 subprocess.call(['ip', 'rule', 'del', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7'])
54 return func
55 else:
56 return unittest.expectedFailure(func)
57
58 return f
59
60 def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
61 def f(func):
62 rc = subprocess.call(['ip', 'rule', 'add', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7'])
63 if rc == 0:
64 subprocess.call(['ip', 'rule', 'del', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7'])
65 return func
66 else:
67 return unittest.expectedFailure(func)
68
69 return f
70
71 def setUpModule():
72
73 os.makedirs(network_unit_file_path, exist_ok=True)
74 os.makedirs(networkd_ci_path, exist_ok=True)
75
76 shutil.rmtree(networkd_ci_path)
77 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
78
79 subprocess.check_call('systemctl stop systemd-networkd.socket', shell=True)
80
81 def tearDownModule():
82 shutil.rmtree(networkd_ci_path)
83
84 subprocess.check_call('systemctl stop systemd-networkd.service', shell=True)
85 subprocess.check_call('systemctl start systemd-networkd.socket', shell=True)
86 subprocess.check_call('systemctl start systemd-networkd.service', shell=True)
87
88 class Utilities():
89 def read_link_attr(self, link, dev, attribute):
90 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
91 return f.readline().strip()
92
93 def read_bridge_port_attr(self, bridge, link, attribute):
94
95 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
96 path_port = 'lower_' + link + '/brport'
97 path = os.path.join(path_bridge, path_port)
98
99 with open(os.path.join(path, attribute)) as f:
100 return f.readline().strip()
101
102 def link_exits(self, link):
103 return os.path.exists(os.path.join('/sys/class/net', link))
104
105 def link_remove(self, links):
106 for link in links:
107 if os.path.exists(os.path.join('/sys/class/net', link)):
108 subprocess.call(['ip', 'link', 'del', 'dev', link])
109 time.sleep(1)
110
111 def read_ipv6_sysctl_attr(self, link, attribute):
112 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
113 return f.readline().strip()
114
115 def read_ipv4_sysctl_attr(self, link, attribute):
116 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
117 return f.readline().strip()
118
119 def copy_unit_to_networkd_unit_path(self, *units):
120 print()
121 for unit in units:
122 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
123 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
124 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
125
126 def remove_unit_from_networkd_path(self, units):
127 for unit in units:
128 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
129 os.remove(os.path.join(network_unit_file_path, unit))
130 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
131 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
132
133 def start_dnsmasq(self, additional_options=''):
134 dnsmasq_command = 'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range=2600::10,2600::20 --dhcp-range=192.168.5.10,192.168.5.200 -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options
135 subprocess.check_call(dnsmasq_command, shell=True)
136
137 time.sleep(10)
138
139 def stop_dnsmasq(self, pid_file):
140 if os.path.exists(pid_file):
141 with open(pid_file, 'r') as f:
142 pid = f.read().rstrip(' \t\r\n\0')
143 os.kill(int(pid), signal.SIGTERM)
144
145 os.remove(pid_file)
146
147 def search_words_in_dnsmasq_log(self, words, show_all=False):
148 if os.path.exists(dnsmasq_log_file):
149 with open (dnsmasq_log_file) as in_file:
150 contents = in_file.read()
151 if show_all:
152 print(contents)
153 for line in contents.split('\n'):
154 if words in line:
155 in_file.close()
156 print("%s, %s" % (words, line))
157 return True
158 return False
159
160 def remove_lease_file(self):
161 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
162 os.remove(os.path.join(networkd_ci_path, 'lease'))
163
164 def remove_log_file(self):
165 if os.path.exists(dnsmasq_log_file):
166 os.remove(dnsmasq_log_file)
167
168 def start_networkd(self):
169 if (os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
170 subprocess.check_call('systemctl stop systemd-networkd', shell=True)
171 os.remove(os.path.join(networkd_runtime_directory, 'state'))
172 subprocess.check_call('systemctl start systemd-networkd', shell=True)
173 else:
174 subprocess.check_call('systemctl restart systemd-networkd', shell=True)
175 time.sleep(5)
176
177 class NetworkdNetDevTests(unittest.TestCase, Utilities):
178
179 links =[
180 '6rdtun99',
181 'bond99',
182 'bridge99',
183 'dropin-test',
184 'dummy98',
185 'erspan-test',
186 'geneve99',
187 'gretap99',
188 'gretun99',
189 'ip6gretap99',
190 'ip6tnl99',
191 'ipiptun99',
192 'ipvlan99',
193 'isataptun99',
194 'macvlan99',
195 'macvtap99',
196 'sittun99',
197 'tap99',
198 'test1',
199 'tun99',
200 'vcan99',
201 'veth99',
202 'vlan99',
203 'vrf99',
204 'vti6tun99',
205 'vtitun99',
206 'vxlan99',
207 'wg98',
208 'wg99']
209
210 units = [
211 '10-dropin-test.netdev',
212 '11-dummy.netdev',
213 '12-dummy.netdev',
214 '21-macvlan.netdev',
215 '21-macvtap.netdev',
216 '21-vlan.netdev',
217 '21-vlan.network',
218 '25-6rd-tunnel.netdev',
219 '25-bond.netdev',
220 '25-bond-balanced-tlb.netdev',
221 '25-bridge.netdev',
222 '25-erspan-tunnel.netdev',
223 '25-geneve.netdev',
224 '25-gretap-tunnel.netdev',
225 '25-gre-tunnel.netdev',
226 '25-ip6gre-tunnel.netdev',
227 '25-ip6tnl-tunnel.netdev',
228 '25-ipip-tunnel-independent.netdev',
229 '25-ipip-tunnel.netdev',
230 '25-ipvlan.netdev',
231 '25-isatap-tunnel.netdev',
232 '25-sit-tunnel.netdev',
233 '25-tap.netdev',
234 '25-tun.netdev',
235 '25-vcan.netdev',
236 '25-veth.netdev',
237 '25-vrf.netdev',
238 '25-vti6-tunnel.netdev',
239 '25-vti-tunnel.netdev',
240 '25-vxlan.netdev',
241 '25-wireguard-23-peers.netdev',
242 '25-wireguard-23-peers.network',
243 '25-wireguard.netdev',
244 '6rd.network',
245 'gre.network',
246 'gretap.network',
247 'gretun.network',
248 'ip6gretap.network',
249 'ip6tnl.network',
250 'ipip.network',
251 'ipvlan.network',
252 'isatap.network',
253 'macvlan.network',
254 'macvtap.network',
255 'sit.network',
256 'vti6.network',
257 'vti.network',
258 'vxlan.network']
259
260 def setUp(self):
261 self.link_remove(self.links)
262
263 def tearDown(self):
264 self.link_remove(self.links)
265 self.remove_unit_from_networkd_path(self.units)
266
267 def test_dropin(self):
268 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
269 self.start_networkd()
270
271 self.assertTrue(self.link_exits('dropin-test'))
272
273 output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
274 print(output)
275 self.assertRegex(output, '00:50:56:c0:00:28')
276
277 output = subprocess.check_output(['networkctl', 'list']).rstrip().decode('utf-8')
278 self.assertRegex(output, '1 lo ')
279 self.assertRegex(output, 'dropin-test')
280
281 output = subprocess.check_output(['networkctl', 'list', 'dropin-test']).rstrip().decode('utf-8')
282 self.assertNotRegex(output, '1 lo ')
283 self.assertRegex(output, 'dropin-test')
284
285 output = subprocess.check_output(['networkctl', 'list', 'dropin-*']).rstrip().decode('utf-8')
286 self.assertNotRegex(output, '1 lo ')
287 self.assertRegex(output, 'dropin-test')
288
289 output = subprocess.check_output(['networkctl', 'status', 'dropin-*']).rstrip().decode('utf-8')
290 self.assertNotRegex(output, '1: lo ')
291 self.assertRegex(output, 'dropin-test')
292
293 ret = subprocess.run(['ethtool', '--driver', 'dropin-test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
294 print(ret.stdout.rstrip().decode('utf-8'))
295 if ret.returncode == 0 and re.search('driver: dummy', ret.stdout.rstrip().decode('utf-8')) != None:
296 self.assertRegex(output, 'Driver: dummy')
297 else:
298 print('ethtool does not support driver field at least for dummy interfaces, skipping test for Driver field of networkctl.')
299
300 def test_bridge(self):
301 self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
302 self.start_networkd()
303
304 self.assertTrue(self.link_exits('bridge99'))
305
306 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'hello_time'))
307 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'max_age'))
308 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','forward_delay'))
309 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','ageing_time'))
310 self.assertEqual('9', self.read_link_attr('bridge99', 'bridge','priority'))
311 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_querier'))
312 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_snooping'))
313 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','stp_state'))
314
315 def test_bond(self):
316 self.copy_unit_to_networkd_unit_path('25-bond.netdev')
317 self.start_networkd()
318
319 self.assertTrue(self.link_exits('bond99'))
320
321 self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode'))
322 self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
323 self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon'))
324 self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate'))
325 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay'))
326 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay'))
327 self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp'))
328 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links'))
329 self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
330 self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
331 self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
332
333 def test_bond_balanced_tlb(self):
334 self.copy_unit_to_networkd_unit_path('25-bond-balanced-tlb.netdev')
335 self.start_networkd()
336
337 self.assertTrue(self.link_exits('bond99'))
338
339 self.assertEqual('balance-tlb 5', self.read_link_attr('bond99', 'bonding', 'mode'))
340 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
341
342 def test_vlan(self):
343 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
344 self.start_networkd()
345
346 self.assertTrue(self.link_exits('vlan99'))
347
348 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
349 print(output)
350 self.assertTrue(output, 'REORDER_HDR')
351 self.assertTrue(output, 'LOOSE_BINDING')
352 self.assertTrue(output, 'GVRP')
353 self.assertTrue(output, 'MVRP')
354 self.assertTrue(output, '99')
355
356 def test_macvtap(self):
357 self.copy_unit_to_networkd_unit_path('21-macvtap.netdev', '11-dummy.netdev', 'macvtap.network')
358 self.start_networkd()
359
360 self.assertTrue(self.link_exits('macvtap99'))
361
362 def test_macvlan(self):
363 self.copy_unit_to_networkd_unit_path('21-macvlan.netdev', '11-dummy.netdev', 'macvlan.network')
364 self.start_networkd()
365
366 self.assertTrue(self.link_exits('macvlan99'))
367
368 @expectedFailureIfModuleIsNotAvailable('ipvlan')
369 def test_ipvlan(self):
370 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
371 self.start_networkd()
372
373 self.assertTrue(self.link_exits('ipvlan99'))
374
375 def test_veth(self):
376 self.copy_unit_to_networkd_unit_path('25-veth.netdev')
377 self.start_networkd()
378
379 self.assertTrue(self.link_exits('veth99'))
380
381 def test_dummy(self):
382 self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
383 self.start_networkd()
384
385 self.assertTrue(self.link_exits('test1'))
386
387 def test_tun(self):
388 self.copy_unit_to_networkd_unit_path('25-tun.netdev')
389 self.start_networkd()
390
391 self.assertTrue(self.link_exits('tun99'))
392
393 def test_tap(self):
394 self.copy_unit_to_networkd_unit_path('25-tap.netdev')
395 self.start_networkd()
396
397 self.assertTrue(self.link_exits('tap99'))
398
399 @expectedFailureIfModuleIsNotAvailable('vrf')
400 def test_vrf(self):
401 self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
402 self.start_networkd()
403
404 self.assertTrue(self.link_exits('vrf99'))
405
406 @expectedFailureIfModuleIsNotAvailable('vcan')
407 def test_vcan(self):
408 self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
409 self.start_networkd()
410
411 self.assertTrue(self.link_exits('vcan99'))
412
413 @expectedFailureIfModuleIsNotAvailable('wireguard')
414 def test_wireguard(self):
415 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
416 self.start_networkd()
417
418 if shutil.which('wg'):
419 subprocess.call('wg')
420 output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
421 self.assertTrue(output, '51820')
422 output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
423 self.assertTrue(output, '0x4d2')
424 output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
425 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
426 output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
427 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20')
428 output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
429 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820')
430
431 self.assertTrue(self.link_exits('wg99'))
432
433 @expectedFailureIfModuleIsNotAvailable('wireguard')
434 def test_wireguard_23_peers(self):
435 self.copy_unit_to_networkd_unit_path('25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network')
436 self.start_networkd()
437
438 if shutil.which('wg'):
439 subprocess.call('wg')
440
441 self.assertTrue(self.link_exits('wg98'))
442
443 def test_geneve(self):
444 self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
445 self.start_networkd()
446
447 self.assertTrue(self.link_exits('geneve99'))
448
449 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
450 print(output)
451 self.assertTrue(output, '192.168.22.1')
452 self.assertTrue(output, '6082')
453 self.assertTrue(output, 'udpcsum')
454 self.assertTrue(output, 'udp6zerocsumrx')
455
456 def test_ipip_tunnel(self):
457 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network')
458 self.start_networkd()
459
460 self.assertTrue(self.link_exits('dummy98'))
461 self.assertTrue(self.link_exits('ipiptun99'))
462
463 def test_gre_tunnel(self):
464 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network')
465 self.start_networkd()
466
467 self.assertTrue(self.link_exits('dummy98'))
468 self.assertTrue(self.link_exits('gretun99'))
469
470 def test_gretap_tunnel(self):
471 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network')
472 self.start_networkd()
473
474 self.assertTrue(self.link_exits('dummy98'))
475 self.assertTrue(self.link_exits('gretap99'))
476
477 def test_ip6gretap_tunnel(self):
478 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretap.network')
479 self.start_networkd()
480
481 self.assertTrue(self.link_exits('dummy98'))
482 self.assertTrue(self.link_exits('ip6gretap99'))
483
484 def test_vti_tunnel(self):
485 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network')
486 self.start_networkd()
487
488 self.assertTrue(self.link_exits('dummy98'))
489 self.assertTrue(self.link_exits('vtitun99'))
490
491 def test_vti6_tunnel(self):
492 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network')
493 self.start_networkd()
494
495 self.assertTrue(self.link_exits('dummy98'))
496 self.assertTrue(self.link_exits('vti6tun99'))
497
498 def test_ip6tnl_tunnel(self):
499 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network')
500 self.start_networkd()
501
502 self.assertTrue(self.link_exits('dummy98'))
503 self.assertTrue(self.link_exits('ip6tnl99'))
504
505 def test_sit_tunnel(self):
506 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network')
507 self.start_networkd()
508
509 self.assertTrue(self.link_exits('dummy98'))
510 self.assertTrue(self.link_exits('sittun99'))
511
512 def test_isatap_tunnel(self):
513 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
514 self.start_networkd()
515
516 self.assertTrue(self.link_exits('dummy98'))
517 self.assertTrue(self.link_exits('isataptun99'))
518
519 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
520 print(output)
521 self.assertRegex(output, "isatap ")
522
523 def test_6rd_tunnel(self):
524 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
525 self.start_networkd()
526
527 self.assertTrue(self.link_exits('dummy98'))
528 self.assertTrue(self.link_exits('sittun99'))
529
530 @expectedFailureIfERSPANModuleIsNotAvailable()
531 def test_erspan_tunnel(self):
532 self.copy_unit_to_networkd_unit_path('25-erspan-tunnel.netdev')
533 self.start_networkd()
534
535 self.assertTrue(self.link_exits('erspan-test'))
536
537 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan-test']).rstrip().decode('utf-8')
538 print(output)
539 self.assertTrue(output, '172.16.1.200')
540 self.assertTrue(output, '172.16.1.100')
541 self.assertTrue(output, '101')
542
543 def test_tunnel_independent(self):
544 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
545 self.start_networkd()
546
547 self.assertTrue(self.link_exits('ipiptun99'))
548
549 def test_vxlan(self):
550 self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network','11-dummy.netdev')
551 self.start_networkd()
552
553 self.assertTrue(self.link_exits('vxlan99'))
554
555 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
556 print(output)
557 self.assertRegex(output, "999")
558 self.assertRegex(output, '5555')
559 self.assertRegex(output, 'l2miss')
560 self.assertRegex(output, 'l3miss')
561 self.assertRegex(output, 'udpcsum')
562 self.assertRegex(output, 'udp6zerocsumtx')
563 self.assertRegex(output, 'udp6zerocsumrx')
564 self.assertRegex(output, 'remcsumtx')
565 self.assertRegex(output, 'remcsumrx')
566 self.assertRegex(output, 'gbp')
567
568 class NetworkdNetWorkTests(unittest.TestCase, Utilities):
569 links = [
570 'bond199',
571 'dummy98',
572 'dummy99',
573 'test1']
574
575 units = [
576 '11-dummy.netdev',
577 '12-dummy.netdev',
578 '23-active-slave.network',
579 '23-bond199.network',
580 '23-primary-slave.network',
581 '23-test1-bond199.network',
582 '25-address-link-section.network',
583 '25-address-section-miscellaneous.network',
584 '25-address-section.network',
585 '25-bind-carrier.network',
586 '25-bond-active-backup-slave.netdev',
587 '25-fibrule-invert.network',
588 '25-fibrule-port-range.network',
589 '25-ipv6-address-label-section.network',
590 '25-neighbor-section.network',
591 '25-link-local-addressing-no.network',
592 '25-link-local-addressing-yes.network',
593 '25-link-section-unmanaged.network',
594 '25-route-gateway.network',
595 '25-route-gateway-on-link.network',
596 '25-route-ipv6-src.network',
597 '25-route-reverse-order.network',
598 '25-route-section.network',
599 '25-route-tcp-window-settings.network',
600 '25-route-type.network',
601 '25-sysctl-disable-ipv6.network',
602 '25-sysctl.network',
603 'configure-without-carrier.network',
604 'routing-policy-rule.network',
605 'test-static.network']
606
607 def setUp(self):
608 self.link_remove(self.links)
609
610 def tearDown(self):
611 self.link_remove(self.links)
612 self.remove_unit_from_networkd_path(self.units)
613
614 def test_static_address(self):
615 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'test-static.network')
616 self.start_networkd()
617
618 self.assertTrue(self.link_exits('dummy98'))
619
620 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
621 print(output)
622 self.assertRegex(output, '192.168.0.15')
623 self.assertRegex(output, '192.168.0.1')
624 self.assertRegex(output, 'routable')
625
626 def test_configure_without_carrier(self):
627 self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
628 self.start_networkd()
629
630 self.assertTrue(self.link_exits('test1'))
631
632 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
633 print(output)
634 self.assertRegex(output, '192.168.0.15')
635 self.assertRegex(output, '192.168.0.1')
636 self.assertRegex(output, 'routable')
637
638 def test_bond_active_slave(self):
639 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
640 self.start_networkd()
641
642 self.assertTrue(self.link_exits('dummy98'))
643 self.assertTrue(self.link_exits('bond199'))
644
645 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
646 print(output)
647 self.assertRegex(output, 'active_slave dummy98')
648
649 def test_bond_primary_slave(self):
650 self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
651 self.start_networkd()
652
653 self.assertTrue(self.link_exits('test1'))
654 self.assertTrue(self.link_exits('bond199'))
655
656 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
657 print(output)
658 self.assertRegex(output, 'primary test1')
659
660 def test_routing_policy_rule(self):
661 self.copy_unit_to_networkd_unit_path('routing-policy-rule.network', '11-dummy.netdev')
662 self.start_networkd()
663
664 self.assertTrue(self.link_exits('test1'))
665
666 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
667 print(output)
668 self.assertRegex(output, '111')
669 self.assertRegex(output, 'from 192.168.100.18')
670 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
671 self.assertRegex(output, 'iif test1')
672 self.assertRegex(output, 'oif test1')
673 self.assertRegex(output, 'lookup 7')
674
675 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
676
677 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
678 def test_routing_policy_rule_port_range(self):
679 self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
680 self.start_networkd()
681
682 self.assertTrue(self.link_exits('test1'))
683
684 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
685 print(output)
686 self.assertRegex(output, '111')
687 self.assertRegex(output, 'from 192.168.100.18')
688 self.assertRegex(output, '1123-1150')
689 self.assertRegex(output, '3224-3290')
690 self.assertRegex(output, 'tcp')
691 self.assertRegex(output, 'lookup 7')
692
693 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
694
695 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
696 def test_routing_policy_rule_invert(self):
697 self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
698 self.start_networkd()
699
700 self.assertTrue(self.link_exits('test1'))
701
702 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
703 print(output)
704 self.assertRegex(output, '111')
705 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
706 self.assertRegex(output, 'tcp')
707 self.assertRegex(output, 'lookup 7')
708
709 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
710
711 def test_address_peer(self):
712 self.copy_unit_to_networkd_unit_path('25-address-section.network', '12-dummy.netdev')
713 self.start_networkd()
714
715 self.assertTrue(self.link_exits('dummy98'))
716
717 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
718 print(output)
719 self.assertRegex(output, 'inet 10.2.3.4 peer 10.2.3.5/16 scope global 32')
720 self.assertRegex(output, 'inet 10.6.7.8/16 brd 10.6.255.255 scope global 33')
721 self.assertRegex(output, 'inet6 2001:db8::20 peer 2001:db8::10/128 scope global')
722
723 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
724 print(output)
725 self.assertRegex(output, 'State: routable \(configured\)')
726
727 def test_address_preferred_lifetime_zero_ipv6(self):
728 self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev')
729 self.start_networkd()
730
731 self.assertTrue(self.link_exits('dummy98'))
732
733 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
734 print(output)
735 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
736 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
737
738 def test_ip_route(self):
739 self.copy_unit_to_networkd_unit_path('25-route-section.network', '12-dummy.netdev')
740 self.start_networkd()
741
742 self.assertTrue(self.link_exits('dummy98'))
743
744 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98']).rstrip().decode('utf-8')
745 print(output)
746 self.assertRegex(output, '192.168.0.1')
747 self.assertRegex(output, 'static')
748 self.assertRegex(output, '192.168.0.0/24')
749
750 def test_ip_route_reverse(self):
751 self.copy_unit_to_networkd_unit_path('25-route-reverse-order.network', '12-dummy.netdev')
752 self.start_networkd()
753
754 self.assertTrue(self.link_exits('dummy98'))
755
756 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
757 print(output)
758 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff')
759 self.assertRegex(output, '2001:1234:5:8f63::1')
760
761 def test_ip_route_blackhole_unreachable_prohibit(self):
762 self.copy_unit_to_networkd_unit_path('25-route-type.network', '12-dummy.netdev')
763 self.start_networkd()
764
765 self.assertTrue(self.link_exits('dummy98'))
766
767 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
768 print(output)
769 self.assertRegex(output, 'blackhole')
770 self.assertRegex(output, 'unreachable')
771 self.assertRegex(output, 'prohibit')
772
773 subprocess.call(['ip', 'route', 'del', 'blackhole', '202.54.1.2'])
774 subprocess.call(['ip', 'route', 'del', 'unreachable', '202.54.1.3'])
775 subprocess.call(['ip', 'route', 'del', 'prohibit', '202.54.1.4'])
776
777 def test_ip_route_tcp_window(self):
778 self.copy_unit_to_networkd_unit_path('25-route-tcp-window-settings.network', '11-dummy.netdev')
779 self.start_networkd()
780
781 self.assertTrue(self.link_exits('test1'))
782
783 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
784 print(output)
785 self.assertRegex(output, 'initcwnd 20')
786 self.assertRegex(output, 'initrwnd 30')
787
788 def test_ip_route_gateway(self):
789 self.copy_unit_to_networkd_unit_path('25-route-gateway.network', '12-dummy.netdev')
790 self.start_networkd()
791
792 self.assertTrue(self.link_exits('dummy98'))
793
794 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
795 print(output)
796 self.assertRegex(output, 'default')
797 self.assertRegex(output, 'via')
798 self.assertRegex(output, '149.10.124.64')
799 self.assertRegex(output, 'proto')
800 self.assertRegex(output, 'static')
801
802 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
803 print(output)
804 self.assertRegex(output, '149.10.124.48/28')
805 self.assertRegex(output, 'proto')
806 self.assertRegex(output, 'kernel')
807 self.assertRegex(output, 'scope')
808 self.assertRegex(output, 'link')
809
810 def test_ip_route_gateway_on_link(self):
811 self.copy_unit_to_networkd_unit_path('25-route-gateway-on-link.network', '12-dummy.netdev')
812 self.start_networkd()
813
814 self.assertTrue(self.link_exits('dummy98'))
815
816 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
817 print(output)
818 self.assertRegex(output, 'default')
819 self.assertRegex(output, 'via')
820 self.assertRegex(output, '149.10.125.65')
821 self.assertRegex(output, 'proto')
822 self.assertRegex(output, 'static')
823 self.assertRegex(output, 'onlink')
824
825 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
826 print(output)
827 self.assertRegex(output, '149.10.124.48/28')
828 self.assertRegex(output, 'proto')
829 self.assertRegex(output, 'kernel')
830 self.assertRegex(output, 'scope')
831 self.assertRegex(output, 'link')
832
833 def test_ip_route_ipv6_src_route(self):
834 # a dummy device does not make the addresses go through tentative state, so we
835 # reuse a bond from an earlier test, which does make the addresses go through
836 # tentative state, and do our test on that
837 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')
838 self.start_networkd()
839
840 self.assertTrue(self.link_exits('dummy98'))
841 self.assertTrue(self.link_exits('bond199'))
842
843 output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8')
844 print(output)
845 self.assertRegex(output, 'abcd::/16')
846 self.assertRegex(output, 'src')
847 self.assertRegex(output, '2001:1234:56:8f63::2')
848
849 def test_ip_link_mac_address(self):
850 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
851 self.start_networkd()
852
853 self.assertTrue(self.link_exits('dummy98'))
854
855 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
856 print(output)
857 self.assertRegex(output, '00:01:02:aa:bb:cc')
858
859 def test_ip_link_unmanaged(self):
860 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
861 self.start_networkd()
862
863 self.assertTrue(self.link_exits('dummy98'))
864
865 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
866 print(output)
867 self.assertRegex(output, 'unmanaged')
868
869 def test_ipv6_address_label(self):
870 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
871 self.start_networkd()
872
873 self.assertTrue(self.link_exits('dummy98'))
874
875 output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
876 print(output)
877 self.assertRegex(output, '2004:da8:1::/64')
878
879 def test_ipv6_neighbor(self):
880 self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
881 self.start_networkd()
882
883 self.assertTrue(self.link_exits('dummy98'))
884
885 output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
886 print(output)
887 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
888 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
889
890 def test_link_local_addressing(self):
891 self.copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev',
892 '25-link-local-addressing-no.network', '12-dummy.netdev')
893 self.start_networkd()
894
895 self.assertTrue(self.link_exits('test1'))
896 self.assertTrue(self.link_exits('dummy98'))
897
898 time.sleep(10)
899
900 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
901 print(output)
902 self.assertRegex(output, 'inet .* scope link')
903 self.assertRegex(output, 'inet6 .* scope link')
904
905 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
906 print(output)
907 self.assertNotRegex(output, 'inet6* .* scope link')
908
909 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
910 print(output)
911 self.assertRegex(output, 'State: degraded \(configured\)')
912
913 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
914 print(output)
915 self.assertRegex(output, 'State: carrier \(configured\)')
916
917 '''
918 Documentation/networking/ip-sysctl.txt
919
920 addr_gen_mode - INTEGER
921 Defines how link-local and autoconf addresses are generated.
922
923 0: generate address based on EUI64 (default)
924 1: do no generate a link-local address, use EUI64 for addresses generated
925 from autoconf
926 2: generate stable privacy addresses, using the secret from
927 stable_secret (RFC7217)
928 3: generate stable privacy addresses, using a random secret if unset
929 '''
930
931 test1_addr_gen_mode = ''
932 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
933 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
934 try:
935 f.readline()
936 except IOError:
937 # if stable_secret is unset, then EIO is returned
938 test1_addr_gen_mode = '0'
939 else:
940 test1_addr_gen_mode = '2'
941 else:
942 test1_addr_gen_mode = '0'
943
944 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
945 self.assertEqual(self.read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '0')
946
947 if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
948 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
949
950 def test_sysctl(self):
951 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
952 self.start_networkd()
953
954 self.assertTrue(self.link_exits('dummy98'))
955
956 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
957 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
958 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
959 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
960 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
961 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
962 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
963
964 def test_sysctl_disable_ipv6(self):
965 self.copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
966
967 print('## Disable ipv6')
968 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=1']), 0)
969 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=1']), 0)
970
971 self.start_networkd()
972
973 self.assertTrue(self.link_exits('dummy98'))
974
975 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
976 print(output)
977 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
978 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
979 print(output)
980 self.assertEqual(output, '')
981 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
982 self.assertRegex(output, 'State: routable \(configured\)')
983
984 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
985
986 print('## Enable ipv6')
987 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=0']), 0)
988 self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=0']), 0)
989
990 self.start_networkd()
991
992 self.assertTrue(self.link_exits('dummy98'))
993
994 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
995 print(output)
996 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
997 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
998 print(output)
999 self.assertRegex(output, 'inet6 .* scope link')
1000 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1001 self.assertRegex(output, 'State: routable \(configured\)')
1002
1003 def test_bind_carrier(self):
1004 self.copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
1005 self.start_networkd()
1006
1007 self.assertTrue(self.link_exits('test1'))
1008
1009 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1010 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1011 time.sleep(2)
1012 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1013 print(output)
1014 self.assertRegex(output, 'UP,LOWER_UP')
1015 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1016 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1017 self.assertRegex(output, 'State: routable \(configured\)')
1018
1019 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy99', 'type', 'dummy']), 0)
1020 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy99', 'up']), 0)
1021 time.sleep(2)
1022 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1023 print(output)
1024 self.assertRegex(output, 'UP,LOWER_UP')
1025 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1026 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1027 self.assertRegex(output, 'State: routable \(configured\)')
1028
1029 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1030 time.sleep(2)
1031 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1032 print(output)
1033 self.assertRegex(output, 'UP,LOWER_UP')
1034 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1035 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1036 self.assertRegex(output, 'State: routable \(configured\)')
1037
1038 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy99']), 0)
1039 time.sleep(2)
1040 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1041 print(output)
1042 self.assertNotRegex(output, 'UP,LOWER_UP')
1043 self.assertRegex(output, 'DOWN')
1044 self.assertNotRegex(output, '192.168.10')
1045 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1046 self.assertRegex(output, 'State: off \(configured\)')
1047
1048 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1049 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1050 time.sleep(2)
1051 output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
1052 print(output)
1053 self.assertRegex(output, 'UP,LOWER_UP')
1054 self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
1055 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1056 self.assertRegex(output, 'State: routable \(configured\)')
1057
1058 class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
1059 links = [
1060 'bond99',
1061 'dummy98',
1062 'test1']
1063
1064 units = [
1065 '11-dummy.netdev',
1066 '12-dummy.netdev',
1067 '25-bond.netdev',
1068 'bond99.network',
1069 'bond-slave.network']
1070
1071 def setUp(self):
1072 self.link_remove(self.links)
1073
1074 def tearDown(self):
1075 self.link_remove(self.links)
1076 self.remove_unit_from_networkd_path(self.units)
1077
1078 def test_bond_operstate(self):
1079 self.copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev',
1080 'bond99.network','bond-slave.network')
1081 self.start_networkd()
1082
1083 self.assertTrue(self.link_exits('bond99'))
1084 self.assertTrue(self.link_exits('dummy98'))
1085 self.assertTrue(self.link_exits('test1'))
1086
1087 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1088 print(output)
1089 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1090
1091 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
1092 print(output)
1093 self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
1094
1095 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond99']).rstrip().decode('utf-8')
1096 print(output)
1097 self.assertRegex(output, 'MASTER,UP,LOWER_UP')
1098
1099 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1100 print(output)
1101 self.assertRegex(output, 'State: enslaved \(configured\)')
1102
1103 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1104 print(output)
1105 self.assertRegex(output, 'State: enslaved \(configured\)')
1106
1107 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1108 print(output)
1109 self.assertRegex(output, 'State: routable \(configured\)')
1110
1111 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
1112 time.sleep(2)
1113
1114 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1115 print(output)
1116 self.assertRegex(output, 'State: off \(configured\)')
1117
1118 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1119 print(output)
1120 self.assertRegex(output, 'State: enslaved \(configured\)')
1121
1122 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1123 print(output)
1124 self.assertRegex(output, 'State: degraded \(configured\)')
1125
1126 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1127 time.sleep(2)
1128
1129 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1130 print(output)
1131 self.assertRegex(output, 'State: enslaved \(configured\)')
1132
1133 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1134 print(output)
1135 self.assertRegex(output, 'State: enslaved \(configured\)')
1136
1137 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1138 print(output)
1139 self.assertRegex(output, 'State: routable \(configured\)')
1140
1141 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
1142 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'test1', 'down']), 0)
1143 time.sleep(2)
1144
1145 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1146 print(output)
1147 self.assertRegex(output, 'State: off \(configured\)')
1148
1149 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1150 print(output)
1151 self.assertRegex(output, 'State: off \(configured\)')
1152
1153 output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
1154 print(output)
1155 self.assertRegex(output, 'State: degraded \(configured\)')
1156
1157 class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
1158 links = [
1159 'bridge99',
1160 'dummy98',
1161 'test1']
1162
1163 units = [
1164 '11-dummy.netdev',
1165 '12-dummy.netdev',
1166 '26-bridge.netdev',
1167 '26-bridge-slave-interface-1.network',
1168 '26-bridge-slave-interface-2.network',
1169 'bridge99-ignore-carrier-loss.network',
1170 'bridge99.network']
1171
1172 def setUp(self):
1173 self.link_remove(self.links)
1174
1175 def tearDown(self):
1176 self.link_remove(self.links)
1177 self.remove_unit_from_networkd_path(self.units)
1178
1179 def test_bridge_property(self):
1180 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1181 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1182 'bridge99.network')
1183 self.start_networkd()
1184
1185 self.assertTrue(self.link_exits('dummy98'))
1186 self.assertTrue(self.link_exits('test1'))
1187 self.assertTrue(self.link_exits('bridge99'))
1188
1189 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
1190 print(output)
1191 self.assertRegex(output, 'master')
1192 self.assertRegex(output, 'bridge')
1193
1194 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1195 print(output)
1196 self.assertRegex(output, 'master')
1197 self.assertRegex(output, 'bridge')
1198
1199 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
1200 print(output)
1201 self.assertRegex(output, '192.168.0.15/24')
1202
1203 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
1204 print(output)
1205 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
1206 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
1207 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
1208 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
1209
1210 # CONFIG_BRIDGE_IGMP_SNOOPING=y
1211 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
1212 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
1213
1214 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
1215 self.assertRegex(output, 'State: enslaved \(configured\)')
1216
1217 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1218 self.assertRegex(output, 'State: enslaved \(configured\)')
1219
1220 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1221 self.assertRegex(output, 'State: routable \(configured\)')
1222
1223 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1224 time.sleep(1)
1225
1226 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
1227 print(output)
1228 self.assertRegex(output, '192.168.0.16/24')
1229
1230 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1231 self.assertRegex(output, 'State: routable \(configured\)')
1232
1233 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1234 time.sleep(3)
1235
1236 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1237 self.assertRegex(output, 'State: degraded \(configured\)')
1238
1239 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1240 time.sleep(3)
1241
1242 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1243 self.assertRegex(output, 'State: no-carrier \(configured\)')
1244
1245 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1246 print(output)
1247 self.assertRegex(output, 'NO-CARRIER')
1248 self.assertNotRegex(output, '192.168.0.15/24')
1249 self.assertNotRegex(output, '192.168.0.16/24')
1250
1251 def test_bridge_ignore_carrier_loss(self):
1252 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
1253 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
1254 'bridge99-ignore-carrier-loss.network')
1255 self.start_networkd()
1256
1257 self.assertTrue(self.link_exits('dummy98'))
1258 self.assertTrue(self.link_exits('test1'))
1259 self.assertTrue(self.link_exits('bridge99'))
1260
1261 self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
1262 time.sleep(1)
1263
1264 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
1265 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1266 time.sleep(3)
1267
1268 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1269 print(output)
1270 self.assertRegex(output, 'NO-CARRIER')
1271 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1272 self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99')
1273
1274 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1275
1276 def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self):
1277 self.copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network',
1278 'bridge99-ignore-carrier-loss.network')
1279 self.start_networkd()
1280
1281 self.assertTrue(self.link_exits('bridge99'))
1282
1283 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1284 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1285 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1286
1287 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1288 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1289 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1290
1291 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1292 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1293 self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
1294
1295 self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
1296 self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
1297
1298 time.sleep(3)
1299
1300 output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
1301 print(output)
1302 self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
1303
1304 output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
1305 self.assertRegex(output, 'State: routable \(configured\)')
1306
1307 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1308 self.assertRegex(output, 'State: enslaved \(configured\)')
1309
1310 output = subprocess.check_output(['ip', 'rule', 'list', 'table', '100']).rstrip().decode('utf-8')
1311 print(output)
1312 self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100')
1313
1314 subprocess.call(['ip', 'rule', 'del', 'table', '100'])
1315
1316 class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
1317 links = ['veth99']
1318
1319 units = [
1320 '23-emit-lldp.network',
1321 '24-lldp.network',
1322 '25-veth.netdev']
1323
1324 def setUp(self):
1325 self.link_remove(self.links)
1326
1327 def tearDown(self):
1328 self.link_remove(self.links)
1329 self.remove_unit_from_networkd_path(self.units)
1330
1331 def test_lldp(self):
1332 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
1333 self.start_networkd()
1334
1335 self.assertTrue(self.link_exits('veth99'))
1336
1337 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
1338 print(output)
1339 self.assertRegex(output, 'veth-peer')
1340 self.assertRegex(output, 'veth99')
1341
1342 class NetworkdNetworkRATests(unittest.TestCase, Utilities):
1343 links = ['veth99']
1344
1345 units = [
1346 '25-veth.netdev',
1347 'ipv6-prefix.network',
1348 'ipv6-prefix-veth.network']
1349
1350 def setUp(self):
1351 self.link_remove(self.links)
1352
1353 def tearDown(self):
1354 self.link_remove(self.links)
1355 self.remove_unit_from_networkd_path(self.units)
1356
1357 def test_ipv6_prefix_delegation(self):
1358 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1359 self.start_networkd()
1360
1361 self.assertTrue(self.link_exits('veth99'))
1362
1363 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1364 print(output)
1365 self.assertRegex(output, '2002:da8:1:0')
1366
1367 class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
1368 links = [
1369 'dummy98',
1370 'veth99']
1371
1372 units = [
1373 '12-dummy.netdev',
1374 '24-search-domain.network',
1375 '25-veth.netdev',
1376 'dhcp-client.network',
1377 'dhcp-client-timezone-router.network',
1378 'dhcp-server.network',
1379 'dhcp-server-timezone-router.network']
1380
1381 def setUp(self):
1382 self.link_remove(self.links)
1383
1384 def tearDown(self):
1385 self.link_remove(self.links)
1386 self.remove_unit_from_networkd_path(self.units)
1387
1388 def test_dhcp_server(self):
1389 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
1390 self.start_networkd()
1391
1392 self.assertTrue(self.link_exits('veth99'))
1393
1394 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1395 print(output)
1396 self.assertRegex(output, '192.168.5.*')
1397 self.assertRegex(output, 'Gateway: 192.168.5.1')
1398 self.assertRegex(output, 'DNS: 192.168.5.1')
1399 self.assertRegex(output, 'NTP: 192.168.5.1')
1400
1401 def test_domain(self):
1402 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1403 self.start_networkd()
1404
1405 self.assertTrue(self.link_exits('dummy98'))
1406
1407 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1408 print(output)
1409 self.assertRegex(output, 'Address: 192.168.42.100')
1410 self.assertRegex(output, 'DNS: 192.168.42.1')
1411 self.assertRegex(output, 'Search Domains: one')
1412
1413 def test_emit_router_timezone(self):
1414 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
1415 self.start_networkd()
1416
1417 self.assertTrue(self.link_exits('veth99'))
1418
1419 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1420 print(output)
1421 self.assertRegex(output, 'Gateway: 192.168.5.*')
1422 self.assertRegex(output, '192.168.5.*')
1423 self.assertRegex(output, 'Europe/Berlin')
1424
1425 class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
1426 links = [
1427 'dummy98',
1428 'veth99',
1429 'vrf99']
1430
1431 units = [
1432 '25-veth.netdev',
1433 '25-vrf.netdev',
1434 '25-vrf.network',
1435 'dhcp-client-anonymize.network',
1436 'dhcp-client-critical-connection.network',
1437 'dhcp-client-ipv4-dhcp-settings.network',
1438 'dhcp-client-ipv4-only-ipv6-disabled.network',
1439 'dhcp-client-ipv4-only.network',
1440 'dhcp-client-ipv6-only.network',
1441 'dhcp-client-ipv6-rapid-commit.network',
1442 'dhcp-client-listen-port.network',
1443 'dhcp-client-route-metric.network',
1444 'dhcp-client-route-table.network',
1445 'dhcp-client-vrf.network',
1446 'dhcp-client.network',
1447 'dhcp-server-veth-peer.network',
1448 'dhcp-v4-server-veth-peer.network',
1449 'static.network']
1450
1451 def setUp(self):
1452 self.link_remove(self.links)
1453 self.stop_dnsmasq(dnsmasq_pid_file)
1454
1455 def tearDown(self):
1456 self.link_remove(self.links)
1457 self.remove_unit_from_networkd_path(self.units)
1458 self.stop_dnsmasq(dnsmasq_pid_file)
1459 self.remove_lease_file()
1460 self.remove_log_file()
1461
1462 def test_dhcp_client_ipv6_only(self):
1463 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1464 self.start_networkd()
1465
1466 self.assertTrue(self.link_exits('veth99'))
1467
1468 self.start_dnsmasq()
1469
1470 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1471 print(output)
1472 self.assertRegex(output, '2600::')
1473 self.assertNotRegex(output, '192.168.5')
1474
1475 def test_dhcp_client_ipv4_only(self):
1476 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1477 self.start_networkd()
1478
1479 self.assertTrue(self.link_exits('veth99'))
1480
1481 self.start_dnsmasq()
1482
1483 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1484 print(output)
1485 self.assertNotRegex(output, '2600::')
1486 self.assertRegex(output, '192.168.5')
1487
1488 def test_dhcp_client_ipv4_ipv6(self):
1489 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
1490 'dhcp-client-ipv4-only.network')
1491 self.start_networkd()
1492
1493 self.assertTrue(self.link_exits('veth99'))
1494
1495 self.start_dnsmasq()
1496
1497 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1498 print(output)
1499 self.assertRegex(output, '2600::')
1500 self.assertRegex(output, '192.168.5')
1501
1502 def test_dhcp_client_settings(self):
1503 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1504 self.start_networkd()
1505
1506 self.assertTrue(self.link_exits('veth99'))
1507
1508 self.start_dnsmasq()
1509
1510 print('## ip address show dev veth99')
1511 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1512 print(output)
1513 self.assertRegex(output, '12:34:56:78:9a:bc')
1514 self.assertRegex(output, '192.168.5')
1515 self.assertRegex(output, '1492')
1516
1517 # issue #8726
1518 print('## ip route show table main dev veth99')
1519 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
1520 print(output)
1521 self.assertNotRegex(output, 'proto dhcp')
1522
1523 print('## ip route show table 211 dev veth99')
1524 output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99']).rstrip().decode('utf-8')
1525 print(output)
1526 self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
1527 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
1528 self.assertRegex(output, '192.168.5.1 proto dhcp scope link')
1529
1530 print('## dnsmasq log')
1531 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
1532 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
1533 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
1534 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
1535
1536 def test_dhcp6_client_settings_rapidcommit_true(self):
1537 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1538 self.start_networkd()
1539
1540 self.assertTrue(self.link_exits('veth99'))
1541
1542 self.start_dnsmasq()
1543
1544 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1545 print(output)
1546 self.assertRegex(output, '12:34:56:78:9a:bc')
1547 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1548
1549 def test_dhcp6_client_settings_rapidcommit_false(self):
1550 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
1551 self.start_networkd()
1552
1553 self.assertTrue(self.link_exits('veth99'))
1554
1555 self.start_dnsmasq()
1556
1557 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1558 print(output)
1559 self.assertRegex(output, '12:34:56:78:9a:bc')
1560 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1561
1562 def test_dhcp_client_settings_anonymize(self):
1563 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
1564 self.start_networkd()
1565
1566 self.assertTrue(self.link_exits('veth99'))
1567
1568 self.start_dnsmasq()
1569
1570 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
1571 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
1572 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
1573
1574 def test_dhcp_client_listen_port(self):
1575 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
1576 self.start_networkd()
1577
1578 self.assertTrue(self.link_exits('veth99'))
1579
1580 self.start_dnsmasq('--dhcp-alternate-port=67,5555')
1581
1582 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1583 print(output)
1584 self.assertRegex(output, '192.168.5.* dynamic')
1585
1586 def test_dhcp_route_table_id(self):
1587 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
1588 self.start_networkd()
1589
1590 self.assertTrue(self.link_exits('veth99'))
1591
1592 self.start_dnsmasq()
1593
1594 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
1595 print(output)
1596 self.assertRegex(output, 'veth99 proto dhcp')
1597 self.assertRegex(output, '192.168.5.1')
1598
1599 def test_dhcp_route_metric(self):
1600 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
1601 self.start_networkd()
1602
1603 self.assertTrue(self.link_exits('veth99'))
1604
1605 self.start_dnsmasq()
1606
1607 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1608 print(output)
1609 self.assertRegex(output, 'metric 24')
1610
1611 def test_dhcp_route_criticalconnection_true(self):
1612 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
1613 self.start_networkd()
1614
1615 self.assertTrue(self.link_exits('veth99'))
1616
1617 self.start_dnsmasq()
1618
1619 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1620 print(output)
1621 self.assertRegex(output, '192.168.5.*')
1622
1623 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
1624 self.stop_dnsmasq(dnsmasq_pid_file)
1625
1626 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1627 time.sleep(125)
1628
1629 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1630 print(output)
1631 self.assertRegex(output, '192.168.5.*')
1632
1633 def test_dhcp_client_reuse_address_as_static(self):
1634 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
1635 self.start_networkd()
1636
1637 self.assertTrue(self.link_exits('veth99'))
1638
1639 self.start_dnsmasq()
1640
1641 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1642 print(output)
1643 self.assertRegex(output, '192.168.5')
1644 self.assertRegex(output, '2600::')
1645
1646 ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
1647 ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
1648 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
1649 print(static_network)
1650
1651 self.remove_unit_from_networkd_path(['dhcp-client.network'])
1652
1653 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
1654 f.write(static_network)
1655
1656 self.start_networkd()
1657
1658 self.assertTrue(self.link_exits('veth99'))
1659
1660 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1661 print(output)
1662 self.assertRegex(output, '192.168.5')
1663 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1664
1665 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1666 print(output)
1667 self.assertRegex(output, '2600::')
1668 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1669
1670 @expectedFailureIfModuleIsNotAvailable('vrf')
1671 def test_dhcp_client_vrf(self):
1672 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network',
1673 '25-vrf.netdev', '25-vrf.network')
1674 self.start_networkd()
1675
1676 self.assertTrue(self.link_exits('veth99'))
1677 self.assertTrue(self.link_exits('vrf99'))
1678
1679 self.start_dnsmasq()
1680
1681 print('## ip -d link show dev vrf99')
1682 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99']).rstrip().decode('utf-8')
1683 print(output)
1684 self.assertRegex(output, 'vrf table 42')
1685
1686 print('## ip address show vrf vrf99')
1687 output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
1688 print(output_ip_vrf)
1689
1690 print('## ip address show dev veth99')
1691 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1692 print(output)
1693 self.assertEqual(output, output_ip_vrf)
1694 self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
1695 self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
1696 self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic noprefixroute')
1697 self.assertRegex(output, 'inet6 .* scope link')
1698
1699 print('## ip route show vrf vrf99')
1700 output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
1701 print(output)
1702 self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
1703 self.assertRegex(output, 'default dev veth99 proto static scope link')
1704 self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254')
1705 self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5')
1706 self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp')
1707 self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
1708
1709 print('## ip route show table main dev veth99')
1710 output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
1711 print(output)
1712 self.assertEqual(output, '')
1713
1714 output = subprocess.check_output(['networkctl', 'status', 'vrf99']).rstrip().decode('utf-8')
1715 print(output)
1716 self.assertRegex(output, 'State: carrier \(configured\)')
1717
1718 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1719 print(output)
1720 self.assertRegex(output, 'State: routable \(configured\)')
1721
1722 if __name__ == '__main__':
1723 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
1724 verbosity=3))