Browse Source

iperf 支持 udp 模式

tangyuxin 6 years ago
parent
commit
c7722895d1
4 changed files with 230 additions and 49 deletions
  1. BIN
      images/iperfc-udp.png
  2. BIN
      images/iperfs-udp.png
  3. 26 1
      iperf/README.md
  4. 204 48
      iperf/iperf.c

BIN
images/iperfc-udp.png


BIN
images/iperfs-udp.png


+ 26 - 1
iperf/README.md

@@ -33,10 +33,18 @@ dns server #1: 223.5.5.5
 
 需要在 RT-Thread 上使用 Finsh/MSH 命令来启动 iperf 服务器,大致效果如下: 
 
+tcp 模式
+
 ```
 msh />iperf -s -p 5001
 ```
 
+udp 模式
+
+```
+msh />iperf -u -s -p 5001
+```
+
 - -s 表示作为服务器启动
 - -p 表示监听 5001 端口
 
@@ -54,8 +62,14 @@ msh />iperf -s -p 5001
 - 点击 `run Lperf!` 开始测试 
 - 等待测试结束。测试时,测试数据会在 shell 界面和 JPerf 软件上显示。
 
+tcp 模式软件设置
+
 ![iperfs](../images/iperfs.png)
 
+udp 模式软件设置
+
+![iperfs-udp](../images/iperfs-udp.png)
+
 ### 2.2 iperf 客户端模式
 
 #### 2.2.1 获取 PC 的 IP 地址
@@ -78,15 +92,26 @@ msh />iperf -s -p 5001
 
 需要在 RT-Thread 上使用 Finsh/MSH 命令来启动 iperf 客户端,大致效果如下: 
 
+tcp 模式
+
 ```
 msh />iperf -c 192.168.12.45 -p 5001
 ```
 
+udp 模式
+
+```
+msh />iperf -u -c 192.168.12.45 -p 5001
+```
+
 - -c 表示作为客户端启动,后面需要加运行服务器端的pc的 IP 地址
 - -p 表示连接 5001 端口
 - 等待测试结束。测试时,测试数据会在 shell 界面和 JPerf 软件上显示。
 
+tcp 模式软件设置
+
 ![iperfc](../images/iperfc.png)
 
- 
+udp 模式软件设置
 
+![iperfc-udp](../images/iperfc-udp.png)

+ 204 - 48
iperf/iperf.c

@@ -35,12 +35,136 @@ typedef struct
 } IPERF_PARAM;
 static IPERF_PARAM param = {IPERF_MODE_STOP, NULL, IPERF_PORT};
 
