Initial commit: ESP32 iperf implementation

This commit is contained in:
Bob 2025-11-08 19:57:11 +00:00
commit b3aa5ad76d
8 changed files with 820 additions and 0 deletions

34
.gitignore vendored Normal file
View File

@ -0,0 +1,34 @@
# Build artifacts
build/
sdkconfig
sdkconfig.old
*.pyc
*.o
*.a
*.so
*.bin
*.elf
*.map
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# Dependencies
dependencies/
managed_components/
# Python
__pycache__/
*.py[cod]
*$py.class
.Python
venv/
env/
# OS
.DS_Store
Thumbs.db

6
CMakeLists.txt Normal file
View File

@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp32-iperf)

118
README.md Normal file
View File

@ -0,0 +1,118 @@
# ESP32 iperf
Network performance testing tool for ESP32 based on iperf2.
## Features
- TCP and UDP client/server modes
- Bandwidth measurement
- Packet loss detection (UDP)
- Console-based control interface
- WiFi station mode support
## Hardware Requirements
- ESP32 development board
- WiFi network
## Software Requirements
- ESP-IDF v5.0 or later
- iperf2 or iperf3 for testing with PC
## Building
1. Set up ESP-IDF environment:
```bash
. $HOME/Code/esp32/esp-idf/export.sh
```
2. Configure WiFi credentials:
```bash
idf.py menuconfig
```
Navigate to "ESP32 iperf Configuration" and set your SSID and password.
3. Build the project:
```bash
idf.py build
```
4. Flash to ESP32:
```bash
idf.py -p /dev/ttyUSB0 flash monitor
```
## Usage
### TCP Server Mode
On ESP32:
```
iperf> iperf -s
```
On PC:
```bash
iperf -c <ESP32_IP>
```
### TCP Client Mode
On PC:
```bash
iperf -s
```
On ESP32:
```
iperf> iperf -c <PC_IP>
```
### UDP Mode
Add `-u` flag for UDP testing:
```
iperf> iperf -s -u
iperf> iperf -c <IP> -u
```
### Options
- `-s` : Run as server
- `-c <ip>` : Run as client, connecting to server IP
- `-u` : Use UDP instead of TCP
- `-p <port>` : Port number (default: 5001)
- `-t <time>` : Test duration in seconds (default: 30)
- `-b <bw>` : Bandwidth limit for UDP in Mbps
- `-a` : Abort running test
### Examples
```bash
# TCP client test for 10 seconds
iperf -c 192.168.1.100 -t 10
# UDP server on port 5002
iperf -s -u -p 5002
# Stop running test
iperf -a
```
## Project Structure
```
esp32-iperf/
├── CMakeLists.txt
├── main/
│ ├── CMakeLists.txt
│ ├── Kconfig.projbuild
│ ├── main.c # WiFi initialization and console
│ ├── iperf.c # iperf implementation
│ └── iperf.h # iperf header
└── README.md
```
## Author
Bob - Creator of iperf2
## License
Open source

2
main/CMakeLists.txt Normal file
View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "main.c" "iperf.c"
INCLUDE_DIRS ".")

21
main/Kconfig.projbuild Normal file
View File

@ -0,0 +1,21 @@
menu "ESP32 iperf Configuration"
config WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) to connect to.
config WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2).
config WIFI_MAXIMUM_RETRY
int "Maximum retry"
default 5
help
Set the Maximum retry to prevent station reconnecting to the AP unlimited when the AP doesn't exist.
endmenu

339
main/iperf.c Normal file
View File

