mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
ci: added standard set of network suite for lwip as a part of weekend test
This commit is contained in:
parent
9dd1b2ffb6
commit
684514b3d6
@ -1079,6 +1079,23 @@ test_weekend_mqtt:
|
|||||||
ENV_FILE: "$CI_PROJECT_DIR/components/mqtt/weekend_test/env.yml"
|
ENV_FILE: "$CI_PROJECT_DIR/components/mqtt/weekend_test/env.yml"
|
||||||
CONFIG_FILE: "$CI_PROJECT_DIR/components/mqtt/weekend_test/config.yml"
|
CONFIG_FILE: "$CI_PROJECT_DIR/components/mqtt/weekend_test/config.yml"
|
||||||
|
|
||||||
|
test_weekend_network:
|
||||||
|
<<: *example_test_template
|
||||||
|
stage: target_test
|
||||||
|
image: $CI_DOCKER_REGISTRY/rpi-net-suite$BOT_DOCKER_IMAGE_TAG
|
||||||
|
tags:
|
||||||
|
- ESP32
|
||||||
|
- Example_WIFI
|
||||||
|
only:
|
||||||
|
variables:
|
||||||
|
- $BOT_LABEL_WEEKEND_TEST
|
||||||
|
variables:
|
||||||
|
TEST_CASE_PATH: "$CI_PROJECT_DIR/components/lwip/weekend_test"
|
||||||
|
TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
|
||||||
|
LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS"
|
||||||
|
ENV_FILE: "$CI_PROJECT_DIR/components/lwip/weekend_test/env.yml"
|
||||||
|
CONFIG_FILE: "$CI_PROJECT_DIR/components/lwip/weekend_test/config.yml"
|
||||||
|
|
||||||
.test_template: &test_template
|
.test_template: &test_template
|
||||||
stage: target_test
|
stage: target_test
|
||||||
when: on_success
|
when: on_success
|
||||||
|
@ -87,6 +87,7 @@ set(COMPONENT_SRCS "apps/dhcpserver/dhcpserver.c"
|
|||||||
"port/esp32/freertos/sys_arch.c"
|
"port/esp32/freertos/sys_arch.c"
|
||||||
"port/esp32/netif/dhcp_state.c"
|
"port/esp32/netif/dhcp_state.c"
|
||||||
"port/esp32/netif/ethernetif.c"
|
"port/esp32/netif/ethernetif.c"
|
||||||
|
"port/esp32/netif/nettestif.c"
|
||||||
"port/esp32/netif/wlanif.c")
|
"port/esp32/netif/wlanif.c")
|
||||||
|
|
||||||
if(CONFIG_LWIP_PPP_SUPPORT)
|
if(CONFIG_LWIP_PPP_SUPPORT)
|
||||||
|
33
components/lwip/port/esp32/include/netif/nettestif.h
Normal file
33
components/lwip/port/esp32/include/netif/nettestif.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2015-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 _NETTEST_LWIP_IF_H_
|
||||||
|
#define _NETTEST_LWIP_IF_H_
|
||||||
|
|
||||||
|
#include "lwip/err.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
err_t nettestif_init(struct netif *netif);
|
||||||
|
|
||||||
|
void nettestif_input(void *buffer, u16_t len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _NETTEST_LWIP_IF_H_ */
|
@ -26,7 +26,7 @@
|
|||||||
#define VALID_NETIF_ID(id) ((id < ESP_IF_MAX) && (id != ESP_IF_WIFI_AP))
|
#define VALID_NETIF_ID(id) ((id < ESP_IF_MAX) && (id != ESP_IF_WIFI_AP))
|
||||||
|
|
||||||
static uint32_t restored_ip_addr[TCPIP_ADAPTER_IF_MAX];
|
static uint32_t restored_ip_addr[TCPIP_ADAPTER_IF_MAX];
|
||||||
static const char *interface_key[] = {"IF_STA", "IF_AP", "IF_ETH"};
|
static const char *interface_key[] = {"IF_STA", "IF_AP", "IF_ETH", "IF_TEST"};
|
||||||
|
|
||||||
_Static_assert(sizeof(interface_key) / sizeof(char*) == TCPIP_ADAPTER_IF_MAX,
|
_Static_assert(sizeof(interface_key) / sizeof(char*) == TCPIP_ADAPTER_IF_MAX,
|
||||||
"Number interface keys differs from number of interfaces");
|
"Number interface keys differs from number of interfaces");
|
||||||
|
105
components/lwip/port/esp32/netif/nettestif.c
Normal file
105
components/lwip/port/esp32/netif/nettestif.c
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#include "lwip/def.h"
|
||||||
|
#include "lwip/mem.h"
|
||||||
|
#include "lwip/pbuf.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
#include "lwip/snmp.h"
|
||||||
|
#include "lwip/ethip6.h"
|
||||||
|
#include "netif/etharp.h"
|
||||||
|
#include "netif/wlanif.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tcpip_adapter.h"
|
||||||
|
|
||||||
|
static struct netif *g_last_netif = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
err_t nettestif_output(struct netif *netif, struct pbuf *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *dat = p->payload;
|
||||||
|
|
||||||
|
/* output the packet to stdout */
|
||||||
|
printf("\nPacketOut:[");
|
||||||
|
for (i=0; i<p->len; i++) {
|
||||||
|
printf("%02x", *dat++);
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
err_t nettestif_init(struct netif *netif)
|
||||||
|
{
|
||||||
|
|
||||||
|
g_last_netif = netif;
|
||||||
|
|
||||||
|
netif->hostname = "espressif";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the snmp variables and counters inside the struct netif.
|
||||||
|
* The last argument should be replaced with your link speed, in units
|
||||||
|
* of bits per second.
|
||||||
|
*/
|
||||||
|
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100);
|
||||||
|
|
||||||
|
/* We directly use etharp_output() here to save a function call.
|
||||||
|
* You can instead declare your own function an call etharp_output()
|
||||||
|
* from it if you have to do some checks before sending (e.g. if link
|
||||||
|
* is available...) */
|
||||||
|
netif->output = etharp_output;
|
||||||
|
#if LWIP_IPV6
|
||||||
|
netif->output_ip6 = ethip6_output;
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
netif->linkoutput = nettestif_output;
|
||||||
|
/* set MAC hardware address length */
|
||||||
|
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||||
|
|
||||||
|
/* set MAC hardware address */
|
||||||
|
|
||||||
|
/* maximum transfer unit */
|
||||||
|
netif->mtu = 1500;
|
||||||
|
|
||||||
|
/* device capabilities */
|
||||||
|
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
|
||||||
|
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
|
||||||
|
|
||||||
|
#if ESP_LWIP
|
||||||
|
#if LWIP_IGMP
|
||||||
|
netif->flags |= NETIF_FLAG_IGMP;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
return ERR_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void nettestif_input(void *buffer, u16_t len)
|
||||||
|
{
|
||||||
|
struct pbuf *p;
|
||||||
|
if (g_last_netif == NULL) {
|
||||||
|
printf("error!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("simul in: %d\n", len);
|
||||||
|
if (len==0) return;
|
||||||
|
|
||||||
|
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
|
||||||
|
p->l2_owner = NULL;
|
||||||
|
memcpy(p->payload, buffer, len);
|
||||||
|
|
||||||
|
/* full packet send to tcpip_thread to process
|
||||||
|
* on success - the packet is processed and deallocated in tcpip stack
|
||||||
|
* on failure - log error and deallocate the packet
|
||||||
|
*/
|
||||||
|
if (g_last_netif->input(p, g_last_netif) != ERR_OK) {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
3
components/lwip/weekend_test/config.yml
Normal file
3
components/lwip/weekend_test/config.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
CaseConfig:
|
||||||
|
- name: lwip_test_suite
|
||||||
|
|
0
components/lwip/weekend_test/env.yml
Normal file
0
components/lwip/weekend_test/env.yml
Normal file
11
components/lwip/weekend_test/esp32_netsuite.cfg
Normal file
11
components/lwip/weekend_test/esp32_netsuite.cfg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[LOGGING]
|
||||||
|
FileMask := LOG_ALL | DEBUG | TTCN_DEBUG
|
||||||
|
ConsoleMask := LOG_ALL | DEBUG | TTCN_DEBUG
|
||||||
|
LogSourceInfo := Yes
|
||||||
|
|
||||||
|
[MODULE_PARAMETERS]
|
||||||
|
libtest.m_ip_dst := "10.0.0.1"
|
||||||
|
libtest.m_ip_src := "10.0.0.2"
|
||||||
|
|
||||||
|
[EXECUTE]
|
||||||
|
esp32_netsuite.control
|
11
components/lwip/weekend_test/esp32_netsuite.ttcn
Normal file
11
components/lwip/weekend_test/esp32_netsuite.ttcn
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module esp32_netsuite {
|
||||||
|
import from tcp_suite all;
|
||||||
|
|
||||||
|
control {
|
||||||
|
execute(tc_tcp_002());
|
||||||
|
execute(tc_tcp_003());
|
||||||
|
execute(tc_tcp_004());
|
||||||
|
execute(tc_tcp_005());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
164
components/lwip/weekend_test/net_suite_test.py
Normal file
164
components/lwip/weekend_test/net_suite_test.py
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
import re
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
from threading import Thread, Event
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
from shutil import copyfile
|
||||||
|
|
||||||
|
try:
|
||||||
|
import IDF
|
||||||
|
except ImportError:
|
||||||
|
# this is a test case write with tiny-test-fw.
|
||||||
|
# to run test cases outside tiny-test-fw,
|
||||||
|
# we need to set environment variable `TEST_FW_PATH`,
|
||||||
|
# then get and insert `TEST_FW_PATH` to sys path before import FW module
|
||||||
|
test_fw_path = os.getenv("TEST_FW_PATH")
|
||||||
|
if test_fw_path and test_fw_path not in sys.path:
|
||||||
|
sys.path.insert(0, test_fw_path)
|
||||||
|
import IDF
|
||||||
|
|
||||||
|
import DUT
|
||||||
|
import Utility
|
||||||
|
|
||||||
|
stop_sock_listener = Event()
|
||||||
|
stop_io_listener = Event()
|
||||||
|
sock = None
|
||||||
|
client_address = None
|
||||||
|
manual_test = False
|
||||||
|
|
||||||
|
|
||||||
|
def io_listener(dut1):
|
||||||
|
global sock
|
||||||
|
global client_address
|
||||||
|
data = b''
|
||||||
|
while not stop_io_listener.is_set():
|
||||||
|
try:
|
||||||
|
data = dut1.expect(re.compile(r"PacketOut:\[([a-fA-F0-9]+)\]"), timeout=5)
|
||||||
|
except DUT.ExpectTimeout:
|
||||||
|
continue
|
||||||
|
if data != () and data[0] != b'':
|
||||||
|
packet_data = data[0]
|
||||||
|
print("Packet_data>{}<".format(packet_data))
|
||||||
|
response = bytearray.fromhex(packet_data.decode())
|
||||||
|
print("Sending to socket:")
|
||||||
|
packet = ' '.join(format(x, '02x') for x in bytearray(response))
|
||||||
|
print("Packet>{}<".format(packet))
|
||||||
|
if client_address is not None:
|
||||||
|
sock.sendto(response, ('127.0.0.1', 7777))
|
||||||
|
|
||||||
|
|
||||||
|
def sock_listener(dut1):
|
||||||
|
global sock
|
||||||
|
global client_address
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
sock.settimeout(5)
|
||||||
|
server_address = '0.0.0.0'
|
||||||
|
server_port = 7771
|
||||||
|
server = (server_address, server_port)
|
||||||
|
sock.bind(server)
|
||||||
|
try:
|
||||||
|
while not stop_sock_listener.is_set():
|
||||||
|
try:
|
||||||
|
payload, client_address = sock.recvfrom(1024)
|
||||||
|
packet = ' '.join(format(x, '02x') for x in bytearray(payload))
|
||||||
|
print("Received from address {}, data {}".format(client_address, packet))
|
||||||
|
dut1.write(str.encode(packet))
|
||||||
|
except socket.timeout:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
sock.close()
|
||||||
|
sock = None
|
||||||
|
|
||||||
|
|
||||||
|
@IDF.idf_example_test(env_tag="Example_WIFI")
|
||||||
|
def lwip_test_suite(env, extra_data):
|
||||||
|
global stop_io_listener
|
||||||
|
global stop_sock_listener
|
||||||
|
"""
|
||||||
|
steps: |
|
||||||
|
1. Rebuilds test suite with esp32_netsuite.ttcn
|
||||||
|
2. Starts listeners on stdout and socket
|
||||||
|
3. Execute ttcn3 test suite
|
||||||
|
4. Collect result from ttcn3
|
||||||
|
"""
|
||||||
|
dut1 = env.get_dut("net_suite", "examples/system/network_tests")
|
||||||
|
# check and log bin size
|
||||||
|
binary_file = os.path.join(dut1.app.binary_path, "net_suite.bin")
|
||||||
|
bin_size = os.path.getsize(binary_file)
|
||||||
|
IDF.log_performance("net_suite", "{}KB".format(bin_size // 1024))
|
||||||
|
IDF.check_performance("net_suite", bin_size // 1024)
|
||||||
|
dut1.start_app()
|
||||||
|
thread1 = Thread(target=sock_listener, args=(dut1, ))
|
||||||
|
thread2 = Thread(target=io_listener, args=(dut1, ))
|
||||||
|
if not manual_test:
|
||||||
|
# Variables refering to esp32 ttcn test suite
|
||||||
|
TTCN_SRC = 'esp32_netsuite.ttcn'
|
||||||
|
TTCN_CFG = 'esp32_netsuite.cfg'
|
||||||
|
# System Paths
|
||||||
|
netsuite_path = os.getenv("NETSUITE_PATH")
|
||||||
|
netsuite_src_path = os.path.join(netsuite_path, "src")
|
||||||
|
test_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
# Building the suite
|
||||||
|
print("Rebuilding the test suite")
|
||||||
|
print("-------------------------")
|
||||||
|
# copy esp32 specific files to ttcn net-suite dir
|
||||||
|
copyfile(os.path.join(test_dir, TTCN_SRC), os.path.join(netsuite_src_path, TTCN_SRC))
|
||||||
|
copyfile(os.path.join(test_dir, TTCN_CFG), os.path.join(netsuite_src_path, TTCN_CFG))
|
||||||
|
proc = subprocess.Popen(['bash', '-c', 'cd ' + netsuite_src_path + ' && source make.sh'],
|
||||||
|
cwd=netsuite_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
output = proc.stdout.read()
|
||||||
|
print("Note: First build step we expect failure (titan/net_suite build system not suitable for multijob make)")
|
||||||
|
print(output)
|
||||||
|
proc = subprocess.Popen(['bash', '-c', 'cd ' + netsuite_src_path + ' && make'],
|
||||||
|
cwd=netsuite_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
print("Note: This time all dependencies shall be generated -- multijob make shall pass")
|
||||||
|
output = proc.stdout.read()
|
||||||
|
print(output)
|
||||||
|
# Executing the test suite
|
||||||
|
thread1.start()
|
||||||
|
thread2.start()
|
||||||
|
time.sleep(2)
|
||||||
|
print("Executing the test suite")
|
||||||
|
print("------------------------")
|
||||||
|
proc = subprocess.Popen(['ttcn3_start', os.path.join(netsuite_src_path,'test_suite'), os.path.join(netsuite_src_path, TTCN_CFG)],
|
||||||
|
stdout=subprocess.PIPE)
|
||||||
|
output = proc.stdout.read()
|
||||||
|
print(output)
|
||||||
|
print("Collecting results")
|
||||||
|
print("------------------")
|
||||||
|
verdict_stats = re.search('(Verdict statistics:.*)', output)
|
||||||
|
if verdict_stats:
|
||||||
|
verdict_stats = verdict_stats.group(1)
|
||||||
|
else:
|
||||||
|
verdict_stats = b""
|
||||||
|
verdict = re.search('Overall verdict: pass', output)
|
||||||
|
if verdict:
|
||||||
|
print("Test passed!")
|
||||||
|
Utility.console_log(verdict_stats, "green")
|
||||||
|
else:
|
||||||
|
Utility.console_log(verdict_stats, "red")
|
||||||
|
raise ValueError('Test failed with: {}'.format(verdict_stats))
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
# Executing the test suite
|
||||||
|
thread1.start()
|
||||||
|
thread2.start()
|
||||||
|
time.sleep(2)
|
||||||
|
while True:
|
||||||
|
time.sleep(0.5)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
print("Executing done, waiting for tests to finish")
|
||||||
|
print("-------------------------------------------")
|
||||||
|
stop_io_listener.set()
|
||||||
|
stop_sock_listener.set()
|
||||||
|
thread1.join()
|
||||||
|
thread2.join()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("Manual execution, please build and start ttcn in a separate console")
|
||||||
|
manual_test = True
|
||||||
|
lwip_test_suite()
|
@ -96,6 +96,7 @@ typedef enum {
|
|||||||
TCPIP_ADAPTER_IF_STA = 0, /**< Wi-Fi STA (station) interface */
|
TCPIP_ADAPTER_IF_STA = 0, /**< Wi-Fi STA (station) interface */
|
||||||
TCPIP_ADAPTER_IF_AP, /**< Wi-Fi soft-AP interface */
|
TCPIP_ADAPTER_IF_AP, /**< Wi-Fi soft-AP interface */
|
||||||
TCPIP_ADAPTER_IF_ETH, /**< Ethernet interface */
|
TCPIP_ADAPTER_IF_ETH, /**< Ethernet interface */
|
||||||
|
TCPIP_ADAPTER_IF_TEST, /**< tcpip stack test interface */
|
||||||
TCPIP_ADAPTER_IF_MAX
|
TCPIP_ADAPTER_IF_MAX
|
||||||
} tcpip_adapter_if_t;
|
} tcpip_adapter_if_t;
|
||||||
|
|
||||||
@ -692,6 +693,19 @@ esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif);
|
|||||||
*/
|
*/
|
||||||
bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if);
|
bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cause the TCP/IP stack to start the test interface with specified MAC and IP.
|
||||||
|
* Test interface is used to exercise network stack with injected packets from SW.
|
||||||
|
*
|
||||||
|
* @param[in] mac Set MAC address of this interface
|
||||||
|
* @param[in] ip_info Set IP address of this interface
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK
|
||||||
|
* - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
|
||||||
|
* - ESP_ERR_NO_MEM
|
||||||
|
*/
|
||||||
|
esp_err_t tcpip_adapter_test_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Install default event handlers for Ethernet interface
|
* @brief Install default event handlers for Ethernet interface
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "netif/wlanif.h"
|
#include "netif/wlanif.h"
|
||||||
#include "netif/ethernetif.h"
|
#include "netif/ethernetif.h"
|
||||||
|
#include "netif/nettestif.h"
|
||||||
|
|
||||||
#include "dhcpserver/dhcpserver.h"
|
#include "dhcpserver/dhcpserver.h"
|
||||||
#include "dhcpserver/dhcpserver_options.h"
|
#include "dhcpserver/dhcpserver_options.h"
|
||||||
@ -161,6 +162,8 @@ static esp_err_t tcpip_adapter_update_default_netif(void)
|
|||||||
netif_set_default(esp_netif[TCPIP_ADAPTER_IF_ETH]);
|
netif_set_default(esp_netif[TCPIP_ADAPTER_IF_ETH]);
|
||||||
} else if (netif_is_up(esp_netif[TCPIP_ADAPTER_IF_AP])) {
|
} else if (netif_is_up(esp_netif[TCPIP_ADAPTER_IF_AP])) {
|
||||||
netif_set_default(esp_netif[TCPIP_ADAPTER_IF_AP]);
|
netif_set_default(esp_netif[TCPIP_ADAPTER_IF_AP]);
|
||||||
|
} else if (netif_is_up(esp_netif[TCPIP_ADAPTER_IF_TEST])) {
|
||||||
|
netif_set_default(esp_netif[TCPIP_ADAPTER_IF_TEST]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@ -210,6 +213,8 @@ static esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac,
|
|||||||
|
|
||||||
dhcps_status = TCPIP_ADAPTER_DHCP_STARTED;
|
dhcps_status = TCPIP_ADAPTER_DHCP_STARTED;
|
||||||
}
|
}
|
||||||
|
} else if (tcpip_if == TCPIP_ADAPTER_IF_TEST) {
|
||||||
|
netif_set_up(esp_netif[tcpip_if]);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpip_adapter_update_default_netif();
|
tcpip_adapter_update_default_netif();
|
||||||
@ -229,6 +234,13 @@ esp_err_t tcpip_adapter_sta_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info
|
|||||||
return tcpip_adapter_start(TCPIP_ADAPTER_IF_STA, mac, ip_info);
|
return tcpip_adapter_start(TCPIP_ADAPTER_IF_STA, mac, ip_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t tcpip_adapter_test_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info)
|
||||||
|
{
|
||||||
|
esp_netif_init_fn[TCPIP_ADAPTER_IF_TEST] = nettestif_init;
|
||||||
|
return tcpip_adapter_start(TCPIP_ADAPTER_IF_TEST, mac, ip_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
esp_err_t tcpip_adapter_ap_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info)
|
esp_err_t tcpip_adapter_ap_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info)
|
||||||
{
|
{
|
||||||
esp_netif_init_fn[TCPIP_ADAPTER_IF_AP] = wlanif_init_ap;
|
esp_netif_init_fn[TCPIP_ADAPTER_IF_AP] = wlanif_init_ap;
|
||||||
|
6
examples/system/network_tests/CMakeLists.txt
Normal file
6
examples/system/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.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(net_suite)
|
9
examples/system/network_tests/Makefile
Normal file
9
examples/system/network_tests/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||||
|
# project subdirectory.
|
||||||
|
#
|
||||||
|
|
||||||
|
PROJECT_NAME := net_suite
|
||||||
|
|
||||||
|
include $(IDF_PATH)/make/project.mk
|
||||||
|
|
66
examples/system/network_tests/README.md
Normal file
66
examples/system/network_tests/README.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# 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 a 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
|
||||||
|
make defconfig
|
||||||
|
make -j4
|
||||||
|
make 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 (Network stack under test) runs normally on target, but a specific interface `TCPIP_ADAPTER_IF_TEST` was created 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---------| -----> | tcpip_adapter/lwip | |
|
||||||
|
| | |--7771/udp--| |--stdin----------| <----- | TCPIP_ADAPTER_IF_TEST | |
|
||||||
|
| +-----------------+ +--------------+ | | +---------+------------------------+ |
|
||||||
|
+---------------------------------------------------------+ +----------------------------------------+
|
||||||
|
```
|
4
examples/system/network_tests/main/CMakeLists.txt
Normal file
4
examples/system/network_tests/main/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
set(COMPONENT_SRCS "net_suite.c")
|
||||||
|
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||||
|
|
||||||
|
register_component()
|
8
examples/system/network_tests/main/component.mk
Normal file
8
examples/system/network_tests/main/component.mk
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
# Main component makefile.
|
||||||
|
#
|
||||||
|
# This Makefile can be left empty. By default, it will take the sources in the
|
||||||
|
# src/ directory, compile them and link them into lib(subdirectory_name).a
|
||||||
|
# in the build directory. This behaviour is entirely configurable,
|
||||||
|
# please read the ESP-IDF documents if you need to do this.
|
||||||
|
#
|
180
examples/system/network_tests/main/net_suite.c
Normal file
180
examples/system/network_tests/main/net_suite.c
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/* 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 "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "esp_event_loop.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
#include "driver/uart.h"
|
||||||
|
#include "esp_console.h"
|
||||||
|
#include "esp_vfs_dev.h"
|
||||||
|
#include "linenoise/linenoise.h"
|
||||||
|
|
||||||
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#include "lwip/debug.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
#include "lwip/tcp.h"
|
||||||
|
void nettestif_input(void *buffer, u16_t len);
|
||||||
|
|
||||||
|
/* these data configures ARP cache so the test IPs are knows */
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main()
|
||||||
|
{
|
||||||
|
char packet[128];
|
||||||
|
|
||||||
|
tcpip_adapter_ip_info_t ip_info;
|
||||||
|
|
||||||
|
uint8_t ap_mac[6] = { 0,0,0,0,0,1};
|
||||||
|
IP4_ADDR(&ip_info.ip, 10, 0 , 0, 1);
|
||||||
|
IP4_ADDR(&ip_info.gw, 10, 0 , 0, 1);
|
||||||
|
IP4_ADDR(&ip_info.netmask, 255, 255 , 255, 0);
|
||||||
|
|
||||||
|
tcpip_adapter_init();
|
||||||
|
|
||||||
|
tcpip_adapter_test_start(ap_mac, &ip_info);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
nettestif_input(arp1, sizeof(arp1));
|
||||||
|
// 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_CONSOLE_UART_NUM,
|
||||||
|
256, 0, 0, NULL, 0) );
|
||||||
|
/* Tell VFS to use UART driver */
|
||||||
|
esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM);
|
||||||
|
esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR);
|
||||||
|
/* Move the caret to the beginning of the next line on '\n' */
|
||||||
|
esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF);
|
||||||
|
linenoiseSetDumbMode(1);
|
||||||
|
|
||||||
|
/* Now read from stdin and pass the data to test netif */
|
||||||
|
while (1) {
|
||||||
|
size_t size;
|
||||||
|
char* line = linenoise("");
|
||||||
|
if (!line) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = process_line(line, packet);
|
||||||
|
|
||||||
|
nettestif_input(packet, size);
|
||||||
|
|
||||||
|
linenoiseFree(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user