You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by pk...@apache.org on 2022/11/21 07:52:32 UTC

[incubator-nuttx-apps] branch master updated: netutils/iperf: add support of multi-instance

This is an automated email from the ASF dual-hosted git repository.

pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 60dc92070 netutils/iperf: add support of multi-instance
60dc92070 is described below

commit 60dc9207012a0fcbcf84345ccfff5005dc441d1e
Author: chao an <an...@xiaomi.com>
AuthorDate: Sun Nov 20 18:23:45 2022 +0800

    netutils/iperf: add support of multi-instance
    
    Signed-off-by: chao an <an...@xiaomi.com>
---
 netutils/iperf/iperf.c      | 289 +++++++++++++++++++++++---------------------
 netutils/iperf/iperf.h      |   2 +-
 netutils/iperf/iperf_main.c |  18 +--
 3 files changed, 159 insertions(+), 150 deletions(-)

diff --git a/netutils/iperf/iperf.c b/netutils/iperf/iperf.c
index 042963cfb..aea1b024e 100644
--- a/netutils/iperf/iperf.c
+++ b/netutils/iperf/iperf.c
@@ -42,7 +42,6 @@
 #define IPERF_REPORT_TASK_NAME       "iperf_report"
 #define IPERF_REPORT_TASK_PRIORITY   100
 #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)
@@ -58,11 +57,12 @@
 
 struct iperf_ctrl_t
 {
+  FAR struct iperf_ctrl_t *flink;
   struct iperf_cfg_t cfg;
   bool finish;
   uintmax_t total_len;
   uint32_t buffer_len;
-  uint8_t *buffer;
+  FAR uint8_t *buffer;
   uint32_t sockfd;
 };
 
@@ -77,27 +77,27 @@ struct iperf_udp_pkt_t
  * Private Data
  ****************************************************************************/
 
-static bool s_iperf_is_running = false;
-static struct iperf_ctrl_t s_iperf_ctrl;
+static pthread_mutex_t g_iperf_ctrl_mutex = PTHREAD_MUTEX_INITIALIZER;
+static sq_queue_t      g_iperf_ctrl_list;
 
 /****************************************************************************
  * Private Functions Prototypes
  ****************************************************************************/
 
