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