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