netutils/iperf: add support of multi-instance

Signed-off-by: chao an <anchao@xiaomi.com>
This commit is contained in:
chao an 2022-11-20 18:23:45 +08:00 committed by Petro Karashchenko
parent 8edfe88187
commit 60dc920701
3 changed files with 159 additions and 150 deletions

View File

@ -42,7 +42,6 @@
#define IPERF_REPORT_TASK_NAME "iperf_report" #define IPERF_REPORT_TASK_NAME "iperf_report"
#define IPERF_REPORT_TASK_PRIORITY 100 #define IPERF_REPORT_TASK_PRIORITY 100
#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)
@ -58,11 +57,12 @@
struct iperf_ctrl_t struct iperf_ctrl_t
{ {
FAR struct iperf_ctrl_t *flink;
struct iperf_cfg_t cfg; struct iperf_cfg_t cfg;
bool finish; bool finish;
uintmax_t total_len; uintmax_t total_len;
uint32_t buffer_len; uint32_t buffer_len;
uint8_t *buffer; FAR uint8_t *buffer;
uint32_t sockfd; uint32_t sockfd;
}; };
@ -77,27 +77,27 @@ struct iperf_udp_pkt_t
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
static bool s_iperf_is_running = false; static pthread_mutex_t g_iperf_ctrl_mutex = PTHREAD_MUTEX_INITIALIZER;
static struct iperf_ctrl_t s_iperf_ctrl; static sq_queue_t g_iperf_ctrl_list;
/**************************************************************************** /****************************************************************************
* Private Functions Prototypes * Private Functions Prototypes
****************************************************************************/ ****************************************************************************/
inline static bool iperf_is_udp_client(void); inline static bool iperf_is_udp_client(FAR struct iperf_ctrl_t *ctrl);
inline static bool iperf_is_udp_server(void); inline static bool iperf_is_udp_server(FAR struct iperf_ctrl_t *ctrl);
inline static bool iperf_is_tcp_client(void); inline static bool iperf_is_tcp_client(FAR struct iperf_ctrl_t *ctrl);
inline static bool iperf_is_tcp_server(void); inline static bool iperf_is_tcp_server(FAR struct iperf_ctrl_t *ctrl);
static int iperf_get_socket_error_code(int sockfd); static int iperf_get_socket_error_code(int sockfd);
static int iperf_show_socket_error_reason(const char *str, int sockfd); static int iperf_show_socket_error_reason(FAR const char *str, int sockfd);
static void iperf_report_task(void *arg); static void iperf_report_task(FAR void *arg);
static int iperf_start_report(void); static int iperf_start_report(FAR struct iperf_ctrl_t *ctrl);
static int iperf_run_tcp_server(void); static int iperf_run_tcp_server(FAR struct iperf_ctrl_t *ctrl);
static int iperf_run_udp_server(void); static int iperf_run_udp_server(FAR struct iperf_ctrl_t *ctrl);
static int iperf_run_udp_client(void); static int iperf_run_udp_client(FAR struct iperf_ctrl_t *ctrl);
static int iperf_run_tcp_client(void); static int iperf_run_tcp_client(FAR struct iperf_ctrl_t *ctrl);
static void iperf_task_traffic(void *arg); static void iperf_task_traffic(FAR void *arg);
static uint32_t iperf_get_buffer_len(void); static uint32_t iperf_get_buffer_len(FAR struct iperf_ctrl_t *ctrl);
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
@ -111,10 +111,10 @@ static uint32_t iperf_get_buffer_len(void);
* *
****************************************************************************/ ****************************************************************************/
inline static bool iperf_is_udp_client(void) inline static bool iperf_is_udp_client(FAR struct iperf_ctrl_t *ctrl)
{ {
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT) return ((ctrl->cfg.flag & IPERF_FLAG_CLIENT)
&& (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP)); && (ctrl->cfg.flag & IPERF_FLAG_UDP));
} }
/**************************************************************************** /****************************************************************************
@ -125,10 +125,10 @@ inline static bool iperf_is_udp_client(void)
* *
****************************************************************************/ ****************************************************************************/
inline static bool iperf_is_udp_server(void) inline static bool iperf_is_udp_server(FAR struct iperf_ctrl_t *ctrl)
{ {
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_SERVER) return ((ctrl->cfg.flag & IPERF_FLAG_SERVER)
&& (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP)); && (ctrl->cfg.flag & IPERF_FLAG_UDP));
} }
/**************************************************************************** /****************************************************************************
@ -139,10 +139,10 @@ inline static bool iperf_is_udp_server(void)
* *
****************************************************************************/ ****************************************************************************/
inline static bool iperf_is_tcp_client(void) inline static bool iperf_is_tcp_client(FAR struct iperf_ctrl_t *ctrl)
{ {
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT) return ((ctrl->cfg.flag & IPERF_FLAG_CLIENT)
&& (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP)); && (ctrl->cfg.flag & IPERF_FLAG_TCP));
} }
/**************************************************************************** /****************************************************************************
@ -153,10 +153,10 @@ inline static bool iperf_is_tcp_client(void)
* *
****************************************************************************/ ****************************************************************************/
inline static bool iperf_is_tcp_server(void) inline static bool iperf_is_tcp_server(FAR struct iperf_ctrl_t *ctrl)
{ {
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_SERVER) return ((ctrl->cfg.flag & IPERF_FLAG_SERVER)
&& (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP)); && (ctrl->cfg.flag & IPERF_FLAG_TCP));
} }
/**************************************************************************** /****************************************************************************
@ -180,7 +180,7 @@ static int iperf_get_socket_error_code(int sockfd)
* *
****************************************************************************/ ****************************************************************************/
static int iperf_show_socket_error_reason(const char *str, int sockfd) static int iperf_show_socket_error_reason(FAR const char *str, int sockfd)
{ {
int err = errno; int err = errno;
if (err != 0) if (err != 0)
@ -226,10 +226,11 @@ static double ts_diff(const struct timespec *a, const struct timespec *b)
* *
****************************************************************************/ ****************************************************************************/
static void iperf_report_task(void *arg) static void iperf_report_task(FAR void *arg)
{ {
uint32_t interval = s_iperf_ctrl.cfg.interval; FAR struct iperf_ctrl_t *ctrl = arg;
uint32_t time = s_iperf_ctrl.cfg.time; uint32_t interval = ctrl->cfg.interval;
uint32_t time = ctrl->cfg.time;
struct timespec now; struct timespec now;
struct timespec start; struct timespec start;
uintmax_t now_len; uintmax_t now_len;
@ -237,7 +238,7 @@ static void iperf_report_task(void *arg)
prctl(PR_SET_NAME, IPERF_REPORT_TASK_NAME); prctl(PR_SET_NAME, IPERF_REPORT_TASK_NAME);
now_len = s_iperf_ctrl.total_len; now_len = ctrl->total_len;
ret = clock_gettime(CLOCK_MONOTONIC, &now); ret = clock_gettime(CLOCK_MONOTONIC, &now);
if (ret != 0) if (ret != 0)
{ {
@ -247,7 +248,7 @@ static void iperf_report_task(void *arg)
start = now; start = now;
printf("\n%19s %16s %18s\n", "Interval", "Transfer", "Bandwidth\n"); printf("\n%19s %16s %18s\n", "Interval", "Transfer", "Bandwidth\n");
while (!s_iperf_ctrl.finish) while (!ctrl->finish)
{ {
uintmax_t last_len; uintmax_t last_len;
struct timespec last; struct timespec last;
@ -255,7 +256,7 @@ static void iperf_report_task(void *arg)
sleep(interval); sleep(interval);
last_len = now_len; last_len = now_len;
last = now; last = now;
now_len = s_iperf_ctrl.total_len; now_len = ctrl->total_len;
ret = clock_gettime(CLOCK_MONOTONIC, &now); ret = clock_gettime(CLOCK_MONOTONIC, &now);
if (ret != 0) if (ret != 0)
{ {
@ -285,7 +286,7 @@ static void iperf_report_task(void *arg)
ts_diff(&now, &start) / 1e6)); ts_diff(&now, &start) / 1e6));
} }
s_iperf_ctrl.finish = true; ctrl->finish = true;
pthread_exit(NULL); pthread_exit(NULL);
} }
@ -298,20 +299,20 @@ static void iperf_report_task(void *arg)
* *
****************************************************************************/ ****************************************************************************/
static int iperf_start_report(void) static int iperf_start_report(FAR struct iperf_ctrl_t *ctrl)
{ {
int ret;
pthread_t thread;
struct sched_param param; struct sched_param param;
pthread_attr_t attr; pthread_attr_t attr;
pthread_t thread;
int ret;
pthread_attr_init(&attr); pthread_attr_init(&attr);
param.sched_priority = IPERF_REPORT_TASK_PRIORITY; param.sched_priority = IPERF_REPORT_TASK_PRIORITY;
pthread_attr_setschedparam(&attr, &param); pthread_attr_setschedparam(&attr, &param);
pthread_attr_setstacksize(&attr, IPERF_REPORT_TASK_STACK); pthread_attr_setstacksize(&attr, IPERF_REPORT_TASK_STACK);
ret = pthread_create(&thread, &attr, (void *)iperf_report_task, ret = pthread_create(&thread, &attr, (FAR void *)iperf_report_task,
NULL); ctrl);
if (ret != 0) if (ret != 0)
{ {
printf("iperf_thread: pthread_create failed: %d, %s\n", printf("iperf_thread: pthread_create failed: %d, %s\n",
@ -332,14 +333,14 @@ static int iperf_start_report(void)
* *
****************************************************************************/ ****************************************************************************/
static int iperf_run_tcp_server(void) static int iperf_run_tcp_server(FAR struct iperf_ctrl_t *ctrl)
{ {
socklen_t addr_len = sizeof(struct sockaddr); socklen_t addr_len = sizeof(struct sockaddr);
struct sockaddr_in remote_addr; struct sockaddr_in remote_addr;
struct sockaddr_in addr; struct sockaddr_in addr;
int actual_recv = 0; int actual_recv = 0;
int want_recv = 0; int want_recv = 0;
uint8_t *buffer; FAR uint8_t *buffer;
int listen_socket; int listen_socket;
struct timeval t; struct timeval t;
int sockfd; int sockfd;
@ -354,9 +355,9 @@ static int iperf_run_tcp_server(void)
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(s_iperf_ctrl.cfg.sport); addr.sin_port = htons(ctrl->cfg.sport);
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.sip; addr.sin_addr.s_addr = ctrl->cfg.sip;
if (bind(listen_socket, (struct sockaddr *)&addr, sizeof(addr)) != 0) if (bind(listen_socket, (FAR struct sockaddr *)&addr, sizeof(addr)) != 0)
{ {
iperf_show_socket_error_reason("tcp server bind", listen_socket); iperf_show_socket_error_reason("tcp server bind", listen_socket);
close(listen_socket); close(listen_socket);
@ -370,13 +371,13 @@ static int iperf_run_tcp_server(void)
return -1; return -1;
} }
buffer = s_iperf_ctrl.buffer; buffer = ctrl->buffer;
want_recv = s_iperf_ctrl.buffer_len; want_recv = ctrl->buffer_len;
while (!s_iperf_ctrl.finish) while (!ctrl->finish)
{ {
/* TODO need to change to non-block mode */ /* TODO need to change to non-block mode */
sockfd = accept(listen_socket, (struct sockaddr *)&remote_addr, sockfd = accept(listen_socket, (FAR struct sockaddr *)&remote_addr,
&addr_len); &addr_len);
if (sockfd < 0) if (sockfd < 0)
{ {
@ -392,14 +393,14 @@ static int iperf_run_tcp_server(void)
inet_ntoa_r(remote_addr.sin_addr, inetaddr, inet_ntoa_r(remote_addr.sin_addr, inetaddr,
sizeof(inetaddr)), sizeof(inetaddr)),
htons(remote_addr.sin_port)); htons(remote_addr.sin_port));
iperf_start_report(); iperf_start_report(ctrl);
t.tv_sec = IPERF_SOCKET_RX_TIMEOUT; t.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
t.tv_usec = 0; t.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t)); setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
} }
while (!s_iperf_ctrl.finish) while (!ctrl->finish)
{ {
actual_recv = recv(sockfd, buffer, want_recv, 0); actual_recv = recv(sockfd, buffer, want_recv, 0);
if (actual_recv == 0) if (actual_recv == 0)
@ -414,26 +415,26 @@ static int iperf_run_tcp_server(void)
* exits after finishing a single connection. * exits after finishing a single connection.
*/ */
s_iperf_ctrl.finish = true; ctrl->finish = true;
break; break;
} }
else if (actual_recv < 0) else if (actual_recv < 0)
{ {
iperf_show_socket_error_reason("tcp server recv", iperf_show_socket_error_reason("tcp server recv",
listen_socket); listen_socket);
s_iperf_ctrl.finish = true; ctrl->finish = true;
break; break;
} }
else else
{ {
s_iperf_ctrl.total_len += actual_recv; ctrl->total_len += actual_recv;
} }
} }
close(sockfd); close(sockfd);
} }
s_iperf_ctrl.finish = true; ctrl->finish = true;
close(listen_socket); close(listen_socket);
return 0; return 0;
@ -447,14 +448,14 @@ static int iperf_run_tcp_server(void)
* *
****************************************************************************/ ****************************************************************************/
static int iperf_run_udp_server(void) static int iperf_run_udp_server(FAR struct iperf_ctrl_t *ctrl)
{ {
socklen_t addr_len = sizeof(struct sockaddr_in); socklen_t addr_len = sizeof(struct sockaddr_in);
struct sockaddr_in addr; struct sockaddr_in addr;
int actual_recv = 0; int actual_recv = 0;
struct timeval t; struct timeval t;
int want_recv = 0; int want_recv = 0;
uint8_t *buffer; FAR uint8_t *buffer;
int sockfd; int sockfd;
int opt; int opt;
bool udp_recv_start = true; bool udp_recv_start = true;
@ -469,30 +470,30 @@ static int iperf_run_udp_server(void)
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(s_iperf_ctrl.cfg.sport); addr.sin_port = htons(ctrl->cfg.sport);
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.sip; addr.sin_addr.s_addr = ctrl->cfg.sip;
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0) if (bind(sockfd, (FAR struct sockaddr *)&addr, sizeof(addr)) != 0)
{ {
iperf_show_socket_error_reason("udp server bind", sockfd); iperf_show_socket_error_reason("udp server bind", sockfd);
return -1; return -1;
} }
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(s_iperf_ctrl.cfg.sport); addr.sin_port = htons(ctrl->cfg.sport);
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.sip; addr.sin_addr.s_addr = ctrl->cfg.sip;
buffer = s_iperf_ctrl.buffer; buffer = ctrl->buffer;
want_recv = s_iperf_ctrl.buffer_len; want_recv = ctrl->buffer_len;
printf("want recv=%d\n", want_recv); printf("want recv=%d\n", want_recv);
t.tv_sec = IPERF_SOCKET_RX_TIMEOUT; t.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
t.tv_usec = 0; t.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t)); setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
while (!s_iperf_ctrl.finish) while (!ctrl->finish)
{ {
actual_recv = recvfrom(sockfd, buffer, want_recv, 0, actual_recv = recvfrom(sockfd, buffer, want_recv, 0,
(struct sockaddr *)&addr, &addr_len); (FAR struct sockaddr *)&addr, &addr_len);
if (actual_recv < 0) if (actual_recv < 0)
{ {
iperf_show_socket_error_reason("udp server recv", sockfd); iperf_show_socket_error_reason("udp server recv", sockfd);
@ -501,15 +502,15 @@ static int iperf_run_udp_server(void)
{ {
if (udp_recv_start == true) if (udp_recv_start == true)
{ {
iperf_start_report(); iperf_start_report(ctrl);
udp_recv_start = false; udp_recv_start = false;
} }
s_iperf_ctrl.total_len += actual_recv; ctrl->total_len += actual_recv;
} }
} }
s_iperf_ctrl.finish = true; ctrl->finish = true;
close(sockfd); close(sockfd);
return 0; return 0;
@ -523,10 +524,10 @@ static int iperf_run_udp_server(void)
* *
****************************************************************************/ ****************************************************************************/
static int iperf_run_udp_client(void) static int iperf_run_udp_client(FAR struct iperf_ctrl_t *ctrl)
{ {
FAR struct iperf_udp_pkt_t *udp;
struct sockaddr_in addr; struct sockaddr_in addr;
struct iperf_udp_pkt_t *udp;
int actual_send = 0; int actual_send = 0;
bool retry = false; bool retry = false;
uint32_t delay = 1; uint32_t delay = 1;
@ -547,16 +548,16 @@ static int iperf_run_udp_client(void)
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(s_iperf_ctrl.cfg.dport); addr.sin_port = htons(ctrl->cfg.dport);
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.dip; addr.sin_addr.s_addr = ctrl->cfg.dip;
iperf_start_report(); iperf_start_report(ctrl);
buffer = s_iperf_ctrl.buffer; buffer = ctrl->buffer;
udp = (struct iperf_udp_pkt_t *)buffer; udp = (FAR struct iperf_udp_pkt_t *)buffer;
want_send = s_iperf_ctrl.buffer_len; want_send = ctrl->buffer_len;
id = 0; id = 0;
while (!s_iperf_ctrl.finish) while (!ctrl->finish)
{ {
if (false == retry) if (false == retry)
{ {
@ -567,7 +568,7 @@ static int iperf_run_udp_client(void)
retry = false; retry = false;
actual_send = sendto(sockfd, buffer, want_send, 0, actual_send = sendto(sockfd, buffer, want_send, 0,
(struct sockaddr *)&addr, sizeof(addr)); (FAR struct sockaddr *)&addr, sizeof(addr));
if (actual_send != want_send) if (actual_send != want_send)
{ {
@ -591,11 +592,11 @@ static int iperf_run_udp_client(void)
} }
else else
{ {
s_iperf_ctrl.total_len += actual_send; ctrl->total_len += actual_send;
} }
} }
s_iperf_ctrl.finish = true; ctrl->finish = true;
close(sockfd); close(sockfd);
return 0; return 0;
@ -609,12 +610,12 @@ static int iperf_run_udp_client(void)
* *
****************************************************************************/ ****************************************************************************/
static int iperf_run_tcp_client(void) static int iperf_run_tcp_client(FAR struct iperf_ctrl_t *ctrl)
{ {
struct sockaddr_in remote_addr; struct sockaddr_in remote_addr;
FAR uint8_t *buffer;
int actual_send = 0; int actual_send = 0;
int want_send = 0; int want_send = 0;
uint8_t *buffer;
int sockfd; int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@ -626,20 +627,20 @@ static int iperf_run_tcp_client(void)
memset(&remote_addr, 0, sizeof(remote_addr)); memset(&remote_addr, 0, sizeof(remote_addr));
remote_addr.sin_family = AF_INET; remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(s_iperf_ctrl.cfg.dport); remote_addr.sin_port = htons(ctrl->cfg.dport);
remote_addr.sin_addr.s_addr = s_iperf_ctrl.cfg.dip; remote_addr.sin_addr.s_addr = ctrl->cfg.dip;
if (connect(sockfd, (struct sockaddr *)&remote_addr, if (connect(sockfd, (FAR struct sockaddr *)&remote_addr,
sizeof(remote_addr)) < 0) sizeof(remote_addr)) < 0)
{ {
iperf_show_socket_error_reason("tcp client connect", sockfd); iperf_show_socket_error_reason("tcp client connect", sockfd);
return -1; return -1;
} }
iperf_start_report(); iperf_start_report(ctrl);
buffer = s_iperf_ctrl.buffer; buffer = ctrl->buffer;
want_send = s_iperf_ctrl.buffer_len; want_send = ctrl->buffer_len;
while (!s_iperf_ctrl.finish) while (!ctrl->finish)
{ {
actual_send = send(sockfd, buffer, want_send, 0); actual_send = send(sockfd, buffer, want_send, 0);
if (actual_send <= 0) if (actual_send <= 0)
@ -649,11 +650,11 @@ static int iperf_run_tcp_client(void)
} }
else else
{ {
s_iperf_ctrl.total_len += actual_send; ctrl->total_len += actual_send;
} }
} }
s_iperf_ctrl.finish = true; ctrl->finish = true;
close(sockfd); close(sockfd);
return 0; return 0;
@ -667,25 +668,27 @@ static int iperf_run_tcp_client(void)
* *
****************************************************************************/ ****************************************************************************/
static void iperf_task_traffic(void *arg) static void iperf_task_traffic(FAR void *arg)
{ {
FAR struct iperf_ctrl_t *ctrl = arg;
prctl(PR_SET_NAME, IPERF_TRAFFIC_TASK_NAME); prctl(PR_SET_NAME, IPERF_TRAFFIC_TASK_NAME);
if (iperf_is_udp_client()) if (iperf_is_udp_client(ctrl))
{ {
iperf_run_udp_client(); iperf_run_udp_client(ctrl);
} }
else if (iperf_is_udp_server()) else if (iperf_is_udp_server(ctrl))
{ {
iperf_run_udp_server(); iperf_run_udp_server(ctrl);
} }
else if (iperf_is_tcp_client()) else if (iperf_is_tcp_client(ctrl))
{ {
iperf_run_tcp_client(); iperf_run_tcp_client(ctrl);
} }
else if (iperf_is_tcp_server()) else if (iperf_is_tcp_server(ctrl))
{ {
iperf_run_tcp_server(); iperf_run_tcp_server(ctrl);
} }
else else
{ {
@ -694,29 +697,28 @@ static void iperf_task_traffic(void *arg)
assert(false); assert(false);
} }
if (s_iperf_ctrl.buffer) if (ctrl->buffer)
{ {
free(s_iperf_ctrl.buffer); free(ctrl->buffer);
s_iperf_ctrl.buffer = NULL; ctrl->buffer = NULL;
} }
printf("iperf exit\n"); printf("iperf exit\n");
s_iperf_is_running = false;
pthread_exit(NULL); pthread_exit(NULL);
} }
static uint32_t iperf_get_buffer_len(void) static uint32_t iperf_get_buffer_len(FAR struct iperf_ctrl_t *ctrl)
{ {
if (iperf_is_udp_client()) if (iperf_is_udp_client(ctrl))
{ {
return IPERF_UDP_TX_LEN; return IPERF_UDP_TX_LEN;
} }
else if (iperf_is_udp_server()) else if (iperf_is_udp_server(ctrl))
{ {
return IPERF_UDP_RX_LEN; return IPERF_UDP_RX_LEN;
} }
else if (iperf_is_tcp_client()) else if (iperf_is_tcp_client(ctrl))
{ {
return IPERF_TCP_TX_LEN; return IPERF_TCP_TX_LEN;
} }
@ -740,54 +742,57 @@ static uint32_t iperf_get_buffer_len(void)
* *
****************************************************************************/ ****************************************************************************/
int iperf_start(struct iperf_cfg_t *cfg) int iperf_start(FAR struct iperf_cfg_t *cfg)
{ {
int ret; struct iperf_ctrl_t ctrl;
void *retval;
struct sched_param param; struct sched_param param;
pthread_t thread;
pthread_attr_t attr; pthread_attr_t attr;
pthread_t thread;
FAR void *retval;
int ret;
if (!cfg) if (!cfg)
{ {
return -1; return -1;
} }
if (s_iperf_is_running) memset(&ctrl, 0, sizeof(ctrl));
{ memcpy(&ctrl.cfg, cfg, sizeof(*cfg));
printf("iperf is running\n"); ctrl.finish = false;
return -1; ctrl.buffer_len = iperf_get_buffer_len(&ctrl);
} ctrl.buffer = (FAR uint8_t *)malloc(ctrl.buffer_len);
if (ctrl.buffer == NULL)
memset(&s_iperf_ctrl, 0, sizeof(s_iperf_ctrl));
memcpy(&s_iperf_ctrl.cfg, cfg, sizeof(*cfg));
s_iperf_is_running = true;
s_iperf_ctrl.finish = false;
s_iperf_ctrl.buffer_len = iperf_get_buffer_len();
s_iperf_ctrl.buffer = (uint8_t *)malloc(s_iperf_ctrl.buffer_len);
if (!s_iperf_ctrl.buffer)
{ {
printf("create buffer: not enough memory\n"); printf("create buffer: not enough memory\n");
return -1; return -1;
} }
memset(s_iperf_ctrl.buffer, 0, s_iperf_ctrl.buffer_len); memset(ctrl.buffer, 0, ctrl.buffer_len);
pthread_attr_init(&attr); pthread_attr_init(&attr);
param.sched_priority = IPERF_TRAFFIC_TASK_PRIORITY; param.sched_priority = IPERF_TRAFFIC_TASK_PRIORITY;
pthread_attr_setschedparam(&attr, &param); pthread_attr_setschedparam(&attr, &param);
pthread_attr_setstacksize(&attr, IPERF_TRAFFIC_TASK_STACK); pthread_attr_setstacksize(&attr, IPERF_TRAFFIC_TASK_STACK);
ret = pthread_create(&thread, &attr, (void *)iperf_task_traffic, ret = pthread_create(&thread, &attr, (FAR void *)iperf_task_traffic,
NULL); &ctrl);
if (ret != 0) if (ret != 0)
{ {
printf("iperf_task_traffic: create task failed: %d\n", ret); printf("iperf_task_traffic: create task failed: %d\n", ret);
free(s_iperf_ctrl.buffer); free(ctrl.buffer);
s_iperf_ctrl.buffer = NULL; ctrl.buffer = NULL;
return -1; return -1;
} }
pthread_mutex_lock(&g_iperf_ctrl_mutex);
sq_addlast((FAR sq_entry_t *)&ctrl, &g_iperf_ctrl_list);
pthread_mutex_unlock(&g_iperf_ctrl_mutex);
pthread_join(thread, &retval); pthread_join(thread, &retval);
pthread_mutex_lock(&g_iperf_ctrl_mutex);
sq_rem((FAR sq_entry_t *)&ctrl, &g_iperf_ctrl_list);
pthread_mutex_unlock(&g_iperf_ctrl_mutex);
return 0; return 0;
} }
@ -801,16 +806,20 @@ int iperf_start(struct iperf_cfg_t *cfg)
int iperf_stop(void) int iperf_stop(void)
{ {
if (s_iperf_is_running) FAR struct iperf_ctrl_t *ctrl;
FAR sq_entry_t *tmp;
FAR sq_entry_t *p;
pthread_mutex_lock(&g_iperf_ctrl_mutex);
sq_for_every_safe(&g_iperf_ctrl_list, p, tmp)
{ {
s_iperf_ctrl.finish = true; ctrl = (FAR struct iperf_ctrl_t *)p;
ctrl->finish = true;
sq_rem(p, &g_iperf_ctrl_list);
} }
while (s_iperf_is_running) pthread_mutex_unlock(&g_iperf_ctrl_mutex);
{
printf("wait current iperf to stop ...\n");
usleep(300 * 1000);
}
return 0; return 0;
} }

View File

@ -76,7 +76,7 @@ struct iperf_cfg_t
* *
****************************************************************************/ ****************************************************************************/
int iperf_start(struct iperf_cfg_t *cfg); int iperf_start(FAR struct iperf_cfg_t *cfg);
/**************************************************************************** /****************************************************************************
* Name: iperf_stop * Name: iperf_stop

View File

@ -50,14 +50,14 @@
struct wifi_iperf_t struct wifi_iperf_t
{ {
struct arg_str *ip; FAR struct arg_str *ip;
struct arg_lit *server; FAR struct arg_lit *server;
struct arg_lit *udp; FAR struct arg_lit *udp;
struct arg_int *port; FAR struct arg_int *port;
struct arg_int *interval; FAR struct arg_int *interval;
struct arg_int *time; FAR struct arg_int *time;
struct arg_lit *abort; FAR struct arg_lit *abort;
struct arg_end *end; FAR struct arg_end *end;
}; };
/**************************************************************************** /****************************************************************************
@ -119,7 +119,7 @@ int main(int argc, FAR char *argv[])
iperf_args.abort = arg_lit0("a", "abort", "abort running iperf"); iperf_args.abort = arg_lit0("a", "abort", "abort running iperf");
iperf_args.end = arg_end(1); iperf_args.end = arg_end(1);
nerrors = arg_parse(argc, argv, (void**) &iperf_args); nerrors = arg_parse(argc, argv, (FAR void**) &iperf_args);
if (nerrors != 0) if (nerrors != 0)
{ {
arg_print_errors(stderr, iperf_args.end, argv[0]); arg_print_errors(stderr, iperf_args.end, argv[0]);