-inline static bool iperf_is_udp_client(void);
-inline static bool iperf_is_udp_server(void);
-inline static bool iperf_is_tcp_client(void);
-inline static bool iperf_is_tcp_server(void);
+inline static bool iperf_is_udp_client(FAR struct iperf_ctrl_t *ctrl);
+inline static bool iperf_is_udp_server(FAR struct iperf_ctrl_t *ctrl);
+inline static bool iperf_is_tcp_client(FAR struct iperf_ctrl_t *ctrl);
+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_show_socket_error_reason(const char *str, int sockfd);
-static void iperf_report_task(void *arg);
-static int iperf_start_report(void);
-static int iperf_run_tcp_server(void);
-static int iperf_run_udp_server(void);
-static int iperf_run_udp_client(void);
-static int iperf_run_tcp_client(void);
-static void iperf_task_traffic(void *arg);
-static uint32_t iperf_get_buffer_len(void);
+static int iperf_show_socket_error_reason(FAR const char *str, int sockfd);
+static void iperf_report_task(FAR void *arg);
+static int iperf_start_report(FAR struct iperf_ctrl_t *ctrl);
+static int iperf_run_tcp_server(FAR struct iperf_ctrl_t *ctrl);
+static int iperf_run_udp_server(FAR struct iperf_ctrl_t *ctrl);
+static int iperf_run_udp_client(FAR struct iperf_ctrl_t *ctrl);
+static int iperf_run_tcp_client(FAR struct iperf_ctrl_t *ctrl);
+static void iperf_task_traffic(FAR void *arg);
+static uint32_t iperf_get_buffer_len(FAR struct iperf_ctrl_t *ctrl);
 
 /****************************************************************************
  * 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)
-         && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP));
+  return ((ctrl->cfg.flag & IPERF_FLAG_CLIENT)
+         && (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)
-         && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP));
+  return ((ctrl->cfg.flag & IPERF_FLAG_SERVER)
+         && (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)
-         && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP));
+  return ((ctrl->cfg.flag & IPERF_FLAG_CLIENT)
+         && (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)
-         && (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP));
+  return ((ctrl->cfg.flag & IPERF_FLAG_SERVER)
+         && (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;
   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;
-  uint32_t time = s_iperf_ctrl.cfg.time;
+  FAR struct iperf_ctrl_t *ctrl = arg;
+  uint32_t interval = ctrl->cfg.interval;
+  uint32_t time = ctrl->cfg.time;
   struct timespec now;
   struct timespec start;
   uintmax_t now_len;
@@ -237,7 +238,7 @@ static void iperf_report_task(void *arg)
 
   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);
   if (ret != 0)
     {
@@ -247,7 +248,7 @@ static void iperf_report_task(void *arg)
 
   start = now;
   printf("\n%19s %16s %18s\n", "Interval", "Transfer", "Bandwidth\n");
-  while (!s_iperf_ctrl.finish)
+  while (!ctrl->finish)
     {
       uintmax_t last_len;
       struct timespec last;
@@ -255,7 +256,7 @@ static void iperf_report_task(void *arg)
       sleep(interval);
       last_len = now_len;
       last = now;
-      now_len = s_iperf_ctrl.total_len;
+      now_len = ctrl->total_len;
       ret = clock_gettime(CLOCK_MONOTONIC, &now);
       if (ret != 0)
         {
@@ -285,7 +286,7 @@ static void iperf_report_task(void *arg)
              ts_diff(&now, &start) / 1e6));
     }
 
-  s_iperf_ctrl.finish = true;
+  ctrl->finish = true;
 
   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;
   pthread_attr_t attr;
+  pthread_t thread;
+  int ret;
 
   pthread_attr_init(&attr);
   param.sched_priority = IPERF_REPORT_TASK_PRIORITY;
   pthread_attr_setschedparam(&attr, &param);
   pthread_attr_setstacksize(&attr, IPERF_REPORT_TASK_STACK);
 
-  ret = pthread_create(&thread, &attr, (void *)iperf_report_task,
-                       NULL);
+  ret = pthread_create(&thread, &attr, (FAR void *)iperf_report_task,
+                       ctrl);
   if (ret != 0)
     {
       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);
   struct sockaddr_in remote_addr;
   struct sockaddr_in addr;
   int actual_recv = 0;
   int want_recv = 0;
-  uint8_t *buffer;
+  FAR uint8_t *buffer;
   int listen_socket;
   struct timeval t;
   int sockfd;
@@ -354,9 +355,9 @@ static int iperf_run_tcp_server(void)
 
   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)
+  addr.sin_port = htons(ctrl->cfg.sport);
+  addr.sin_addr.s_addr = ctrl->cfg.sip;
+  if (bind(listen_socket, (FAR struct sockaddr *)&addr, sizeof(addr)) != 0)
     {
       iperf_show_socket_error_reason("tcp server bind", listen_socket);
       close(listen_socket);
@@ -370,13 +371,13 @@ static int iperf_run_tcp_server(void)
       return -1;
     }
 
-  buffer = s_iperf_ctrl.buffer;
-  want_recv = s_iperf_ctrl.buffer_len;
-  while (!s_iperf_ctrl.finish)
+  buffer = ctrl->buffer;
+  want_recv = ctrl->buffer_len;
+  while (!ctrl->finish)
     {
       /* 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);
       if (sockfd < 0)
         {
@@ -392,14 +393,14 @@ static int iperf_run_tcp_server(void)
                  inet_ntoa_r(remote_addr.sin_addr, inetaddr,
                              sizeof(inetaddr)),
                  htons(remote_addr.sin_port));
-          iperf_start_report();
+          iperf_start_report(ctrl);
 
           t.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
           t.tv_usec = 0;
           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);
           if (actual_recv == 0)
@@ -414,26 +415,26 @@ static int iperf_run_tcp_server(void)
                * exits after finishing a single connection.
                */
 
-              s_iperf_ctrl.finish = true;
+              ctrl->finish = true;
               break;
             }
           else if (actual_recv < 0)
             {
               iperf_show_socket_error_reason("tcp server recv",
                                              listen_socket);
-              s_iperf_ctrl.finish = true;
+              ctrl->finish = true;
               break;
             }
           else
             {
-              s_iperf_ctrl.total_len += actual_recv;
+              ctrl->total_len += actual_recv;
             }
         }
 
       close(sockfd);
     }
 
-  s_iperf_ctrl.finish = true;
+  ctrl->finish = true;
   close(listen_socket);
 
   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);
   struct sockaddr_in addr;
   int actual_recv = 0;
   struct timeval t;
   int want_recv = 0;
-  uint8_t *buffer;
+  FAR uint8_t *buffer;
   int sockfd;
   int opt;
   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));
 
   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)
