test: move network_tests from examples/ to tools/test_apps

This commit is contained in:
Fu Hanxi
2023-10-12 16:17:22 +02:00
parent fbf8d06477
commit ca63d0f943
6 changed files with 0 additions and 0 deletions

View 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)

View 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----------| <----- | | |
| +-----------------+ +--------------+ | | +---------+------------------------+ |
+---------------------------------------------------------+ +----------------------------------------+
```

View File

@@ -0,0 +1,2 @@
idf_component_register(SRCS "net_suite.c" "stdinout.c"
INCLUDE_DIRS ".")

View 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);
}
}
}

View 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;
}

View 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