mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feat/move_iperf_component' into 'master'
feat: move iperf to component registry Closes RDT-618 See merge request espressif/esp-idf!29537
This commit is contained in:
commit
38733a752d
@ -3,5 +3,5 @@ dependencies:
|
|||||||
path: ${IDF_PATH}/examples/bluetooth/esp_ble_mesh/common_components/fast_prov
|
path: ${IDF_PATH}/examples/bluetooth/esp_ble_mesh/common_components/fast_prov
|
||||||
example_init:
|
example_init:
|
||||||
path: ${IDF_PATH}/examples/bluetooth/esp_ble_mesh/common_components/example_init
|
path: ${IDF_PATH}/examples/bluetooth/esp_ble_mesh/common_components/example_init
|
||||||
iperf:
|
espressif/iperf:
|
||||||
path: ${IDF_PATH}/examples/common_components/iperf
|
version: "~0.1.1"
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
idf_component_register(SRCS "iperf.c"
|
|
||||||
"wifi_stats.c"
|
|
||||||
"wifi_twt.c"
|
|
||||||
"wifi_cmd.c"
|
|
||||||
INCLUDE_DIRS "include"
|
|
||||||
REQUIRES lwip
|
|
||||||
PRIV_REQUIRES esp_timer)
|
|
||||||
|
|
||||||
if(CONFIG_SOC_WIFI_HE_SUPPORT)
|
|
||||||
idf_component_optional_requires(PRIVATE esp_wifi console)
|
|
||||||
endif()
|
|
@ -1,31 +0,0 @@
|
|||||||
menu "Iperf Configuration"
|
|
||||||
|
|
||||||
config IPERF_SOCKET_RX_TIMEOUT
|
|
||||||
int "iperf socket TCP/UDP rx timeout in seconds"
|
|
||||||
default 10
|
|
||||||
help
|
|
||||||
The value is used for iperf socket TCP/UDP rx timeout, iperf will be aborted
|
|
||||||
and socket will be closed and shutdown.
|
|
||||||
|
|
||||||
config IPERF_SOCKET_TCP_TX_TIMEOUT
|
|
||||||
int "iperf socket TCP tx timeout in seconds"
|
|
||||||
default 10
|
|
||||||
help
|
|
||||||
The value is used for iperf socket TCP tx timeout, iperf will be aborted
|
|
||||||
and socket will be closed and shutdown.
|
|
||||||
|
|
||||||
config IPERF_TRAFFIC_TASK_PRIORITY
|
|
||||||
int "iperf traffic task priority"
|
|
||||||
default 4
|
|
||||||
range 1 24
|
|
||||||
help
|
|
||||||
The value is used for iperf traffic task priority.
|
|
||||||
|
|
||||||
config IPERF_REPORT_TASK_PRIORITY
|
|
||||||
int "iperf result report task priority"
|
|
||||||
default 6
|
|
||||||
range 1 24
|
|
||||||
help
|
|
||||||
The value is used for iperf result report task priority.
|
|
||||||
|
|
||||||
endmenu
|
|
@ -1,14 +0,0 @@
|
|||||||
# iperf Component
|
|
||||||
|
|
||||||
This directory contains an implementation for iperf network performance tester
|
|
||||||
|
|
||||||
Note that it's incompatible with `iperf3`
|
|
||||||
|
|
||||||
This component is used as part of the following ESP-IDF examples:
|
|
||||||
- [esp_wifi](../../wifi/iperf).
|
|
||||||
- [wifi_coexist](../../bluetooth/esp_ble_mesh/wifi_coexist).
|
|
||||||
- [ethernet](../../ethernet/iperf)
|
|
||||||
|
|
||||||
To learn more about how to use this component, please check API Documentation from header file [iperf.h](./include/iperf.h).
|
|
||||||
|
|
||||||
Please note that this component is not considered to be a part of ESP-IDF stable API, and only for example use for now.
|
|
@ -1,89 +0,0 @@
|
|||||||
/* Iperf Example - iperf declaration
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __IPERF_H_
|
|
||||||
#define __IPERF_H_
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_types.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IPERF_IP_TYPE_IPV4 0
|
|
||||||
#define IPERF_IP_TYPE_IPV6 1
|
|
||||||
#define IPERF_TRANS_TYPE_TCP 0
|
|
||||||
#define IPERF_TRANS_TYPE_UDP 1
|
|
||||||
|
|
||||||
#define IPERF_FLAG_SET(cfg, flag) ((cfg) |= (flag))
|
|
||||||
#define IPERF_FLAG_CLR(cfg, flag) ((cfg) &= (~(flag)))
|
|
||||||
|
|
||||||
#define IPERF_FLAG_CLIENT (1)
|
|
||||||
#define IPERF_FLAG_SERVER (1 << 1)
|
|
||||||
#define IPERF_FLAG_TCP (1 << 2)
|
|
||||||
#define IPERF_FLAG_UDP (1 << 3)
|
|
||||||
|
|
||||||
#define IPERF_DEFAULT_PORT 5001
|
|
||||||
#define IPERF_DEFAULT_INTERVAL 3
|
|
||||||
#define IPERF_DEFAULT_TIME 30
|
|
||||||
#define IPERF_DEFAULT_NO_BW_LIMIT -1
|
|
||||||
|
|
||||||
#define IPERF_TRAFFIC_TASK_NAME "iperf_traffic"
|
|
||||||
#define IPERF_TRAFFIC_TASK_PRIORITY CONFIG_IPERF_TRAFFIC_TASK_PRIORITY
|
|
||||||
#define IPERF_TRAFFIC_TASK_STACK 4096
|
|
||||||
#define IPERF_REPORT_TASK_NAME "iperf_report"
|
|
||||||
#define IPERF_REPORT_TASK_PRIORITY CONFIG_IPERF_REPORT_TASK_PRIORITY
|
|
||||||
#define IPERF_REPORT_TASK_STACK 4096
|
|
||||||
|
|
||||||
#define IPERF_DEFAULT_IPV4_UDP_TX_LEN (1470)
|
|
||||||
#define IPERF_DEFAULT_IPV6_UDP_TX_LEN (1450)
|
|
||||||
#define IPERF_DEFAULT_UDP_RX_LEN (16 << 10)
|
|
||||||
#define IPERF_DEFAULT_TCP_TX_LEN (16 << 10)
|
|
||||||
#define IPERF_DEFAULT_TCP_RX_LEN (16 << 10)
|
|
||||||
|
|
||||||
#define IPERF_MAX_DELAY 64
|
|
||||||
|
|
||||||
#define IPERF_SOCKET_RX_TIMEOUT CONFIG_IPERF_SOCKET_RX_TIMEOUT
|
|
||||||
#define IPERF_SOCKET_TCP_TX_TIMEOUT CONFIG_IPERF_SOCKET_TCP_TX_TIMEOUT
|
|
||||||
#define IPERF_SOCKET_ACCEPT_TIMEOUT 5
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
MBITS_PER_SEC, KBITS_PER_SEC, BITS_PER_SEC
|
|
||||||
} iperf_output_format;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t flag;
|
|
||||||
union {
|
|
||||||
uint32_t destination_ip4;
|
|
||||||
char *destination_ip6;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
uint32_t source_ip4;
|
|
||||||
char *source_ip6;
|
|
||||||
};
|
|
||||||
uint8_t type;
|
|
||||||
uint16_t dport;
|
|
||||||
uint16_t sport;
|
|
||||||
uint32_t interval;
|
|
||||||
uint32_t time;
|
|
||||||
uint16_t len_send_buf;
|
|
||||||
int32_t bw_lim;
|
|
||||||
iperf_output_format format;
|
|
||||||
} iperf_cfg_t;
|
|
||||||
|
|
||||||
esp_err_t iperf_start(iperf_cfg_t *cfg);
|
|
||||||
|
|
||||||
esp_err_t iperf_stop(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS || CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
|
||||||
|
|
||||||
int wifi_cmd_get_tx_statistics(int argc, char **argv);
|
|
||||||
int wifi_cmd_clr_tx_statistics(int argc, char **argv);
|
|
||||||
|
|
||||||
int wifi_cmd_get_rx_statistics(int argc, char **argv);
|
|
||||||
int wifi_cmd_clr_rx_statistics(int argc, char **argv);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,609 +0,0 @@
|
|||||||
/* Iperf Example - iperf implementation
|
|
||||||
|
|
||||||
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 "sdkconfig.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_rom_sys.h"
|
|
||||||
#include "esp_timer.h"
|
|
||||||
#include "iperf.h"
|
|
||||||
#include "wifi_stats.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
iperf_cfg_t cfg;
|
|
||||||
bool finish;
|
|
||||||
uint32_t actual_len;
|
|
||||||
uint32_t buffer_len;
|
|
||||||
uint8_t *buffer;
|
|
||||||
uint32_t sockfd;
|
|
||||||
} iperf_ctrl_t;
|
|
||||||
|
|
||||||
static bool s_iperf_is_running = false;
|
|
||||||
static iperf_ctrl_t s_iperf_ctrl;
|
|
||||||
static const char *TAG = "iperf";
|
|
||||||
|
|
||||||
inline static bool iperf_is_udp_client(void)
|
|
||||||
{
|
|
||||||
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static bool iperf_is_udp_server(void)
|
|
||||||
{
|
|
||||||
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_SERVER) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static bool iperf_is_tcp_client(void)
|
|
||||||
{
|
|
||||||
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static bool iperf_is_tcp_server(void)
|
|
||||||
{
|
|
||||||
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_SERVER) && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int iperf_get_socket_error_code(int sockfd)
|
|
||||||
{
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int iperf_show_socket_error_reason(const char *str, int sockfd)
|
|
||||||
{
|
|
||||||
int err = errno;
|
|
||||||
if (err != 0) {
|
|
||||||
ESP_LOGW(TAG, "%s error, error code: %d, reason: %s", str, err, strerror(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iperf_report_task(void *arg)
|
|
||||||
{
|
|
||||||
uint32_t interval = s_iperf_ctrl.cfg.interval;
|
|
||||||
uint32_t time = s_iperf_ctrl.cfg.time;
|
|
||||||
TickType_t delay_interval = (interval * 1000) / portTICK_PERIOD_MS;
|
|
||||||
uint32_t cur = 0;
|
|
||||||
double average = 0;
|
|
||||||
double actual_bandwidth = 0;
|
|
||||||
int k = 1;
|
|
||||||
const double coefficient[3] = {1048576.0, 1024.0, 1.0};
|
|
||||||
const char unit[3] = {'M', 'K', '\0'};
|
|
||||||
iperf_output_format format = s_iperf_ctrl.cfg.format;
|
|
||||||
|
|
||||||
printf("\n%16s %s\n", "Interval", "Bandwidth");
|
|
||||||
while (!s_iperf_ctrl.finish) {
|
|
||||||
vTaskDelay(delay_interval);
|
|
||||||
actual_bandwidth = (s_iperf_ctrl.actual_len / coefficient[format] * 8) / interval;
|
|
||||||
printf("%4" PRIi32 "-%4" PRIi32 " sec %.2f %cbits/sec\n", cur, cur + interval,
|
|
||||||
actual_bandwidth, unit[format]);
|
|
||||||
cur += interval;
|
|
||||||
average = ((average * (k - 1) / k) + (actual_bandwidth / k));
|
|
||||||
k++;
|
|
||||||
s_iperf_ctrl.actual_len = 0;
|
|
||||||
if (cur >= time) {
|
|
||||||
printf("%4d-%4" PRIu32 " sec %.2f %cbits/sec\n", 0, time,
|
|
||||||
average, unit[format]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s_iperf_ctrl.finish = true;
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t iperf_start_report(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = xTaskCreatePinnedToCore(iperf_report_task, IPERF_REPORT_TASK_NAME, IPERF_REPORT_TASK_STACK, NULL, IPERF_REPORT_TASK_PRIORITY, NULL, CONFIG_FREERTOS_NUMBER_OF_CORES - 1);
|
|
||||||
|
|
||||||
if (ret != pdPASS) {
|
|
||||||
ESP_LOGE(TAG, "create task %s failed", IPERF_REPORT_TASK_NAME);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void IRAM_ATTR socket_recv(int recv_socket, struct sockaddr_storage listen_addr, uint8_t type)
|
|
||||||
{
|
|
||||||
bool iperf_recv_start = true;
|
|
||||||
uint8_t *buffer;
|
|
||||||
int want_recv = 0;
|
|
||||||
int actual_recv = 0;
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
socklen_t socklen = (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
|
|
||||||
#else
|
|
||||||
socklen_t socklen = sizeof(struct sockaddr_in);
|
|
||||||
#endif
|
|
||||||
const char *error_log = (type == IPERF_TRANS_TYPE_TCP) ? "tcp server recv" : "udp server recv";
|
|
||||||
|
|
||||||
buffer = s_iperf_ctrl.buffer;
|
|
||||||
want_recv = s_iperf_ctrl.buffer_len;
|
|
||||||
while (!s_iperf_ctrl.finish) {
|
|
||||||
actual_recv = recvfrom(recv_socket, buffer, want_recv, 0, (struct sockaddr *)&listen_addr, &socklen);
|
|
||||||
if (actual_recv < 0) {
|
|
||||||
iperf_show_socket_error_reason(error_log, recv_socket);
|
|
||||||
s_iperf_ctrl.finish = true;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
if (iperf_recv_start) {
|
|
||||||
iperf_start_report();
|
|
||||||
iperf_recv_start = false;
|
|
||||||
}
|
|
||||||
s_iperf_ctrl.actual_len += actual_recv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void IRAM_ATTR socket_send(int send_socket, struct sockaddr_storage dest_addr, uint8_t type, int bw_lim)
|
|
||||||
{
|
|
||||||
uint8_t *buffer;
|
|
||||||
uint32_t *pkt_id_p;
|
|
||||||
uint32_t pkt_cnt = 0;
|
|
||||||
int actual_send = 0;
|
|
||||||
int want_send = 0;
|
|
||||||
int period_us = -1;
|
|
||||||
int delay_us = 0;
|
|
||||||
int64_t prev_time = 0;
|
|
||||||
int64_t send_time = 0;
|
|
||||||
int err = 0;
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
const socklen_t socklen = (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
|
|
||||||
#else
|
|
||||||
const socklen_t socklen = sizeof(struct sockaddr_in);
|
|
||||||
#endif
|
|
||||||
const char *error_log = (type == IPERF_TRANS_TYPE_TCP) ? "tcp client send" : "udp client send";
|
|
||||||
|
|
||||||
buffer = s_iperf_ctrl.buffer;
|
|
||||||
pkt_id_p = (uint32_t *)s_iperf_ctrl.buffer;
|
|
||||||
want_send = s_iperf_ctrl.buffer_len;
|
|
||||||
iperf_start_report();
|
|
||||||
|
|
||||||
if (bw_lim > 0) {
|
|
||||||
period_us = want_send * 8 / bw_lim;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!s_iperf_ctrl.finish) {
|
|
||||||
if (period_us > 0) {
|
|
||||||
send_time = esp_timer_get_time();
|
|
||||||
if (actual_send > 0){
|
|
||||||
// Last packet "send" was successful, check how much off the previous loop duration was to the ideal send period. Result will adjust the
|
|
||||||
// next send delay.
|
|
||||||
delay_us += period_us + (int32_t)(prev_time - send_time);
|
|
||||||
} else {
|
|
||||||
// Last packet "send" was not successful. Ideally we should try to catch up the whole previous loop duration (e.g. prev_time - send_time).
|
|
||||||
// However, that's not possible since the most probable reason why the send was unsuccessful is the HW was not able to process the packet.
|
|
||||||
// Hence, we cannot queue more packets with shorter (or no) delay to catch up since we are already at the performance edge. The best we
|
|
||||||
// can do is to reset the send delay (which is probably big negative number) and start all over again.
|
|
||||||
delay_us = 0;
|
|
||||||
}
|
|
||||||
prev_time = send_time;
|
|
||||||
}
|
|
||||||
*pkt_id_p = htonl(pkt_cnt++); // datagrams need to be sequentially numbered
|
|
||||||
actual_send = sendto(send_socket, buffer, want_send, 0, (struct sockaddr *)&dest_addr, socklen);
|
|
||||||
if (actual_send != want_send) {
|
|
||||||
if (type == IPERF_TRANS_TYPE_UDP) {
|
|
||||||
err = iperf_get_socket_error_code(send_socket);
|
|
||||||
// ENOMEM is expected under heavy load => do not print it
|
|
||||||
if (err != ENOMEM) {
|
|
||||||
iperf_show_socket_error_reason(error_log, send_socket);
|
|
||||||
}
|
|
||||||
} else if (type == IPERF_TRANS_TYPE_TCP) {
|
|
||||||
iperf_show_socket_error_reason(error_log, send_socket);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s_iperf_ctrl.actual_len += actual_send;
|
|
||||||
}
|
|
||||||
// The send delay may be negative, it indicates we are trying to catch up and hence to not delay the loop at all.
|
|
||||||
if (delay_us > 0) {
|
|
||||||
esp_rom_delay_us(delay_us);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t iperf_run_tcp_server(void)
|
|
||||||
{
|
|
||||||
int listen_socket = -1;
|
|
||||||
int client_socket = -1;
|
|
||||||
int opt = 1;
|
|
||||||
int err = 0;
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
struct sockaddr_in remote_addr;
|
|
||||||
struct timeval timeout = { 0 };
|
|
||||||
socklen_t addr_len = sizeof(struct sockaddr);
|
|
||||||
struct sockaddr_storage listen_addr = { 0 };
|
|
||||||
|
|
||||||
struct sockaddr_in listen_addr4 = { 0 };
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
struct sockaddr_in6 listen_addr6 = { 0 };
|
|
||||||
ESP_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), ESP_FAIL, exit, TAG, "Ivalid AF types");
|
|
||||||
#else
|
|
||||||
ESP_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), ESP_FAIL, exit, TAG, "Invalid AF types");
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
|
||||||
// The TCP server listen at the address "::", which means all addresses can be listened to.
|
|
||||||
inet6_aton("::", &listen_addr6.sin6_addr);
|
|
||||||
listen_addr6.sin6_family = AF_INET6;
|
|
||||||
listen_addr6.sin6_port = htons(s_iperf_ctrl.cfg.sport);
|
|
||||||
|
|
||||||
listen_socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_IPV6);
|
|
||||||
ESP_GOTO_ON_FALSE((listen_socket >= 0), ESP_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
|
||||||
|
|
||||||
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
||||||
setsockopt(listen_socket, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Socket created");
|
|
||||||
|
|
||||||
err = bind(listen_socket, (struct sockaddr *)&listen_addr6, sizeof(listen_addr6));
|
|
||||||
ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET6);
|
|
||||||
err = listen(listen_socket, 1);
|
|
||||||
ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Error occurred during listen: errno %d", errno);
|
|
||||||
|
|
||||||
memcpy(&listen_addr, &listen_addr6, sizeof(listen_addr6));
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
|
||||||
listen_addr4.sin_family = AF_INET;
|
|
||||||
listen_addr4.sin_port = htons(s_iperf_ctrl.cfg.sport);
|
|
||||||
listen_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.source_ip4;
|
|
||||||
|
|
||||||
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
ESP_GOTO_ON_FALSE((listen_socket >= 0), ESP_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
|
||||||
|
|
||||||
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Socket created");
|
|
||||||
|
|
||||||
err = bind(listen_socket, (struct sockaddr *)&listen_addr4, sizeof(listen_addr4));
|
|
||||||
ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET);
|
|
||||||
|
|
||||||
err = listen(listen_socket, 5);
|
|
||||||
ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Error occurred during listen: errno %d", errno);
|
|
||||||
memcpy(&listen_addr, &listen_addr4, sizeof(listen_addr4));
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
|
|
||||||
setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
|
||||||
client_socket = accept(listen_socket, (struct sockaddr *)&remote_addr, &addr_len);
|
|
||||||
ESP_GOTO_ON_FALSE((client_socket >= 0), ESP_FAIL, exit, TAG, "Unable to accept connection: errno %d", errno);
|
|
||||||
ESP_LOGI(TAG, "accept: %s,%d", inet_ntoa(remote_addr.sin_addr), htons(remote_addr.sin_port));
|
|
||||||
|
|
||||||
timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
|
|
||||||
setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
|
||||||
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
|
||||||
wifi_cmd_clr_tx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
|
||||||
wifi_cmd_clr_rx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
socket_recv(client_socket, listen_addr, IPERF_TRANS_TYPE_TCP);
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
|
||||||
wifi_cmd_get_rx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
|
||||||
wifi_cmd_get_tx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
exit:
|
|
||||||
if (client_socket != -1) {
|
|
||||||
close(client_socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listen_socket != -1) {
|
|
||||||
shutdown(listen_socket, 0);
|
|
||||||
close(listen_socket);
|
|
||||||
ESP_LOGI(TAG, "TCP Socket server is closed.");
|
|
||||||
}
|
|
||||||
s_iperf_ctrl.finish = true;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t iperf_run_tcp_client(void)
|
|
||||||
{
|
|
||||||
int client_socket = -1;
|
|
||||||
int err = 0;
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
struct sockaddr_storage dest_addr = { 0 };
|
|
||||||
struct sockaddr_in dest_addr4 = { 0 };
|
|
||||||
struct timeval timeout = { 0 };
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
struct sockaddr_in6 dest_addr6 = { 0 };
|
|
||||||
ESP_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), ESP_FAIL, exit, TAG, "Ivalid AF types");
|
|
||||||
#else
|
|
||||||
ESP_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), ESP_FAIL, exit, TAG, "Invalid AF types");
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
|
||||||
client_socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_IPV6);
|
|
||||||
ESP_GOTO_ON_FALSE((client_socket >= 0), ESP_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
|
||||||
|
|
||||||
inet6_aton(s_iperf_ctrl.cfg.destination_ip6, &dest_addr6.sin6_addr);
|
|
||||||
dest_addr6.sin6_family = AF_INET6;
|
|
||||||
dest_addr6.sin6_port = htons(s_iperf_ctrl.cfg.dport);
|
|
||||||
|
|
||||||
err = connect(client_socket, (struct sockaddr *)&dest_addr6, sizeof(struct sockaddr_in6));
|
|
||||||
ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Socket unable to connect: errno %d", errno);
|
|
||||||
ESP_LOGI(TAG, "Successfully connected");
|
|
||||||
memcpy(&dest_addr, &dest_addr6, sizeof(dest_addr6));
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
|
||||||
client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
ESP_GOTO_ON_FALSE((client_socket >= 0), ESP_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
|
||||||
|
|
||||||
dest_addr4.sin_family = AF_INET;
|
|
||||||
dest_addr4.sin_port = htons(s_iperf_ctrl.cfg.dport);
|
|
||||||
dest_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.destination_ip4;
|
|
||||||
err = connect(client_socket, (struct sockaddr *)&dest_addr4, sizeof(struct sockaddr_in));
|
|
||||||
ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Socket unable to connect: errno %d", errno);
|
|
||||||
ESP_LOGI(TAG, "Successfully connected");
|
|
||||||
memcpy(&dest_addr, &dest_addr4, sizeof(dest_addr4));
|
|
||||||
}
|
|
||||||
timeout.tv_sec = IPERF_SOCKET_TCP_TX_TIMEOUT;
|
|
||||||
setsockopt(client_socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
|
||||||
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
|
||||||
wifi_cmd_clr_rx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
|
||||||
wifi_cmd_clr_tx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_TCP, s_iperf_ctrl.cfg.bw_lim);
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
|
||||||
wifi_cmd_get_rx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
|
||||||
wifi_cmd_get_tx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
exit:
|
|
||||||
if (client_socket != -1) {
|
|
||||||
shutdown(client_socket, 0);
|
|
||||||
close(client_socket);
|
|
||||||
ESP_LOGI(TAG, "TCP Socket client is closed.");
|
|
||||||
}
|
|
||||||
s_iperf_ctrl.finish = true;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t iperf_run_udp_server(void)
|
|
||||||
{
|
|
||||||
int listen_socket = -1;
|
|
||||||
int opt = 1;
|
|
||||||
int err = 0;
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
struct timeval timeout = { 0 };
|
|
||||||
struct sockaddr_storage listen_addr = { 0 };
|
|
||||||
struct sockaddr_in listen_addr4 = { 0 };
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
struct sockaddr_in6 listen_addr6 = { 0 };
|
|
||||||
ESP_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), ESP_FAIL, exit, TAG, "Ivalid AF types");
|
|
||||||
#else
|
|
||||||
ESP_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), ESP_FAIL, exit, TAG, "Ivalid AF types");
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
|
||||||
// The UDP server listen at the address "::", which means all addresses can be listened to.
|
|
||||||
inet6_aton("::", &listen_addr6.sin6_addr);
|
|
||||||
listen_addr6.sin6_family = AF_INET6;
|
|
||||||
listen_addr6.sin6_port = htons(s_iperf_ctrl.cfg.sport);
|
|
||||||
|
|
||||||
listen_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
ESP_GOTO_ON_FALSE((listen_socket >= 0), ESP_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
|
||||||
ESP_LOGI(TAG, "Socket created");
|
|
||||||
|
|
||||||
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
||||||
|
|
||||||
err = bind(listen_socket, (struct sockaddr *)&listen_addr6, sizeof(struct sockaddr_in6));
|
|
||||||
ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Socket unable to bind: errno %d", errno);
|
|
||||||
ESP_LOGI(TAG, "Socket bound, port %" PRIu16, listen_addr6.sin6_port);
|
|
||||||
|
|
||||||
memcpy(&listen_addr, &listen_addr6, sizeof(listen_addr6));
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
|
||||||
listen_addr4.sin_family = AF_INET;
|
|
||||||
listen_addr4.sin_port = htons(s_iperf_ctrl.cfg.sport);
|
|
||||||
listen_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.source_ip4;
|
|
||||||
|
|
||||||
listen_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
ESP_GOTO_ON_FALSE((listen_socket >= 0), ESP_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
|
||||||
ESP_LOGI(TAG, "Socket created");
|
|
||||||
|
|
||||||
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
||||||
|
|
||||||
err = bind(listen_socket, (struct sockaddr *)&listen_addr4, sizeof(struct sockaddr_in));
|
|
||||||
ESP_GOTO_ON_FALSE((err == 0), ESP_FAIL, exit, TAG, "Socket unable to bind: errno %d", errno);
|
|
||||||
ESP_LOGI(TAG, "Socket bound, port %d", listen_addr4.sin_port);
|
|
||||||
memcpy(&listen_addr, &listen_addr4, sizeof(listen_addr4));
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
|
|
||||||
setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
|
||||||
wifi_cmd_clr_rx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
socket_recv(listen_socket, listen_addr, IPERF_TRANS_TYPE_UDP);
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
|
||||||
wifi_cmd_get_rx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
exit:
|
|
||||||
if (listen_socket != -1) {
|
|
||||||
shutdown(listen_socket, 0);
|
|
||||||
close(listen_socket);
|
|
||||||
}
|
|
||||||
ESP_LOGI(TAG, "Udp socket server is closed.");
|
|
||||||
s_iperf_ctrl.finish = true;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t iperf_run_udp_client(void)
|
|
||||||
{
|
|
||||||
int client_socket = -1;
|
|
||||||
int opt = 1;
|
|
||||||
esp_err_t ret = ESP_OK;
|
|
||||||
struct sockaddr_storage dest_addr = { 0 };
|
|
||||||
struct sockaddr_in dest_addr4 = { 0 };
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
struct sockaddr_in6 dest_addr6 = { 0 };
|
|
||||||
ESP_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6 || s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), ESP_FAIL, exit, TAG, "Ivalid AF types");
|
|
||||||
#else
|
|
||||||
ESP_GOTO_ON_FALSE((s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4), ESP_FAIL, exit, TAG, "Ivalid AF types");
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
|
||||||
inet6_aton(s_iperf_ctrl.cfg.destination_ip6, &dest_addr6.sin6_addr);
|
|
||||||
dest_addr6.sin6_family = AF_INET6;
|
|
||||||
dest_addr6.sin6_port = htons(s_iperf_ctrl.cfg.dport);
|
|
||||||
|
|
||||||
client_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6);
|
|
||||||
ESP_GOTO_ON_FALSE((client_socket >= 0), ESP_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
|
||||||
ESP_LOGI(TAG, "Socket created, sending to %s:%" PRIu16, s_iperf_ctrl.cfg.destination_ip6, s_iperf_ctrl.cfg.dport);
|
|
||||||
|
|
||||||
setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
||||||
memcpy(&dest_addr, &dest_addr6, sizeof(dest_addr6));
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
|
||||||
dest_addr4.sin_family = AF_INET;
|
|
||||||
dest_addr4.sin_port = htons(s_iperf_ctrl.cfg.dport);
|
|
||||||
dest_addr4.sin_addr.s_addr = s_iperf_ctrl.cfg.destination_ip4;
|
|
||||||
|
|
||||||
client_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
ESP_GOTO_ON_FALSE((client_socket >= 0), ESP_FAIL, exit, TAG, "Unable to create socket: errno %d", errno);
|
|
||||||
ESP_LOGI(TAG, "Socket created, sending to %d.%d.%d.%d:%" PRIu16,
|
|
||||||
(uint16_t) s_iperf_ctrl.cfg.destination_ip4 & 0xFF,
|
|
||||||
(uint16_t) (s_iperf_ctrl.cfg.destination_ip4 >> 8) & 0xFF,
|
|
||||||
(uint16_t) (s_iperf_ctrl.cfg.destination_ip4 >> 16) & 0xFF,
|
|
||||||
(uint16_t) (s_iperf_ctrl.cfg.destination_ip4 >> 24) & 0xFF,
|
|
||||||
s_iperf_ctrl.cfg.dport);
|
|
||||||
|
|
||||||
setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
||||||
memcpy(&dest_addr, &dest_addr4, sizeof(dest_addr4));
|
|
||||||
}
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
|
||||||
wifi_cmd_clr_tx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_UDP, s_iperf_ctrl.cfg.bw_lim);
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
|
||||||
wifi_cmd_get_tx_statistics(0, NULL);
|
|
||||||
#endif
|
|
||||||
exit:
|
|
||||||
if (client_socket != -1) {
|
|
||||||
shutdown(client_socket, 0);
|
|
||||||
close(client_socket);
|
|
||||||
}
|
|
||||||
s_iperf_ctrl.finish = true;
|
|
||||||
ESP_LOGI(TAG, "UDP Socket client is closed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iperf_task_traffic(void *arg)
|
|
||||||
{
|
|
||||||
if (iperf_is_udp_client()) {
|
|
||||||
iperf_run_udp_client();
|
|
||||||
} else if (iperf_is_udp_server()) {
|
|
||||||
iperf_run_udp_server();
|
|
||||||
} else if (iperf_is_tcp_client()) {
|
|
||||||
iperf_run_tcp_client();
|
|
||||||
} else {
|
|
||||||
iperf_run_tcp_server();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_iperf_ctrl.buffer) {
|
|
||||||
free(s_iperf_ctrl.buffer);
|
|
||||||
s_iperf_ctrl.buffer = NULL;
|
|
||||||
}
|
|
||||||
ESP_LOGI(TAG, "iperf exit");
|
|
||||||
s_iperf_is_running = false;
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t iperf_get_buffer_len(void)
|
|
||||||
{
|
|
||||||
if (iperf_is_udp_client()) {
|
|
||||||
#ifdef CONFIG_LWIP_IPV6
|
|
||||||
if (s_iperf_ctrl.cfg.len_send_buf) {
|
|
||||||
return s_iperf_ctrl.cfg.len_send_buf;
|
|
||||||
} else if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
|
||||||
return IPERF_DEFAULT_IPV6_UDP_TX_LEN;
|
|
||||||
} else {
|
|
||||||
return IPERF_DEFAULT_IPV4_UDP_TX_LEN;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return (s_iperf_ctrl.cfg.len_send_buf == 0 ? IPERF_DEFAULT_IPV4_UDP_TX_LEN : s_iperf_ctrl.cfg.len_send_buf);
|
|
||||||
#endif
|
|
||||||
} else if (iperf_is_udp_server()) {
|
|
||||||
return IPERF_DEFAULT_UDP_RX_LEN;
|
|
||||||
} else if (iperf_is_tcp_client()) {
|
|
||||||
return (s_iperf_ctrl.cfg.len_send_buf == 0 ? IPERF_DEFAULT_TCP_TX_LEN : s_iperf_ctrl.cfg.len_send_buf);
|
|
||||||
} else {
|
|
||||||
return IPERF_DEFAULT_TCP_RX_LEN;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t iperf_start(iperf_cfg_t *cfg)
|
|
||||||
{
|
|
||||||
BaseType_t ret;
|
|
||||||
|
|
||||||
if (!cfg) {
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_iperf_is_running) {
|
|
||||||
ESP_LOGW(TAG, "iperf is running");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&s_iperf_ctrl, 0, sizeof(s_iperf_ctrl));
|
|
||||||
memcpy(&s_iperf_ctrl.cfg, cfg, sizeof(*cfg));
|
|
||||||
s_iperf_is_running = true;
|
|
||||||
s_iperf_ctrl.finish = false;
|
|
||||||
s_iperf_ctrl.buffer_len = iperf_get_buffer_len();
|
|
||||||
s_iperf_ctrl.buffer = (uint8_t *)malloc(s_iperf_ctrl.buffer_len);
|
|
||||||
if (!s_iperf_ctrl.buffer) {
|
|
||||||
ESP_LOGE(TAG, "create buffer: not enough memory");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
memset(s_iperf_ctrl.buffer, 0, s_iperf_ctrl.buffer_len);
|
|
||||||
ret = xTaskCreatePinnedToCore(iperf_task_traffic, IPERF_TRAFFIC_TASK_NAME, IPERF_TRAFFIC_TASK_STACK, NULL, IPERF_TRAFFIC_TASK_PRIORITY, NULL, CONFIG_FREERTOS_NUMBER_OF_CORES - 1);
|
|
||||||
if (ret != pdPASS) {
|
|
||||||
ESP_LOGE(TAG, "create task %s failed", IPERF_TRAFFIC_TASK_NAME);
|
|
||||||
free(s_iperf_ctrl.buffer);
|
|
||||||
s_iperf_ctrl.buffer = NULL;
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t iperf_stop(void)
|
|
||||||
{
|
|
||||||
if (s_iperf_is_running) {
|
|
||||||
s_iperf_ctrl.finish = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (s_iperf_is_running) {
|
|
||||||
ESP_LOGI(TAG, "wait current iperf to stop ...");
|
|
||||||
vTaskDelay(300 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -38,7 +38,6 @@ examples/ethernet/iperf:
|
|||||||
- esp_driver_gpio
|
- esp_driver_gpio
|
||||||
- esp_driver_spi
|
- esp_driver_spi
|
||||||
depends_filepatterns:
|
depends_filepatterns:
|
||||||
- examples/common_components/iperf/**/*
|
|
||||||
- examples/common_components/protocol_examples_common/**/*
|
- examples/common_components/protocol_examples_common/**/*
|
||||||
- examples/system/console/advanced/components/cmd_system/**/*
|
- examples/system/console/advanced/components/cmd_system/**/*
|
||||||
- examples/ethernet/basic/components/ethernet_init/**/*
|
- examples/ethernet/basic/components/ethernet_init/**/*
|
||||||
|
@ -3,5 +3,5 @@ dependencies:
|
|||||||
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system
|
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system
|
||||||
ethernet_init:
|
ethernet_init:
|
||||||
path: ${IDF_PATH}/examples/ethernet/basic/components/ethernet_init
|
path: ${IDF_PATH}/examples/ethernet/basic/components/ethernet_init
|
||||||
iperf:
|
espressif/iperf:
|
||||||
path: ${IDF_PATH}/examples/common_components/iperf
|
version: "~0.1.1"
|
||||||
|
@ -11,8 +11,6 @@
|
|||||||
- lwip
|
- lwip
|
||||||
- openthread
|
- openthread
|
||||||
depends_filepatterns:
|
depends_filepatterns:
|
||||||
- examples/common_components/iperf/*
|
|
||||||
- examples/common_components/iperf/**/*
|
|
||||||
- examples/openthread/*
|
- examples/openthread/*
|
||||||
- examples/openthread/**/*
|
- examples/openthread/**/*
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ dependencies:
|
|||||||
version: ">=5.0"
|
version: ">=5.0"
|
||||||
protocol_examples_common:
|
protocol_examples_common:
|
||||||
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
|
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
|
||||||
iperf:
|
|
||||||
path: ${IDF_PATH}/examples/common_components/iperf
|
|
||||||
ot_led:
|
ot_led:
|
||||||
path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_led
|
path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_led
|
||||||
|
espressif/iperf:
|
||||||
|
version: "~0.1.1"
|
||||||
|
@ -4,7 +4,7 @@ dependencies:
|
|||||||
version: "~1.0.0"
|
version: "~1.0.0"
|
||||||
idf:
|
idf:
|
||||||
version: ">=4.1.0"
|
version: ">=4.1.0"
|
||||||
iperf:
|
|
||||||
path: ${IDF_PATH}/examples/common_components/iperf
|
|
||||||
ot_led:
|
ot_led:
|
||||||
path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_led
|
path: ${IDF_PATH}/examples/openthread/ot_common_components/ot_led
|
||||||
|
espressif/iperf:
|
||||||
|
version: "~0.1.1"
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
idf_component_register(SRCS "cmd_wifi.c"
|
idf_component_register(SRCS "iperf_example_main.c"
|
||||||
"iperf_example_main.c"
|
|
||||||
INCLUDE_DIRS ".")
|
INCLUDE_DIRS ".")
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
/* Iperf example — declarations of command registration functions.
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "cmd_system.h"
|
|
||||||
#include "cmd_wifi.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,616 +0,0 @@
|
|||||||
/* Iperf Example - wifi commands
|
|
||||||
|
|
||||||
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 <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_console.h"
|
|
||||||
#include "argtable3/argtable3.h"
|
|
||||||
#include "cmd_decl.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/event_groups.h"
|
|
||||||
#include "esp_wifi.h"
|
|
||||||
#include "esp_netif.h"
|
|
||||||
#include "esp_event.h"
|
|
||||||
#include "esp_mac.h"
|
|
||||||
#include "iperf.h"
|
|
||||||
#include "esp_coexist.h"
|
|
||||||
#include "wifi_cmd.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
struct arg_str *ip;
|
|
||||||
struct arg_lit *server;
|
|
||||||
struct arg_lit *udp;
|
|
||||||
struct arg_lit *version;
|
|
||||||
struct arg_int *port;
|
|
||||||
struct arg_int *length;
|
|
||||||
struct arg_int *interval;
|
|
||||||
struct arg_int *time;
|
|
||||||
struct arg_int *bw_limit;
|
|
||||||
struct arg_lit *abort;
|
|
||||||
struct arg_end *end;
|
|
||||||
} wifi_iperf_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
struct arg_str *ssid;
|
|
||||||
struct arg_str *password;
|
|
||||||
struct arg_end *end;
|
|
||||||
} wifi_args_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
struct arg_str *ssid;
|
|
||||||
struct arg_end *end;
|
|
||||||
} wifi_scan_arg_t;
|
|
||||||
|
|
||||||
static wifi_iperf_t iperf_args;
|
|
||||||
static wifi_args_t sta_args;
|
|
||||||
static wifi_scan_arg_t scan_args;
|
|
||||||
static wifi_args_t ap_args;
|
|
||||||
static bool reconnect = true;
|
|
||||||
static const char *TAG = "cmd_wifi";
|
|
||||||
esp_netif_t *netif_ap = NULL;
|
|
||||||
esp_netif_t *netif_sta = NULL;
|
|
||||||
|
|
||||||
EventGroupHandle_t wifi_event_group;
|
|
||||||
const int CONNECTED_BIT = BIT0;
|
|
||||||
const int DISCONNECTED_BIT = BIT1;
|
|
||||||
|
|
||||||
static void scan_done_handler(void *arg, esp_event_base_t event_base,
|
|
||||||
int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
uint16_t sta_number = 0;
|
|
||||||
uint8_t i;
|
|
||||||
wifi_ap_record_t *ap_list_buffer;
|
|
||||||
|
|
||||||
esp_wifi_scan_get_ap_num(&sta_number);
|
|
||||||
if (!sta_number) {
|
|
||||||
ESP_LOGE(TAG, "No AP found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ap_list_buffer = malloc(sta_number * sizeof(wifi_ap_record_t));
|
|
||||||
if (ap_list_buffer == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to malloc buffer to print scan results");
|
|
||||||
esp_wifi_clear_ap_list();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_wifi_scan_get_ap_records(&sta_number, (wifi_ap_record_t *)ap_list_buffer) == ESP_OK) {
|
|
||||||
for (i = 0; i < sta_number; i++) {
|
|
||||||
#if CONFIG_SOC_WIFI_HE_SUPPORT
|
|
||||||
char ssid_rssi[46] = { 0, };
|
|
||||||
sprintf(ssid_rssi, "[%s][rssi=%d]", ap_list_buffer[i].ssid, ap_list_buffer[i].rssi);
|
|
||||||
if (ap_list_buffer[i].phy_11ax) {
|
|
||||||
ESP_LOGW(TAG,
|
|
||||||
"[%2d]%45s authmode:0x%x, channel:%2d[%d], phymode:%4s, "MACSTR", bssid-index:%d, bss_color:%d, disabled:%d",
|
|
||||||
i, ssid_rssi, ap_list_buffer[i].authmode,
|
|
||||||
ap_list_buffer[i].primary, ap_list_buffer[i].second,
|
|
||||||
ap_list_buffer[i].phy_11ax ? "11ax" : (ap_list_buffer[i].phy_11n ? "11n" :
|
|
||||||
(ap_list_buffer[i].phy_11g ? "11g" : (ap_list_buffer[i].phy_11b ? "11b" : ""))),
|
|
||||||
MAC2STR(ap_list_buffer[i].bssid), ap_list_buffer[i].he_ap.bssid_index,
|
|
||||||
ap_list_buffer[i].he_ap.bss_color, ap_list_buffer[i].he_ap.bss_color_disabled);
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(TAG,
|
|
||||||
"[%2d]%45s authmode:0x%x, channel:%2d[%d], phymode:%4s, "MACSTR"",
|
|
||||||
i, ssid_rssi, ap_list_buffer[i].authmode,
|
|
||||||
ap_list_buffer[i].primary, ap_list_buffer[i].second,
|
|
||||||
ap_list_buffer[i].phy_11ax ? "11ax" : (ap_list_buffer[i].phy_11n ? "11n" :
|
|
||||||
(ap_list_buffer[i].phy_11g ? "11g" : (ap_list_buffer[i].phy_11b ? "11b" : ""))),
|
|
||||||
MAC2STR(ap_list_buffer[i].bssid));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ESP_LOGI(TAG, "[%s][rssi=%d]", ap_list_buffer[i].ssid, ap_list_buffer[i].rssi);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(ap_list_buffer);
|
|
||||||
ESP_LOGI(TAG, "sta scan done");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void got_ip_handler(void *arg, esp_event_base_t event_base,
|
|
||||||
int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
xEventGroupClearBits(wifi_event_group, DISCONNECTED_BIT);
|
|
||||||
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void disconnect_handler(void *arg, esp_event_base_t event_base,
|
|
||||||
int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
if (reconnect) {
|
|
||||||
ESP_LOGI(TAG, "sta disconnect, reconnect...");
|
|
||||||
esp_wifi_connect();
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(TAG, "sta disconnect");
|
|
||||||
}
|
|
||||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
|
||||||
xEventGroupSetBits(wifi_event_group, DISCONNECTED_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void initialise_wifi(void)
|
|
||||||
{
|
|
||||||
esp_log_level_set("wifi", ESP_LOG_WARN);
|
|
||||||
static bool initialized = false;
|
|
||||||
|
|
||||||
if (initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_netif_init());
|
|
||||||
wifi_event_group = xEventGroupCreate();
|
|
||||||
ESP_ERROR_CHECK( esp_event_loop_create_default() );
|
|
||||||
netif_ap = esp_netif_create_default_wifi_ap();
|
|
||||||
assert(netif_ap);
|
|
||||||
netif_sta = esp_netif_create_default_wifi_sta();
|
|
||||||
assert(netif_sta);
|
|
||||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
|
||||||
WIFI_EVENT_SCAN_DONE,
|
|
||||||
&scan_done_handler,
|
|
||||||
NULL,
|
|
||||||
NULL));
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
|
||||||
WIFI_EVENT_STA_DISCONNECTED,
|
|
||||||
&disconnect_handler,
|
|
||||||
NULL,
|
|
||||||
NULL));
|
|
||||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
|
|
||||||
IP_EVENT_STA_GOT_IP,
|
|
||||||
&got_ip_handler,
|
|
||||||
NULL,
|
|
||||||
NULL));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) );
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL) );
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_start() );
|
|
||||||
|
|
||||||
#if CONFIG_EXTERNAL_COEX_ENABLE
|
|
||||||
esp_external_coex_gpio_set_t gpio_pin;
|
|
||||||
gpio_pin.request = 1;
|
|
||||||
gpio_pin.priority = 2;
|
|
||||||
gpio_pin.grant = 3;
|
|
||||||
#if SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
|
||||||
gpio_pin.tx_line = 4;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
esp_external_coex_set_work_mode(EXTERNAL_COEX_LEADER_ROLE);
|
|
||||||
#if SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
|
||||||
ESP_ERROR_CHECK(esp_enable_extern_coex_gpio_pin(EXTERN_COEX_WIRE_4, gpio_pin));
|
|
||||||
#else
|
|
||||||
ESP_ERROR_CHECK(esp_enable_extern_coex_gpio_pin(EXTERN_COEX_WIRE_3, gpio_pin));
|
|
||||||
#endif /* SOC_EXTERNAL_COEX_LEADER_TX_LINE */
|
|
||||||
#endif /* CONFIG_EXTERNAL_COEX_ENABLE */
|
|
||||||
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_MU_STATS
|
|
||||||
esp_wifi_enable_rx_statistics(true, true);
|
|
||||||
#else
|
|
||||||
esp_wifi_enable_rx_statistics(true, false);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
|
||||||
esp_wifi_enable_tx_statistics(ESP_WIFI_ACI_BE, true);
|
|
||||||
#endif
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool wifi_cmd_sta_join(const char *ssid, const char *pass, bool enable_he_mcs9)
|
|
||||||
{
|
|
||||||
int bits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, 0, 1, 0);
|
|
||||||
|
|
||||||
wifi_config_t wifi_config = { 0 };
|
|
||||||
|
|
||||||
strlcpy((char *) wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
|
|
||||||
if (pass) {
|
|
||||||
strlcpy((char *) wifi_config.sta.password, pass, sizeof(wifi_config.sta.password));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable_he_mcs9 == true) {
|
|
||||||
wifi_config.sta.he_mcs9_enabled = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bits & CONNECTED_BIT) {
|
|
||||||
reconnect = false;
|
|
||||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
|
||||||
ESP_ERROR_CHECK( esp_wifi_disconnect() );
|
|
||||||
xEventGroupWaitBits(wifi_event_group, DISCONNECTED_BIT, 0, 1, portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
|
|
||||||
reconnect = true;
|
|
||||||
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
|
|
||||||
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
|
|
||||||
esp_wifi_connect();
|
|
||||||
|
|
||||||
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, 0, 1, 5000 / portTICK_PERIOD_MS);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wifi_cmd_sta(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int nerrors = arg_parse(argc, argv, (void **) &sta_args);
|
|
||||||
|
|
||||||
if (nerrors != 0) {
|
|
||||||
arg_print_errors(stderr, sta_args.end, argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "sta connecting to '%s'", sta_args.ssid->sval[0]);
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
|
||||||
wifi_cmd_sta_join(sta_args.ssid->sval[0], sta_args.password->sval[0], false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wifi_cmd_sta40(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int nerrors = arg_parse(argc, argv, (void **) &sta_args);
|
|
||||||
|
|
||||||
if (nerrors != 0) {
|
|
||||||
arg_print_errors(stderr, sta_args.end, argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_protocol(0, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_bandwidth(0, WIFI_BW_HT40));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "sta connecting to '%s'", sta_args.ssid->sval[0]);
|
|
||||||
wifi_cmd_sta_join(sta_args.ssid->sval[0], sta_args.password->sval[0], false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wifi_cmd_sta_mcs89(int argc, char **argv)
|
|
||||||
{
|
|
||||||
#if CONFIG_SOC_WIFI_HE_SUPPORT
|
|
||||||
int nerrors = arg_parse(argc, argv, (void **) &sta_args);
|
|
||||||
if (nerrors != 0) {
|
|
||||||
arg_print_errors(stderr, sta_args.end, argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_protocol(0, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_bandwidth(0, WIFI_BW_HT20));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "sta connecting to '%s'", sta_args.ssid->sval[0]);
|
|
||||||
wifi_cmd_sta_join(sta_args.ssid->sval[0], sta_args.password->sval[0], true);
|
|
||||||
#else
|
|
||||||
ESP_LOGW(TAG, "HE-MCS[0, 9] is not supported");
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool wifi_cmd_sta_scan(const char *ssid)
|
|
||||||
{
|
|
||||||
wifi_scan_config_t scan_config = { 0 };
|
|
||||||
scan_config.ssid = (uint8_t *) ssid;
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
|
|
||||||
esp_wifi_scan_start(&scan_config, false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wifi_cmd_scan(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int nerrors = arg_parse(argc, argv, (void **) &scan_args);
|
|
||||||
|
|
||||||
if (nerrors != 0) {
|
|
||||||
arg_print_errors(stderr, scan_args.end, argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "sta start to scan");
|
|
||||||
if ( scan_args.ssid->count == 1 ) {
|
|
||||||
wifi_cmd_sta_scan(scan_args.ssid->sval[0]);
|
|
||||||
} else {
|
|
||||||
wifi_cmd_sta_scan(NULL);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool wifi_cmd_ap_set(const char *ssid, const char *pass)
|
|
||||||
{
|
|
||||||
wifi_config_t wifi_config = {
|
|
||||||
.ap = {
|
|
||||||
.ssid = "",
|
|
||||||
.ssid_len = 0,
|
|
||||||
.max_connection = 4,
|
|
||||||
.password = "",
|
|
||||||
.authmode = WIFI_AUTH_WPA_WPA2_PSK
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
reconnect = false;
|
|
||||||
strlcpy((char *) wifi_config.ap.ssid, ssid, sizeof(wifi_config.ap.ssid));
|
|
||||||
if (pass) {
|
|
||||||
if (strlen(pass) != 0 && strlen(pass) < 8) {
|
|
||||||
reconnect = true;
|
|
||||||
ESP_LOGE(TAG, "password less than 8");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
strlcpy((char *) wifi_config.ap.password, pass, sizeof(wifi_config.ap.password));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(pass) == 0) {
|
|
||||||
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wifi_cmd_ap(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int nerrors = arg_parse(argc, argv, (void **) &ap_args);
|
|
||||||
|
|
||||||
if (nerrors != 0) {
|
|
||||||
arg_print_errors(stderr, ap_args.end, argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
wifi_cmd_ap_set(ap_args.ssid->sval[0], ap_args.password->sval[0]);
|
|
||||||
ESP_LOGI(TAG, "AP mode, %s %s", ap_args.ssid->sval[0], ap_args.password->sval[0]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wifi_cmd_query(int argc, char **argv)
|
|
||||||
{
|
|
||||||
wifi_config_t cfg;
|
|
||||||
wifi_mode_t mode;
|
|
||||||
|
|
||||||
esp_wifi_get_mode(&mode);
|
|
||||||
if (WIFI_MODE_AP == mode) {
|
|
||||||
esp_wifi_get_config(WIFI_IF_AP, &cfg);
|
|
||||||
ESP_LOGI(TAG, "AP mode, %s %s", cfg.ap.ssid, cfg.ap.password);
|
|
||||||
} else if (WIFI_MODE_STA == mode) {
|
|
||||||
int bits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, 0, 1, 0);
|
|
||||||
if (bits & CONNECTED_BIT) {
|
|
||||||
esp_wifi_get_config(WIFI_IF_STA, &cfg);
|
|
||||||
ESP_LOGI(TAG, "sta mode, connected %s", cfg.ap.ssid);
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(TAG, "sta mode, disconnected");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ESP_LOGI(TAG, "NULL mode");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t wifi_get_local_ip(void)
|
|
||||||
{
|
|
||||||
int bits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, 0, 1, 0);
|
|
||||||
esp_netif_t *netif = netif_ap;
|
|
||||||
esp_netif_ip_info_t ip_info;
|
|
||||||
wifi_mode_t mode;
|
|
||||||
|
|
||||||
esp_wifi_get_mode(&mode);
|
|
||||||
if (WIFI_MODE_STA == mode) {
|
|
||||||
bits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, 0, 1, 0);
|
|
||||||
if (bits & CONNECTED_BIT) {
|
|
||||||
netif = netif_sta;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "sta has no IP");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_netif_get_ip_info(netif, &ip_info);
|
|
||||||
return ip_info.ip.addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wifi_cmd_iperf(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int nerrors = arg_parse(argc, argv, (void **) &iperf_args);
|
|
||||||
iperf_cfg_t cfg;
|
|
||||||
|
|
||||||
if (nerrors != 0) {
|
|
||||||
arg_print_errors(stderr, iperf_args.end, argv[0]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&cfg, 0, sizeof(cfg));
|
|
||||||
|
|
||||||
// now wifi iperf only support IPV4 address
|
|
||||||
cfg.type = IPERF_IP_TYPE_IPV4;
|
|
||||||
|
|
||||||
if ( iperf_args.abort->count != 0) {
|
|
||||||
iperf_stop();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ((iperf_args.ip->count == 0) && (iperf_args.server->count == 0)) ||
|
|
||||||
((iperf_args.ip->count != 0) && (iperf_args.server->count != 0)) ) {
|
|
||||||
ESP_LOGE(TAG, "should specific client/server mode");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iperf_args.ip->count == 0) {
|
|
||||||
cfg.flag |= IPERF_FLAG_SERVER;
|
|
||||||
} else {
|
|
||||||
cfg.destination_ip4 = esp_ip4addr_aton(iperf_args.ip->sval[0]);
|
|
||||||
cfg.flag |= IPERF_FLAG_CLIENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.source_ip4 = wifi_get_local_ip();
|
|
||||||
if (cfg.source_ip4 == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iperf_args.udp->count == 0) {
|
|
||||||
cfg.flag |= IPERF_FLAG_TCP;
|
|
||||||
} else {
|
|
||||||
cfg.flag |= IPERF_FLAG_UDP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iperf_args.length->count == 0) {
|
|
||||||
cfg.len_send_buf = 0;
|
|
||||||
} else {
|
|
||||||
cfg.len_send_buf = iperf_args.length->ival[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iperf_args.port->count == 0) {
|
|
||||||
cfg.sport = IPERF_DEFAULT_PORT;
|
|
||||||
cfg.dport = IPERF_DEFAULT_PORT;
|
|
||||||
} else {
|
|
||||||
if (cfg.flag & IPERF_FLAG_SERVER) {
|
|
||||||
cfg.sport = iperf_args.port->ival[0];
|
|
||||||
cfg.dport = IPERF_DEFAULT_PORT;
|
|
||||||
} else {
|
|
||||||
cfg.sport = IPERF_DEFAULT_PORT;
|
|
||||||
cfg.dport = iperf_args.port->ival[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iperf_args.interval->count == 0) {
|
|
||||||
cfg.interval = IPERF_DEFAULT_INTERVAL;
|
|
||||||
} else {
|
|
||||||
cfg.interval = iperf_args.interval->ival[0];
|
|
||||||
if (cfg.interval <= 0) {
|
|
||||||
cfg.interval = IPERF_DEFAULT_INTERVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iperf_args.time->count == 0) {
|
|
||||||
cfg.time = IPERF_DEFAULT_TIME;
|
|
||||||
} else {
|
|
||||||
cfg.time = iperf_args.time->ival[0];
|
|
||||||
if (cfg.time <= cfg.interval) {
|
|
||||||
cfg.time = cfg.interval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* iperf -b */
|
|
||||||
if (iperf_args.bw_limit->count == 0) {
|
|
||||||
cfg.bw_lim = IPERF_DEFAULT_NO_BW_LIMIT;
|
|
||||||
} else {
|
|
||||||
cfg.bw_lim = iperf_args.bw_limit->ival[0];
|
|
||||||
if (cfg.bw_lim <= 0) {
|
|
||||||
cfg.bw_lim = IPERF_DEFAULT_NO_BW_LIMIT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "mode=%s-%s sip=%" PRId32 ".%" PRId32 ".%" PRId32 ".%" PRId32 ":%d,\
|
|
||||||
dip=%" PRId32 ".%" PRId32 ".%" PRId32 ".%" PRId32 ":%d,\
|
|
||||||
interval=%" PRId32 ", time=%" PRId32 "",
|
|
||||||
cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp",
|
|
||||||
cfg.flag & IPERF_FLAG_SERVER ? "server" : "client",
|
|
||||||
cfg.source_ip4 & 0xFF, (cfg.source_ip4 >> 8) & 0xFF, (cfg.source_ip4 >> 16) & 0xFF,
|
|
||||||
(cfg.source_ip4 >> 24) & 0xFF, cfg.sport,
|
|
||||||
cfg.destination_ip4 & 0xFF, (cfg.destination_ip4 >> 8) & 0xFF,
|
|
||||||
(cfg.destination_ip4 >> 16) & 0xFF, (cfg.destination_ip4 >> 24) & 0xFF, cfg.dport,
|
|
||||||
cfg.interval, cfg.time);
|
|
||||||
|
|
||||||
iperf_start(&cfg);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void register_wifi(void)
|
|
||||||
{
|
|
||||||
sta_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
|
|
||||||
sta_args.password = arg_str0(NULL, NULL, "<pass>", "password of AP");
|
|
||||||
sta_args.end = arg_end(2);
|
|
||||||
|
|
||||||
const esp_console_cmd_t sta_cmd = {
|
|
||||||
.command = "sta",
|
|
||||||
.help = "WiFi is station mode, join specified soft-AP",
|
|
||||||
.hint = NULL,
|
|
||||||
.func = &wifi_cmd_sta,
|
|
||||||
.argtable = &sta_args
|
|
||||||
};
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK( esp_console_cmd_register(&sta_cmd) );
|
|
||||||
|
|
||||||
const esp_console_cmd_t sta40_cmd = {
|
|
||||||
.command = "sta40",
|
|
||||||
.help = "WiFi is station mode, set protocol to bgn and cbw to 40MHz, join a specified AP",
|
|
||||||
.hint = NULL,
|
|
||||||
.func = &wifi_cmd_sta40,
|
|
||||||
.argtable = &sta_args
|
|
||||||
};
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK( esp_console_cmd_register(&sta40_cmd) );
|
|
||||||
|
|
||||||
const esp_console_cmd_t stamcs89_cmd = {
|
|
||||||
.command = "stamcs89",
|
|
||||||
.help = "WiFi is station mode, set protocol to ax and mcs set to HE-MCS[0,9], join a specified AP",
|
|
||||||
.hint = NULL,
|
|
||||||
.func = &wifi_cmd_sta_mcs89,
|
|
||||||
.argtable = &sta_args
|
|
||||||
};
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK( esp_console_cmd_register(&stamcs89_cmd) );
|
|
||||||
|
|
||||||
scan_args.ssid = arg_str0(NULL, NULL, "<ssid>", "SSID of AP want to be scanned");
|
|
||||||
scan_args.end = arg_end(1);
|
|
||||||
|
|
||||||
const esp_console_cmd_t scan_cmd = {
|
|
||||||
.command = "scan",
|
|
||||||
.help = "WiFi is station mode, start scan ap",
|
|
||||||
.hint = NULL,
|
|
||||||
.func = &wifi_cmd_scan,
|
|
||||||
.argtable = &scan_args
|
|
||||||
};
|
|
||||||
|
|
||||||
ap_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
|
|
||||||
ap_args.password = arg_str0(NULL, NULL, "<pass>", "password of AP");
|
|
||||||
ap_args.end = arg_end(2);
|
|
||||||
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK( esp_console_cmd_register(&scan_cmd) );
|
|
||||||
|
|
||||||
const esp_console_cmd_t ap_cmd = {
|
|
||||||
.command = "ap",
|
|
||||||
.help = "AP mode, configure ssid and password",
|
|
||||||
.hint = NULL,
|
|
||||||
.func = &wifi_cmd_ap,
|
|
||||||
.argtable = &ap_args
|
|
||||||
};
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK( esp_console_cmd_register(&ap_cmd) );
|
|
||||||
|
|
||||||
const esp_console_cmd_t query_cmd = {
|
|
||||||
.command = "query",
|
|
||||||
.help = "query WiFi info",
|
|
||||||
.hint = NULL,
|
|
||||||
.func = &wifi_cmd_query,
|
|
||||||
};
|
|
||||||
ESP_ERROR_CHECK( esp_console_cmd_register(&query_cmd) );
|
|
||||||
|
|
||||||
iperf_args.ip = arg_str0("c", "client", "<ip>", "run in client mode, connecting to <host>");
|
|
||||||
iperf_args.server = arg_lit0("s", "server", "run in server mode");
|
|
||||||
iperf_args.udp = arg_lit0("u", "udp", "use UDP rather than TCP");
|
|
||||||
iperf_args.version = arg_lit0("V", "ipv6_domain", "use IPV6 address rather than IPV4");
|
|
||||||
iperf_args.port = arg_int0("p", "port", "<port>", "server port to listen on/connect to");
|
|
||||||
iperf_args.length = arg_int0("l", "len", "<length>", "Set read/write buffer size");
|
|
||||||
iperf_args.interval = arg_int0("i", "interval", "<interval>", "seconds between periodic bandwidth reports");
|
|
||||||
iperf_args.time = arg_int0("t", "time", "<time>", "time in seconds to transmit for (default 10 secs)");
|
|
||||||
iperf_args.bw_limit = arg_int0("b", "bandwidth", "<bandwidth>", "bandwidth to send at in Mbits/sec");
|
|
||||||
iperf_args.abort = arg_lit0("a", "abort", "abort running iperf");
|
|
||||||
iperf_args.end = arg_end(1);
|
|
||||||
const esp_console_cmd_t iperf_cmd = {
|
|
||||||
.command = "iperf",
|
|
||||||
.help = "iperf command",
|
|
||||||
.hint = NULL,
|
|
||||||
.func = &wifi_cmd_iperf,
|
|
||||||
.argtable = &iperf_args
|
|
||||||
};
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK( esp_console_cmd_register(&iperf_cmd) );
|
|
||||||
|
|
||||||
register_wifi_cmd();
|
|
||||||
register_wifi_stats();
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Register WiFi functions
|
|
||||||
void register_wifi(void);
|
|
||||||
void initialise_wifi(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,5 +1,9 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
cmd_system:
|
cmd_system:
|
||||||
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system
|
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system
|
||||||
iperf:
|
espressif/iperf-cmd:
|
||||||
path: ${IDF_PATH}/examples/common_components/iperf
|
version: "~0.1.1"
|
||||||
|
esp-qa/wifi-cmd:
|
||||||
|
version: "~0.0.2"
|
||||||
|
esp-qa/ping-cmd:
|
||||||
|
version: "~0.0.1"
|
||||||
|
@ -14,7 +14,58 @@
|
|||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "esp_console.h"
|
#include "esp_console.h"
|
||||||
#include "cmd_decl.h"
|
#include "cmd_system.h"
|
||||||
|
|
||||||
|
/* component manager */
|
||||||
|
#include "iperf.h"
|
||||||
|
#include "wifi_cmd.h"
|
||||||
|
#include "iperf_cmd.h"
|
||||||
|
#include "ping_cmd.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS || CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
||||||
|
#include "esp_wifi_he.h"
|
||||||
|
#endif
|
||||||
|
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
||||||
|
extern int wifi_cmd_get_tx_statistics(int argc, char **argv);
|
||||||
|
extern int wifi_cmd_clr_tx_statistics(int argc, char **argv);
|
||||||
|
#endif
|
||||||
|
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
||||||
|
extern int wifi_cmd_get_rx_statistics(int argc, char **argv);
|
||||||
|
extern int wifi_cmd_clr_rx_statistics(int argc, char **argv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void iperf_hook_show_wifi_stats(iperf_traffic_type_t type, iperf_status_t status)
|
||||||
|
{
|
||||||
|
if (status == IPERF_STARTED) {
|
||||||
|
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
||||||
|
if (type != IPERF_UDP_SERVER) {
|
||||||
|
wifi_cmd_clr_tx_statistics(0, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
||||||
|
if (type != IPERF_UDP_CLIENT) {
|
||||||
|
wifi_cmd_clr_rx_statistics(0, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == IPERF_STOPPED) {
|
||||||
|
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
||||||
|
if (type != IPERF_UDP_SERVER) {
|
||||||
|
wifi_cmd_get_tx_statistics(0, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
||||||
|
if (type != IPERF_UDP_SERVER) {
|
||||||
|
wifi_cmd_get_rx_statistics(0, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
@ -25,7 +76,22 @@ void app_main(void)
|
|||||||
}
|
}
|
||||||
ESP_ERROR_CHECK( ret );
|
ESP_ERROR_CHECK( ret );
|
||||||
|
|
||||||
initialise_wifi();
|
/* initialise wifi */
|
||||||
|
app_wifi_initialise_config_t config = APP_WIFI_CONFIG_DEFAULT();
|
||||||
|
config.storage = WIFI_STORAGE_RAM;
|
||||||
|
config.ps_type = WIFI_PS_NONE;
|
||||||
|
app_initialise_wifi(&config);
|
||||||
|
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_STATS
|
||||||
|
#if CONFIG_ESP_WIFI_ENABLE_WIFI_RX_MU_STATS
|
||||||
|
esp_wifi_enable_rx_statistics(true, true);
|
||||||
|
#else
|
||||||
|
esp_wifi_enable_rx_statistics(true, false);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if CONFIG_ESP_WIFI_ENABLE_WIFI_TX_STATS
|
||||||
|
esp_wifi_enable_tx_statistics(ESP_WIFI_ACI_BE, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
esp_console_repl_t *repl = NULL;
|
esp_console_repl_t *repl = NULL;
|
||||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||||
@ -45,7 +111,11 @@ void app_main(void)
|
|||||||
|
|
||||||
/* Register commands */
|
/* Register commands */
|
||||||
register_system();
|
register_system();
|
||||||
register_wifi();
|
app_register_all_wifi_commands();
|
||||||
|
app_register_iperf_commands();
|
||||||
|
app_register_ping_commands();
|
||||||
|
app_register_iperf_hook_func(iperf_hook_show_wifi_stats);
|
||||||
|
|
||||||
|
|
||||||
printf("\n ==================================================\n");
|
printf("\n ==================================================\n");
|
||||||
printf(" | Steps to test WiFi throughput |\n");
|
printf(" | Steps to test WiFi throughput |\n");
|
||||||
|
@ -16,19 +16,12 @@ The test env wifi_iperf do need the following config::
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import time
|
|
||||||
from typing import Any
|
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
import pexpect
|
|
||||||
import pytest
|
import pytest
|
||||||
from common_test_methods import get_env_config_variable
|
from common_test_methods import get_env_config_variable
|
||||||
from common_test_methods import get_host_ip_by_interface
|
from common_test_methods import get_host_ip_by_interface
|
||||||
from idf_iperf_test_util import IperfUtility
|
from idf_iperf_test_util import IperfUtility
|
||||||
from idf_iperf_test_util.IperfUtility import SCAN_RETRY_COUNT
|
|
||||||
from idf_iperf_test_util.IperfUtility import SCAN_TIMEOUT
|
|
||||||
from idf_iperf_test_util.IperfUtility import TEST_TIME
|
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
# configurations
|
# configurations
|
||||||
@ -39,105 +32,6 @@ NO_BANDWIDTH_LIMIT = -1 # iperf send bandwith is not limited
|
|||||||
BEST_PERFORMANCE_CONFIG = '99'
|
BEST_PERFORMANCE_CONFIG = '99'
|
||||||
|
|
||||||
|
|
||||||
class IperfTestUtilitySoftap(IperfUtility.IperfTestUtility):
|
|
||||||
""" iperf test implementation """
|
|
||||||
def __init__(self, dut: Dut, softap_dut: Dut, config_name:str, test_result:Any=None) -> None:
|
|
||||||
IperfUtility.IperfTestUtility.__init__(self, dut, config_name, 'softap', '1234567890', None, None, test_result)
|
|
||||||
self.softap_dut = softap_dut
|
|
||||||
self.softap_ip = '192.168.4.1'
|
|
||||||
|
|
||||||
def setup(self) -> Tuple[str,int]:
|
|
||||||
"""
|
|
||||||
setup iperf test:
|
|
||||||
|
|
||||||
1. kill current iperf process
|
|
||||||
2. reboot DUT (currently iperf is not very robust, need to reboot DUT)
|
|
||||||
3. scan to get AP RSSI
|
|
||||||
4. connect to AP
|
|
||||||
"""
|
|
||||||
self.softap_dut.write('restart')
|
|
||||||
self.softap_dut.expect_exact("Type 'help' to get the list of commands.")
|
|
||||||
self.softap_dut.expect('iperf>', timeout=30)
|
|
||||||
self.softap_dut.write('ap {} {}'.format(self.ap_ssid, self.ap_password))
|
|
||||||
self.dut.write('restart')
|
|
||||||
self.dut.expect_exact("Type 'help' to get the list of commands.")
|
|
||||||
self.dut.expect('iperf>', timeout=30)
|
|
||||||
self.dut.write('scan {}'.format(self.ap_ssid))
|
|
||||||
for _ in range(SCAN_RETRY_COUNT):
|
|
||||||
try:
|
|
||||||
rssi = int(self.dut.expect(r'\[{}]\[rssi=(-\d+)]'.format(self.ap_ssid),
|
|
||||||
timeout=SCAN_TIMEOUT).group(1))
|
|
||||||
break
|
|
||||||
except pexpect.TIMEOUT:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
raise AssertionError('Failed to scan AP')
|
|
||||||
self.dut.write('sta {} {}'.format(self.ap_ssid, self.ap_password))
|
|
||||||
dut_ip = self.dut.expect(r'sta ip: ([\d.]+), mask: ([\d.]+), gw: ([\d.]+)').group(1).decode('utf-8')
|
|
||||||
return dut_ip, rssi
|
|
||||||
|
|
||||||
def _test_once(self, proto:str, direction:str, bw_limit:int) -> Tuple[str, int, int]:
|
|
||||||
""" do measure once for one type """
|
|
||||||
# connect and scan to get RSSI
|
|
||||||
dut_ip, rssi = self.setup()
|
|
||||||
|
|
||||||
assert direction in ['rx', 'tx']
|
|
||||||
assert proto in ['tcp', 'udp']
|
|
||||||
|
|
||||||
# run iperf test
|
|
||||||
if direction == 'tx':
|
|
||||||
if proto == 'tcp':
|
|
||||||
self.softap_dut.write('iperf -s -i 1 -t {}'.format(TEST_TIME))
|
|
||||||
# wait until DUT TCP server created
|
|
||||||
try:
|
|
||||||
self.softap_dut.expect('iperf tcp server create successfully', timeout=1)
|
|
||||||
except pexpect.TIMEOUT:
|
|
||||||
# compatible with old iperf example binary
|
|
||||||
pass
|
|
||||||
if bw_limit > 0:
|
|
||||||
self.dut.write('iperf -c {} -i 1 -t {} -b {}'.format(self.softap_ip, TEST_TIME, bw_limit))
|
|
||||||
else:
|
|
||||||
self.dut.write('iperf -c {} -i 1 -t {}'.format(self.softap_ip, TEST_TIME))
|
|
||||||
else:
|
|
||||||
self.softap_dut.write('iperf -s -u -i 1 -t {}'.format(TEST_TIME))
|
|
||||||
if bw_limit > 0:
|
|
||||||
self.dut.write('iperf -c {} -u -i 1 -t {} -b {}'.format(self.softap_ip, TEST_TIME, bw_limit))
|
|
||||||
else:
|
|
||||||
self.dut.write('iperf -c {} -u -i 1 -t {}'.format(self.softap_ip, TEST_TIME))
|
|
||||||
else:
|
|
||||||
if proto == 'tcp':
|
|
||||||
self.dut.write('iperf -s -i 1 -t {}'.format(TEST_TIME))
|
|
||||||
# wait until DUT TCP server created
|
|
||||||
try:
|
|
||||||
self.dut.expect('iperf tcp server create successfully', timeout=1)
|
|
||||||
except pexpect.TIMEOUT:
|
|
||||||
# compatible with old iperf example binary
|
|
||||||
pass
|
|
||||||
if bw_limit > 0:
|
|
||||||
self.softap_dut.write('iperf -c {} -i 1 -t {} -b {}'.format(dut_ip, TEST_TIME, bw_limit))
|
|
||||||
else:
|
|
||||||
self.softap_dut.write('iperf -c {} -i 1 -t {}'.format(dut_ip, TEST_TIME))
|
|
||||||
else:
|
|
||||||
self.dut.write('iperf -s -u -i 1 -t {}'.format(TEST_TIME))
|
|
||||||
if bw_limit > 0:
|
|
||||||
self.softap_dut.write('iperf -c {} -u -i 1 -t {} -b {}'.format(dut_ip, TEST_TIME, bw_limit))
|
|
||||||
else:
|
|
||||||
self.softap_dut.write('iperf -c {} -u -i 1 -t {}'.format(dut_ip, TEST_TIME))
|
|
||||||
time.sleep(TEST_TIME + 5)
|
|
||||||
|
|
||||||
if direction == 'tx':
|
|
||||||
server_raw_data = self.dut.expect(pexpect.TIMEOUT, timeout=0).decode('utf-8')
|
|
||||||
else:
|
|
||||||
server_raw_data = self.dut.expect(pexpect.TIMEOUT, timeout=0).decode('utf-8')
|
|
||||||
self.dut.write('iperf -a')
|
|
||||||
self.softap_dut.write('iperf -a')
|
|
||||||
self.dut.write('heap')
|
|
||||||
heap_size = self.dut.expect(r'min heap size: (\d+)\D').group(1)
|
|
||||||
|
|
||||||
# return server raw data (for parsing test results) and RSSI
|
|
||||||
return server_raw_data, rssi, heap_size
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.esp32
|
@pytest.mark.esp32
|
||||||
@pytest.mark.temp_skip_ci(targets=['esp32s2', 'esp32c3', 'esp32s3'], reason='lack of runners (run only for ESP32)')
|
@pytest.mark.temp_skip_ci(targets=['esp32s2', 'esp32c3', 'esp32s3'], reason='lack of runners (run only for ESP32)')
|
||||||
@pytest.mark.timeout(1200)
|
@pytest.mark.timeout(1200)
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
idf_component_register(SRCS "itwt.c"
|
idf_component_register(SRCS "itwt_main.c"
|
||||||
|
"wifi_stats_cmd.c"
|
||||||
|
"wifi_itwt_cmd.c"
|
||||||
INCLUDE_DIRS ".")
|
INCLUDE_DIRS ".")
|
||||||
|
@ -3,7 +3,3 @@ dependencies:
|
|||||||
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system
|
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_system
|
||||||
cmd_nvs:
|
cmd_nvs:
|
||||||
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_nvs
|
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_nvs
|
||||||
cmd_wifi:
|
|
||||||
path: ${IDF_PATH}/examples/system/console/advanced/components/cmd_wifi
|
|
||||||
iperf:
|
|
||||||
path: ${IDF_PATH}/examples/common_components/iperf
|
|
||||||
|
@ -26,11 +26,12 @@
|
|||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "esp_console.h"
|
#include "esp_console.h"
|
||||||
#include "cmd_system.h"
|
#include "cmd_system.h"
|
||||||
#include "wifi_cmd.h"
|
|
||||||
#include "esp_wifi_he.h"
|
#include "esp_wifi_he.h"
|
||||||
#include "esp_pm.h"
|
#include "esp_pm.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
|
|
||||||
|
#include "wifi_cmd.h"
|
||||||
|
|
||||||
/*******************************************************
|
/*******************************************************
|
||||||
* Constants
|
* Constants
|
||||||
*******************************************************/
|
*******************************************************/
|
@ -10,12 +10,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void register_wifi_cmd(void);
|
|
||||||
void register_wifi_itwt(void);
|
void register_wifi_itwt(void);
|
||||||
void register_wifi_stats(void);
|
void register_wifi_stats(void);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -1034,8 +1034,6 @@ examples/build_system/cmake/multi_config/main/func.h
|
|||||||
examples/build_system/cmake/multi_config/main/func_dev.c
|
examples/build_system/cmake/multi_config/main/func_dev.c
|
||||||
examples/build_system/cmake/multi_config/main/func_prod.c
|
examples/build_system/cmake/multi_config/main/func_prod.c
|
||||||
examples/build_system/cmake/multi_config/main/multi_config_example_main.c
|
examples/build_system/cmake/multi_config/main/multi_config_example_main.c
|
||||||
examples/common_components/iperf/include/iperf.h
|
|
||||||
examples/common_components/iperf/iperf.c
|
|
||||||
examples/common_components/protocol_examples_common/addr_from_stdin.c
|
examples/common_components/protocol_examples_common/addr_from_stdin.c
|
||||||
examples/common_components/protocol_examples_common/include/addr_from_stdin.h
|
examples/common_components/protocol_examples_common/include/addr_from_stdin.h
|
||||||
examples/common_components/protocol_examples_common/include/protocol_examples_common.h
|
examples/common_components/protocol_examples_common/include/protocol_examples_common.h
|
||||||
@ -1192,9 +1190,6 @@ examples/wifi/fast_scan/main/fast_scan.c
|
|||||||
examples/wifi/ftm/main/ftm_main.c
|
examples/wifi/ftm/main/ftm_main.c
|
||||||
examples/wifi/getting_started/softAP/main/softap_example_main.c
|
examples/wifi/getting_started/softAP/main/softap_example_main.c
|
||||||
examples/wifi/getting_started/station/main/station_example_main.c
|
examples/wifi/getting_started/station/main/station_example_main.c
|
||||||
examples/wifi/iperf/main/cmd_decl.h
|
|
||||||
examples/wifi/iperf/main/cmd_wifi.c
|
|
||||||
examples/wifi/iperf/main/cmd_wifi.h
|
|
||||||
examples/wifi/iperf/main/iperf_example_main.c
|
examples/wifi/iperf/main/iperf_example_main.c
|
||||||
examples/wifi/power_save/main/power_save.c
|
examples/wifi/power_save/main/power_save.c
|
||||||
examples/wifi/roaming/main/roaming_example.c
|
examples/wifi/roaming/main/roaming_example.c
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -33,7 +33,7 @@ class TestResult(object):
|
|||||||
""" record, analysis test result and convert data to output format """
|
""" record, analysis test result and convert data to output format """
|
||||||
|
|
||||||
PC_BANDWIDTH_LOG_PATTERN = re.compile(r'(\d+\.\d+)\s*-\s*(\d+.\d+)\s+sec\s+[\d.]+\s+MBytes\s+([\d.]+)\s+Mbits\/sec')
|
PC_BANDWIDTH_LOG_PATTERN = re.compile(r'(\d+\.\d+)\s*-\s*(\d+.\d+)\s+sec\s+[\d.]+\s+MBytes\s+([\d.]+)\s+Mbits\/sec')
|
||||||
DUT_BANDWIDTH_LOG_PATTERN = re.compile(r'(\d+)-\s+(\d+)\s+sec\s+([\d.]+)\s+Mbits/sec')
|
DUT_BANDWIDTH_LOG_PATTERN = re.compile(r'([\d.]+)\s*-\s*([\d.]+)\s+sec\s+([\d.]+)\s+Mbits/sec')
|
||||||
|
|
||||||
ZERO_POINT_THRESHOLD = -88 # RSSI, dbm
|
ZERO_POINT_THRESHOLD = -88 # RSSI, dbm
|
||||||
ZERO_THROUGHPUT_THRESHOLD = -92 # RSSI, dbm
|
ZERO_THROUGHPUT_THRESHOLD = -92 # RSSI, dbm
|
||||||
@ -278,7 +278,7 @@ class IperfTestUtility(object):
|
|||||||
self.dut.write('restart')
|
self.dut.write('restart')
|
||||||
self.dut.expect_exact("Type 'help' to get the list of commands.")
|
self.dut.expect_exact("Type 'help' to get the list of commands.")
|
||||||
self.dut.expect('iperf>')
|
self.dut.expect('iperf>')
|
||||||
self.dut.write('scan {}'.format(self.ap_ssid))
|
self.dut.write('sta_scan {}'.format(self.ap_ssid))
|
||||||
for _ in range(SCAN_RETRY_COUNT):
|
for _ in range(SCAN_RETRY_COUNT):
|
||||||
try:
|
try:
|
||||||
rssi = int(self.dut.expect(r'\[{}]\[rssi=(-\d+)]'.format(self.ap_ssid),
|
rssi = int(self.dut.expect(r'\[{}]\[rssi=(-\d+)]'.format(self.ap_ssid),
|
||||||
@ -288,7 +288,7 @@ class IperfTestUtility(object):
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
raise AssertionError('Failed to scan AP')
|
raise AssertionError('Failed to scan AP')
|
||||||
self.dut.write('sta {} {}'.format(self.ap_ssid, self.ap_password))
|
self.dut.write('sta_connect {} {}'.format(self.ap_ssid, self.ap_password))
|
||||||
dut_ip = self.dut.expect(r'sta ip: ([\d.]+), mask: ([\d.]+), gw: ([\d.]+)').group(1)
|
dut_ip = self.dut.expect(r'sta ip: ([\d.]+), mask: ([\d.]+), gw: ([\d.]+)').group(1)
|
||||||
return dut_ip, rssi
|
return dut_ip, rssi
|
||||||
|
|
||||||
@ -338,7 +338,7 @@ class IperfTestUtility(object):
|
|||||||
self.dut.write('iperf -s -i 1 -t {}'.format(TEST_TIME))
|
self.dut.write('iperf -s -i 1 -t {}'.format(TEST_TIME))
|
||||||
# wait until DUT TCP server created
|
# wait until DUT TCP server created
|
||||||
try:
|
try:
|
||||||
self.dut.expect('iperf: Socket created', timeout=5)
|
self.dut.expect('Socket created', timeout=5)
|
||||||
except pexpect.TIMEOUT:
|
except pexpect.TIMEOUT:
|
||||||
# compatible with old iperf example binary
|
# compatible with old iperf example binary
|
||||||
logging.info('create iperf tcp server fail')
|
logging.info('create iperf tcp server fail')
|
||||||
@ -358,7 +358,7 @@ class IperfTestUtility(object):
|
|||||||
self.dut.write('iperf -s -u -i 1 -t {}'.format(TEST_TIME))
|
self.dut.write('iperf -s -u -i 1 -t {}'.format(TEST_TIME))
|
||||||
# wait until DUT TCP server created
|
# wait until DUT TCP server created
|
||||||
try:
|
try:
|
||||||
self.dut.expect('iperf: Socket bound', timeout=5)
|
self.dut.expect('Socket bound', timeout=5)
|
||||||
except pexpect.TIMEOUT:
|
except pexpect.TIMEOUT:
|
||||||
# compatible with old iperf example binary
|
# compatible with old iperf example binary
|
||||||
logging.info('create iperf udp server fail')
|
logging.info('create iperf udp server fail')
|
||||||
|
Loading…
Reference in New Issue
Block a user