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