+  addr.sin_port = htons(ctrl->cfg.sport);
+  addr.sin_addr.s_addr = ctrl->cfg.sip;
+  if (bind(sockfd, (FAR struct sockaddr *)&addr, sizeof(addr)) != 0)
     {
       iperf_show_socket_error_reason("udp server bind", sockfd);
       return -1;
     }
 
   addr.sin_family = AF_INET;
-  addr.sin_port = htons(s_iperf_ctrl.cfg.sport);
-  addr.sin_addr.s_addr = s_iperf_ctrl.cfg.sip;
+  addr.sin_port = htons(ctrl->cfg.sport);
+  addr.sin_addr.s_addr = ctrl->cfg.sip;
 
-  buffer = s_iperf_ctrl.buffer;
-  want_recv = s_iperf_ctrl.buffer_len;
+  buffer = ctrl->buffer;
+  want_recv = ctrl->buffer_len;
   printf("want recv=%d\n", want_recv);
 
   t.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
   t.tv_usec = 0;
   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,
-                             (struct sockaddr *)&addr, &addr_len);
+                             (FAR struct sockaddr *)&addr, &addr_len);
       if (actual_recv < 0)
         {
           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)
             {
-              iperf_start_report();
+              iperf_start_report(ctrl);
               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);
 
   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 iperf_udp_pkt_t *udp;
   int actual_send = 0;
   bool retry = false;
   uint32_t delay = 1;
@@ -547,16 +548,16 @@ static int iperf_run_udp_client(void)
   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;
+  addr.sin_port = htons(ctrl->cfg.dport);
+  addr.sin_addr.s_addr = ctrl->cfg.dip;
 
-  iperf_start_report();
-  buffer = s_iperf_ctrl.buffer;
-  udp = (struct iperf_udp_pkt_t *)buffer;
-  want_send = s_iperf_ctrl.buffer_len;
+  iperf_start_report(ctrl);
+  buffer = ctrl->buffer;
+  udp = (FAR struct iperf_udp_pkt_t *)buffer;
+  want_send = ctrl->buffer_len;
   id = 0;
 
-  while (!s_iperf_ctrl.finish)
+  while (!ctrl->finish)
     {
       if (false == retry)
         {
@@ -567,7 +568,7 @@ static int iperf_run_udp_client(void)
 
       retry = false;
       actual_send = sendto(sockfd, buffer, want_send, 0,
-                           (struct sockaddr *)&addr, sizeof(addr));
+                           (FAR struct sockaddr *)&addr, sizeof(addr));
 
       if (actual_send != want_send)
         {
@@ -591,11 +592,11 @@ static int iperf_run_udp_client(void)
         }
       else
         {
-          s_iperf_ctrl.total_len += actual_send;
+          ctrl->total_len += actual_send;
         }
     }
 
-  s_iperf_ctrl.finish = true;
+  ctrl->finish = true;
   close(sockfd);
 
   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;
+  FAR uint8_t *buffer;
   int actual_send = 0;
   int want_send = 0;
-  uint8_t *buffer;
   int sockfd;
 
   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));
   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,
+  remote_addr.sin_port = htons(ctrl->cfg.dport);
+  remote_addr.sin_addr.s_addr = ctrl->cfg.dip;
+  if (connect(sockfd, (FAR struct sockaddr *)&remote_addr,
               sizeof(remote_addr)) < 0)
     {
       iperf_show_socket_error_reason("tcp client connect", sockfd);
       return -1;
     }
 
-  iperf_start_report();
-  buffer = s_iperf_ctrl.buffer;
-  want_send = s_iperf_ctrl.buffer_len;
+  iperf_start_report(ctrl);
+  buffer = ctrl->buffer;
+  want_send = ctrl->buffer_len;
 
-  while (!s_iperf_ctrl.finish)
+  while (!ctrl->finish)
     {
       actual_send = send(sockfd, buffer, want_send, 0);
       if (actual_send <= 0)
@@ -649,11 +650,11 @@ static int iperf_run_tcp_client(void)
         }
       else
         {
-          s_iperf_ctrl.total_len += actual_send;
+          ctrl->total_len += actual_send;
         }
     }
 
-  s_iperf_ctrl.finish = true;
+  ctrl->finish = true;
   close(sockfd);
 
   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);
 
-  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
     {
@@ -694,29 +697,28 @@ static void iperf_task_traffic(void *arg)
       assert(false);
     }
 
-  if (s_iperf_ctrl.buffer)
+  if (ctrl->buffer)
     {
-      free(s_iperf_ctrl.buffer);
-      s_iperf_ctrl.buffer = NULL;
+      free(ctrl->buffer);
+      ctrl->buffer = NULL;
     }
 
   printf("iperf exit\n");
-  s_iperf_is_running = false;
 
   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;
     }
