4ff3dafd6293e11b91caa15dc047eae3f4e8a074
[pandora-u-boot.git] / test / py / tests / test_net.py
1 # SPDX-License-Identifier: GPL-2.0
2 # Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3
4 # Test various network-related functionality, such as the dhcp, ping, and
5 # tftpboot commands.
6
7 import pytest
8 import u_boot_utils
9 import uuid
10 import datetime
11
12 """
13 Note: This test relies on boardenv_* containing configuration values to define
14 which network environment is available for testing. Without this, this test
15 will be automatically skipped.
16
17 For example:
18
19 # Boolean indicating whether the Ethernet device is attached to USB, and hence
20 # USB enumeration needs to be performed prior to network tests.
21 # This variable may be omitted if its value is False.
22 env__net_uses_usb = False
23
24 # Boolean indicating whether the Ethernet device is attached to PCI, and hence
25 # PCI enumeration needs to be performed prior to network tests.
26 # This variable may be omitted if its value is False.
27 env__net_uses_pci = True
28
29 # True if a DHCP server is attached to the network, and should be tested.
30 # If DHCP testing is not possible or desired, this variable may be omitted or
31 # set to False.
32 env__net_dhcp_server = True
33
34 # True if a DHCPv6 server is attached to the network, and should be tested.
35 # If DHCPv6 testing is not possible or desired, this variable may be omitted or
36 # set to False.
37 env__net_dhcp6_server = True
38
39 # A list of environment variables that should be set in order to configure a
40 # static IP. If solely relying on DHCP, this variable may be omitted or set to
41 # an empty list.
42 env__net_static_env_vars = [
43     ('ipaddr', '10.0.0.100'),
44     ('netmask', '255.255.255.0'),
45     ('serverip', '10.0.0.1'),
46 ]
47
48 # Details regarding a file that may be read from a TFTP server. This variable
49 # may be omitted or set to None if TFTP testing is not possible or desired.
50 env__net_tftp_readable_file = {
51     'fn': 'ubtest-readable.bin',
52     'addr': 0x10000000,
53     'size': 5058624,
54     'crc32': 'c2244b26',
55     'timeout': 50000,
56     'fnu': 'ubtest-upload.bin',
57 }
58
59 # Details regarding a file that may be read from a NFS server. This variable
60 # may be omitted or set to None if NFS testing is not possible or desired.
61 env__net_nfs_readable_file = {
62     'fn': 'ubtest-readable.bin',
63     'addr': 0x10000000,
64     'size': 5058624,
65     'crc32': 'c2244b26',
66 }
67
68 # Details regarding a file that may be read from a TFTP server. This variable
69 # may be omitted or set to None if PXE testing is not possible or desired.
70 env__net_pxe_readable_file = {
71     'fn': 'default',
72     'addr': 0x2000000,
73     'size': 74,
74     'timeout': 50000,
75     'pattern': 'Linux',
76 }
77
78 # True if a router advertisement service is connected to the network, and should
79 # be tested. If router advertisement testing is not possible or desired, this
80 variable may be omitted or set to False.
81 env__router_on_net = True
82 """
83
84 net_set_up = False
85 net6_set_up = False
86
87 def test_net_pre_commands(u_boot_console):
88     """Execute any commands required to enable network hardware.
89
90     These commands are provided by the boardenv_* file; see the comment at the
91     beginning of this file.
92     """
93
94     init_usb = u_boot_console.config.env.get('env__net_uses_usb', False)
95     if init_usb:
96         u_boot_console.run_command('usb start')
97
98     init_pci = u_boot_console.config.env.get('env__net_uses_pci', False)
99     if init_pci:
100         u_boot_console.run_command('pci enum')
101
102     u_boot_console.run_command('net list')
103
104 @pytest.mark.buildconfigspec('cmd_dhcp')
105 def test_net_dhcp(u_boot_console):
106     """Test the dhcp command.
107
108     The boardenv_* file may be used to enable/disable this test; see the
109     comment at the beginning of this file.
110     """
111
112     test_dhcp = u_boot_console.config.env.get('env__net_dhcp_server', False)
113     if not test_dhcp:
114         pytest.skip('No DHCP server available')
115
116     u_boot_console.run_command('setenv autoload no')
117     output = u_boot_console.run_command('dhcp')
118     assert 'DHCP client bound to address ' in output
119
120     global net_set_up
121     net_set_up = True
122
123 @pytest.mark.buildconfigspec('cmd_dhcp6')
124 def test_net_dhcp6(u_boot_console):
125     """Test the dhcp6 command.
126
127     The boardenv_* file may be used to enable/disable this test; see the
128     comment at the beginning of this file.
129     """
130
131     test_dhcp6 = u_boot_console.config.env.get('env__net_dhcp6_server', False)
132     if not test_dhcp6:
133         pytest.skip('No DHCP6 server available')
134
135     u_boot_console.run_command('setenv autoload no')
136     output = u_boot_console.run_command('dhcp6')
137     assert 'DHCP6 client bound to ' in output
138
139     global net6_set_up
140     net6_set_up = True
141
142 @pytest.mark.buildconfigspec('net')
143 def test_net_setup_static(u_boot_console):
144     """Set up a static IP configuration.
145
146     The configuration is provided by the boardenv_* file; see the comment at
147     the beginning of this file.
148     """
149
150     env_vars = u_boot_console.config.env.get('env__net_static_env_vars', None)
151     if not env_vars:
152         pytest.skip('No static network configuration is defined')
153
154     for (var, val) in env_vars:
155         u_boot_console.run_command('setenv %s %s' % (var, val))
156
157     global net_set_up
158     net_set_up = True
159
160 @pytest.mark.buildconfigspec('cmd_ping')
161 def test_net_ping(u_boot_console):
162     """Test the ping command.
163
164     The $serverip (as set up by either test_net_dhcp or test_net_setup_static)
165     is pinged. The test validates that the host is alive, as reported by the
166     ping command's output.
167     """
168
169     if not net_set_up:
170         pytest.skip('Network not initialized')
171
172     output = u_boot_console.run_command('ping $serverip')
173     assert 'is alive' in output
174
175 @pytest.mark.buildconfigspec('IPV6_ROUTER_DISCOVERY')
176 def test_net_network_discovery(u_boot_console):
177     """Test the network discovery feature of IPv6.
178
179     An IPv6 network command (ping6 in this case) is run to make U-Boot send a
180     router solicitation packet, receive a router advertisement message, and
181     parse it.
182     A router advertisement service needs to be running for this test to succeed.
183     U-Boot receives the RA, processes it, and if successful, assigns the gateway
184     IP and prefix length.
185     The configuration is provided by the boardenv_* file; see the comment at
186     the beginning of this file.
187     """
188
189     router_on_net = u_boot_console.config.env.get('env__router_on_net', False)
190     if not router_on_net:
191         pytest.skip('No router on network')
192
193     fake_host_ip = 'fe80::215:5dff:fef6:2ec6'
194     output = u_boot_console.run_command('ping6 ' + fake_host_ip)
195     assert 'ROUTER SOLICITATION 1' in output
196     assert 'Set gatewayip6:' in output
197     assert '0000:0000:0000:0000:0000:0000:0000:0000' not in output
198
199 @pytest.mark.buildconfigspec('cmd_net')
200 def test_net_tftpboot(u_boot_console):
201     """Test the tftpboot command.
202
203     A file is downloaded from the TFTP server, its size and optionally its
204     CRC32 are validated.
205
206     The details of the file to download are provided by the boardenv_* file;
207     see the comment at the beginning of this file.
208     """
209
210     if not net_set_up:
211         pytest.skip('Network not initialized')
212
213     f = u_boot_console.config.env.get('env__net_tftp_readable_file', None)
214     if not f:
215         pytest.skip('No TFTP readable file to read')
216
217     addr = f.get('addr', None)
218
219     fn = f['fn']
220     if not addr:
221         output = u_boot_console.run_command('tftpboot %s' % (fn))
222     else:
223         output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
224     expected_text = 'Bytes transferred = '
225     sz = f.get('size', None)
226     if sz:
227         expected_text += '%d' % sz
228     assert expected_text in output
229
230     expected_crc = f.get('crc32', None)
231     if not expected_crc:
232         return
233
234     if u_boot_console.config.buildconfig.get('config_cmd_crc32', 'n') != 'y':
235         return
236
237     output = u_boot_console.run_command('crc32 $fileaddr $filesize')
238     assert expected_crc in output
239
240 @pytest.mark.buildconfigspec('cmd_nfs')
241 def test_net_nfs(u_boot_console):
242     """Test the nfs command.
243
244     A file is downloaded from the NFS server, its size and optionally its
245     CRC32 are validated.
246
247     The details of the file to download are provided by the boardenv_* file;
248     see the comment at the beginning of this file.
249     """
250
251     if not net_set_up:
252         pytest.skip('Network not initialized')
253
254     f = u_boot_console.config.env.get('env__net_nfs_readable_file', None)
255     if not f:
256         pytest.skip('No NFS readable file to read')
257
258     addr = f.get('addr', None)
259     if not addr:
260         addr = u_boot_utils.find_ram_base(u_boot_console)
261
262     fn = f['fn']
263     output = u_boot_console.run_command('nfs %x %s' % (addr, fn))
264     expected_text = 'Bytes transferred = '
265     sz = f.get('size', None)
266     if sz:
267         expected_text += '%d' % sz
268     assert expected_text in output
269
270     expected_crc = f.get('crc32', None)
271     if not expected_crc:
272         return
273
274     if u_boot_console.config.buildconfig.get('config_cmd_crc32', 'n') != 'y':
275         return
276
277     output = u_boot_console.run_command('crc32 %x $filesize' % addr)
278     assert expected_crc in output
279
280 @pytest.mark.buildconfigspec("cmd_net")
281 @pytest.mark.buildconfigspec("cmd_pxe")
282 def test_net_pxe_get(u_boot_console):
283     """Test the pxe get command.
284
285     A pxe configuration file is downloaded from the TFTP server and interpreted
286     to boot the images mentioned in pxe configuration file.
287
288     The details of the file to download are provided by the boardenv_* file;
289     see the comment at the beginning of this file.
290     """
291
292     if not net_set_up:
293         pytest.skip("Network not initialized")
294
295     test_net_setup_static(u_boot_console)
296
297     f = u_boot_console.config.env.get("env__net_pxe_readable_file", None)
298     if not f:
299         pytest.skip("No PXE readable file to read")
300
301     addr = f.get("addr", None)
302     timeout = f.get("timeout", u_boot_console.p.timeout)
303
304     pxeuuid = uuid.uuid1()
305     u_boot_console.run_command(f"setenv pxeuuid {pxeuuid}")
306     expected_text_uuid = f"Retrieving file: pxelinux.cfg/{pxeuuid}"
307
308     ethaddr = u_boot_console.run_command("echo $ethaddr")
309     ethaddr = ethaddr.replace(':', '-')
310     expected_text_ethaddr = f"Retrieving file: pxelinux.cfg/01-{ethaddr}"
311
312     ip = u_boot_console.run_command("echo $ipaddr")
313     ip = ip.split('.')
314     ipaddr_file = "".join(['%02x' % int(x) for x in ip]).upper()
315     expected_text_ipaddr = f"Retrieving file: pxelinux.cfg/{ipaddr_file}"
316     expected_text_default = f"Retrieving file: pxelinux.cfg/default"
317
318     with u_boot_console.temporary_timeout(timeout):
319         output = u_boot_console.run_command("pxe get")
320
321     assert "TIMEOUT" not in output
322     assert expected_text_uuid in output
323     assert expected_text_ethaddr in output
324     assert expected_text_ipaddr in output
325
326     i = 1
327     for i in range(0, len(ipaddr_file) - 1):
328         expected_text_ip = f"Retrieving file: pxelinux.cfg/{ipaddr_file[:-i]}"
329         assert expected_text_ip in output
330         i += 1
331
332     assert expected_text_default in output
333     assert "Config file 'default.boot' found" in output
334
335 @pytest.mark.buildconfigspec("cmd_crc32")
336 @pytest.mark.buildconfigspec("cmd_net")
337 @pytest.mark.buildconfigspec("cmd_tftpput")
338 def test_net_tftpput(u_boot_console):
339     """Test the tftpput command.
340
341     A file is downloaded from the TFTP server and then uploaded to the TFTP
342     server, its size and its CRC32 are validated.
343
344     The details of the file to download are provided by the boardenv_* file;
345     see the comment at the beginning of this file.
346     """
347
348     if not net_set_up:
349         pytest.skip("Network not initialized")
350
351     f = u_boot_console.config.env.get("env__net_tftp_readable_file", None)
352     if not f:
353         pytest.skip("No TFTP readable file to read")
354
355     addr = f.get("addr", None)
356     if not addr:
357         addr = u_boot_utils.find_ram_base(u_boot_console)
358
359     sz = f.get("size", None)
360     timeout = f.get("timeout", u_boot_console.p.timeout)
361     fn = f["fn"]
362     fnu = f.get("fnu", "_".join([datetime.datetime.now().strftime("%y%m%d%H%M%S"), fn]))
363     expected_text = "Bytes transferred = "
364     if sz:
365         expected_text += "%d" % sz
366
367     with u_boot_console.temporary_timeout(timeout):
368         output = u_boot_console.run_command("tftpboot %x %s" % (addr, fn))
369
370     assert "TIMEOUT" not in output
371     assert expected_text in output
372
373     expected_tftpb_crc = f.get("crc32", None)
374
375     output = u_boot_console.run_command("crc32 $fileaddr $filesize")
376     assert expected_tftpb_crc in output
377
378     with u_boot_console.temporary_timeout(timeout):
379         output = u_boot_console.run_command(
380             "tftpput $fileaddr $filesize $serverip:%s" % (fnu)
381         )
382
383     expected_text = "Bytes transferred = "
384     if sz:
385         expected_text += "%d" % sz
386         addr = addr + sz
387     assert "TIMEOUT" not in output
388     assert "Access violation" not in output
389     assert expected_text in output
390
391     with u_boot_console.temporary_timeout(timeout):
392         output = u_boot_console.run_command("tftpboot %x %s" % (addr, fnu))
393
394     expected_text = "Bytes transferred = "
395     if sz:
396         expected_text += "%d" % sz
397     assert "TIMEOUT" not in output
398     assert expected_text in output
399
400     output = u_boot_console.run_command("crc32 $fileaddr $filesize")
401     assert expected_tftpb_crc in output