diff --git a/components/lwip/apps/ping/ping_sock.c b/components/lwip/apps/ping/ping_sock.c index 28cce40ff7..fc302cfa73 100644 --- a/components/lwip/apps/ping/ping_sock.c +++ b/components/lwip/apps/ping/ping_sock.c @@ -133,7 +133,8 @@ static int esp_ping_receive(esp_ping_t *ep) if (IP_IS_V6_VAL(recv_addr)) { // Currently we process IPv6 struct ip6_hdr *iphdr = (struct ip6_hdr *)buf; struct icmp6_echo_hdr *iecho6 = (struct icmp6_echo_hdr *)(buf + sizeof(struct ip6_hdr)); // IPv6 head length is 40 - if ((iecho6->id == ep->packet_hdr->id) && (iecho6->seqno == ep->packet_hdr->seqno)) { + if ((iecho6->type == ICMP6_TYPE_EREP) // only check the ICMPv6 echo reply types + && (iecho6->id == ep->packet_hdr->id) && (iecho6->seqno == ep->packet_hdr->seqno)) { ip_addr_copy(ep->recv_addr, recv_addr); ep->received++; ep->recv_len = IP6H_PLEN(iphdr) - sizeof(struct icmp6_echo_hdr); //The data portion of ICMPv6 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/common_components/protocol_examples_common/stdin_out.c b/examples/common_components/protocol_examples_common/stdin_out.c index 9f3a5163f3..57c61fb8f8 100644 --- a/examples/common_components/protocol_examples_common/stdin_out.c +++ b/examples/common_components/protocol_examples_common/stdin_out.c @@ -15,8 +15,7 @@ esp_err_t example_configure_stdin_stdout(void) { - static bool configured = false; - if (configured) { + if (uart_is_driver_installed((uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM)) { return ESP_OK; } // Initialize VFS & UART so we can use std::cout/cin @@ -29,6 +28,5 @@ esp_err_t example_configure_stdin_stdout(void) uart_vfs_dev_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR); /* Move the caret to the beginning of the next line on '\n' */ uart_vfs_dev_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF); - configured = true; return ESP_OK; } 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