@ -0,0 +1,339 @@
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "esp_err.h"
#include "iperf.h"
static const char *TAG = "iperf";
typedef struct {
iperf_cfg_t cfg;
bool finish;
uint32_t total_len;
uint32_t buffer_len;
uint8_t *buffer;
uint32_t sockfd;
} iperf_ctrl_t;
static iperf_ctrl_t s_iperf_ctrl = {0};
static TaskHandle_t s_iperf_task_handle = NULL;
static void socket_send(int sockfd, const uint8_t *buffer, int len)
{
int actual_send = 0;
while (actual_send < len) {
int send_len = send(sockfd, buffer + actual_send, len - actual_send, 0);
if (send_len < 0) {
ESP_LOGE(TAG, "send failed: errno %d", errno);
break;
}
actual_send += send_len;
}
}
static int socket_recv(int sockfd, uint8_t *buffer, int len, TickType_t timeout_ticks)
{
struct timeval timeout;
timeout.tv_sec = timeout_ticks / configTICK_RATE_HZ;
timeout.tv_usec = (timeout_ticks % configTICK_RATE_HZ) * (1000000 / configTICK_RATE_HZ);
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
ESP_LOGE(TAG, "setsockopt failed: errno %d", errno);
return -1;
}
return recv(sockfd, buffer, len, 0);
}
static esp_err_t iperf_start_tcp_server(iperf_ctrl_t *ctrl)
{
struct sockaddr_in addr;
int listen_sock;
int opt = 1;
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
return ESP_FAIL;
}
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
addr.sin_family = AF_INET;
addr.sin_port = htons(ctrl->cfg.sport);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
ESP_LOGE(TAG, "Socket bind failed: errno %d", errno);
close(listen_sock);
return ESP_FAIL;
}
if (listen(listen_sock, 5) != 0) {
ESP_LOGE(TAG, "Socket listen failed: errno %d", errno);
close(listen_sock);
return ESP_FAIL;
}
ESP_LOGI(TAG, "TCP server listening on port %d", ctrl->cfg.sport);
while (!ctrl->finish) {
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
int client_sock = accept(listen_sock, (struct sockaddr *)&client_addr, &addr_len);
if (client_sock < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
continue;
}
ESP_LOGE(TAG, "Accept failed: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Client connected from %s", inet_ntoa(client_addr.sin_addr));
uint64_t total_len = 0;
int recv_len;
while (!ctrl->finish) {
recv_len = socket_recv(client_sock, ctrl->buffer, ctrl->buffer_len,
pdMS_TO_TICKS(IPERF_SOCKET_RX_TIMEOUT * 1000));
if (recv_len <= 0) {
break;
}
total_len += recv_len;
}
ESP_LOGI(TAG, "TCP server received: %llu bytes", total_len);
close(client_sock);
}
close(listen_sock);
return ESP_OK;
}
static esp_err_t iperf_start_tcp_client(iperf_ctrl_t *ctrl)
{
struct sockaddr_in addr;
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
return ESP_FAIL;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(ctrl->cfg.dport);
addr.sin_addr.s_addr = htonl(ctrl->cfg.dip);
ESP_LOGI(TAG, "Connecting to TCP server...");
if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
ESP_LOGE(TAG, "Socket connect failed: errno %d", errno);
close(sockfd);
return ESP_FAIL;
}
ESP_LOGI(TAG, "Connected to TCP server");
uint64_t total_len = 0;
uint32_t start_time = xTaskGetTickCount();
uint32_t end_time = start_time + pdMS_TO_TICKS(ctrl->cfg.time * 1000);
while (!ctrl->finish && xTaskGetTickCount() < end_time) {
socket_send(sockfd, ctrl->buffer, ctrl->buffer_len);
total_len += ctrl->buffer_len;
}
uint32_t actual_time = (xTaskGetTickCount() - start_time) / configTICK_RATE_HZ;
float bandwidth = (float)total_len * 8 / actual_time / 1000000; // Mbps
ESP_LOGI(TAG, "TCP client sent: %llu bytes in %u seconds (%.2f Mbps)",
total_len, actual_time, bandwidth);
close(sockfd);
return ESP_OK;
}
static esp_err_t iperf_start_udp_server(iperf_ctrl_t *ctrl)
{
struct sockaddr_in addr;
int sockfd;
int opt = 1;
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
return ESP_FAIL;
}
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
addr.sin_family = AF_INET;
addr.sin_port = htons(ctrl->cfg.sport);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
ESP_LOGE(TAG, "Socket bind failed: errno %d", errno);
close(sockfd);
return ESP_FAIL;
}
ESP_LOGI(TAG, "UDP server listening on port %d", ctrl->cfg.sport);
uint64_t total_len = 0;
uint32_t packet_count = 0;
int32_t last_id = -1;
uint32_t lost_packets = 0;
while (!ctrl->finish) {
int recv_len = socket_recv(sockfd, ctrl->buffer, ctrl->buffer_len,
pdMS_TO_TICKS(IPERF_SOCKET_RX_TIMEOUT * 1000));
if (recv_len <= 0) {
continue;
}
total_len += recv_len;
packet_count++;
// Check for lost packets using UDP header
if (recv_len >= sizeof(udp_datagram)) {
udp_datagram *header = (udp_datagram *)ctrl->buffer;
int32_t current_id = ntohl(header->id);
if (last_id >= 0 && current_id > last_id + 1) {
lost_packets += (current_id - last_id - 1);
}
last_id = current_id;
}
}
float loss_rate = packet_count > 0 ? (float)lost_packets * 100 / packet_count : 0;
ESP_LOGI(TAG, "UDP server received: %llu bytes, %u packets, %u lost (%.2f%%)",
total_len, packet_count, lost_packets, loss_rate);
close(sockfd);
return ESP_OK;
}
static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl)
{
struct sockaddr_in addr;
int sockfd;
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
return ESP_FAIL;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(ctrl->cfg.dport);
addr.sin_addr.s_addr = htonl(ctrl->cfg.dip);
ESP_LOGI(TAG, "Starting UDP client");
uint64_t total_len = 0;
uint32_t packet_count = 0;
uint32_t start_time = xTaskGetTickCount();
uint32_t end_time = start_time + pdMS_TO_TICKS(ctrl->cfg.time * 1000);
while (!ctrl->finish && xTaskGetTickCount() < end_time) {
udp_datagram *header = (udp_datagram *)ctrl->buffer;
header->id = htonl(packet_count);
int send_len = sendto(sockfd, ctrl->buffer, ctrl->buffer_len, 0,
(struct sockaddr *)&addr, sizeof(addr));
if (send_len > 0) {
total_len += send_len;
packet_count++;
}
// Bandwidth limiting
if (ctrl->cfg.bw_lim > 0) {
vTaskDelay(1);
}
}
uint32_t actual_time = (xTaskGetTickCount() - start_time) / configTICK_RATE_HZ;
float bandwidth = actual_time > 0 ? (float)total_len * 8 / actual_time / 1000000 : 0;
ESP_LOGI(TAG, "UDP client sent: %llu bytes, %u packets in %u seconds (%.2f Mbps)",
total_len, packet_count, actual_time, bandwidth);
close(sockfd);
return ESP_OK;
}
static void iperf_task(void *arg)
{
iperf_ctrl_t *ctrl = (iperf_ctrl_t *)arg;
if (ctrl->cfg.flag & IPERF_FLAG_TCP) {
if (ctrl->cfg.flag & IPERF_FLAG_SERVER) {
iperf_start_tcp_server(ctrl);
} else {
iperf_start_tcp_client(ctrl);
}
} else {
if (ctrl->cfg.flag & IPERF_FLAG_SERVER) {
iperf_start_udp_server(ctrl);
} else {
iperf_start_udp_client(ctrl);
}
}
if (ctrl->buffer) {
free(ctrl->buffer);
ctrl->buffer = NULL;
}
ESP_LOGI(TAG, "iperf task finished");
s_iperf_task_handle = NULL;
vTaskDelete(NULL);
}
void iperf_start(iperf_cfg_t *cfg)
{
if (s_iperf_task_handle != NULL) {
ESP_LOGW(TAG, "iperf is already running");
return;
}
memcpy(&s_iperf_ctrl.cfg, cfg, sizeof(iperf_cfg_t));
s_iperf_ctrl.finish = false;
// Allocate buffer
if (cfg->flag & IPERF_FLAG_TCP) {
s_iperf_ctrl.buffer_len = cfg->flag & IPERF_FLAG_SERVER ?
IPERF_TCP_RX_LEN : IPERF_TCP_TX_LEN;
} else {
s_iperf_ctrl.buffer_len = cfg->flag & IPERF_FLAG_SERVER ?
IPERF_UDP_RX_LEN : IPERF_UDP_TX_LEN;
}
s_iperf_ctrl.buffer = (uint8_t *)malloc(s_iperf_ctrl.buffer_len);
if (!s_iperf_ctrl.buffer) {
ESP_LOGE(TAG, "Failed to allocate buffer");
return;
}
memset(s_iperf_ctrl.buffer, 0, s_iperf_ctrl.buffer_len);
xTaskCreate(iperf_task, "iperf", 4096, &s_iperf_ctrl, IPERF_TRAFFIC_TASK_PRIORITY,
&s_iperf_task_handle);
}
void iperf_stop(void)
{
if (s_iperf_task_handle != NULL) {
s_iperf_ctrl.finish = true;
ESP_LOGI(TAG, "Stopping iperf...");
}
}

