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