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