mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 21:24:32 +02:00
openthread: add iperf example for ot-network test
This commit is contained in:
@@ -91,4 +91,10 @@ menu "OpenThread"
|
|||||||
help
|
help
|
||||||
Override the shipped libopenthread_br.a and libopenthread_port.a, for internal builds.
|
Override the shipped libopenthread_br.a and libopenthread_port.a, for internal builds.
|
||||||
|
|
||||||
|
config OPENTHREAD_NUM_MESSAGE_BUFFERS
|
||||||
|
int "The number of openthread message buffers"
|
||||||
|
depends on OPENTHREAD_ENABLED
|
||||||
|
default 65
|
||||||
|
range 50 100
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@@ -95,7 +95,7 @@
|
|||||||
*
|
*
|
||||||
* The number of message buffers in buffer pool
|
* The number of message buffers in buffer pool
|
||||||
*/
|
*/
|
||||||
#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 50
|
#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS CONFIG_OPENTHREAD_NUM_MESSAGE_BUFFERS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def OPENTHREAD_CONFIG_COAP_API_ENABLE
|
* @def OPENTHREAD_CONFIG_COAP_API_ENABLE
|
||||||
|
@@ -23,7 +23,9 @@ typedef struct {
|
|||||||
struct arg_str *ip;
|
struct arg_str *ip;
|
||||||
struct arg_lit *server;
|
struct arg_lit *server;
|
||||||
struct arg_lit *udp;
|
struct arg_lit *udp;
|
||||||
|
struct arg_lit *version;
|
||||||
struct arg_int *port;
|
struct arg_int *port;
|
||||||
|
struct arg_int *length;
|
||||||
struct arg_int *interval;
|
struct arg_int *interval;
|
||||||
struct arg_int *time;
|
struct arg_int *time;
|
||||||
struct arg_lit *abort;
|
struct arg_lit *abort;
|
||||||
@@ -323,6 +325,9 @@ static int wifi_cmd_iperf(int argc, char **argv)
|
|||||||
|
|
||||||
memset(&cfg, 0, sizeof(cfg));
|
memset(&cfg, 0, sizeof(cfg));
|
||||||
|
|
||||||
|
// wifi iperf only support IPV4 address
|
||||||
|
cfg.type = IPERF_IP_TYPE_IPV4;
|
||||||
|
|
||||||
if ( iperf_args.abort->count != 0) {
|
if ( iperf_args.abort->count != 0) {
|
||||||
iperf_stop();
|
iperf_stop();
|
||||||
return 0;
|
return 0;
|
||||||
@@ -337,15 +342,21 @@ static int wifi_cmd_iperf(int argc, char **argv)
|
|||||||
if (iperf_args.ip->count == 0) {
|
if (iperf_args.ip->count == 0) {
|
||||||
cfg.flag |= IPERF_FLAG_SERVER;
|
cfg.flag |= IPERF_FLAG_SERVER;
|
||||||
} else {
|
} else {
|
||||||
cfg.dip = esp_ip4addr_aton(iperf_args.ip->sval[0]);
|
cfg.destination_ip4 = esp_ip4addr_aton(iperf_args.ip->sval[0]);
|
||||||
cfg.flag |= IPERF_FLAG_CLIENT;
|
cfg.flag |= IPERF_FLAG_CLIENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.sip = wifi_get_local_ip();
|
cfg.source_ip4 = wifi_get_local_ip();
|
||||||
if (cfg.sip == 0) {
|
if (cfg.source_ip4 == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iperf_args.length->count == 0) {
|
||||||
|
cfg.len_send_buf = 0;
|
||||||
|
} else {
|
||||||
|
cfg.len_send_buf = iperf_args.length->ival[0];
|
||||||
|
}
|
||||||
|
|
||||||
if (iperf_args.udp->count == 0) {
|
if (iperf_args.udp->count == 0) {
|
||||||
cfg.flag |= IPERF_FLAG_TCP;
|
cfg.flag |= IPERF_FLAG_TCP;
|
||||||
} else {
|
} else {
|
||||||
@@ -386,8 +397,10 @@ static int wifi_cmd_iperf(int argc, char **argv)
|
|||||||
ESP_LOGI(TAG, "mode=%s-%s sip=%d.%d.%d.%d:%d, dip=%d.%d.%d.%d:%d, interval=%d, time=%d",
|
ESP_LOGI(TAG, "mode=%s-%s sip=%d.%d.%d.%d:%d, dip=%d.%d.%d.%d:%d, interval=%d, time=%d",
|
||||||
cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp",
|
cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp",
|
||||||
cfg.flag & IPERF_FLAG_SERVER ? "server" : "client",
|
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.source_ip4 & 0xFF, (cfg.source_ip4 >> 8) & 0xFF, (cfg.source_ip4 >> 16) & 0xFF,
|
||||||
cfg.dip & 0xFF, (cfg.dip >> 8) & 0xFF, (cfg.dip >> 16) & 0xFF, (cfg.dip >> 24) & 0xFF, cfg.dport,
|
(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);
|
cfg.interval, cfg.time);
|
||||||
|
|
||||||
iperf_start(&cfg);
|
iperf_start(&cfg);
|
||||||
@@ -471,7 +484,9 @@ void register_wifi(void)
|
|||||||
iperf_args.ip = arg_str0("c", "client", "<ip>", "run in client mode, connecting to <host>");
|
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.server = arg_lit0("s", "server", "run in server mode");
|
||||||
iperf_args.udp = arg_lit0("u", "udp", "use UDP rather than TCP");
|
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.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.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.time = arg_int0("t", "time", "<time>", "time in seconds to transmit for (default 10 secs)");
|
||||||
iperf_args.abort = arg_lit0("a", "abort", "abort running iperf");
|
iperf_args.abort = arg_lit0("a", "abort", "abort running iperf");
|
||||||
|
@@ -10,12 +10,20 @@
|
|||||||
#ifndef __IPERF_H_
|
#ifndef __IPERF_H_
|
||||||
#define __IPERF_H_
|
#define __IPERF_H_
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "esp_types.h"
|
#define IPERF_IP_TYPE_IPV4 0
|
||||||
#include "esp_err.h"
|
#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_CLIENT (1)
|
||||||
#define IPERF_FLAG_SERVER (1 << 1)
|
#define IPERF_FLAG_SERVER (1 << 1)
|
||||||
@@ -27,12 +35,11 @@ extern "C" {
|
|||||||
#define IPERF_DEFAULT_TIME 30
|
#define IPERF_DEFAULT_TIME 30
|
||||||
|
|
||||||
#define IPERF_TRAFFIC_TASK_NAME "iperf_traffic"
|
#define IPERF_TRAFFIC_TASK_NAME "iperf_traffic"
|
||||||
#define IPERF_TRAFFIC_TASK_PRIORITY 10
|
#define IPERF_TRAFFIC_TASK_PRIORITY 4
|
||||||
#define IPERF_TRAFFIC_TASK_STACK 4096
|
#define IPERF_TRAFFIC_TASK_STACK 4096
|
||||||
#define IPERF_REPORT_TASK_NAME "iperf_report"
|
#define IPERF_REPORT_TASK_NAME "iperf_report"
|
||||||
#define IPERF_REPORT_TASK_PRIORITY 20
|
#define IPERF_REPORT_TASK_PRIORITY 6
|
||||||
#define IPERF_REPORT_TASK_STACK 4096
|
#define IPERF_REPORT_TASK_STACK 4096
|
||||||
#define IPERF_REPORT_TASK_NAME "iperf_report"
|
|
||||||
|
|
||||||
#define IPERF_UDP_TX_LEN (1472)
|
#define IPERF_UDP_TX_LEN (1472)
|
||||||
#define IPERF_UDP_RX_LEN (16 << 10)
|
#define IPERF_UDP_RX_LEN (16 << 10)
|
||||||
@@ -46,12 +53,20 @@ extern "C" {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t flag;
|
uint32_t flag;
|
||||||
uint32_t dip;
|
union {
|
||||||
uint32_t sip;
|
uint32_t destination_ip4;
|
||||||
|
char *destination_ip6;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
uint32_t source_ip4;
|
||||||
|
char *source_ip6;
|
||||||
|
};
|
||||||
|
uint8_t type;
|
||||||
uint16_t dport;
|
uint16_t dport;
|
||||||
uint16_t sport;
|
uint16_t sport;
|
||||||
uint32_t interval;
|
uint32_t interval;
|
||||||
uint32_t time;
|
uint32_t time;
|
||||||
|
uint16_t len_send_buf;
|
||||||
} iperf_cfg_t;
|
} iperf_cfg_t;
|
||||||
|
|
||||||
esp_err_t iperf_start(iperf_cfg_t *cfg);
|
esp_err_t iperf_start(iperf_cfg_t *cfg);
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "esp_check.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "iperf.h"
|
#include "iperf.h"
|
||||||
|
|
||||||
@@ -24,12 +25,6 @@ typedef struct {
|
|||||||
uint32_t sockfd;
|
uint32_t sockfd;
|
||||||
} iperf_ctrl_t;
|
} iperf_ctrl_t;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t id;
|
|
||||||
uint32_t sec;
|
|
||||||
uint32_t usec;
|
|
||||||
} iperf_udp_pkt_t;
|
|
||||||
|
|
||||||
static bool s_iperf_is_running = false;
|
static bool s_iperf_is_running = false;
|
||||||
static iperf_ctrl_t s_iperf_ctrl;
|
static iperf_ctrl_t s_iperf_ctrl;
|
||||||
static const char *TAG = "iperf";
|
static const char *TAG = "iperf";
|
||||||
@@ -56,7 +51,6 @@ inline static bool iperf_is_tcp_server(void)
|
|||||||
|
|
||||||
static int iperf_get_socket_error_code(int sockfd)
|
static int iperf_get_socket_error_code(int sockfd)
|
||||||
{
|
{
|
||||||
|
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,123 +107,34 @@ static esp_err_t iperf_start_report(void)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t IRAM_ATTR iperf_run_tcp_server(void)
|
static void socket_recv(int recv_socket, struct sockaddr_storage listen_addr, uint8_t type)
|
||||||
{
|
{
|
||||||
socklen_t addr_len = sizeof(struct sockaddr);
|
bool udp_recv_start = true;
|
||||||
struct sockaddr_in remote_addr;
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
int actual_recv = 0;
|
|
||||||
int want_recv = 0;
|
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
int listen_socket;
|
int want_recv = 0;
|
||||||
struct timeval t;
|
int actual_recv = 0;
|
||||||
int sockfd;
|
socklen_t addr_len = sizeof(struct sockaddr);
|
||||||
int opt = 1;
|
|
||||||
|
|
||||||
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
||||||
if (listen_socket < 0) {
|
|
||||||
iperf_show_socket_error_reason("tcp server create", listen_socket);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(s_iperf_ctrl.cfg.sport);
|
|
||||||
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.sip;
|
|
||||||
if (bind(listen_socket, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
|
|
||||||
iperf_show_socket_error_reason("tcp server bind", listen_socket);
|
|
||||||
close(listen_socket);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listen(listen_socket, 5) < 0) {
|
|
||||||
iperf_show_socket_error_reason("tcp server listen", listen_socket);
|
|
||||||
close(listen_socket);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("iperf tcp server create successfully\n");
|
|
||||||
buffer = s_iperf_ctrl.buffer;
|
buffer = s_iperf_ctrl.buffer;
|
||||||
want_recv = s_iperf_ctrl.buffer_len;
|
want_recv = s_iperf_ctrl.buffer_len;
|
||||||
|
|
||||||
while (!s_iperf_ctrl.finish) {
|
while (!s_iperf_ctrl.finish) {
|
||||||
|
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
||||||
/*TODO need to change to non-block mode */
|
addr_len = sizeof(struct sockaddr_in6);
|
||||||
sockfd = accept(listen_socket, (struct sockaddr *)&remote_addr, &addr_len);
|
actual_recv = recvfrom(recv_socket, buffer, want_recv, 0, (struct sockaddr *)&listen_addr, &addr_len);
|
||||||
if (sockfd < 0) {
|
} else if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
||||||
iperf_show_socket_error_reason("tcp server listen", listen_socket);
|
addr_len = sizeof(struct sockaddr_in);
|
||||||
close(listen_socket);
|
actual_recv = recvfrom(recv_socket, buffer, want_recv, 0, (struct sockaddr *)&listen_addr, &addr_len);
|
||||||
return ESP_FAIL;
|
|
||||||
} else {
|
|
||||||
printf("accept: %s,%d\n", inet_ntoa(remote_addr.sin_addr), htons(remote_addr.sin_port));
|
|
||||||
iperf_start_report();
|
|
||||||
|
|
||||||
t.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
|
|
||||||
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!s_iperf_ctrl.finish) {
|
|
||||||
actual_recv = recv(sockfd, buffer, want_recv, 0);
|
|
||||||
if (actual_recv < 0) {
|
if (actual_recv < 0) {
|
||||||
iperf_show_socket_error_reason("tcp server recv", listen_socket);
|
if (type == IPERF_TRANS_TYPE_TCP) {
|
||||||
|
iperf_show_socket_error_reason("tcp server recv", recv_socket);
|
||||||
|
}
|
||||||
|
if (type == IPERF_TRANS_TYPE_UDP) {
|
||||||
|
iperf_show_socket_error_reason("udp server recv", recv_socket);
|
||||||
|
}
|
||||||
s_iperf_ctrl.finish = true;
|
s_iperf_ctrl.finish = true;
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
s_iperf_ctrl.total_len += actual_recv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(sockfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
s_iperf_ctrl.finish = true;
|
|
||||||
close(listen_socket);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t IRAM_ATTR iperf_run_udp_server(void)
|
|
||||||
{
|
|
||||||
socklen_t addr_len = sizeof(struct sockaddr_in);
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
int actual_recv = 0;
|
|
||||||
struct timeval t;
|
|
||||||
int want_recv = 0;
|
|
||||||
uint8_t *buffer;
|
|
||||||
int sockfd;
|
|
||||||
int opt = 1;
|
|
||||||
bool udp_recv_start = true ;
|
|
||||||
|
|
||||||
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
if (sockfd < 0) {
|
|
||||||
iperf_show_socket_error_reason("udp server create", sockfd);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(s_iperf_ctrl.cfg.sport);
|
|
||||||
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.sip;
|
|
||||||
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
|
|
||||||
iperf_show_socket_error_reason("udp server bind", sockfd);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(s_iperf_ctrl.cfg.sport);
|
|
||||||
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.sip;
|
|
||||||
|
|
||||||
buffer = s_iperf_ctrl.buffer;
|
|
||||||
want_recv = s_iperf_ctrl.buffer_len;
|
|
||||||
ESP_LOGI(TAG, "want recv=%d", want_recv);
|
|
||||||
|
|
||||||
t.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
|
|
||||||
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
|
|
||||||
|
|
||||||
while (!s_iperf_ctrl.finish) {
|
|
||||||
actual_recv = recvfrom(sockfd, buffer, want_recv, 0, (struct sockaddr *)&addr, &addr_len);
|
|
||||||
if (actual_recv < 0) {
|
|
||||||
iperf_show_socket_error_reason("udp server recv", sockfd);
|
|
||||||
} else {
|
} else {
|
||||||
if (udp_recv_start) {
|
if (udp_recv_start) {
|
||||||
iperf_start_report();
|
iperf_start_report();
|
||||||
@@ -238,56 +143,36 @@ static esp_err_t IRAM_ATTR iperf_run_udp_server(void)
|
|||||||
s_iperf_ctrl.total_len += actual_recv;
|
s_iperf_ctrl.total_len += actual_recv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s_iperf_ctrl.finish = true;
|
|
||||||
close(sockfd);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t iperf_run_udp_client(void)
|
static void socket_send(int send_socket, struct sockaddr_storage dest_addr, uint8_t type)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
|
||||||
iperf_udp_pkt_t *udp;
|
|
||||||
int actual_send = 0;
|
|
||||||
bool retry = false;
|
bool retry = false;
|
||||||
uint32_t delay = 1;
|
|
||||||
int want_send = 0;
|
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
int sockfd;
|
uint8_t delay = 0;
|
||||||
int opt = 1;
|
int actual_send = 0;
|
||||||
int err;
|
int want_send = 0;
|
||||||
int id;
|
int err = 0;
|
||||||
|
|
||||||
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
if (sockfd < 0) {
|
|
||||||
iperf_show_socket_error_reason("udp client create", sockfd);
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(s_iperf_ctrl.cfg.dport);
|
|
||||||
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.dip;
|
|
||||||
|
|
||||||
iperf_start_report();
|
|
||||||
buffer = s_iperf_ctrl.buffer;
|
buffer = s_iperf_ctrl.buffer;
|
||||||
udp = (iperf_udp_pkt_t *)buffer;
|
|
||||||
want_send = s_iperf_ctrl.buffer_len;
|
want_send = s_iperf_ctrl.buffer_len;
|
||||||
id = 0;
|
iperf_start_report();
|
||||||
|
|
||||||
while (!s_iperf_ctrl.finish) {
|
while (!s_iperf_ctrl.finish) {
|
||||||
|
if (type == IPERF_TRANS_TYPE_UDP) {
|
||||||
if (false == retry) {
|
if (false == retry) {
|
||||||
id++;
|
|
||||||
udp->id = htonl(id);
|
|
||||||
delay = 1;
|
delay = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
retry = false;
|
retry = false;
|
||||||
actual_send = sendto(sockfd, buffer, want_send, 0, (struct sockaddr *)&addr, sizeof(addr));
|
}
|
||||||
|
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
||||||
|
actual_send = sendto(send_socket, buffer, want_send, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in6));
|
||||||
|
} else if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
||||||
|
actual_send = sendto(send_socket, buffer, want_send, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in));
|
||||||
|
}
|
||||||
if (actual_send != want_send) {
|
if (actual_send != want_send) {
|
||||||
err = iperf_get_socket_error_code(sockfd);
|
if (type == IPERF_TRANS_TYPE_UDP) {
|
||||||
|
err = iperf_get_socket_error_code(send_socket);
|
||||||
if (err == ENOMEM) {
|
if (err == ENOMEM) {
|
||||||
vTaskDelay(delay);
|
vTaskDelay(delay);
|
||||||
if (delay < IPERF_MAX_DELAY) {
|
if (delay < IPERF_MAX_DELAY) {
|
||||||
@@ -296,58 +181,251 @@ static esp_err_t iperf_run_udp_client(void)
|
|||||||
retry = true;
|
retry = true;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
||||||
ESP_LOGE(TAG, "udp client send abort: err=%d", err);
|
ESP_LOGE(TAG, "udp client send abort: err=%d", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == IPERF_TRANS_TYPE_TCP) {
|
||||||
|
iperf_show_socket_error_reason("tcp client send", send_socket);
|
||||||
|
ESP_LOGI(TAG, "tcp client send error\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s_iperf_ctrl.total_len += actual_send;
|
s_iperf_ctrl.total_len += actual_send;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t IRAM_ATTR 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_in6 listen_addr6 = { 0 };
|
||||||
|
struct sockaddr_in listen_addr4 = { 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");
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
|
||||||
|
setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||||
|
|
||||||
|
memcpy(&listen_addr, &listen_addr6, sizeof(listen_addr6));
|
||||||
|
} else 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
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\n", 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));
|
||||||
|
|
||||||
|
socket_recv(client_socket, listen_addr, IPERF_TRANS_TYPE_TCP);
|
||||||
|
exit:
|
||||||
|
if (listen_socket != -1) {
|
||||||
|
shutdown(listen_socket, 0);
|
||||||
|
close(listen_socket);
|
||||||
|
ESP_LOGI(TAG, "TCP Socket server is closed.");
|
||||||
|
}
|
||||||
s_iperf_ctrl.finish = true;
|
s_iperf_ctrl.finish = true;
|
||||||
close(sockfd);
|
return ret;
|
||||||
return ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t iperf_run_tcp_client(void)
|
static esp_err_t iperf_run_tcp_client(void)
|
||||||
{
|
{
|
||||||
struct sockaddr_in remote_addr;
|
int client_socket = -1;
|
||||||
int actual_send = 0;
|
int err = 0;
|
||||||
int want_send = 0;
|
esp_err_t ret = ESP_OK;
|
||||||
uint8_t *buffer;
|
struct sockaddr_storage dest_addr = { 0 };
|
||||||
int sockfd;
|
struct sockaddr_in6 dest_addr6 = { 0 };
|
||||||
|
struct sockaddr_in dest_addr4 = { 0 };
|
||||||
|
|
||||||
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
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");
|
||||||
if (sockfd < 0) {
|
|
||||||
iperf_show_socket_error_reason("tcp client create", sockfd);
|
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
||||||
return ESP_FAIL;
|
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 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&remote_addr, 0, sizeof(remote_addr));
|
socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_TCP);
|
||||||
remote_addr.sin_family = AF_INET;
|
exit:
|
||||||
remote_addr.sin_port = htons(s_iperf_ctrl.cfg.dport);
|
if (client_socket != -1) {
|
||||||
remote_addr.sin_addr.s_addr = s_iperf_ctrl.cfg.dip;
|
shutdown(client_socket, 0);
|
||||||
if (connect(sockfd, (struct sockaddr *)&remote_addr, sizeof(remote_addr)) < 0) {
|
close(client_socket);
|
||||||
iperf_show_socket_error_reason("tcp client connect", sockfd);
|
ESP_LOGI(TAG, "TCP Socket client is closed.");
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iperf_start_report();
|
|
||||||
buffer = s_iperf_ctrl.buffer;
|
|
||||||
want_send = s_iperf_ctrl.buffer_len;
|
|
||||||
while (!s_iperf_ctrl.finish) {
|
|
||||||
actual_send = send(sockfd, buffer, want_send, 0);
|
|
||||||
if (actual_send <= 0) {
|
|
||||||
iperf_show_socket_error_reason("tcp client send", sockfd);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
s_iperf_ctrl.total_len += actual_send;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s_iperf_ctrl.finish = true;
|
s_iperf_ctrl.finish = true;
|
||||||
close(sockfd);
|
return ret;
|
||||||
return ESP_OK;
|
}
|
||||||
|
|
||||||
|
static esp_err_t IRAM_ATTR 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_in6 listen_addr6 = { 0 };
|
||||||
|
struct sockaddr_in listen_addr4 = { 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");
|
||||||
|
|
||||||
|
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 %d", listen_addr6.sin6_port);
|
||||||
|
|
||||||
|
memcpy(&listen_addr, &listen_addr6, sizeof(listen_addr6));
|
||||||
|
} else 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));
|
||||||
|
|
||||||
|
socket_recv(listen_socket, listen_addr, IPERF_TRANS_TYPE_UDP);
|
||||||
|
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_in6 dest_addr6 = { 0 };
|
||||||
|
struct sockaddr_in dest_addr4 = { 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");
|
||||||
|
|
||||||
|
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:%d", 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 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", s_iperf_ctrl.cfg.destination_ip4, s_iperf_ctrl.cfg.dport);
|
||||||
|
|
||||||
|
setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||||
|
memcpy(&dest_addr, &dest_addr4, sizeof(dest_addr4));
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_UDP);
|
||||||
|
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)
|
static void iperf_task_traffic(void *arg)
|
||||||
@@ -374,11 +452,11 @@ static void iperf_task_traffic(void *arg)
|
|||||||
static uint32_t iperf_get_buffer_len(void)
|
static uint32_t iperf_get_buffer_len(void)
|
||||||
{
|
{
|
||||||
if (iperf_is_udp_client()) {
|
if (iperf_is_udp_client()) {
|
||||||
return IPERF_UDP_TX_LEN;
|
return (s_iperf_ctrl.cfg.len_send_buf == 0 ? IPERF_UDP_TX_LEN : s_iperf_ctrl.cfg.len_send_buf);
|
||||||
} else if (iperf_is_udp_server()) {
|
} else if (iperf_is_udp_server()) {
|
||||||
return IPERF_UDP_RX_LEN;
|
return IPERF_UDP_RX_LEN;
|
||||||
} else if (iperf_is_tcp_client()) {
|
} else if (iperf_is_tcp_client()) {
|
||||||
return IPERF_TCP_TX_LEN;
|
return (s_iperf_ctrl.cfg.len_send_buf == 0 ? IPERF_TCP_TX_LEN : s_iperf_ctrl.cfg.len_send_buf);
|
||||||
} else {
|
} else {
|
||||||
return IPERF_TCP_RX_LEN;
|
return IPERF_TCP_RX_LEN;
|
||||||
}
|
}
|
||||||
@@ -409,7 +487,6 @@ esp_err_t iperf_start(iperf_cfg_t *cfg)
|
|||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
memset(s_iperf_ctrl.buffer, 0, s_iperf_ctrl.buffer_len);
|
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, portNUM_PROCESSORS - 1);
|
ret = xTaskCreatePinnedToCore(iperf_task_traffic, IPERF_TRAFFIC_TASK_NAME, IPERF_TRAFFIC_TASK_STACK, NULL, IPERF_TRAFFIC_TASK_PRIORITY, NULL, portNUM_PROCESSORS - 1);
|
||||||
if (ret != pdPASS) {
|
if (ret != pdPASS) {
|
||||||
ESP_LOGE(TAG, "create task %s failed", IPERF_TRAFFIC_TASK_NAME);
|
ESP_LOGE(TAG, "create task %s failed", IPERF_TRAFFIC_TASK_NAME);
|
||||||
@@ -417,7 +494,6 @@ esp_err_t iperf_start(iperf_cfg_t *cfg)
|
|||||||
s_iperf_ctrl.buffer = NULL;
|
s_iperf_ctrl.buffer = NULL;
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,6 +507,5 @@ esp_err_t iperf_stop(void)
|
|||||||
ESP_LOGI(TAG, "wait current iperf to stop ...");
|
ESP_LOGI(TAG, "wait current iperf to stop ...");
|
||||||
vTaskDelay(300 / portTICK_PERIOD_MS);
|
vTaskDelay(300 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
@@ -65,7 +65,9 @@ static struct {
|
|||||||
struct arg_str *ip;
|
struct arg_str *ip;
|
||||||
struct arg_lit *server;
|
struct arg_lit *server;
|
||||||
struct arg_lit *udp;
|
struct arg_lit *udp;
|
||||||
|
struct arg_lit *version;
|
||||||
struct arg_int *port;
|
struct arg_int *port;
|
||||||
|
struct arg_int *length;
|
||||||
struct arg_int *interval;
|
struct arg_int *interval;
|
||||||
struct arg_int *time;
|
struct arg_int *time;
|
||||||
struct arg_lit *abort;
|
struct arg_lit *abort;
|
||||||
@@ -84,6 +86,9 @@ static int eth_cmd_iperf(int argc, char **argv)
|
|||||||
|
|
||||||
memset(&cfg, 0, sizeof(cfg));
|
memset(&cfg, 0, sizeof(cfg));
|
||||||
|
|
||||||
|
// ethernet iperf only support IPV4 address
|
||||||
|
cfg.type = IPERF_IP_TYPE_IPV4;
|
||||||
|
|
||||||
/* iperf -a */
|
/* iperf -a */
|
||||||
if (iperf_args.abort->count != 0) {
|
if (iperf_args.abort->count != 0) {
|
||||||
iperf_stop();
|
iperf_stop();
|
||||||
@@ -102,15 +107,22 @@ static int eth_cmd_iperf(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
/* iperf -c SERVER_ADDRESS */
|
/* iperf -c SERVER_ADDRESS */
|
||||||
else {
|
else {
|
||||||
cfg.dip = esp_ip4addr_aton(iperf_args.ip->sval[0]);
|
cfg.destination_ip4 = esp_ip4addr_aton(iperf_args.ip->sval[0]);
|
||||||
cfg.flag |= IPERF_FLAG_CLIENT;
|
cfg.flag |= IPERF_FLAG_CLIENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iperf_args.length->count == 0) {
|
||||||
|
cfg.len_send_buf = 0;
|
||||||
|
} else {
|
||||||
|
cfg.len_send_buf = iperf_args.length->ival[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* acquiring for ip, could blocked here */
|
/* acquiring for ip, could blocked here */
|
||||||
xEventGroupWaitBits(eth_event_group, GOTIP_BIT, pdFALSE, pdTRUE, portMAX_DELAY);
|
xEventGroupWaitBits(eth_event_group, GOTIP_BIT, pdFALSE, pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
cfg.sip = ip.ip.addr;
|
cfg.source_ip4 = ip.ip.addr;
|
||||||
if (cfg.sip == 0) {
|
if (cfg.source_ip4 == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,8 +170,10 @@ static int eth_cmd_iperf(int argc, char **argv)
|
|||||||
printf("mode=%s-%s sip=%d.%d.%d.%d:%d, dip=%d.%d.%d.%d:%d, interval=%d, time=%d\r\n",
|
printf("mode=%s-%s sip=%d.%d.%d.%d:%d, dip=%d.%d.%d.%d:%d, interval=%d, time=%d\r\n",
|
||||||
cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp",
|
cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp",
|
||||||
cfg.flag & IPERF_FLAG_SERVER ? "server" : "client",
|
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.source_ip4 & 0xFF, (cfg.source_ip4 >> 8) & 0xFF, (cfg.source_ip4 >> 16) & 0xFF,
|
||||||
cfg.dip & 0xFF, (cfg.dip >> 8) & 0xFF, (cfg.dip >> 16) & 0xFF, (cfg.dip >> 24) & 0xFF, cfg.dport,
|
(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);
|
cfg.interval, cfg.time);
|
||||||
|
|
||||||
iperf_start(&cfg);
|
iperf_start(&cfg);
|
||||||
@@ -324,8 +338,10 @@ void register_ethernet(void)
|
|||||||
"run in client mode, connecting to <host>");
|
"run in client mode, connecting to <host>");
|
||||||
iperf_args.server = arg_lit0("s", "server", "run in server mode");
|
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.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>",
|
iperf_args.port = arg_int0("p", "port", "<port>",
|
||||||
"server port to listen on/connect to");
|
"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>",
|
iperf_args.interval = arg_int0("i", "interval", "<interval>",
|
||||||
"seconds between periodic bandwidth reports");
|
"seconds between periodic bandwidth reports");
|
||||||
iperf_args.time = arg_int0("t", "time", "<time>", "time in seconds to transmit for (default 10 secs)");
|
iperf_args.time = arg_int0("t", "time", "<time>", "time in seconds to transmit for (default 10 secs)");
|
||||||
|
@@ -2,5 +2,7 @@
|
|||||||
# in this exact order for cmake to work correctly
|
# in this exact order for cmake to work correctly
|
||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/iperf)
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
|
||||||
project(esp_ot_cli)
|
project(esp_ot_cli)
|
||||||
|
@@ -5,4 +5,6 @@
|
|||||||
|
|
||||||
PROJECT_NAME := esp_ot_cli
|
PROJECT_NAME := esp_ot_cli
|
||||||
|
|
||||||
|
EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/iperf
|
||||||
|
|
||||||
include $(IDF_PATH)/make/project.mk
|
include $(IDF_PATH)/make/project.mk
|
||||||
|
@@ -84,7 +84,9 @@ leader
|
|||||||
Done
|
Done
|
||||||
```
|
```
|
||||||
|
|
||||||
## Example1: TCP/UDP server and client
|
## Example1: Set up network
|
||||||
|
|
||||||
|
You need to prepare two esp32h2(or two ESP devices each connected to a 15.4 RCP) and flashed with this example.
|
||||||
|
|
||||||
### Step 1 Configure the project
|
### Step 1 Configure the project
|
||||||
|
|
||||||
@@ -92,10 +94,7 @@ Done
|
|||||||
idf.py menuconfig
|
idf.py menuconfig
|
||||||
```
|
```
|
||||||
|
|
||||||
Enable the operation: Example Configuration -> Enable custom command in ot-cli -> Enable openthread tcp/udp socket
|
|
||||||
|
|
||||||
### Step 2 Build, Flash, and Run
|
### Step 2 Build, Flash, and Run
|
||||||
You need to prepare two ESP devices each connected to a 15.4 RCP and flashed with this example.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
idf.py -p PORT flash monitor
|
idf.py -p PORT flash monitor
|
||||||
@@ -136,7 +135,6 @@ Done
|
|||||||
leader
|
leader
|
||||||
Done
|
Done
|
||||||
```
|
```
|
||||||
|
|
||||||
Now the first device has formed a Thread network, on the second device run:
|
Now the first device has formed a Thread network, on the second device run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -174,7 +172,21 @@ Done
|
|||||||
|
|
||||||
Now the second device has joined the Thread network and acting as a router (or a child).
|
Now the second device has joined the Thread network and acting as a router (or a child).
|
||||||
|
|
||||||
### Step 4 Set up tcp/udp socket server and client
|
## Example2: TCP/UDP server and client
|
||||||
|
|
||||||
|
You need to prepare two ESP devices each connected to a 15.4 RCP and flashed with this example.
|
||||||
|
|
||||||
|
### Step 1 Configure the project and Set up network
|
||||||
|
|
||||||
|
```bash
|
||||||
|
idf.py menuconfig
|
||||||
|
```
|
||||||
|
Enable the operation: Example Configuration -> Enable custom command in ot-cli
|
||||||
|
|
||||||
|
After configuring the project project, you should follow 'Example1' to set up network.
|
||||||
|
|
||||||
|
|
||||||
|
### Step 2 Set up tcp/udp socket server and client
|
||||||
|
|
||||||
In leader device, run this command in command line shell.
|
In leader device, run this command in command line shell.
|
||||||
|
|
||||||
@@ -243,3 +255,64 @@ I (38321) ot_secket: This message is from server
|
|||||||
I (38323) ot_secket: Socket client is closed.
|
I (38323) ot_secket: Socket client is closed.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Example3 iperf:
|
||||||
|
|
||||||
|
### Step 1 Configure the project and Set up network
|
||||||
|
|
||||||
|
```bash
|
||||||
|
idf.py menuconfig
|
||||||
|
```
|
||||||
|
Enable the operation: Openthread -> Enable custom command in ot-cli
|
||||||
|
|
||||||
|
After configuring the project project, you should follow 'Example1' to set up network.
|
||||||
|
|
||||||
|
### Step 2 Iperf test:
|
||||||
|
|
||||||
|
Run this command for iperf help:
|
||||||
|
```bash
|
||||||
|
iperf
|
||||||
|
I(272113) OPENTHREAD:[INFO]-CLI-----: execute command: iperf
|
||||||
|
---iperf parameter---
|
||||||
|
-s : server mode, only receive
|
||||||
|
-u : upd mode
|
||||||
|
-V : use IPV6 address
|
||||||
|
-c <addr> : client mode, only transmit
|
||||||
|
-i <interval> : seconds between periodic bandwidth reports
|
||||||
|
-t <time> : time in seconds to transmit for (default 10 secs)
|
||||||
|
-p <port> : server port to listen on/connect to
|
||||||
|
-l <len_send_buf> : the lenth of send buffer
|
||||||
|
---example---
|
||||||
|
create a tcp server : iperf -s -i 3 -p 5001 -t 60
|
||||||
|
create a udp client : iperf -c <addr> -u -i 3 -t 60 -p 5001 -l 512
|
||||||
|
Done
|
||||||
|
```
|
||||||
|
|
||||||
|
In leader device, run this command to get the leader IPv6 address.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> ipaddr
|
||||||
|
fd00:db8:0:0:0:ff:fe00:fc00
|
||||||
|
fd00:db8:0:0:0:ff:fe00:ac00
|
||||||
|
fd00:db8:0:0:284a:cb4a:cb3b:2a42
|
||||||
|
fe80:0:0:0:146e:a00:0:1
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run this command in command line shell.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# for setting up an iperf tcp server
|
||||||
|
> iperf -V -s -i 3 -p 5001 -t 20
|
||||||
|
|
||||||
|
# for setting up an iperf udp server
|
||||||
|
> iperf -V -s -u -i 3 -p 5001 -t 20
|
||||||
|
```
|
||||||
|
|
||||||
|
In router device, run this command in command line shell.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# for setting up an iperf tcp client
|
||||||
|
> iperf -V -c fd00:db8:0:0:284a:cb4a:cb3b:2a42 -i 1 -t 14 -p 5001 -l 512
|
||||||
|
|
||||||
|
# for setting up an iperf udp client
|
||||||
|
> iperf -V -c fd00:db8:0:0:284a:cb4a:cb3b:2a42 -u -i 1 -t 14 -p 5001 -l 512
|
||||||
|
```
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
set(srcs "esp_ot_cli.c")
|
set(srcs "esp_ot_cli.c")
|
||||||
|
|
||||||
if(CONFIG_OPENTHREAD_CLI_ESP_EXTENSION)
|
if(CONFIG_OPENTHREAD_CLI_ESP_EXTENSION)
|
||||||
list(APPEND srcs "esp_ot_cli_extension.c" "esp_ot_tcp_socket.c" "esp_ot_udp_socket.c")
|
list(APPEND srcs "esp_ot_cli_extension.c" "esp_ot_tcp_socket.c" "esp_ot_udp_socket.c" "esp_ot_iperf.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@@ -1,19 +1,12 @@
|
|||||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "esp_openthread.h"
|
#include "esp_openthread.h"
|
||||||
#include "esp_ot_cli_extension.h"
|
#include "esp_ot_cli_extension.h"
|
||||||
|
#include "esp_ot_iperf.h"
|
||||||
#include "esp_ot_tcp_socket.h"
|
#include "esp_ot_tcp_socket.h"
|
||||||
#include "esp_ot_udp_socket.h"
|
#include "esp_ot_udp_socket.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
@@ -26,6 +19,7 @@ static const otCliCommand kCommands[] = {
|
|||||||
{"tcpsockclient", esp_ot_process_tcp_client},
|
{"tcpsockclient", esp_ot_process_tcp_client},
|
||||||
{"udpsockserver", esp_ot_process_udp_server},
|
{"udpsockserver", esp_ot_process_udp_server},
|
||||||
{"udpsockclient", esp_ot_process_udp_client},
|
{"udpsockclient", esp_ot_process_udp_client},
|
||||||
|
{"iperf", esp_ot_process_iperf}
|
||||||
};
|
};
|
||||||
|
|
||||||
void esp_cli_custom_command_init()
|
void esp_cli_custom_command_init()
|
||||||
|
@@ -1,18 +1,10 @@
|
|||||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
98
examples/openthread/ot_cli/main/esp_ot_iperf.c
Normal file
98
examples/openthread/ot_cli/main/esp_ot_iperf.c
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_ot_iperf.h"
|
||||||
|
#include "iperf.h"
|
||||||
|
#include "openthread/cli.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define TAG "ot-iperf"
|
||||||
|
|
||||||
|
void esp_ot_process_iperf(void *aContext, uint8_t aArgsLength, char *aArgs[])
|
||||||
|
{
|
||||||
|
(void)(aContext);
|
||||||
|
(void)(aArgsLength);
|
||||||
|
iperf_cfg_t cfg;
|
||||||
|
memset(&cfg, 0, sizeof(cfg));
|
||||||
|
// set iperf default flag: tcp server
|
||||||
|
IPERF_FLAG_SET(cfg.flag, IPERF_FLAG_TCP);
|
||||||
|
IPERF_FLAG_SET(cfg.flag, IPERF_FLAG_SERVER);
|
||||||
|
cfg.time = IPERF_DEFAULT_TIME;
|
||||||
|
cfg.type = IPERF_IP_TYPE_IPV4;
|
||||||
|
if (aArgsLength == 0) {
|
||||||
|
otCliOutputFormat("---iperf parameter---\n");
|
||||||
|
otCliOutputFormat("-V : use IPV6 address\n");
|
||||||
|
otCliOutputFormat("-s : server mode, only receive\n");
|
||||||
|
otCliOutputFormat("-u : upd mode\n");
|
||||||
|
otCliOutputFormat("-c <addr> : client mode, only transmit\n");
|
||||||
|
otCliOutputFormat("-i <interval> : seconds between periodic bandwidth reports\n");
|
||||||
|
otCliOutputFormat("-t <time> : time in seconds to transmit for (default 30 secs)\n");
|
||||||
|
otCliOutputFormat("-p <port> : server port to listen on/connect to\n");
|
||||||
|
otCliOutputFormat("-l <len_send_buf> : the lenth of send buffer\n");
|
||||||
|
otCliOutputFormat("---example---\n");
|
||||||
|
otCliOutputFormat("create a tcp server : iperf -s -i 3 -p 5001 -t 60\n");
|
||||||
|
otCliOutputFormat("create a udp client : iperf -c <addr> -u -i 3 -t 60 -p 5001 -l 512\n");
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < aArgsLength; i++) {
|
||||||
|
if (strcmp(aArgs[i], "-c") == 0) {
|
||||||
|
IPERF_FLAG_SET(cfg.flag, IPERF_FLAG_CLIENT);
|
||||||
|
IPERF_FLAG_CLR(cfg.flag, IPERF_FLAG_SERVER);
|
||||||
|
i++;
|
||||||
|
cfg.destination_ip6 = aArgs[i];
|
||||||
|
otCliOutputFormat("ip:%s\n", cfg.destination_ip6);
|
||||||
|
} else if (strcmp(aArgs[i], "-s") == 0) {
|
||||||
|
IPERF_FLAG_SET(cfg.flag, IPERF_FLAG_SERVER);
|
||||||
|
IPERF_FLAG_CLR(cfg.flag, IPERF_FLAG_CLIENT);
|
||||||
|
} else if (strcmp(aArgs[i], "-V") == 0) {
|
||||||
|
cfg.type = IPERF_IP_TYPE_IPV6;
|
||||||
|
} else if (strcmp(aArgs[i], "-u") == 0) {
|
||||||
|
IPERF_FLAG_SET(cfg.flag, IPERF_FLAG_UDP);
|
||||||
|
IPERF_FLAG_CLR(cfg.flag, IPERF_FLAG_TCP);
|
||||||
|
} else if (strcmp(aArgs[i], "-p") == 0) {
|
||||||
|
i++;
|
||||||
|
if (cfg.flag & IPERF_FLAG_SERVER) {
|
||||||
|
cfg.sport = atoi(aArgs[i]);
|
||||||
|
cfg.dport = IPERF_DEFAULT_PORT;
|
||||||
|
} else {
|
||||||
|
cfg.sport = IPERF_DEFAULT_PORT;
|
||||||
|
cfg.dport = atoi(aArgs[i]);
|
||||||
|
}
|
||||||
|
otCliOutputFormat("dp:%d\n", cfg.dport);
|
||||||
|
otCliOutputFormat("sp:%d\n", cfg.sport);
|
||||||
|
} else if (strcmp(aArgs[i], "-i") == 0) {
|
||||||
|
i++;
|
||||||
|
if (atoi(aArgs[i]) < 0) {
|
||||||
|
cfg.interval = IPERF_DEFAULT_INTERVAL;
|
||||||
|
} else {
|
||||||
|
cfg.interval = atoi(aArgs[i]);
|
||||||
|
}
|
||||||
|
otCliOutputFormat("i:%d\n", cfg.interval);
|
||||||
|
} else if (strcmp(aArgs[i], "-t") == 0) {
|
||||||
|
i++;
|
||||||
|
cfg.time = atoi(aArgs[i]);
|
||||||
|
if (cfg.time <= cfg.interval) {
|
||||||
|
cfg.time = cfg.interval;
|
||||||
|
}
|
||||||
|
otCliOutputFormat("t:%d\n", cfg.time);
|
||||||
|
} else if (strcmp(aArgs[i], "-l") == 0) {
|
||||||
|
i++;
|
||||||
|
if (atoi(aArgs[i]) <= 0) {
|
||||||
|
ESP_LOGE(TAG, "Invalid arguments.");
|
||||||
|
} else {
|
||||||
|
cfg.len_send_buf = atoi(aArgs[i]);
|
||||||
|
}
|
||||||
|
} else if (strcmp(aArgs[i], "-a") == 0) {
|
||||||
|
iperf_stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iperf_start(&cfg);
|
||||||
|
}
|
||||||
|
}
|
20
examples/openthread/ot_cli/main/esp_ot_iperf.h
Normal file
20
examples/openthread/ot_cli/main/esp_ot_iperf.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief User command "iperf" process.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void esp_ot_process_iperf(void *aContext, uint8_t aArgsLength, char *aArgs[]);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
@@ -32,7 +24,7 @@ static void tcp_socket_server_task(void *pvParameters)
|
|||||||
int opt = 1;
|
int opt = 1;
|
||||||
int port = CONFIG_OPENTHREAD_CLI_TCP_SERVER_PORT;
|
int port = CONFIG_OPENTHREAD_CLI_TCP_SERVER_PORT;
|
||||||
int client_sock = 0;
|
int client_sock = 0;
|
||||||
struct timeval timeout;
|
struct timeval timeout = { 0 };
|
||||||
struct sockaddr_storage source_addr; // Large enough for both IPv6
|
struct sockaddr_storage source_addr; // Large enough for both IPv6
|
||||||
struct sockaddr_in6 listen_addr = { 0 };
|
struct sockaddr_in6 listen_addr = { 0 };
|
||||||
// The TCP server listen at the address "::", which means all addresses can be listened to.
|
// The TCP server listen at the address "::", which means all addresses can be listened to.
|
||||||
@@ -154,7 +146,7 @@ void esp_ot_process_tcp_client(void *aContext, uint8_t aArgsLength, char *aArgs[
|
|||||||
{
|
{
|
||||||
(void)(aContext);
|
(void)(aContext);
|
||||||
(void)(aArgsLength);
|
(void)(aArgsLength);
|
||||||
if (aArgs[0] == NULL) {
|
if (aArgsLength == 0) {
|
||||||
ESP_LOGE(TAG, "Invalid arguments.");
|
ESP_LOGE(TAG, "Invalid arguments.");
|
||||||
} else {
|
} else {
|
||||||
xTaskCreate(tcp_socket_client_task, "ot_tcp_socket_client", 4096, aArgs[0], 4, NULL);
|
xTaskCreate(tcp_socket_client_task, "ot_tcp_socket_client", 4096, aArgs[0], 4, NULL);
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
@@ -30,8 +22,9 @@ static void udp_socket_server_task(void *pvParameters)
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
int len;
|
int len;
|
||||||
int listen_sock;
|
int listen_sock;
|
||||||
|
|
||||||
int port = CONFIG_OPENTHREAD_CLI_UDP_SERVER_PORT;
|
int port = CONFIG_OPENTHREAD_CLI_UDP_SERVER_PORT;
|
||||||
struct timeval timeout;
|
struct timeval timeout = { 0 };
|
||||||
struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
|
struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
|
||||||
struct sockaddr_in6 listen_addr;
|
struct sockaddr_in6 listen_addr;
|
||||||
|
|
||||||
@@ -39,7 +32,7 @@ static void udp_socket_server_task(void *pvParameters)
|
|||||||
listen_addr.sin6_family = AF_INET6;
|
listen_addr.sin6_family = AF_INET6;
|
||||||
listen_addr.sin6_port = htons(port);
|
listen_addr.sin6_port = htons(port);
|
||||||
|
|
||||||
listen_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6);
|
listen_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
ESP_GOTO_ON_FALSE((listen_sock >= 0), ESP_OK, exit, TAG, "Unable to create socket: errno %d", errno);
|
ESP_GOTO_ON_FALSE((listen_sock >= 0), ESP_OK, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||||
ESP_LOGI(TAG, "Socket created");
|
ESP_LOGI(TAG, "Socket created");
|
||||||
|
|
||||||
@@ -98,7 +91,7 @@ static void udp_socket_client_task(void *pvParameters)
|
|||||||
dest_addr.sin6_family = AF_INET6;
|
dest_addr.sin6_family = AF_INET6;
|
||||||
dest_addr.sin6_port = htons(port);
|
dest_addr.sin6_port = htons(port);
|
||||||
|
|
||||||
client_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6);
|
client_sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
ESP_GOTO_ON_FALSE((client_sock >= 0), ESP_OK, exit, TAG, "Unable to create socket: errno %d", errno);
|
ESP_GOTO_ON_FALSE((client_sock >= 0), ESP_OK, exit, TAG, "Unable to create socket: errno %d", errno);
|
||||||
ESP_LOGI(TAG, "Socket created, sending to %s:%d", host_ip, port);
|
ESP_LOGI(TAG, "Socket created, sending to %s:%d", host_ip, port);
|
||||||
|
|
||||||
@@ -135,7 +128,7 @@ void esp_ot_process_udp_client(void *aContext, uint8_t aArgsLength, char *aArgs[
|
|||||||
{
|
{
|
||||||
(void)(aContext);
|
(void)(aContext);
|
||||||
(void)(aArgsLength);
|
(void)(aArgsLength);
|
||||||
if (aArgs[0] == NULL) {
|
if (aArgsLength == 0) {
|
||||||
ESP_LOGE(TAG, "Invalid arguments.");
|
ESP_LOGE(TAG, "Invalid arguments.");
|
||||||
} else {
|
} else {
|
||||||
xTaskCreate(udp_socket_client_task, "ot_udp_socket_client", 4096, aArgs[0], 4, NULL);
|
xTaskCreate(udp_socket_client_task, "ot_udp_socket_client", 4096, aArgs[0], 4, NULL);
|
||||||
|
@@ -1,16 +1,8 @@
|
|||||||
// Copyright 2021 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@ CONFIG_OPENTHREAD_ENABLED=y
|
|||||||
#
|
#
|
||||||
# lwIP
|
# lwIP
|
||||||
#
|
#
|
||||||
|
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
|
||||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
|
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
|
||||||
CONFIG_LWIP_MULTICAST_PING=y
|
CONFIG_LWIP_MULTICAST_PING=y
|
||||||
# end of lwIP
|
# end of lwIP
|
||||||
|
@@ -24,7 +24,9 @@ typedef struct {
|
|||||||
struct arg_str *ip;
|
struct arg_str *ip;
|
||||||
struct arg_lit *server;
|
struct arg_lit *server;
|
||||||
struct arg_lit *udp;
|
struct arg_lit *udp;
|
||||||
|
struct arg_lit *version;
|
||||||
struct arg_int *port;
|
struct arg_int *port;
|
||||||
|
struct arg_int *length;
|
||||||
struct arg_int *interval;
|
struct arg_int *interval;
|
||||||
struct arg_int *time;
|
struct arg_int *time;
|
||||||
struct arg_lit *abort;
|
struct arg_lit *abort;
|
||||||
@@ -321,6 +323,9 @@ static int wifi_cmd_iperf(int argc, char** argv)
|
|||||||
|
|
||||||
memset(&cfg, 0, sizeof(cfg));
|
memset(&cfg, 0, sizeof(cfg));
|
||||||
|
|
||||||
|
// now wifi iperf only support IPV4 address
|
||||||
|
cfg.type = IPERF_IP_TYPE_IPV4;
|
||||||
|
|
||||||
if ( iperf_args.abort->count != 0) {
|
if ( iperf_args.abort->count != 0) {
|
||||||
iperf_stop();
|
iperf_stop();
|
||||||
return 0;
|
return 0;
|
||||||
@@ -335,12 +340,12 @@ static int wifi_cmd_iperf(int argc, char** argv)
|
|||||||
if (iperf_args.ip->count == 0) {
|
if (iperf_args.ip->count == 0) {
|
||||||
cfg.flag |= IPERF_FLAG_SERVER;
|
cfg.flag |= IPERF_FLAG_SERVER;
|
||||||
} else {
|
} else {
|
||||||
cfg.dip = esp_ip4addr_aton(iperf_args.ip->sval[0]);
|
cfg.destination_ip4 = esp_ip4addr_aton(iperf_args.ip->sval[0]);
|
||||||
cfg.flag |= IPERF_FLAG_CLIENT;
|
cfg.flag |= IPERF_FLAG_CLIENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.sip = wifi_get_local_ip();
|
cfg.source_ip4 = wifi_get_local_ip();
|
||||||
if (cfg.sip == 0) {
|
if (cfg.source_ip4 == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,6 +355,12 @@ static int wifi_cmd_iperf(int argc, char** argv)
|
|||||||
cfg.flag |= IPERF_FLAG_UDP;
|
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) {
|
if (iperf_args.port->count == 0) {
|
||||||
cfg.sport = IPERF_DEFAULT_PORT;
|
cfg.sport = IPERF_DEFAULT_PORT;
|
||||||
cfg.dport = IPERF_DEFAULT_PORT;
|
cfg.dport = IPERF_DEFAULT_PORT;
|
||||||
@@ -384,8 +395,10 @@ static int wifi_cmd_iperf(int argc, char** argv)
|
|||||||
ESP_LOGI(TAG, "mode=%s-%s sip=%d.%d.%d.%d:%d, dip=%d.%d.%d.%d:%d, interval=%d, time=%d",
|
ESP_LOGI(TAG, "mode=%s-%s sip=%d.%d.%d.%d:%d, dip=%d.%d.%d.%d:%d, interval=%d, time=%d",
|
||||||
cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp",
|
cfg.flag & IPERF_FLAG_TCP ? "tcp" : "udp",
|
||||||
cfg.flag & IPERF_FLAG_SERVER ? "server" : "client",
|
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.source_ip4 & 0xFF, (cfg.source_ip4 >> 8) & 0xFF, (cfg.source_ip4 >> 16) & 0xFF,
|
||||||
cfg.dip&0xFF, (cfg.dip>>8)&0xFF, (cfg.dip>>16)&0xFF, (cfg.dip>>24)&0xFF, cfg.dport,
|
(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);
|
cfg.interval, cfg.time);
|
||||||
|
|
||||||
iperf_start(&cfg);
|
iperf_start(&cfg);
|
||||||
@@ -448,7 +461,9 @@ void register_wifi(void)
|
|||||||
iperf_args.ip = arg_str0("c", "client", "<ip>", "run in client mode, connecting to <host>");
|
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.server = arg_lit0("s", "server", "run in server mode");
|
||||||
iperf_args.udp = arg_lit0("u", "udp", "use UDP rather than TCP");
|
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.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.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.time = arg_int0("t", "time", "<time>", "time in seconds to transmit for (default 10 secs)");
|
||||||
iperf_args.abort = arg_lit0("a", "abort", "abort running iperf");
|
iperf_args.abort = arg_lit0("a", "abort", "abort running iperf");
|
||||||
|
Reference in New Issue
Block a user