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