-  else if (iperf_is_udp_server())
+  else if (iperf_is_udp_server(ctrl))
     {
       return IPERF_UDP_RX_LEN;
     }
-  else if (iperf_is_tcp_client())
+  else if (iperf_is_tcp_client(ctrl))
     {
       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;
-  void *retval;
+  struct iperf_ctrl_t ctrl;
   struct sched_param param;
-  pthread_t thread;
   pthread_attr_t attr;
+  pthread_t thread;
+  FAR void *retval;
+  int ret;
 
   if (!cfg)
     {
       return -1;
     }
 
-  if (s_iperf_is_running)
-    {
-      printf("iperf is running\n");
-      return -1;
-    }
-
-  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)
+  memset(&ctrl, 0, sizeof(ctrl));
+  memcpy(&ctrl.cfg, cfg, sizeof(*cfg));
+  ctrl.finish = false;
+  ctrl.buffer_len = iperf_get_buffer_len(&ctrl);
+  ctrl.buffer = (FAR uint8_t *)malloc(ctrl.buffer_len);
+  if (ctrl.buffer == NULL)
     {
       printf("create buffer: not enough memory\n");
       return -1;
     }
 
-  memset(s_iperf_ctrl.buffer, 0, s_iperf_ctrl.buffer_len);
+  memset(ctrl.buffer, 0, ctrl.buffer_len);
   pthread_attr_init(&attr);
   param.sched_priority = IPERF_TRAFFIC_TASK_PRIORITY;
   pthread_attr_setschedparam(&attr, &param);
   pthread_attr_setstacksize(&attr, IPERF_TRAFFIC_TASK_STACK);
-  ret = pthread_create(&thread, &attr, (void *)iperf_task_traffic,
-                       NULL);
+  ret = pthread_create(&thread, &attr, (FAR void *)iperf_task_traffic,
+                       &ctrl);
 
   if (ret != 0)
     {
       printf("iperf_task_traffic: create task failed: %d\n", ret);
-      free(s_iperf_ctrl.buffer);
-      s_iperf_ctrl.buffer = NULL;
+      free(ctrl.buffer);
+      ctrl.buffer = NULL;
       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_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;
 }
 
@@ -801,16 +806,20 @@ int iperf_start(struct iperf_cfg_t *cfg)
 
 int iperf_stop(void)
 {
-  if (s_iperf_is_running)
-    {
-      s_iperf_ctrl.finish = true;
-    }
+  FAR struct iperf_ctrl_t *ctrl;
+  FAR sq_entry_t *tmp;
+  FAR sq_entry_t *p;
+
+  pthread_mutex_lock(&g_iperf_ctrl_mutex);
 
-  while (s_iperf_is_running)
+  sq_for_every_safe(&g_iperf_ctrl_list, p, tmp)
     {
-      printf("wait current iperf to stop ...\n");
-      usleep(300 * 1000);
+      ctrl = (FAR struct iperf_ctrl_t *)p;
+      ctrl->finish = true;
+      sq_rem(p, &g_iperf_ctrl_list);
     }
 
+  pthread_mutex_unlock(&g_iperf_ctrl_mutex);
+
   return 0;
 }
diff --git a/netutils/iperf/iperf.h b/netutils/iperf/iperf.h
index f4e56da06..55dc89819 100644
--- a/netutils/iperf/iperf.h
+++ b/netutils/iperf/iperf.h
@@ -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
diff --git a/netutils/iperf/iperf_main.c b/netutils/iperf/iperf_main.c
index 528e8107a..f6ad87c23 100644
--- a/netutils/iperf/iperf_main.c
+++ b/netutils/iperf/iperf_main.c
@@ -50,14 +50,14 @@
 
 struct wifi_iperf_t
 {
-  struct arg_str *ip;
-  struct arg_lit *server;
-  struct arg_lit *udp;
-  struct arg_int *port;
-  struct arg_int *interval;
-  struct arg_int *time;
-  struct arg_lit *abort;
-  struct arg_end *end;
+  FAR struct arg_str *ip;
+  FAR struct arg_lit *server;
+  FAR struct arg_lit *udp;
+  FAR struct arg_int *port;
+  FAR struct arg_int *interval;
+  FAR struct arg_int *time;
+  FAR struct arg_lit *abort;
+  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.end = arg_end(1);
 
-  nerrors = arg_parse(argc, argv, (void**) &iperf_args);
+  nerrors = arg_parse(argc, argv, (FAR void**) &iperf_args);
   if (nerrors != 0)
     {
       arg_print_errors(stderr, iperf_args.end, argv[0]);