+static void iperf_udp_client(void *thread_param)
+{
+    int sock;
+    rt_uint32_t *buffer;
+    struct sockaddr_in server;
+    rt_uint32_t packet_count = 0;
+    rt_uint32_t tick;
+    int send_size;
+
+    send_size = IPERF_BUFSZ > 1470 ? 1470 : IPERF_BUFSZ;
+    buffer = malloc(IPERF_BUFSZ);
+    if (buffer == NULL)
+    {
+        return;
+    }
+    memset(buffer, 0x00, IPERF_BUFSZ);
+    sock = socket(PF_INET, SOCK_DGRAM, 0);
+    if(sock < 0)
+    {
+        rt_kprintf("can't create socket!! exit\n");
+        return;
+    }
+    server.sin_family = PF_INET;
+    server.sin_port = htons(param.port);
+    server.sin_addr.s_addr = inet_addr(param.host);
+    rt_kprintf("iperf udp mode run...\n");
+    while (param.mode != IPERF_MODE_STOP)
+    {
+        packet_count++;
+        tick = rt_tick_get();
+        buffer[0] = htonl(packet_count);
+        buffer[1] = htonl(tick / RT_TICK_PER_SECOND);
+        buffer[2] = htonl((tick % RT_TICK_PER_SECOND) * 1000);
+        sendto(sock, buffer, send_size, 0, (struct sockaddr *)&server, sizeof(struct sockaddr_in));
+    }
+    closesocket(sock);
+    free(buffer);
+}
+
+static void iperf_udp_server(void *thread_param)
+{
+    int sock;
+    rt_uint32_t *buffer;
+    struct sockaddr_in server;
+    struct sockaddr_in sender;
+    int sender_len, r_size;
+    rt_uint64_t sentlen;
+    rt_uint32_t pcount = 0, last_pcount = 0;
+    rt_uint32_t lost, total;
+    rt_tick_t tick1, tick2;
+    float f;
+    char speed[64] = { 0 };
+    struct timeval timeout;
+
+    buffer = malloc(IPERF_BUFSZ);
+    if (buffer == NULL)
+    {
+        return;
+    }
+    sock = socket(PF_INET, SOCK_DGRAM, 0);
+    if(sock < 0)
+    {
+        rt_kprintf("can't create socket!! exit\n");
+        return;
+    }
+    server.sin_family = PF_INET;
+    server.sin_port = htons(param.port);
+    server.sin_addr.s_addr = inet_addr("0.0.0.0");
+
+    timeout.tv_sec = 2;
+    timeout.tv_usec = 0;
+    if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1)
+    {
+        rt_kprintf("setsockopt failed!!");
+        closesocket(sock);
+        free(buffer);
+        return;
+    }
+    if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0)
+    {
+        rt_kprintf("iperf server bind failed!! exit\n");
+        closesocket(sock);
+        free(buffer);
+        return;
+    }
+    while (param.mode != IPERF_MODE_STOP)
+    {
+        tick1 = rt_tick_get();
+        tick2 = tick1;
+        lost = 0;
+        total = 0;
+        sentlen = 0;
+        while ((tick2 - tick1) < (RT_TICK_PER_SECOND * 5))
+        {
+            r_size = recvfrom(sock, buffer, IPERF_BUFSZ, 0, (struct sockaddr *)&sender, (socklen_t*)&sender_len);
+            if (r_size > 12)
+            {
+                pcount = ntohl(buffer[0]);
+                if (last_pcount < pcount)
+                {
+                    lost += pcount - last_pcount - 1;
+                    total += pcount - last_pcount;
+                }
+                else
+                {
+                    last_pcount = pcount;
+                }
+                last_pcount = pcount;
+                sentlen += r_size;
+            }
+            tick2 = rt_tick_get();
+        }
+        if (sentlen > 0)
+        {
+            f = (float)(sentlen * RT_TICK_PER_SECOND / 125 / (tick2 - tick1));
+            f /= 1000.0f;
+            snprintf(speed, sizeof(speed), "%.4f Mbps! lost:%d total:%d\n", f, lost, total);
+            rt_kprintf("%s", speed);
+        }
+    }
+    free(buffer);
+    closesocket(sock);
+}
+
 static void iperf_client(void *thread_param)
 {
     int i;
     int sock;
     int ret;
-
+    int tips = 1;
     uint8_t *send_buf;
     rt_uint64_t sentlen;
     rt_tick_t tick1, tick2;
@@ -71,9 +195,12 @@ static void iperf_client(void *thread_param)
         ret = connect(sock, (const struct sockaddr *)&addr, sizeof(addr));
         if (ret == -1)
         {
-            rt_kprintf("Connect failed!\n");
+            if (tips)
+            {
+                rt_kprintf("Connect to iperf server faile, Waiting for the server to open!\n");
+                tips = 0;
+            }
             closesocket(sock);
-
             rt_thread_delay(RT_TICK_PER_SECOND);
             continue;
         }
@@ -120,8 +247,10 @@ static void iperf_client(void *thread_param)
         closesocket(sock);
 
         rt_thread_delay(RT_TICK_PER_SECOND * 2);
-        rt_kprintf("disconnected!\n");
+        rt_kprintf("Disconnected, iperf server shut down!\n");
+        tips = 1;
     }
+    free(send_buf);
 }
 
 void iperf_server(void *thread_param)
@@ -217,7 +346,8 @@ void iperf_server(void *thread_param)
                 recvlen = 0;
             }
         }
-
+        rt_kprintf("client disconnected (%s, %d)\n",
+                   inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
         if (connected >= 0) closesocket(connected);
         connected = -1;
     }
@@ -244,8 +374,8 @@ void iperf_usage(void)
     rt_kprintf("Miscellaneous:\n");
     rt_kprintf("  -h           print this message and quit\n");
     rt_kprintf("  --stop       stop iperf program\n");
-
-    return ;
+    rt_kprintf("  -u           testing UDP protocol");
+    return;
 }
 
 int iperf(int argc, char **argv)
