diff --git a/components/lwip/lwip b/components/lwip/lwip index d2e3d21a85..149b87eba4 160000 --- a/components/lwip/lwip +++ b/components/lwip/lwip @@ -1 +1 @@ -Subproject commit d2e3d21a85bd2e92c9f5e7835eda6fa3ce451831 +Subproject commit 149b87eba4faf2198000e82d0364540aa63f98d7 diff --git a/examples/protocols/icmp_echo/main/echo_example_main.c b/examples/protocols/icmp_echo/main/echo_example_main.c index a300757479..67f68093d2 100644 --- a/examples/protocols/icmp_echo/main/echo_example_main.c +++ b/examples/protocols/icmp_echo/main/echo_example_main.c @@ -62,11 +62,16 @@ static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args) } else { loss = 0; } +#ifdef CONFIG_LWIP_IPV4 if (IP_IS_V4(&target_addr)) { printf("\n--- %s ping statistics ---\n", inet_ntoa(*ip_2_ip4(&target_addr))); - } else { + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (IP_IS_V6(&target_addr)) { printf("\n--- %s ping statistics ---\n", inet6_ntoa(*ip_2_ip6(&target_addr))); } +#endif printf("%" PRIu32 " packets transmitted, %" PRIu32 " received, %" PRIu32 "%% packet loss, time %" PRIu32 "ms\n", transmitted, received, loss, total_time_ms); // delete the ping sessions, so that we clean up all resources and can create a new ping session @@ -81,6 +86,7 @@ static struct { struct arg_int *count; struct arg_int *tos; struct arg_int *ttl; + struct arg_int *interface; struct arg_str *host; struct arg_end *end; } ping_args; @@ -119,6 +125,10 @@ static int do_ping_cmd(int argc, char **argv) config.ttl = (uint32_t)(ping_args.ttl->ival[0]); } + if (ping_args.interface->count > 0) { + config.interface = (uint32_t)(ping_args.interface->ival[0]); + } + // parse IP address struct sockaddr_in6 sock_addr6; ip_addr_t target_addr; @@ -136,13 +146,18 @@ static int do_ping_cmd(int argc, char **argv) printf("ping: unknown host %s\n", ping_args.host->sval[0]); return 1; } +#ifdef CONFIG_LWIP_IPV4 if (res->ai_family == AF_INET) { struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr; inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4); - } else { + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (res->ai_family == AF_INET6) { struct in6_addr addr6 = ((struct sockaddr_in6 *) (res->ai_addr))->sin6_addr; inet6_addr_to_ip6addr(ip_2_ip6(&target_addr), &addr6); } +#endif freeaddrinfo(res); } config.target_addr = target_addr; @@ -169,6 +184,7 @@ static void register_ping(void) ping_args.count = arg_int0("c", "count", "", "Stop after sending count packets"); ping_args.tos = arg_int0("Q", "tos", "", "Set Type of Service related bits in IP datagrams"); ping_args.ttl = arg_int0("T", "ttl", "", "Set Time to Live related bits in IP datagrams"); + ping_args.interface = arg_int0("I", "interface", "", "Set Interface number"); ping_args.host = arg_str1(NULL, NULL, "", "Host address"); ping_args.end = arg_end(1); const esp_console_cmd_t ping_cmd = { @@ -232,6 +248,9 @@ void app_main(void) /* automatic connection per menuconfig */ ESP_ERROR_CHECK(example_connect()); #endif + struct ifreq ifr; + ESP_ERROR_CHECK(esp_netif_get_netif_impl_name(EXAMPLE_INTERFACE, ifr.ifr_name)); + printf("Connected on interface: %s (%d)", ifr.ifr_name, esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE)); /* register command `ping` */ register_ping(); diff --git a/examples/protocols/icmp_echo/pytest_icmp_echo.py b/examples/protocols/icmp_echo/pytest_icmp_echo.py index cd00ff645e..6496613f45 100644 --- a/examples/protocols/icmp_echo/pytest_icmp_echo.py +++ b/examples/protocols/icmp_echo/pytest_icmp_echo.py @@ -1,6 +1,6 @@ -# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - +import logging import os import pytest @@ -55,3 +55,33 @@ def test_protocols_icmp_echo(dut: Dut) -> None: ) def test_protocols_icmp_echo_esp32c2_26mhz(dut: Dut) -> None: _run_test(dut) + + +@pytest.mark.esp32 +@pytest.mark.wifi_router +@pytest.mark.parametrize('config', ['ipv6_only',], indirect=True) +def test_protocols_icmp_echo_ipv6_only(dut: Dut) -> None: + # Parse IP address of STA + logging.info('Waiting to connect with AP') + if dut.app.sdkconfig.get('EXAMPLE_WIFI_SSID_PWD_FROM_STDIN') is True: + dut.expect('Please input ssid password:') + env_name = 'wifi_router' + ap_ssid = get_env_config_variable(env_name, 'ap_ssid') + ap_password = get_env_config_variable(env_name, 'ap_password') + dut.write(f'{ap_ssid} {ap_password}') + # expect all 8 octets from IPv6 (assumes it's printed in the long form) + ipv6_r = r':'.join((r'[0-9a-fA-F]{4}',) * 8) + ipv6 = dut.expect(ipv6_r, timeout=30)[0].decode() + logging.info(f'Connected AP with IPv6={ipv6}') + interface_nr = dut.expect(r'Connected on interface: [a-z]{2}\d \((\d+)\)', timeout=30)[1].decode() + + # ping our own address to simplify things + dut.write('ping -I {} {} -c 5'.format(interface_nr, ipv6)) + + # expect at least two packets (there could be lost packets) + ip = dut.expect(r'64 bytes from ([0-9a-fA-F:]+) icmp_seq=\d ttl=\d+ time=\d+ ms')[1].decode() + dut.expect(fr'64 bytes from {ip} icmp_seq=[2-5] ttl=\d+ time=') + + dut.expect(r'5 packets transmitted, [2-5] received, \d{1,3}% packet loss') + dut.write('') + dut.expect('esp>') diff --git a/examples/protocols/icmp_echo/sdkconfig.ci.ipv6_only b/examples/protocols/icmp_echo/sdkconfig.ci.ipv6_only new file mode 100644 index 0000000000..4d475d3f8d --- /dev/null +++ b/examples/protocols/icmp_echo/sdkconfig.ci.ipv6_only @@ -0,0 +1,6 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y +CONFIG_EXAMPLE_CONNECT_IPV4=n +CONFIG_EXAMPLE_CONNECT_IPV6=y +CONFIG_LWIP_IPV4=n +CONFIG_LWIP_IPV6=y