mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
test: move network_tests from examples/ to tools/test_apps
This commit is contained in:
6
tools/test_apps/protocols/network_tests/CMakeLists.txt
Normal file
6
tools/test_apps/protocols/network_tests/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(net_suite)
|
68
tools/test_apps/protocols/network_tests/README.md
Normal file
68
tools/test_apps/protocols/network_tests/README.md
Normal file
@@ -0,0 +1,68 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
# Intel net test suite for LwIP network stack
|
||||
|
||||
This project provides a test interface to esp32 network stack in order to execute standard set of
|
||||
Intel network test suite defined in TTCN3 framework.
|
||||
|
||||
## Important notice
|
||||
*This is an internal ESP-IDF test and not a user project example*
|
||||
|
||||
## Execute net test suite
|
||||
|
||||
These network tests could be executed in both manual or automated mode in CI.
|
||||
|
||||
Note: TTCN3 engine works reliably only on Linux and Windows.
|
||||
|
||||
## Setup TTCN3
|
||||
|
||||
* Clone a repository https://github.com/intel/net-test-suites.git and install titan core as described in the README.md
|
||||
* Copy files `esp32_netsuite.cfg` and `esp32_netsuite.ttcn` (located in `$IDF_PATH/components/lwip/weekend_test`) to `src` subdir of the cloned repository `net-test-suites`
|
||||
* Rebuild the netsuite tests (according to README.md in net-test-suite) by executing `source make.sh` in `src` subdir
|
||||
|
||||
|
||||
## Build application
|
||||
|
||||
```
|
||||
cd $IDF_PATH/examples/system/network_tests
|
||||
idf.py build
|
||||
idf.py -p PORT flash
|
||||
```
|
||||
|
||||
## Run test
|
||||
Open two terminals (1) and (2)
|
||||
1) Start the test server which would pass packets from TTCN3 test suite into ESP32 board in `$IDF_PATH/components/lwip/weekend_test`
|
||||
```
|
||||
python net_suite_test.py
|
||||
```
|
||||
|
||||
2) Start test suite in TTCN3 environment in `src` subdir of the cloned repository `net-test-suites.git`
|
||||
```
|
||||
ttcn3_start test_suite esp32_netsuite.cfg
|
||||
```
|
||||
|
||||
## Internal connection
|
||||
|
||||
Purpose of this test is to execute standard network suite on a ESP32 network stack.
|
||||
|
||||
DUT, Device (Network stack in this case) under test, runs normally on target, but a specific interface with configured esp-netif for passing arbitrary data to
|
||||
and from the network stack. Embedded code `net_suite.c` implements an application which serves stdin/stdout and propagates the data to/from this test interface.
|
||||
|
||||
Standard Intel net suite executed by TTCN3 engine uses udp ports for input/ouput of network packets. Python script `net_suite.py` translates this communication
|
||||
from/to those udp ports to stdin/stdout, where after propagating over USB/UART to the ESP32 board are processed in the network stack (on the target).
|
||||
|
||||
Actual test execution, progress, evaluation and test reporting is done using standard net-test-suite scripts running on PC.
|
||||
|
||||
```
|
||||
PC
|
||||
+---------------------------------------------------------+ ESP32 board
|
||||
| | +----------------------------------------+
|
||||
| TTCN3 engine | | +----------------------------------+ |
|
||||
| | | | net_suite.c | |
|
||||
| +-----------------+ +--------------+ | | | +------------------------+ |
|
||||
| | net-test-suite |--7777/udp--| net_suite.py |--stdout---------| -----> | esp_netif / lwip | |
|
||||
| | |--7771/udp--| |--stdin----------| <----- | | |
|
||||
| +-----------------+ +--------------+ | | +---------+------------------------+ |
|
||||
+---------------------------------------------------------+ +----------------------------------------+
|
||||
```
|
@@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "net_suite.c" "stdinout.c"
|
||||
INCLUDE_DIRS ".")
|
140
tools/test_apps/protocols/network_tests/main/net_suite.c
Normal file
140
tools/test_apps/protocols/network_tests/main/net_suite.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
/* Net-suite test code
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_log.h"
|
||||
#include "stdinout.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/debug.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
/* these test data are used to populate the ARP cache so the IPs are known */
|
||||
static char arp1[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x01,
|
||||
0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x01
|
||||
};
|
||||
|
||||
/* Test data (ICMP packet) for verification of tcp ip test netif
|
||||
00-00-00-00-00-01-00-00-00-00-00-02-08-00-45-00-00-1c-00-00-00-00-ff-01-a7-de-0a-00-00-02-0a-00-00-01-08-00-f7-fd-00-01-00-01
|
||||
*/
|
||||
|
||||
/* creating test pcb */
|
||||
static struct tcp_pcb *test_pcb;
|
||||
|
||||
err_t test_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
|
||||
{
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void test_error(void *arg, err_t err)
|
||||
{
|
||||
printf("Error CB from pcb %d\n", err);
|
||||
}
|
||||
|
||||
err_t test_poll(void *arg, struct tcp_pcb *tpcb)
|
||||
{
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t test_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_UNUSED_ARG(err);
|
||||
|
||||
tcp_setprio(newpcb, TCP_PRIO_MIN);
|
||||
tcp_arg(newpcb, NULL);
|
||||
tcp_recv(newpcb, test_recv);
|
||||
tcp_err(newpcb, test_error);
|
||||
tcp_poll(newpcb, test_poll, 0);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void test_tcp_init(void)
|
||||
{
|
||||
test_pcb = tcp_new();
|
||||
if (test_pcb != NULL) {
|
||||
err_t err;
|
||||
/* Binding this test_pcb to 4242 to accept connections on this port
|
||||
* - this has to be configured as DUT endpoint
|
||||
* - all network traffic from and to network stack is tracked in nettestif
|
||||
*/
|
||||
err = tcp_bind(test_pcb, IP_ADDR_ANY, 4242);
|
||||
if (err == ERR_OK) {
|
||||
test_pcb = tcp_listen(test_pcb);
|
||||
tcp_accept(test_pcb, test_accept);
|
||||
} else {
|
||||
printf("cannot bind test_pcb\n");
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
printf("cannot create test_pcb\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
char packet[128];
|
||||
|
||||
// Netif configs
|
||||
//
|
||||
esp_netif_ip_info_t ip_info;
|
||||
uint8_t mac[] = { 0,0,0,0,0,1};
|
||||
esp_netif_inherent_config_t netif_common_config = {
|
||||
.flags = ESP_NETIF_FLAG_AUTOUP,
|
||||
.ip_info = (esp_netif_ip_info_t*)&ip_info,
|
||||
.if_key = "TEST",
|
||||
.if_desc = "net_test_if"
|
||||
};
|
||||
esp_netif_set_ip4_addr(&ip_info.ip, 10, 0 , 0, 1);
|
||||
esp_netif_set_ip4_addr(&ip_info.gw, 10, 0 , 0, 1);
|
||||
esp_netif_set_ip4_addr(&ip_info.netmask, 255, 255 , 255, 0);
|
||||
|
||||
esp_netif_config_t config = {
|
||||
.base = &netif_common_config, // use specific behaviour configuration
|
||||
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA, // use default WIFI-like network stack configuration
|
||||
};
|
||||
|
||||
// Netif creation and configuration
|
||||
//
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
esp_netif_t* netif = esp_netif_new(&config);
|
||||
assert(netif);
|
||||
esp_netif_attach(netif, netsuite_io_new());
|
||||
|
||||
// Start the netif in a manual way, no need for events
|
||||
//
|
||||
esp_netif_set_mac(netif, mac);
|
||||
esp_netif_action_start(netif, NULL, 0, NULL);
|
||||
|
||||
// initializes TCP endpoint on DUT per https://github.com/intel/net-test-suites#21-endpoints
|
||||
test_tcp_init();
|
||||
// Inject ARP packet to let the network stack know about IP/MAC of the counterpart
|
||||
esp_netif_receive(netif, arp1, sizeof(arp1), NULL);
|
||||
|
||||
/* Now read from stdin and pass the data to test netif */
|
||||
while (1) {
|
||||
/* read one packet from the I/O object */
|
||||
ssize_t len = netsuite_io_get_packet(packet, sizeof(packet));
|
||||
if (len > 0) {
|
||||
/* input the packet to esp-netif */
|
||||
esp_netif_receive(netif, packet, len, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
181
tools/test_apps/protocols/network_tests/main/stdinout.c
Normal file
181
tools/test_apps/protocols/network_tests/main/stdinout.c
Normal file
@@ -0,0 +1,181 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "esp_netif.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
#include "linenoise/linenoise.h"
|
||||
|
||||
//
|
||||
// Internal functions declaration referenced in io object
|
||||
//
|
||||
static esp_err_t netsuite_io_transmit(void *h, void *buffer, size_t len);
|
||||
static esp_err_t netsuite_io_transmit_wrap(void *h, void *buffer, size_t len, void *netstack_buf);
|
||||
static esp_err_t netsuite_io_attach(esp_netif_t * esp_netif, void * args);
|
||||
|
||||
/**
|
||||
* @brief IO object netif related configuration with data-path function callbacks
|
||||
* and pointer to the IO object instance (unused as this is a singleton)
|
||||
*/
|
||||
const esp_netif_driver_ifconfig_t c_driver_ifconfig = {
|
||||
.driver_free_rx_buffer = NULL,
|
||||
.transmit = netsuite_io_transmit,
|
||||
.transmit_wrap = netsuite_io_transmit_wrap,
|
||||
.handle = "netsuite-io-object" // this IO object is a singleton, its handle uses as a name
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief IO object base structure used to point to internal attach function
|
||||
*/
|
||||
const esp_netif_driver_base_t s_driver_base = {
|
||||
.post_attach = netsuite_io_attach
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Transmit function called from esp_netif to output network stack data
|
||||
*
|
||||
* Note: This API has to conform to esp-netif transmit prototype
|
||||
*
|
||||
* @param h Opaque pointer representing the io driver (unused, const string in this case)
|
||||
* @param data data buffer
|
||||
* @param length length of data to send
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
static esp_err_t netsuite_io_transmit(void *h, void *buffer, size_t len)
|
||||
{
|
||||
/* output the packet to stdout */
|
||||
char *data = buffer;
|
||||
printf("\nPacketOut:[");
|
||||
for (size_t i=0; i<len; i++) {
|
||||
printf("%02x", *data++);
|
||||
}
|
||||
printf("]\n");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit wrapper that is typically used for buffer handling and optimization.
|
||||
* Here just wraps the netsuite_io_transmit().
|
||||
*
|
||||
* @note The netstack_buf could be a ref-counted network stack buffer and might be used
|
||||
* by the lower layers directly if an additional handling is practical.
|
||||
* See docs on `esp_wifi_internal_tx_by_ref()` in components/esp_wifi/include/esp_private/wifi.h
|
||||
*/
|
||||
static esp_err_t netsuite_io_transmit_wrap(void *h, void *buffer, size_t len, void *netstack_buf)
|
||||
{
|
||||
return netsuite_io_transmit(h, buffer, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Post attach adapter for netsuite i/o
|
||||
*
|
||||
* Used to exchange internal callbacks and context between esp-netif and the I/O object.
|
||||
* In case of netsuite I/O, it only updates the driver config with internal callbacks and
|
||||
* its instance pointer (const string in this case)
|
||||
*
|
||||
* @param esp_netif handle to esp-netif object
|
||||
* @param args pointer to netsuite IO
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
static esp_err_t netsuite_io_attach(esp_netif_t * esp_netif, void * args)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &c_driver_ifconfig));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process line read from serial input, character by character
|
||||
*
|
||||
* Converts from hex string to byte stream, so it can be processed
|
||||
* in test network interface
|
||||
*
|
||||
* @param line
|
||||
* @param packet
|
||||
*
|
||||
* @return size of packet
|
||||
*/
|
||||
static size_t process_line(char* line, char* packet)
|
||||
{
|
||||
size_t count = 0;
|
||||
size_t i;
|
||||
|
||||
for (i=0; i< strlen(line); i++) {
|
||||
char c = line[i];
|
||||
// accept both separators between bytes
|
||||
if (c == '-' || c == ' ') {
|
||||
++count;
|
||||
// Processing numeric characters
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
packet[count] *= 16;
|
||||
packet[count] += c - '0';
|
||||
// Processing alpha-numeric hex characters
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
packet[count] *= 16;
|
||||
packet[count] += c - 'a' + 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (i>0 && strlen(line)>0) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Created (initializes) the i/o object and returns handle ready to be attached to the esp-netif
|
||||
*/
|
||||
void * netsuite_io_new(void)
|
||||
{
|
||||
// Initialize VFS & UART so we can use std::cout/cin
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
/* Install UART driver for interrupt-driven reads and writes */
|
||||
ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM,
|
||||
256, 0, 0, NULL, 0) );
|
||||
/* Tell VFS to use UART driver */
|
||||
esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
esp_vfs_dev_uart_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' */
|
||||
esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF);
|
||||
linenoiseSetDumbMode(1);
|
||||
return (void *)&s_driver_base;
|
||||
}
|
||||
|
||||
/**
|
||||
* I/O receive function
|
||||
*/
|
||||
ssize_t netsuite_io_get_packet(char *packet, size_t max_len)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
/* read packet from stdin */
|
||||
char* line = linenoise("");
|
||||
if (!line) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* convert to binary */
|
||||
size = process_line(line, packet);
|
||||
|
||||
if (size > max_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
linenoiseFree(line);
|
||||
|
||||
return size;
|
||||
}
|
36
tools/test_apps/protocols/network_tests/main/stdinout.h
Normal file
36
tools/test_apps/protocols/network_tests/main/stdinout.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _NET_SUITE_STDINOUT_H
|
||||
#define _NET_SUITE_STDINOUT_H
|
||||
|
||||
/**
|
||||
* @brief Gets one packet from stdin
|
||||
*
|
||||
* @param packet ptr to the packet buffer
|
||||
* @param max_len maximum size of allocated data buffer
|
||||
*
|
||||
* @return actual size of received packet (-1 in case of error)
|
||||
*/
|
||||
|
||||
ssize_t netsuite_io_get_packet(char *packet, size_t max_len);
|
||||
|
||||
/**
|
||||
* @brief Initializes the I/O object handle to be attached to esp-netif instance
|
||||
*
|
||||
* @return I/O object pointer
|
||||
*/
|
||||
void * netsuite_io_new(void);
|
||||
|
||||
#endif //_NET_SUITE_STDINOUT_H
|
Reference in New Issue
Block a user