59
main/iperf.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef IPERF_H
#define IPERF_H
#include <stdint.h>
#include <stdbool.h>
#define IPERF_FLAG_CLIENT (1 << 0)
#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_TRAFFIC_TASK_PRIORITY 4
#define IPERF_REPORT_TASK_PRIORITY 5
#define IPERF_SOCKET_RX_TIMEOUT 10
#define IPERF_SOCKET_ACCEPT_TIMEOUT 5
#define IPERF_UDP_TX_LEN (1470)
#define IPERF_UDP_RX_LEN (16 << 10)
#define IPERF_TCP_TX_LEN (16 << 10)
#define IPERF_TCP_RX_LEN (16 << 10)
typedef struct {
uint32_t flag;
uint8_t type;
uint16_t dip;
uint16_t dport;
uint16_t sport;
uint32_t interval;
uint32_t time;
uint16_t bw_lim;
uint32_t buffer_len;
} iperf_cfg_t;
typedef struct {
uint64_t total_len;
uint32_t buffer_len;
uint32_t sockfd;
uint32_t actual_len;
uint32_t packet_count;
uint8_t *buffer;
uint32_t udp_lost_counter;
uint32_t udp_packet_counter;
} iperf_traffic_t;
// UDP header for iperf
typedef struct {
int32_t id;
uint32_t tv_sec;
uint32_t tv_usec;
} udp_datagram;
void iperf_start(iperf_cfg_t *cfg);
void iperf_stop(void);
#endif // IPERF_H

