tests: ethernet: esp32: Functional test for CI

Functional test for Ethernet for CI device testing

Signed-off-by: Raffael Rostagno <raffael.rostagno@espressif.com>
This commit is contained in:
Raffael Rostagno 2024-09-05 14:39:19 -03:00 committed by Anas Nashif
parent 8a7a737a14
commit aaaffd20a6
6 changed files with 217 additions and 0 deletions

View file

@ -0,0 +1,9 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(ethernet_test)
target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View file

@ -0,0 +1,20 @@
# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
# SPDX-License-Identifier: Apache-2.0
mainmenu "Ethernet Test"
source "Kconfig.zephyr"
config DHCP_ASSIGN_TIMEOUT
int "DHCP Assign Timeout (in seconds)"
default 30
help
Timeout duration for receiving IPv4 address from DHCP.
If no address is assigned within this time, test will fail.
config GATEWAY_PING_TIMEOUT
int "Gateway Ping Timeout (in seconds)"
default 10
help
Timeout duration for pinging the network gateway.
If no reply is received within this time, test will fail.

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
&eth {
status = "okay";
};
&phy {
status = "okay";
};
&mdio {
status = "okay";
};

View file

@ -0,0 +1,19 @@
CONFIG_ZTEST=y
CONFIG_NETWORKING=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_IPV6=n
CONFIG_NET_IPV4=y
CONFIG_NET_ARP=y
CONFIG_NET_UDP=y
CONFIG_NET_DHCPV4=y
CONFIG_NET_DHCPV4_OPTION_CALLBACKS=y
CONFIG_DNS_RESOLVER=y
CONFIG_SYS_HEAP_AUTO=y
CONFIG_INIT_STACKS=y
CONFIG_NET_MGMT=y
CONFIG_NET_MGMT_EVENT=y
CONFIG_NET_LOG=y
CONFIG_LOG=y

View file

@ -0,0 +1,146 @@
/*
* Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#include <zephyr/logging/log.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/net_core.h>
#include <zephyr/net/net_context.h>
#include <zephyr/net/net_mgmt.h>
#include <zephyr/net/ethernet.h>
#include <zephyr/net/icmp.h>
LOG_MODULE_REGISTER(ethernet_test, LOG_LEVEL_INF);
#include "net_private.h"
#define DHCP_OPTION_NTP (42)
#define TEST_DATA "ICMP dummy data"
K_SEM_DEFINE(net_event, 0, 1);
static struct net_if *iface;
static uint8_t ntp_server[4];
static struct net_mgmt_event_callback mgmt_cb;
static struct net_dhcpv4_option_callback dhcp_cb;
static void ipv4_event(struct net_mgmt_event_callback *cb, uint32_t mgmt_event,
struct net_if *iface)
{
if ((mgmt_event != NET_EVENT_IPV4_ADDR_ADD) ||
(iface->config.ip.ipv4->unicast[0].ipv4.addr_type != NET_ADDR_DHCP)) {
return;
}
char buf[NET_IPV4_ADDR_LEN];
LOG_INF("Address[%d]: %s", net_if_get_by_iface(iface),
net_addr_ntop(AF_INET, &iface->config.ip.ipv4->unicast[0].ipv4.address.in_addr, buf,
sizeof(buf)));
LOG_INF("Subnet[%d]: %s", net_if_get_by_iface(iface),
net_addr_ntop(AF_INET, &iface->config.ip.ipv4->unicast[0].netmask, buf,
sizeof(buf)));
LOG_INF("Router[%d]: %s", net_if_get_by_iface(iface),
net_addr_ntop(AF_INET, &iface->config.ip.ipv4->gw, buf, sizeof(buf)));
LOG_INF("Lease time[%d]: %u seconds", net_if_get_by_iface(iface),
iface->config.dhcpv4.lease_time);
/* release processing of IPV4 event by test case */
k_sem_give(&net_event);
}
static int icmp_event(struct net_icmp_ctx *ctx, struct net_pkt *pkt, struct net_icmp_ip_hdr *hdr,
struct net_icmp_hdr *icmp_hdr, void *user_data)
{
struct net_ipv4_hdr *ip_hdr = hdr->ipv4;
LOG_INF("Received echo reply from %s", net_sprint_ipv4_addr(&ip_hdr->src));
k_sem_give(&net_event);
return 0;
}
static void option_handler(struct net_dhcpv4_option_callback *cb, size_t length,
enum net_dhcpv4_msg_type msg_type, struct net_if *iface)
{
char buf[NET_IPV4_ADDR_LEN];
LOG_INF("DHCP Option %d: %s", cb->option,
net_addr_ntop(AF_INET, cb->data, buf, sizeof(buf)));
}
ZTEST(ethernet, test_dhcp_check)
{
LOG_INF("Waiting for IPV4 assign event...");
zassert_equal(k_sem_take(&net_event, K_SECONDS(CONFIG_DHCP_ASSIGN_TIMEOUT)), 0,
"IPV4 address assign event timeout");
LOG_INF("DHCP check successful");
}
ZTEST(ethernet, test_icmp_check)
{
struct net_icmp_ping_params params;
struct net_icmp_ctx ctx;
struct in_addr gw_addr_4;
struct sockaddr_in dst4 = {0};
int ret;
gw_addr_4 = net_if_ipv4_get_gw(iface);
zassert_not_equal(gw_addr_4.s_addr, 0, "Gateway address is not set");
ret = net_icmp_init_ctx(&ctx, NET_ICMPV4_ECHO_REPLY, 0, icmp_event);
zassert_equal(ret, 0, "Cannot init ICMP (%d)", ret);
dst4.sin_family = AF_INET;
memcpy(&dst4.sin_addr, &gw_addr_4, sizeof(gw_addr_4));
params.identifier = 1234;
params.sequence = 5678;
params.tc_tos = 1;
params.priority = 2;
params.data = TEST_DATA;
params.data_size = sizeof(TEST_DATA);
LOG_INF("Pinging the gateway...");
ret = net_icmp_send_echo_request(&ctx, iface, (struct sockaddr *)&dst4, &params, NULL);
zassert_equal(ret, 0, "Cannot send ICMP echo request (%d)", ret);
zassert_equal(k_sem_take(&net_event, K_SECONDS(CONFIG_GATEWAY_PING_TIMEOUT)), 0,
"Gateway ping (ICMP) timed out");
net_icmp_cleanup_ctx(&ctx);
}
static void *ethernet_setup(void)
{
iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET));
net_mgmt_init_event_callback(&mgmt_cb, ipv4_event, NET_EVENT_IPV4_ADDR_ADD);
net_mgmt_add_event_callback(&mgmt_cb);
net_dhcpv4_init_option_callback(&dhcp_cb, option_handler, DHCP_OPTION_NTP, ntp_server,
sizeof(ntp_server));
net_dhcpv4_add_option_callback(&dhcp_cb);
/* reset semaphore that tracks IPV4 assign event */
k_sem_reset(&net_event);
LOG_INF("Starting DHCPv4 client on %s: index=%d", net_if_get_device(iface)->name,
net_if_get_by_iface(iface));
net_dhcpv4_start(iface);
return NULL;
}
ZTEST_SUITE(ethernet, NULL, ethernet_setup, NULL, NULL, NULL);

View file

@ -0,0 +1,6 @@
tests:
boards.esp32.ethernet:
platform_allow:
- esp32_ethernet_kit/esp32/procpu
tags:
- ethernet