@@ -253,53 +383,60 @@ int iperf(int argc, char **argv)
     int mode = 0; /* server mode */
     char *host = NULL;
     int port = IPERF_PORT;
+    int use_udp = 0;
+    int index = 1;
 
-    if (argc == 1) goto __usage;
-    else
+    if (argc == 1)
     {
-        if (strcmp(argv[1], "-h") == 0) goto __usage;
-        else if (strcmp(argv[1], "--stop") == 0)
-        {
-            /* stop iperf */
-            param.mode = IPERF_MODE_STOP;
-            return 0;
-        }
-        else if (strcmp(argv[1], "-s") == 0)
-        {
-            mode = IPERF_MODE_SERVER; /* server mode */
+        goto __usage;
+    }
+    if (strcmp(argv[1], "-u") == 0)
+    {
+        index = 2;
+        use_udp = 1;
+    }
+    if (strcmp(argv[index], "-h") == 0) goto __usage;
+    else if (strcmp(argv[index], "--stop") == 0)
+    {
+        /* stop iperf */
+        param.mode = IPERF_MODE_STOP;
+        return 0;
+    }
+    else if (strcmp(argv[index], "-s") == 0)
+    {
+        mode = IPERF_MODE_SERVER; /* server mode */
 
-            /* iperf -s -p 5000 */
-            if (argc == 4)
+        /* iperf -s -p 5000 */
+        if ((argc == 4) || (argc == 5))
+        {
+            if (strcmp(argv[index + 1], "-p") == 0)
             {
-                if (strcmp(argv[2], "-p") == 0)
-                {
-                    port = atoi(argv[3]);
-                }
-                else goto __usage;
+                port = atoi(argv[index + 2]);
             }
+            else goto __usage;
         }
-        else if (strcmp(argv[1], "-c") == 0)
-        {
-            mode = IPERF_MODE_CLIENT; /* client mode */
-            if (argc < 3) goto __usage;
+    }
+    else if (strcmp(argv[index], "-c") == 0)
+    {
+        mode = IPERF_MODE_CLIENT; /* client mode */
+        if (argc < 3) goto __usage;
 
-            host = argv[2];
-            if (argc == 5)
+        host = argv[index + 1];
+        if ((argc == 5) || (argc == 6))
+        {
+            /* iperf -c host -p port */
+            if (strcmp(argv[index + 2], "-p") == 0)
             {
-                /* iperf -c host -p port */
-                if (strcmp(argv[3], "-p") == 0)
-                {
-                    port = atoi(argv[4]);
-                }
-                else goto __usage;
+                port = atoi(argv[index + 3]);
             }
+            else goto __usage;
         }
-        else if (strcmp(argv[1], "-h") == 0)
-        {
-            goto __usage;
-        }
-        else goto __usage;
     }
+    else if (strcmp(argv[index], "-h") == 0)
+    {
+        goto __usage;
+    }
+    else goto __usage;
 
     /* start iperf */
     if (param.mode == IPERF_MODE_STOP)
@@ -315,13 +452,32 @@ int iperf(int argc, char **argv)
         }
         if (host) param.host = rt_strdup(host);
 
-        if (mode == IPERF_MODE_CLIENT)
-            tid = rt_thread_create("iperfc", iperf_client, RT_NULL,
+        if (use_udp)
+        {
+            if (mode == IPERF_MODE_CLIENT)
+            {
+                tid = rt_thread_create("iperfc", iperf_udp_client, RT_NULL,
+                                   2048, 20, 20);
+            }
+            else if (mode == IPERF_MODE_SERVER)
+            {
+                tid = rt_thread_create("iperfd", iperf_udp_server, RT_NULL,
+                                   2048, 10, 20);
+            }
+        }
+        else
+        {
+            if (mode == IPERF_MODE_CLIENT)
+            {
+                tid = rt_thread_create("iperfc", iperf_client, RT_NULL,
                                    2048, 20, 20);
-        else if (mode == IPERF_MODE_SERVER)
-            tid = rt_thread_create("iperfd", iperf_server, RT_NULL,
+            }
+            else if (mode == IPERF_MODE_SERVER)
+            {
+                tid = rt_thread_create("iperfd", iperf_server, RT_NULL,
                                    2048, 20, 20);
-
+            }
+        }
         if (tid) rt_thread_startup(tid);
     }
     else