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