]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/test-network/systemd-networkd-tests.py
Merge pull request #11647 from thom311/hashmap-avoid-compiler-warning
[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 threading
13 import time
14 import unittest
15 from shutil import copytree
16
17 network_unit_file_path='/run/systemd/network'
18 networkd_runtime_directory='/run/systemd/netif'
19 networkd_ci_path='/run/networkd-ci'
20 network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
21 network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
22
23 dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid'
24 dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file'
25
26 def is_module_available(module_name):
27 lsmod_output = subprocess.check_output('lsmod', universal_newlines=True)
28 module_re = re.compile(r'^{0}\b'.format(re.escape(module_name)), re.MULTILINE)
29 return module_re.search(lsmod_output) or not subprocess.call(["modprobe", module_name])
30
31 def expectedFailureIfModuleIsNotAvailable(module_name):
32 def f(func):
33 if not is_module_available(module_name):
34 return unittest.expectedFailure(func)
35 return func
36
37 return f
38
39 def expectedFailureIfERSPANModuleIsNotAvailable():
40 def f(func):
41 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'])
42 if rc == 0:
43 subprocess.call(['ip', 'link', 'del', 'erspan99'])
44 return func
45 else:
46 return unittest.expectedFailure(func)
47
48 return f
49
50 def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable():
51 def f(func):
52 rc = subprocess.call(['ip', 'rule', 'add', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7'])
53 if rc == 0:
54 subprocess.call(['ip', 'rule', 'del', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7'])
55 return func
56 else:
57 return unittest.expectedFailure(func)
58
59 return f
60
61 def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
62 def f(func):
63 rc = subprocess.call(['ip', 'rule', 'add', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7'])
64 if rc == 0:
65 subprocess.call(['ip', 'rule', 'del', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7'])
66 return func
67 else:
68 return unittest.expectedFailure(func)
69
70 return f
71
72 def setUpModule():
73
74 os.makedirs(network_unit_file_path, exist_ok=True)
75 os.makedirs(networkd_ci_path, exist_ok=True)
76
77 shutil.rmtree(networkd_ci_path)
78 copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path)
79
80 subprocess.check_call('systemctl stop systemd-networkd.socket', shell=True)
81
82 def tearDownModule():
83 shutil.rmtree(networkd_ci_path)
84
85 subprocess.check_call('systemctl stop systemd-networkd.service', shell=True)
86 subprocess.check_call('systemctl start systemd-networkd.socket', shell=True)
87 subprocess.check_call('systemctl start systemd-networkd.service', shell=True)
88
89 class Utilities():
90 dhcp_server_data = []
91
92 def read_link_attr(self, link, dev, attribute):
93 with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f:
94 return f.readline().strip()
95
96 def read_bridge_port_attr(self, bridge, link, attribute):
97
98 path_bridge = os.path.join('/sys/devices/virtual/net', bridge)
99 path_port = 'lower_' + link + '/brport'
100 path = os.path.join(path_bridge, path_port)
101
102 with open(os.path.join(path, attribute)) as f:
103 return f.readline().strip()
104
105 def link_exits(self, link):
106 return os.path.exists(os.path.join('/sys/class/net', link))
107
108 def link_remove(self, links):
109 for link in links:
110 if os.path.exists(os.path.join('/sys/class/net', link)):
111 subprocess.call(['ip', 'link', 'del', 'dev', link])
112 time.sleep(1)
113
114 def read_ipv6_sysctl_attr(self, link, attribute):
115 with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f:
116 return f.readline().strip()
117
118 def read_ipv4_sysctl_attr(self, link, attribute):
119 with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f:
120 return f.readline().strip()
121
122 def copy_unit_to_networkd_unit_path(self, *units):
123 for unit in units:
124 shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
125 if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
126 copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d'))
127
128 def remove_unit_from_networkd_path(self, units):
129 for unit in units:
130 if (os.path.exists(os.path.join(network_unit_file_path, unit))):
131 os.remove(os.path.join(network_unit_file_path, unit))
132 if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
133 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
134
135 def start_dnsmasq(self):
136 subprocess.check_call('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', shell=True)
137
138 time.sleep(10)
139
140 def stop_dnsmasq(self, pid_file):
141 if os.path.exists(pid_file):
142 with open(pid_file, 'r') as f:
143 pid = f.read().rstrip(' \t\r\n\0')
144 os.kill(int(pid), signal.SIGTERM)
145
146 os.remove(pid_file)
147
148 def search_words_in_dnsmasq_log(self, words, show_all=False):
149 if os.path.exists(dnsmasq_log_file):
150 with open (dnsmasq_log_file) as in_file:
151 contents = in_file.read()
152 if show_all:
153 print(contents)
154 for line in contents.split('\n'):
155 if words in line:
156 in_file.close()
157 print("%s, %s" % (words, line))
158 return True
159 return False
160
161 def remove_lease_file(self):
162 if os.path.exists(os.path.join(networkd_ci_path, 'lease')):
163 os.remove(os.path.join(networkd_ci_path, 'lease'))
164
165 def remove_log_file(self):
166 if os.path.exists(dnsmasq_log_file):
167 os.remove(dnsmasq_log_file)
168
169 def start_networkd(self):
170 if (os.path.exists(os.path.join(networkd_runtime_directory, 'state'))):
171 subprocess.check_call('systemctl stop systemd-networkd', shell=True)
172 os.remove(os.path.join(networkd_runtime_directory, 'state'))
173 subprocess.check_call('systemctl start systemd-networkd', shell=True)
174 else:
175 subprocess.check_call('systemctl restart systemd-networkd', shell=True)
176 time.sleep(5)
177 print()
178
179 global ip
180 global port
181
182 class DHCPServer(threading.Thread):
183 def __init__(self, name):
184 threading.Thread.__init__(self)
185 self.name = name
186
187 def run(self):
188 self.start_dhcp_server()
189
190 def start_dhcp_server(self):
191 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
192
193 server_address = ('0.0.0.0', 67)
194 sock.bind(server_address)
195
196 print('Starting DHCP Server ...\n')
197 data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
198
199 global ip
200 ip = addr[0]
201
202 global port
203 port = addr[1]
204 sock.close()
205
206 class NetworkdNetDevTests(unittest.TestCase, Utilities):
207
208 links =[
209 '6rdtun99',
210 'bond99',
211 'bridge99',
212 'dropin-test',
213 'dummy98',
214 'erspan-test',
215 'geneve99',
216 'gretap99',
217 'gretun99',
218 'ip6gretap99',
219 'ip6tnl99',
220 'ipiptun99',
221 'ipvlan99',
222 'isataptun99',
223 'macvlan99',
224 'macvtap99',
225 'sittun99',
226 'tap99',
227 'test1',
228 'tun99',
229 'vcan99',
230 'veth99',
231 'vlan99',
232 'vrf99',
233 'vti6tun99',
234 'vtitun99',
235 'vxlan99',
236 'wg98',
237 'wg99']
238
239 units = [
240 '10-dropin-test.netdev',
241 '11-dummy.netdev',
242 '12-dummy.netdev',
243 '21-macvlan.netdev',
244 '21-macvtap.netdev',
245 '21-vlan.netdev',
246 '21-vlan.network',
247 '25-6rd-tunnel.netdev',
248 '25-bond.netdev',
249 '25-bond-balanced-tlb.netdev',
250 '25-bridge.netdev',
251 '25-erspan-tunnel.netdev',
252 '25-geneve.netdev',
253 '25-gretap-tunnel.netdev',
254 '25-gre-tunnel.netdev',
255 '25-ip6gre-tunnel.netdev',
256 '25-ip6tnl-tunnel.netdev',
257 '25-ipip-tunnel-independent.netdev',
258 '25-ipip-tunnel.netdev',
259 '25-ipvlan.netdev',
260 '25-isatap-tunnel.netdev',
261 '25-sit-tunnel.netdev',
262 '25-tap.netdev',
263 '25-tun.netdev',
264 '25-vcan.netdev',
265 '25-veth.netdev',
266 '25-vrf.netdev',
267 '25-vti6-tunnel.netdev',
268 '25-vti-tunnel.netdev',
269 '25-vxlan.netdev',
270 '25-wireguard-23-peers.netdev',
271 '25-wireguard-23-peers.network',
272 '25-wireguard.netdev',
273 '6rd.network',
274 'gre.network',
275 'gretap.network',
276 'gretun.network',
277 'ip6gretap.network',
278 'ip6tnl.network',
279 'ipip.network',
280 'ipvlan.network',
281 'isatap.network',
282 'macvlan.network',
283 'macvtap.network',
284 'sit.network',
285 'vti6.network',
286 'vti.network',
287 'vxlan.network']
288
289 def setUp(self):
290 self.link_remove(self.links)
291
292 def tearDown(self):
293 self.link_remove(self.links)
294 self.remove_unit_from_networkd_path(self.units)
295
296 def test_dropin(self):
297 self.copy_unit_to_networkd_unit_path('10-dropin-test.netdev')
298 self.start_networkd()
299
300 self.assertTrue(self.link_exits('dropin-test'))
301
302 output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
303 print(output)
304 self.assertRegex(output, '00:50:56:c0:00:28')
305
306 def test_bridge(self):
307 self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
308 self.start_networkd()
309
310 self.assertTrue(self.link_exits('bridge99'))
311
312 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'hello_time'))
313 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge', 'max_age'))
314 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','forward_delay'))
315 self.assertEqual('900', self.read_link_attr('bridge99', 'bridge','ageing_time'))
316 self.assertEqual('9', self.read_link_attr('bridge99', 'bridge','priority'))
317 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_querier'))
318 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','multicast_snooping'))
319 self.assertEqual('1', self.read_link_attr('bridge99', 'bridge','stp_state'))
320
321 def test_bond(self):
322 self.copy_unit_to_networkd_unit_path('25-bond.netdev')
323 self.start_networkd()
324
325 self.assertTrue(self.link_exits('bond99'))
326
327 self.assertEqual('802.3ad 4', self.read_link_attr('bond99', 'bonding', 'mode'))
328 self.assertEqual('layer3+4 1', self.read_link_attr('bond99', 'bonding', 'xmit_hash_policy'))
329 self.assertEqual('1000', self.read_link_attr('bond99', 'bonding', 'miimon'))
330 self.assertEqual('fast 1', self.read_link_attr('bond99', 'bonding', 'lacp_rate'))
331 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'updelay'))
332 self.assertEqual('2000', self.read_link_attr('bond99', 'bonding', 'downdelay'))
333 self.assertEqual('4', self.read_link_attr('bond99', 'bonding', 'resend_igmp'))
334 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'min_links'))
335 self.assertEqual('1218', self.read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio'))
336 self.assertEqual('811', self.read_link_attr('bond99', 'bonding', 'ad_user_port_key'))
337 self.assertEqual('00:11:22:33:44:55', self.read_link_attr('bond99', 'bonding', 'ad_actor_system'))
338
339 def test_bond_balanced_tlb(self):
340 self.copy_unit_to_networkd_unit_path('25-bond-balanced-tlb.netdev')
341 self.start_networkd()
342
343 self.assertTrue(self.link_exits('bond99'))
344
345 self.assertEqual('balance-tlb 5', self.read_link_attr('bond99', 'bonding', 'mode'))
346 self.assertEqual('1', self.read_link_attr('bond99', 'bonding', 'tlb_dynamic_lb'))
347
348 def test_vlan(self):
349 self.copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', '21-vlan.network')
350 self.start_networkd()
351
352 self.assertTrue(self.link_exits('vlan99'))
353
354 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
355 print(output)
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, '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('macvlan99'))
373
374 @expectedFailureIfModuleIsNotAvailable('ipvlan')
375 def test_ipvlan(self):
376 self.copy_unit_to_networkd_unit_path('25-ipvlan.netdev', '11-dummy.netdev', 'ipvlan.network')
377 self.start_networkd()
378
379 self.assertTrue(self.link_exits('ipvlan99'))
380
381 def test_veth(self):
382 self.copy_unit_to_networkd_unit_path('25-veth.netdev')
383 self.start_networkd()
384
385 self.assertTrue(self.link_exits('veth99'))
386
387 def test_dummy(self):
388 self.copy_unit_to_networkd_unit_path('11-dummy.netdev')
389 self.start_networkd()
390
391 self.assertTrue(self.link_exits('test1'))
392
393 def test_tun(self):
394 self.copy_unit_to_networkd_unit_path('25-tun.netdev')
395 self.start_networkd()
396
397 self.assertTrue(self.link_exits('tun99'))
398
399 def test_tap(self):
400 self.copy_unit_to_networkd_unit_path('25-tap.netdev')
401 self.start_networkd()
402
403 self.assertTrue(self.link_exits('tap99'))
404
405 @expectedFailureIfModuleIsNotAvailable('vrf')
406 def test_vrf(self):
407 self.copy_unit_to_networkd_unit_path('25-vrf.netdev')
408 self.start_networkd()
409
410 self.assertTrue(self.link_exits('vrf99'))
411
412 @expectedFailureIfModuleIsNotAvailable('vcan')
413 def test_vcan(self):
414 self.copy_unit_to_networkd_unit_path('25-vcan.netdev')
415 self.start_networkd()
416
417 self.assertTrue(self.link_exits('vcan99'))
418
419 @expectedFailureIfModuleIsNotAvailable('wireguard')
420 def test_wireguard(self):
421 self.copy_unit_to_networkd_unit_path('25-wireguard.netdev')
422 self.start_networkd()
423
424 if shutil.which('wg'):
425 subprocess.call('wg')
426 output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
427 self.assertTrue(output, '51820')
428 output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
429 self.assertTrue(output, '0x4d2')
430 output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
431 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
432 output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
433 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20')
434 output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
435 self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820')
436
437 self.assertTrue(self.link_exits('wg99'))
438
439 @expectedFailureIfModuleIsNotAvailable('wireguard')
440 def test_wireguard_23_peers(self):
441 self.copy_unit_to_networkd_unit_path('25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network')
442 self.start_networkd()
443
444 if shutil.which('wg'):
445 subprocess.call('wg')
446
447 self.assertTrue(self.link_exits('wg98'))
448
449 def test_geneve(self):
450 self.copy_unit_to_networkd_unit_path('25-geneve.netdev')
451 self.start_networkd()
452
453 self.assertTrue(self.link_exits('geneve99'))
454
455 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
456 print(output)
457 self.assertTrue(output, '192.168.22.1')
458 self.assertTrue(output, '6082')
459 self.assertTrue(output, 'udpcsum')
460 self.assertTrue(output, 'udp6zerocsumrx')
461
462 def test_ipip_tunnel(self):
463 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network')
464 self.start_networkd()
465
466 self.assertTrue(self.link_exits('dummy98'))
467 self.assertTrue(self.link_exits('ipiptun99'))
468
469 def test_gre_tunnel(self):
470 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network')
471 self.start_networkd()
472
473 self.assertTrue(self.link_exits('dummy98'))
474 self.assertTrue(self.link_exits('gretun99'))
475
476 def test_gretap_tunnel(self):
477 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network')
478 self.start_networkd()
479
480 self.assertTrue(self.link_exits('dummy98'))
481 self.assertTrue(self.link_exits('gretap99'))
482
483 def test_ip6gretap_tunnel(self):
484 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretap.network')
485 self.start_networkd()
486
487 self.assertTrue(self.link_exits('dummy98'))
488 self.assertTrue(self.link_exits('ip6gretap99'))
489
490 def test_vti_tunnel(self):
491 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network')
492 self.start_networkd()
493
494 self.assertTrue(self.link_exits('dummy98'))
495 self.assertTrue(self.link_exits('vtitun99'))
496
497 def test_vti6_tunnel(self):
498 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network')
499 self.start_networkd()
500
501 self.assertTrue(self.link_exits('dummy98'))
502 self.assertTrue(self.link_exits('vti6tun99'))
503
504 def test_ip6tnl_tunnel(self):
505 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network')
506 self.start_networkd()
507
508 self.assertTrue(self.link_exits('dummy98'))
509 self.assertTrue(self.link_exits('ip6tnl99'))
510
511 def test_sit_tunnel(self):
512 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network')
513 self.start_networkd()
514
515 self.assertTrue(self.link_exits('dummy98'))
516 self.assertTrue(self.link_exits('sittun99'))
517
518 def test_isatap_tunnel(self):
519 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
520 self.start_networkd()
521
522 self.assertTrue(self.link_exits('dummy98'))
523 self.assertTrue(self.link_exits('isataptun99'))
524
525 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
526 print(output)
527 self.assertRegex(output, "isatap ")
528
529 def test_6rd_tunnel(self):
530 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
531 self.start_networkd()
532
533 self.assertTrue(self.link_exits('dummy98'))
534 self.assertTrue(self.link_exits('sittun99'))
535
536 @expectedFailureIfERSPANModuleIsNotAvailable()
537 def test_erspan_tunnel(self):
538 self.copy_unit_to_networkd_unit_path('25-erspan-tunnel.netdev')
539 self.start_networkd()
540
541 self.assertTrue(self.link_exits('erspan-test'))
542
543 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan-test']).rstrip().decode('utf-8')
544 print(output)
545 self.assertTrue(output, '172.16.1.200')
546 self.assertTrue(output, '172.16.1.100')
547 self.assertTrue(output, '101')
548
549 def test_tunnel_independent(self):
550 self.copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev')
551 self.start_networkd()
552
553 self.assertTrue(self.link_exits('ipiptun99'))
554
555 def test_vxlan(self):
556 self.copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network','11-dummy.netdev')
557 self.start_networkd()
558
559 self.assertTrue(self.link_exits('vxlan99'))
560
561 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
562 print(output)
563 self.assertRegex(output, "999")
564 self.assertRegex(output, '5555')
565 self.assertRegex(output, 'l2miss')
566 self.assertRegex(output, 'l3miss')
567 self.assertRegex(output, 'udpcsum')
568 self.assertRegex(output, 'udp6zerocsumtx')
569 self.assertRegex(output, 'udp6zerocsumrx')
570 self.assertRegex(output, 'remcsumtx')
571 self.assertRegex(output, 'remcsumrx')
572 self.assertRegex(output, 'gbp')
573
574 class NetworkdNetWorkTests(unittest.TestCase, Utilities):
575 links = [
576 'bond199',
577 'dummy98',
578 'test1']
579
580 units = [
581 '11-dummy.netdev',
582 '12-dummy.netdev',
583 '23-active-slave.network',
584 '23-bond199.network',
585 '23-primary-slave.network',
586 '23-test1-bond199.network',
587 '25-address-link-section.network',
588 '25-address-section-miscellaneous.network',
589 '25-address-section.network',
590 '25-bond-active-backup-slave.netdev',
591 '25-fibrule-invert.network',
592 '25-fibrule-port-range.network',
593 '25-ipv6-address-label-section.network',
594 '25-neighbor-section.network',
595 '25-link-section-unmanaged.network',
596 '25-route-gateway.network',
597 '25-route-gateway-on-link.network',
598 '25-route-ipv6-src.network',
599 '25-route-reverse-order.network',
600 '25-route-section.network',
601 '25-route-tcp-window-settings.network',
602 '25-route-type.network',
603 '25-sysctl.network',
604 'configure-without-carrier.network',
605 'routing-policy-rule.network',
606 'test-static.network']
607
608 def setUp(self):
609 self.link_remove(self.links)
610
611 def tearDown(self):
612 self.link_remove(self.links)
613 self.remove_unit_from_networkd_path(self.units)
614
615 def test_static_address(self):
616 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'test-static.network')
617 self.start_networkd()
618
619 self.assertTrue(self.link_exits('dummy98'))
620
621 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
622 print(output)
623 self.assertRegex(output, '192.168.0.15')
624 self.assertRegex(output, '192.168.0.1')
625 self.assertRegex(output, 'routable')
626
627 def test_configure_without_carrier(self):
628 self.copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev')
629 self.start_networkd()
630
631 self.assertTrue(self.link_exits('test1'))
632
633 output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
634 print(output)
635 self.assertRegex(output, '192.168.0.15')
636 self.assertRegex(output, '192.168.0.1')
637 self.assertRegex(output, 'routable')
638
639 def test_bond_active_slave(self):
640 self.copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev')
641 self.start_networkd()
642
643 self.assertTrue(self.link_exits('dummy98'))
644 self.assertTrue(self.link_exits('bond199'))
645
646 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
647 print(output)
648 self.assertRegex(output, 'active_slave dummy98')
649
650 def test_bond_primary_slave(self):
651 self.copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-test1-bond199.network', '25-bond-active-backup-slave.netdev', '11-dummy.netdev')
652 self.start_networkd()
653
654 self.assertTrue(self.link_exits('test1'))
655 self.assertTrue(self.link_exits('bond199'))
656
657 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
658 print(output)
659 self.assertRegex(output, 'primary test1')
660
661 def test_routing_policy_rule(self):
662 self.copy_unit_to_networkd_unit_path('routing-policy-rule.network', '11-dummy.netdev')
663 self.start_networkd()
664
665 self.assertTrue(self.link_exits('test1'))
666
667 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
668 print(output)
669 self.assertRegex(output, '111')
670 self.assertRegex(output, 'from 192.168.100.18')
671 self.assertRegex(output, r'tos (?:0x08|throughput)\s')
672 self.assertRegex(output, 'iif test1')
673 self.assertRegex(output, 'oif test1')
674 self.assertRegex(output, 'lookup 7')
675
676 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
677
678 @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable()
679 def test_routing_policy_rule_port_range(self):
680 self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev')
681 self.start_networkd()
682
683 self.assertTrue(self.link_exits('test1'))
684
685 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
686 print(output)
687 self.assertRegex(output, '111')
688 self.assertRegex(output, 'from 192.168.100.18')
689 self.assertRegex(output, '1123-1150')
690 self.assertRegex(output, '3224-3290')
691 self.assertRegex(output, 'tcp')
692 self.assertRegex(output, 'lookup 7')
693
694 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
695
696 @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable()
697 def test_routing_policy_rule_invert(self):
698 self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev')
699 self.start_networkd()
700
701 self.assertTrue(self.link_exits('test1'))
702
703 output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
704 print(output)
705 self.assertRegex(output, '111')
706 self.assertRegex(output, 'not.*?from.*?192.168.100.18')
707 self.assertRegex(output, 'tcp')
708 self.assertRegex(output, 'lookup 7')
709
710 subprocess.call(['ip', 'rule', 'del', 'table', '7'])
711
712 def test_address_peer(self):
713 self.copy_unit_to_networkd_unit_path('25-address-section.network', '12-dummy.netdev')
714 self.start_networkd()
715
716 self.assertTrue(self.link_exits('dummy98'))
717
718 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
719 print(output)
720 self.assertRegex(output, 'inet 10.2.3.4 peer 10.2.3.5/16 scope global 32')
721 self.assertRegex(output, 'inet 10.6.7.8/16 brd 10.6.255.255 scope global 33')
722 self.assertRegex(output, 'inet6 2001:db8::20 peer 2001:db8::10/128 scope global')
723
724 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
725 print(output)
726 self.assertRegex(output, 'State: routable \(configured\)')
727
728 def test_address_preferred_lifetime_zero_ipv6(self):
729 self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev')
730 self.start_networkd()
731
732 self.assertTrue(self.link_exits('dummy98'))
733
734 output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
735 print(output)
736 self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
737 self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
738
739 def test_ip_route(self):
740 self.copy_unit_to_networkd_unit_path('25-route-section.network', '12-dummy.netdev')
741 self.start_networkd()
742
743 self.assertTrue(self.link_exits('dummy98'))
744
745 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98']).rstrip().decode('utf-8')
746 print(output)
747 self.assertRegex(output, '192.168.0.1')
748 self.assertRegex(output, 'static')
749 self.assertRegex(output, '192.168.0.0/24')
750
751 def test_ip_route_reverse(self):
752 self.copy_unit_to_networkd_unit_path('25-route-reverse-order.network', '12-dummy.netdev')
753 self.start_networkd()
754
755 self.assertTrue(self.link_exits('dummy98'))
756
757 output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
758 print(output)
759 self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff')
760 self.assertRegex(output, '2001:1234:5:8f63::1')
761
762 def test_ip_route_blackhole_unreachable_prohibit(self):
763 self.copy_unit_to_networkd_unit_path('25-route-type.network', '12-dummy.netdev')
764 self.start_networkd()
765
766 self.assertTrue(self.link_exits('dummy98'))
767
768 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
769 print(output)
770 self.assertRegex(output, 'blackhole')
771 self.assertRegex(output, 'unreachable')
772 self.assertRegex(output, 'prohibit')
773
774 subprocess.call(['ip', 'route', 'del', 'blackhole', '202.54.1.2'])
775 subprocess.call(['ip', 'route', 'del', 'unreachable', '202.54.1.3'])
776 subprocess.call(['ip', 'route', 'del', 'prohibit', '202.54.1.4'])
777
778 def test_ip_route_tcp_window(self):
779 self.copy_unit_to_networkd_unit_path('25-route-tcp-window-settings.network', '11-dummy.netdev')
780 self.start_networkd()
781
782 self.assertTrue(self.link_exits('test1'))
783
784 output = subprocess.check_output(['ip', 'route', 'list']).rstrip().decode('utf-8')
785 print(output)
786 self.assertRegex(output, 'initcwnd 20')
787 self.assertRegex(output, 'initrwnd 30')
788
789 def test_ip_route_gateway(self):
790 self.copy_unit_to_networkd_unit_path('25-route-gateway.network', '12-dummy.netdev')
791 self.start_networkd()
792
793 self.assertTrue(self.link_exits('dummy98'))
794
795 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
796 print(output)
797 self.assertRegex(output, 'default')
798 self.assertRegex(output, 'via')
799 self.assertRegex(output, '149.10.124.64')
800 self.assertRegex(output, 'proto')
801 self.assertRegex(output, 'static')
802
803 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
804 print(output)
805 self.assertRegex(output, '149.10.124.48/28')
806 self.assertRegex(output, 'proto')
807 self.assertRegex(output, 'kernel')
808 self.assertRegex(output, 'scope')
809 self.assertRegex(output, 'link')
810
811 def test_ip_route_gateway_on_link(self):
812 self.copy_unit_to_networkd_unit_path('25-route-gateway-on-link.network', '12-dummy.netdev')
813 self.start_networkd()
814
815 self.assertTrue(self.link_exits('dummy98'))
816
817 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
818 print(output)
819 self.assertRegex(output, 'default')
820 self.assertRegex(output, 'via')
821 self.assertRegex(output, '149.10.125.65')
822 self.assertRegex(output, 'proto')
823 self.assertRegex(output, 'static')
824 self.assertRegex(output, 'onlink')
825
826 output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'dummy98', 'src', '149.10.124.58']).rstrip().decode('utf-8')
827 print(output)
828 self.assertRegex(output, '149.10.124.48/28')
829 self.assertRegex(output, 'proto')
830 self.assertRegex(output, 'kernel')
831 self.assertRegex(output, 'scope')
832 self.assertRegex(output, 'link')
833
834 def test_ip_route_ipv6_src_route(self):
835 # a dummy device does not make the addresses go through tentative state, so we
836 # reuse a bond from an earlier test, which does make the addresses go through
837 # tentative state, and do our test on that
838 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')
839 self.start_networkd()
840
841 self.assertTrue(self.link_exits('dummy98'))
842 self.assertTrue(self.link_exits('bond199'))
843
844 output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8')
845 print(output)
846 self.assertRegex(output, 'abcd::/16')
847 self.assertRegex(output, 'src')
848 self.assertRegex(output, '2001:1234:56:8f63::2')
849
850 def test_ip_link_mac_address(self):
851 self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev')
852 self.start_networkd()
853
854 self.assertTrue(self.link_exits('dummy98'))
855
856 output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
857 print(output)
858 self.assertRegex(output, '00:01:02:aa:bb:cc')
859
860 def test_ip_link_unmanaged(self):
861 self.copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev')
862 self.start_networkd()
863
864 self.assertTrue(self.link_exits('dummy98'))
865
866 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
867 print(output)
868 self.assertRegex(output, 'unmanaged')
869
870 def test_ipv6_address_label(self):
871 self.copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev')
872 self.start_networkd()
873
874 self.assertTrue(self.link_exits('dummy98'))
875
876 output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
877 print(output)
878 self.assertRegex(output, '2004:da8:1::/64')
879
880 def test_ipv6_neighbor(self):
881 self.copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev')
882 self.start_networkd()
883
884 self.assertTrue(self.link_exits('dummy98'))
885
886 output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
887 print(output)
888 self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
889 self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
890
891 def test_sysctl(self):
892 self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev')
893 self.start_networkd()
894
895 self.assertTrue(self.link_exits('dummy98'))
896
897 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1')
898 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2')
899 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3')
900 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5')
901 self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1')
902 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
903 self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
904
905 class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
906 links = [
907 'bridge99',
908 'dummy98',
909 'test1']
910
911 units = [
912 '11-dummy.netdev',
913 '12-dummy.netdev',
914 '26-bridge.netdev',
915 '26-bridge-slave-interface-1.network',
916 '26-bridge-slave-interface-2.network',
917 'bridge99.network']
918
919 def setUp(self):
920 self.link_remove(self.links)
921
922 def tearDown(self):
923 self.link_remove(self.links)
924 self.remove_unit_from_networkd_path(self.units)
925
926 def test_bridge_property(self):
927 self.copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev',
928 '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network',
929 'bridge99.network')
930 self.start_networkd()
931
932 self.assertTrue(self.link_exits('dummy98'))
933 self.assertTrue(self.link_exits('test1'))
934 self.assertTrue(self.link_exits('bridge99'))
935
936 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
937 print(output)
938 self.assertRegex(output, 'master')
939 self.assertRegex(output, 'bridge')
940
941 output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
942 print(output)
943 self.assertRegex(output, 'master')
944 self.assertRegex(output, 'bridge')
945
946 output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
947 print(output)
948 self.assertRegex(output, '192.168.0.15')
949 self.assertRegex(output, '192.168.0.1')
950
951 output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
952 print(output)
953 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
954 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
955 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1')
956 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1')
957
958 # CONFIG_BRIDGE_IGMP_SNOOPING=y
959 if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
960 self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
961
962 class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
963 links = ['veth99']
964
965 units = [
966 '23-emit-lldp.network',
967 '24-lldp.network',
968 '25-veth.netdev']
969
970 def setUp(self):
971 self.link_remove(self.links)
972
973 def tearDown(self):
974 self.link_remove(self.links)
975 self.remove_unit_from_networkd_path(self.units)
976
977 def test_lldp(self):
978 self.copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev')
979 self.start_networkd()
980
981 self.assertTrue(self.link_exits('veth99'))
982
983 output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
984 print(output)
985 self.assertRegex(output, 'veth-peer')
986 self.assertRegex(output, 'veth99')
987
988 class NetworkdNetworkRATests(unittest.TestCase, Utilities):
989 links = ['veth99']
990
991 units = [
992 '25-veth.netdev',
993 'ipv6-prefix.network',
994 'ipv6-prefix-veth.network']
995
996 def setUp(self):
997 self.link_remove(self.links)
998
999 def tearDown(self):
1000 self.link_remove(self.links)
1001 self.remove_unit_from_networkd_path(self.units)
1002
1003 def test_ipv6_prefix_delegation(self):
1004 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network')
1005 self.start_networkd()
1006
1007 self.assertTrue(self.link_exits('veth99'))
1008
1009 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1010 print(output)
1011 self.assertRegex(output, '2002:da8:1:0')
1012
1013 class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
1014 links = [
1015 'dummy98',
1016 'veth99']
1017
1018 units = [
1019 '12-dummy.netdev',
1020 '24-search-domain.network',
1021 '25-veth.netdev',
1022 'dhcp-client.network',
1023 'dhcp-client-timezone-router.network',
1024 'dhcp-server.network',
1025 'dhcp-server-timezone-router.network']
1026
1027 def setUp(self):
1028 self.link_remove(self.links)
1029
1030 def tearDown(self):
1031 self.link_remove(self.links)
1032 self.remove_unit_from_networkd_path(self.units)
1033
1034 def test_dhcp_server(self):
1035 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network')
1036 self.start_networkd()
1037
1038 self.assertTrue(self.link_exits('veth99'))
1039
1040 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1041 print(output)
1042 self.assertRegex(output, '192.168.5.*')
1043 self.assertRegex(output, 'Gateway: 192.168.5.1')
1044 self.assertRegex(output, 'DNS: 192.168.5.1')
1045 self.assertRegex(output, 'NTP: 192.168.5.1')
1046
1047 def test_domain(self):
1048 self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network')
1049 self.start_networkd()
1050
1051 self.assertTrue(self.link_exits('dummy98'))
1052
1053 output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
1054 print(output)
1055 self.assertRegex(output, 'Address: 192.168.42.100')
1056 self.assertRegex(output, 'DNS: 192.168.42.1')
1057 self.assertRegex(output, 'Search Domains: one')
1058
1059 def test_emit_router_timezone(self):
1060 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network')
1061 self.start_networkd()
1062
1063 self.assertTrue(self.link_exits('veth99'))
1064
1065 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1066 print(output)
1067 self.assertRegex(output, 'Gateway: 192.168.5.*')
1068 self.assertRegex(output, '192.168.5.*')
1069 self.assertRegex(output, 'Europe/Berlin')
1070
1071 class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
1072 links = [
1073 'dummy98',
1074 'veth99']
1075
1076 units = [
1077 '25-veth.netdev',
1078 'dhcp-client-anonymize.network',
1079 'dhcp-client-critical-connection.network',
1080 'dhcp-client-ipv4-dhcp-settings.network',
1081 'dhcp-client-ipv4-only-ipv6-disabled.network',
1082 'dhcp-client-ipv4-only.network',
1083 'dhcp-client-ipv6-only.network',
1084 'dhcp-client-ipv6-rapid-commit.network',
1085 'dhcp-client-listen-port.network',
1086 'dhcp-client-route-metric.network',
1087 'dhcp-client-route-table.network',
1088 'dhcp-client.network',
1089 'dhcp-server-veth-peer.network',
1090 'dhcp-v4-server-veth-peer.network',
1091 'static.network']
1092
1093 def setUp(self):
1094 self.link_remove(self.links)
1095 self.stop_dnsmasq(dnsmasq_pid_file)
1096
1097 def tearDown(self):
1098 self.link_remove(self.links)
1099 self.remove_unit_from_networkd_path(self.units)
1100 self.stop_dnsmasq(dnsmasq_pid_file)
1101 self.remove_lease_file()
1102 self.remove_log_file()
1103
1104 def test_dhcp_client_ipv6_only(self):
1105 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1106 self.start_networkd()
1107
1108 self.assertTrue(self.link_exits('veth99'))
1109
1110 self.start_dnsmasq()
1111
1112 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1113 print(output)
1114 self.assertRegex(output, '2600::')
1115 self.assertNotRegex(output, '192.168.5')
1116
1117 def test_dhcp_client_ipv4_only(self):
1118 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
1119 self.start_networkd()
1120
1121 self.assertTrue(self.link_exits('veth99'))
1122
1123 self.start_dnsmasq()
1124
1125 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1126 print(output)
1127 self.assertNotRegex(output, '2600::')
1128 self.assertRegex(output, '192.168.5')
1129
1130 def test_dhcp_client_ipv4_ipv6(self):
1131 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network',
1132 'dhcp-client-ipv4-only.network')
1133 self.start_networkd()
1134
1135 self.assertTrue(self.link_exits('veth99'))
1136
1137 self.start_dnsmasq()
1138
1139 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1140 print(output)
1141 self.assertRegex(output, '2600::')
1142 self.assertRegex(output, '192.168.5')
1143
1144 def test_dhcp_client_settings(self):
1145 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network')
1146 self.start_networkd()
1147
1148 self.assertTrue(self.link_exits('veth99'))
1149
1150 self.start_dnsmasq()
1151
1152 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1153 print(output)
1154 self.assertRegex(output, '12:34:56:78:9a:bc')
1155 self.assertRegex(output, '192.168.5')
1156 self.assertRegex(output, '1492')
1157
1158 output = subprocess.check_output(['ip', 'route']).rstrip().decode('utf-8')
1159 print(output)
1160 self.assertRegex(output, 'default.*dev veth99 proto dhcp')
1161
1162 self.assertTrue(self.search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True))
1163 self.assertTrue(self.search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc'))
1164 self.assertTrue(self.search_words_in_dnsmasq_log('client provides name: test-hostname'))
1165 self.assertTrue(self.search_words_in_dnsmasq_log('26:mtu'))
1166
1167 def test_dhcp6_client_settings_rapidcommit_true(self):
1168 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
1169 self.start_networkd()
1170
1171 self.assertTrue(self.link_exits('veth99'))
1172
1173 self.start_dnsmasq()
1174
1175 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1176 print(output)
1177 self.assertRegex(output, '12:34:56:78:9a:bc')
1178 self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1179
1180 def test_dhcp6_client_settings_rapidcommit_false(self):
1181 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network')
1182 self.start_networkd()
1183
1184 self.assertTrue(self.link_exits('veth99'))
1185
1186 self.start_dnsmasq()
1187
1188 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1189 print(output)
1190 self.assertRegex(output, '12:34:56:78:9a:bc')
1191 self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
1192
1193 def test_dhcp_client_settings_anonymize(self):
1194 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network')
1195 self.start_networkd()
1196
1197 self.assertTrue(self.link_exits('veth99'))
1198
1199 self.start_dnsmasq()
1200
1201 self.assertFalse(self.search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True))
1202 self.assertFalse(self.search_words_in_dnsmasq_log('test-hostname'))
1203 self.assertFalse(self.search_words_in_dnsmasq_log('26:mtu'))
1204
1205 def test_dhcp_client_listen_port(self):
1206 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network')
1207
1208 dh_server = DHCPServer("dhcp_server")
1209 dh_server.start()
1210
1211 self.start_networkd()
1212
1213 self.assertTrue(self.link_exits('veth99'))
1214
1215 global port
1216 global ip
1217
1218 self.assertRegex(str(port), '5555')
1219 self.assertRegex(str(ip), '0.0.0.0')
1220
1221 dh_server.join()
1222
1223 def test_dhcp_route_table_id(self):
1224 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network')
1225 self.start_networkd()
1226
1227 self.assertTrue(self.link_exits('veth99'))
1228
1229 self.start_dnsmasq()
1230
1231 output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
1232 print(output)
1233 self.assertRegex(output, 'veth99 proto dhcp')
1234 self.assertRegex(output, '192.168.5.1')
1235
1236 def test_dhcp_route_metric(self):
1237 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network')
1238 self.start_networkd()
1239
1240 self.assertTrue(self.link_exits('veth99'))
1241
1242 self.start_dnsmasq()
1243
1244 output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
1245 print(output)
1246 self.assertRegex(output, 'metric 24')
1247
1248 def test_dhcp_route_criticalconnection_true(self):
1249 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-critical-connection.network')
1250 self.start_networkd()
1251
1252 self.assertTrue(self.link_exits('veth99'))
1253
1254 self.start_dnsmasq()
1255
1256 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1257 print(output)
1258 self.assertRegex(output, '192.168.5.*')
1259
1260 # Stoping dnsmasq as networkd won't be allowed to renew the DHCP lease.
1261 self.stop_dnsmasq(dnsmasq_pid_file)
1262
1263 # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
1264 time.sleep(125)
1265
1266 output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
1267 print(output)
1268 self.assertRegex(output, '192.168.5.*')
1269
1270 def test_dhcp_client_reuse_address_as_static(self):
1271 self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network')
1272 self.start_networkd()
1273
1274 self.assertTrue(self.link_exits('veth99'))
1275
1276 self.start_dnsmasq()
1277
1278 output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1279 print(output)
1280 self.assertRegex(output, '192.168.5')
1281 self.assertRegex(output, '2600::')
1282
1283 ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output)
1284 ipv6_address = re.search('2600::[0-9a-f:]*/128', output)
1285 static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()])
1286 print(static_network)
1287
1288 self.remove_unit_from_networkd_path(['dhcp-client.network'])
1289
1290 with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f:
1291 f.write(static_network)
1292
1293 self.start_networkd()
1294
1295 self.assertTrue(self.link_exits('veth99'))
1296
1297 output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1298 print(output)
1299 self.assertRegex(output, '192.168.5')
1300 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1301
1302 output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
1303 print(output)
1304 self.assertRegex(output, '2600::')
1305 self.assertRegex(output, 'valid_lft forever preferred_lft forever')
1306
1307 if __name__ == '__main__':
1308 unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout,
1309 verbosity=3))