openthread: add iperf example for ot-network test
This commit is contained in:
@@ -10,12 +10,20 @@
|
||||
#ifndef __IPERF_H_
|
||||
#define __IPERF_H_
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_types.h"
|
||||
#include "esp_err.h"
|
||||
#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)
|
||||
@@ -27,12 +35,11 @@ extern "C" {
|
||||
#define IPERF_DEFAULT_TIME 30
|
||||
|
||||
#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_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_NAME "iperf_report"
|
||||
|
||||
#define IPERF_UDP_TX_LEN (1472)
|
||||
#define IPERF_UDP_RX_LEN (16 << 10)
|
||||
@@ -46,12 +53,20 @@ extern "C" {
|
||||
|
||||
typedef struct {
|
||||
uint32_t flag;
|
||||
uint32_t dip;
|
||||
uint32_t sip;
|
||||
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;
|
||||
} iperf_cfg_t;
|
||||
|
||||
esp_err_t iperf_start(iperf_cfg_t *cfg);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
#include "iperf.h"
|
||||
|
||||
@@ -24,12 +25,6 @@ typedef struct {
|
||||
uint32_t sockfd;
|
||||
} 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 iperf_ctrl_t s_iperf_ctrl;
|
||||
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)
|
||||
{
|
||||
|
||||
return errno;
|
||||
}
|
||||
|
||||
@@ -113,241 +107,325 @@ static esp_err_t iperf_start_report(void)
|
||||
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)
|
||||
{
|
||||
bool udp_recv_start = true;
|
||||
uint8_t *buffer;
|
||||
int want_recv = 0;
|
||||
int actual_recv = 0;
|
||||
socklen_t addr_len = sizeof(struct sockaddr);
|
||||
struct sockaddr_in remote_addr;
|
||||
struct sockaddr_in addr;
|
||||
int actual_recv = 0;
|
||||
int want_recv = 0;
|
||||
uint8_t *buffer;
|
||||
int listen_socket;
|
||||
struct timeval t;
|
||||
int sockfd;
|
||||
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;
|
||||
want_recv = s_iperf_ctrl.buffer_len;
|
||||
while (!s_iperf_ctrl.finish) {
|
||||
|
||||
/*TODO need to change to non-block mode */
|
||||
sockfd = accept(listen_socket, (struct sockaddr *)&remote_addr, &addr_len);
|
||||
if (sockfd < 0) {
|
||||
iperf_show_socket_error_reason("tcp server listen", listen_socket);
|
||||
close(listen_socket);
|
||||
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) {
|
||||
iperf_show_socket_error_reason("tcp server recv", listen_socket);
|
||||
s_iperf_ctrl.finish = true;
|
||||
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 (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV6) {
|
||||
addr_len = sizeof(struct sockaddr_in6);
|
||||
actual_recv = recvfrom(recv_socket, buffer, want_recv, 0, (struct sockaddr *)&listen_addr, &addr_len);
|
||||
} else if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
||||
addr_len = sizeof(struct sockaddr_in);
|
||||
actual_recv = recvfrom(recv_socket, buffer, want_recv, 0, (struct sockaddr *)&listen_addr, &addr_len);
|
||||
}
|
||||
if (actual_recv < 0) {
|
||||
iperf_show_socket_error_reason("udp server recv", sockfd);
|
||||
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;
|
||||
break;
|
||||
} else {
|
||||
if(udp_recv_start){
|
||||
if (udp_recv_start) {
|
||||
iperf_start_report();
|
||||
udp_recv_start = false;
|
||||
}
|
||||
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;
|
||||
uint32_t delay = 1;
|
||||
int want_send = 0;
|
||||
uint8_t *buffer;
|
||||
int sockfd;
|
||||
int opt = 1;
|
||||
int err;
|
||||
int id;
|
||||
uint8_t delay = 0;
|
||||
int actual_send = 0;
|
||||
int want_send = 0;
|
||||
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;
|
||||
udp = (iperf_udp_pkt_t *)buffer;
|
||||
want_send = s_iperf_ctrl.buffer_len;
|
||||
id = 0;
|
||||
iperf_start_report();
|
||||
|
||||
while (!s_iperf_ctrl.finish) {
|
||||
if (false == retry) {
|
||||
id++;
|
||||
udp->id = htonl(id);
|
||||
delay = 1;
|
||||
if (type == IPERF_TRANS_TYPE_UDP) {
|
||||
if (false == retry) {
|
||||
delay = 1;
|
||||
}
|
||||
retry = false;
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
retry = false;
|
||||
actual_send = sendto(sockfd, buffer, want_send, 0, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
||||
if (actual_send != want_send) {
|
||||
err = iperf_get_socket_error_code(sockfd);
|
||||
if (err == ENOMEM) {
|
||||
vTaskDelay(delay);
|
||||
if (delay < IPERF_MAX_DELAY) {
|
||||
delay <<= 1;
|
||||
if (type == IPERF_TRANS_TYPE_UDP) {
|
||||
err = iperf_get_socket_error_code(send_socket);
|
||||
if (err == ENOMEM) {
|
||||
vTaskDelay(delay);
|
||||
if (delay < IPERF_MAX_DELAY) {
|
||||
delay <<= 1;
|
||||
}
|
||||
retry = true;
|
||||
continue;
|
||||
} else {
|
||||
if (s_iperf_ctrl.cfg.type == IPERF_IP_TYPE_IPV4) {
|
||||
ESP_LOGE(TAG, "udp client send abort: err=%d", err);
|
||||
}
|
||||
}
|
||||
retry = true;
|
||||
continue;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
close(sockfd);
|
||||
return ESP_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t iperf_run_tcp_client(void)
|
||||
{
|
||||
struct sockaddr_in remote_addr;
|
||||
int actual_send = 0;
|
||||
int want_send = 0;
|
||||
uint8_t *buffer;
|
||||
int sockfd;
|
||||
int client_socket = -1;
|
||||
int err = 0;
|
||||
esp_err_t ret = ESP_OK;
|
||||
struct sockaddr_storage dest_addr = { 0 };
|
||||
struct sockaddr_in6 dest_addr6 = { 0 };
|
||||
struct sockaddr_in dest_addr4 = { 0 };
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sockfd < 0) {
|
||||
iperf_show_socket_error_reason("tcp client create", sockfd);
|
||||
return ESP_FAIL;
|
||||
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) {
|
||||
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));
|
||||
remote_addr.sin_family = AF_INET;
|
||||
remote_addr.sin_port = htons(s_iperf_ctrl.cfg.dport);
|
||||
remote_addr.sin_addr.s_addr = s_iperf_ctrl.cfg.dip;
|
||||
if (connect(sockfd, (struct sockaddr *)&remote_addr, sizeof(remote_addr)) < 0) {
|
||||
iperf_show_socket_error_reason("tcp client connect", sockfd);
|
||||
return ESP_FAIL;
|
||||
socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_TCP);
|
||||
exit:
|
||||
if (client_socket != -1) {
|
||||
shutdown(client_socket, 0);
|
||||
close(client_socket);
|
||||
ESP_LOGI(TAG, "TCP Socket client is closed.");
|
||||
}
|
||||
|
||||
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;
|
||||
close(sockfd);
|
||||
return ESP_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -374,11 +452,11 @@ static void iperf_task_traffic(void *arg)
|
||||
static uint32_t iperf_get_buffer_len(void)
|
||||
{
|
||||
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()) {
|
||||
return IPERF_UDP_RX_LEN;
|
||||
} 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 {
|
||||
return IPERF_TCP_RX_LEN;
|
||||
}
|
||||
@@ -409,7 +487,6 @@ esp_err_t iperf_start(iperf_cfg_t *cfg)
|
||||
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, portNUM_PROCESSORS - 1);
|
||||
if (ret != pdPASS) {
|
||||
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;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -431,6 +507,5 @@ esp_err_t iperf_stop(void)
|
||||
ESP_LOGI(TAG, "wait current iperf to stop ...");
|
||||
vTaskDelay(300 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user