241
main/main.c Normal file
View File

@ -0,0 +1,241 @@
#include <stdio.h>
#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.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_console.h"
#include "argtable3/argtable3.h"
#include "esp_netif.h"
#include "lwip/inet.h"
#include "iperf.h"
#define WIFI_SSID CONFIG_WIFI_SSID
#define WIFI_PASS CONFIG_WIFI_PASSWORD
#define WIFI_MAXIMUM_RETRY CONFIG_WIFI_MAXIMUM_RETRY
static const char *TAG = "main";
static EventGroupHandle_t s_wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
static int s_retry_num = 0;
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
if (s_retry_num < WIFI_MAXIMUM_RETRY) {
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "retry to connect to the AP");
} else {
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
}
ESP_LOGI(TAG,"connect to the AP fail");
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
s_retry_num = 0;
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
void wifi_init_sta(void)
{
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&event_handler,
NULL,
&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&event_handler,
NULL,
&instance_got_ip));
wifi_config_t wifi_config = {
.sta = {
.ssid = WIFI_SSID,
.password = WIFI_PASS,
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
ESP_ERROR_CHECK(esp_wifi_start() );
ESP_LOGI(TAG, "wifi_init_sta finished.");
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "connected to ap SSID:%s", WIFI_SSID);
} else if (bits & WIFI_FAIL_BIT) {
ESP_LOGI(TAG, "Failed to connect to SSID:%s", WIFI_SSID);
} else {
ESP_LOGE(TAG, "UNEXPECTED EVENT");
}
}
/* Console command structure for iperf */
static struct {
struct arg_str *ip;
struct arg_lit *server;
struct arg_lit *udp;
struct arg_lit *client;
struct arg_int *port;
struct arg_int *interval;
struct arg_int *time;
struct arg_int *bw;
struct arg_lit *abort;
struct arg_end *end;
} iperf_args;
static int cmd_iperf(int argc, char **argv)
{
int nerrors = arg_parse(argc, argv, (void **)&iperf_args);
if (nerrors != 0) {
arg_print_errors(stderr, iperf_args.end, argv[0]);
return 1;
}
/* Check if needs to abort */
if (iperf_args.abort->count != 0) {
iperf_stop();
return 0;
}
iperf_cfg_t cfg;
memset(&cfg, 0, sizeof(cfg));
/* Set protocol type */
cfg.flag |= (iperf_args.udp->count == 0) ? IPERF_FLAG_TCP : IPERF_FLAG_UDP;
/* Set server/client mode */
if (iperf_args.server->count != 0) {
cfg.flag |= IPERF_FLAG_SERVER;
cfg.sport = IPERF_DEFAULT_PORT;
if (iperf_args.port->count != 0) {
cfg.sport = iperf_args.port->ival[0];
}
} else {
cfg.flag |= IPERF_FLAG_CLIENT;
cfg.dport = IPERF_DEFAULT_PORT;
if (iperf_args.port->count != 0) {
cfg.dport = iperf_args.port->ival[0];
}
if (iperf_args.ip->count == 0) {
ESP_LOGE(TAG, "Please input destination IP address");
return 1;
}
cfg.dip = ipaddr_addr(iperf_args.ip->sval[0]);
if (cfg.dip == IPADDR_NONE) {
ESP_LOGE(TAG, "Invalid IP address: %s", iperf_args.ip->sval[0]);
return 1;
}
}
/* Set test time */
cfg.time = IPERF_DEFAULT_TIME;
if (iperf_args.time->count != 0) {
cfg.time = iperf_args.time->ival[0];
}
/* Set bandwidth limit for UDP */
cfg.bw_lim = 0;
if (iperf_args.bw->count != 0) {
cfg.bw_lim = iperf_args.bw->ival[0];
}
ESP_LOGI(TAG, "mode=%s-%s sip=%u.%u.%u.%u:%u, dip=%u.%u.%u.%u:%u, interval=%u, time=%u",
(cfg.flag & IPERF_FLAG_TCP) ? "tcp" : "udp",
(cfg.flag & IPERF_FLAG_SERVER) ? "server" : "client",
cfg.sip & 0xFF, (cfg.sip >> 8) & 0xFF, (cfg.sip >> 16) & 0xFF, (cfg.sip >> 24) & 0xFF, cfg.sport,
cfg.dip & 0xFF, (cfg.dip >> 8) & 0xFF, (cfg.dip >> 16) & 0xFF, (cfg.dip >> 24) & 0xFF, cfg.dport,
cfg.interval, cfg.time);
iperf_start(&cfg);
return 0;
}
static void register_iperf(void)
{
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.port = arg_int0("p", "port", "<port>", "server port to listen on/connect to");
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 30 secs)");
iperf_args.bw = 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 = &cmd_iperf,
.argtable = &iperf_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&iperf_cmd));
}
static void initialize_console(void)
{
esp_console_repl_t *repl = NULL;
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
repl_config.prompt = "iperf>";
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
register_iperf();
ESP_ERROR_CHECK(esp_console_start_repl(repl));
}
void app_main(void)
{
ESP_LOGI(TAG, "ESP32 iperf starting...");
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// Initialize WiFi
wifi_init_sta();
// Initialize console
initialize_console();
ESP_LOGI(TAG, "Ready. Type 'iperf --help' for usage");
}