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