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