netutils/iperf: add support of multi-instance
Signed-off-by: chao an <anchao@xiaomi.com>
This commit is contained in:
parent
8edfe88187
commit
60dc920701
@ -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, ¶m);
|
pthread_attr_setschedparam(&attr, ¶m);
|
||||||
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, ¶m);
|
pthread_attr_setschedparam(&attr, ¶m);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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]);
|
||||||
|
Loading…
Reference in New Issue
Block a user