• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 ASR Microelectronics (Shanghai) Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "lwip_app_iperf.h"
17 #ifdef LWIP_APP_IPERF
18 #include <unistd.h>
19 #include <lwip/inet.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include "iperf_printf.h"
23 #include "lega_rtos.h"
24 
25 #define IPERF_PORT 5001
26 #define IPERF_CLIENT_TIMEOUT_MS 0xFFFFFFFF
27 
28 lega_semaphore_t iperf_Semaphore = NULL;
29 volatile IPERF_TCP_SERVER_STATUS iperf_tcp_server_status;
30 volatile IPERF_UDP_SERVER_STATUS iperf_udp_server_status;
31 volatile IPERF_TCP_CLINET_STATUS iperf_tcp_client_status;
32 volatile IPERF_UDP_CLIENT_STATUS iperf_udp_client_status;
33 char iperf_send_buf[SEND_BUFSIZE];
34 struct lwip_iperf_config_t iperf_config;
35 lega_timer_t iperf_output_timer;
36 struct lwip_iperf_outputInfo txperf_outinfo;
37 struct lwip_iperf_outputInfo rxperf_outinfo;
38 struct lwip_iperf_outputInfo utxperf_outinfo;
39 struct lwip_iperf_outputInfo urxperf_outinfo;
40 
iperf_value_format(char * format_value,int format_value_len,u64_t value)41 void iperf_value_format(char *format_value, int format_value_len, u64_t value)
42 {
43     u64_t gv = value / (1000000000ULL);
44     u64_t mv = value / (1000000ULL);
45     u64_t kv = value / (1000ULL);
46 
47     lega_rtos_declare_critical();
48     lega_rtos_enter_critical();
49 
50     if (gv == 0) {
51         if (mv == 0) {
52             if (kv == 0) {
53                 snprintf(format_value, format_value_len, "%llu", value);
54             } else {
55                 snprintf(format_value, format_value_len, "%llu.%02uK", kv, (unsigned int)(value % 1000) / 10);
56             }
57         } else {
58             snprintf(format_value, format_value_len, "%llu.%02uM", mv, (unsigned int)(value % 1000000) / 10000);
59         }
60     } else {
61         snprintf(format_value, format_value_len, "%llu.%02uG", gv, (unsigned int)(value % 1000000000) / 10000000);
62     }
63 
64     lega_rtos_exit_critical();
65 }
66 
do_iperf_terminate_timer(char * mode,struct lwip_iperf_outputInfo * outputInfo)67 void do_iperf_terminate_timer(char *mode, struct lwip_iperf_outputInfo *outputInfo)
68 {
69     u64_t bytes = outputInfo->currentByte;
70     u64_t packets = outputInfo->currentPacketNum;
71     char byteFormat[24] = {0};
72     char bitFormat[24] = {0};
73     lega_rtos_stop_timer(&iperf_output_timer);
74     iperf_value_format(byteFormat, sizeof(byteFormat), bytes);
75     iperf_value_format(bitFormat, sizeof(bitFormat), (bytes * (8ULL)) / ((u64_t)outputInfo->seconds));
76     iperf_printf("%s:total %d sec    %llu packets    %s Bytes    %s bits/sec\r\n", mode, outputInfo->seconds, packets,
77                  byteFormat, bitFormat);
78     memset(outputInfo, 0, sizeof(struct lwip_iperf_outputInfo));
79 }
do_iperf_terminate(char * mode,struct lwip_iperf_outputInfo * outputInfo,discon_handle_t discon)80 void do_iperf_terminate(char *mode, struct lwip_iperf_outputInfo *outputInfo, discon_handle_t discon)
81 {
82     do_iperf_terminate_timer(mode, outputInfo);
83     discon();
84 }
85 
lega_wifi_iperf_usage()86 static void lega_wifi_iperf_usage()
87 {
88     iperf_printf("usage: iperf -c host [-p port] [-u] [-t]\r\n\
89 aiperf -s [-p port] [-u] [-t]\r\n\
90 -c host     :run as iperf client connect to host\r\n\
91 -s          :run as iperf server\r\n\
92 -p port     :client connect to/server port default 5001\r\n\
93 -u          :use udp do iperf client/server\r\n\
94              If -u not enable, use tcp default\r\n\
95 -t          :terminate iperf client/server/all\r\n\
96 -d          :tx packets delay time(ms) default 10\r\n");
97 }
lega_wifi_iperf(int argc,char ** argv)98 void lega_wifi_iperf(int argc, char **argv)
99 {
100     int c = 0;
101     struct lwip_iperf_config_t temp_config = {0};
102 
103     temp_config.port = IPERF_PORT;
104     temp_config.tx_delay_ms = 2;
105 
106     for (c = 1; c < argc; c++) {
107         if (strcmp(argv[c], "-c") == 0) {
108             temp_config.mode = IPERF_MODE_CLIENT;
109             if (inet_aton(argv[++c], &(temp_config.ipaddr)) == 0) {
110                 goto IPERF_PARSE_FAIL;
111             }
112         } else if (strcmp(argv[c], "-p") == 0) {
113             temp_config.port = strtoul(argv[++c], NULL, 10);
114             if (temp_config.port <= 0 || temp_config.port > 65536) {
115                 goto IPERF_PARSE_FAIL;
116             }
117         } else if (strcmp(argv[c], "-s") == 0) {
118             temp_config.mode = IPERF_MODE_SERVER;
119         } else if (strcmp(argv[c], "-u") == 0) {
120             temp_config.protocol = IPERF_PROTOCOL_UDP;
121         } else if (strcmp(argv[c], "-t") == 0) {
122             temp_config.termFlag = 1;
123         } else if (strcmp(argv[c], "-d") == 0) {
124             temp_config.tx_delay_ms = atoi(argv[c + 1]);
125             c++;
126         } else {
127             goto IPERF_PARSE_FAIL;
128         }
129     }
130 
131     if ((temp_config.termFlag == 0) && (iperf_config.termFlag == 0)) {
132         iperf_printf("please close your last iperf connection firstly!\n");
133         goto IPERF_PARSE_FAIL;
134     } else if ((temp_config.termFlag == 1) && (iperf_config.termFlag == 0)) {
135         iperf_config.termFlag = 1;
136     } else {
137         memcpy(&iperf_config, &temp_config, sizeof(iperf_config));
138     }
139 
140     if ((iperf_config.mode == IPERF_MODE_UNINIT) && (iperf_config.termFlag != 1)) {
141         goto IPERF_PARSE_FAIL;
142     }
143     if ((iperf_config.mode == IPERF_MODE_CLIENT) && (iperf_Semaphore != NULL)) {
144         if (lega_rtos_set_semaphore(&iperf_Semaphore) == kNoErr) {
145             // iperf_printf("Begin to run iperf client:\n");
146         } else {
147             iperf_printf("Run iperf client fail for semaphore error\n");
148         }
149         return;
150     }
151     if (iperf_config.protocol == IPERF_PROTOCOL_TCP) {
152         if (iperf_config.mode == IPERF_MODE_SERVER) {
153             // tcp server
154             if (iperf_config.termFlag == 1) {
155                 // iperf_printf("Terminate iperf tcp server");
156                 // terminate_rxperf();
157                 do_iperf_terminate("tcp server", &rxperf_outinfo, clear_rxperf);
158             } else {
159                 if (iperf_tcp_server_status <= IPERF_TCP_SERVER_INIT) {
160                     rxperf_init();
161                     start_rxperf_application(iperf_config.port);
162                 } else {
163                     iperf_printf("iperf tcp server already running status:%d,please terminate it before run again!\r\n",
164                                  iperf_tcp_server_status);
165                 }
166             }
167         }
168     } else {
169         if (iperf_config.mode == IPERF_MODE_SERVER) {
170             // udp server
171             if (iperf_config.termFlag == 1) {
172 
173                 do_iperf_terminate("udp server", &urxperf_outinfo, clear_urxperf);
174             } else {
175                 if (iperf_udp_server_status <= IPERF_UDP_SERVER_INIT) {
176                     iperf_udp_server_status = IPERF_UDP_SERVER_INIT;
177                     urxperf_init();
178                     start_urxperf_application(iperf_config.port);
179                 } else {
180                     iperf_printf("iperf udp server already running status:%d,please terminate it before run again!\r\n",
181                                  iperf_udp_server_status);
182                 }
183             }
184         }
185     }
186     return;
187 IPERF_PARSE_FAIL:
188     lega_wifi_iperf_usage();
189     return;
190 }
191 
do_iperf_output(char * mode,struct lwip_iperf_outputInfo * outputInfo)192 void do_iperf_output(char *mode, struct lwip_iperf_outputInfo *outputInfo)
193 {
194     u64_t bytes = outputInfo->currentByte - outputInfo->lastByte;
195     u64_t packets = outputInfo->currentPacketNum - outputInfo->lastPacketNum;
196     char byteFormat[24] = {0};
197     char bitFormat[24] = {0};
198     iperf_value_format(byteFormat, sizeof(byteFormat), bytes);
199     iperf_value_format(bitFormat, sizeof(bitFormat), bytes * (8ULL));
200     outputInfo->seconds++;
201     if (bytes != 0) {
202         iperf_printf("%s:%d-%d sec    %llu packets    %s Bytes    %s bits/sec\r\n", mode, outputInfo->seconds - 1,
203                      outputInfo->seconds, packets, byteFormat, bitFormat);
204     }
205     outputInfo->lastByte = outputInfo->currentByte;
206     outputInfo->lastPacketNum = outputInfo->currentPacketNum;
207 }
208 
iperf_output(void * args)209 void iperf_output(void *args)
210 {
211     printf("\nlalala %s\n", __func__);
212     if (iperf_tcp_client_status == IPERF_TCP_CLIENT_TXRUNNING) {
213         do_iperf_output("tcp client", &txperf_outinfo);
214     }
215     if (iperf_tcp_server_status == IPERF_TCP_SERVER_RXRUNNING) {
216         do_iperf_output("tcp server", &rxperf_outinfo);
217     }
218     if (iperf_udp_client_status == IPERF_UDP_CLIENT_TXRUNNING) {
219         do_iperf_output("udp client", &utxperf_outinfo);
220     }
221     if (iperf_udp_server_status == IPERF_UDP_SERVER_RXRUNNING) {
222         do_iperf_output("udp server", &urxperf_outinfo);
223     }
224 
225 }
lega_wifi_iperf_client_start()226 void lega_wifi_iperf_client_start()
227 {
228     int count = 0;
229     if (lega_rtos_init_timer(&iperf_output_timer, IPERF_OUTPUT_INTERVIEW * 1000, iperf_output, NULL) != kNoErr) {
230         iperf_printf("iperf timer fail!\r\n");
231     }
232     for (;;) {
233         if (lega_rtos_get_semaphore(&iperf_Semaphore, IPERF_CLIENT_TIMEOUT_MS) == kNoErr) {
234             // AT command set lwip_iperf_config over and begin to run
235 
236             if (iperf_config.mode != IPERF_MODE_CLIENT) {
237                 continue;
238             }
239             if (iperf_config.protocol == IPERF_PROTOCOL_TCP) {
240                 if (iperf_config.termFlag == 1) {
241                     do_iperf_terminate("tcp client", &txperf_outinfo, disconnect_txperf);
242                     continue;
243                 }
244 
245                 if (iperf_tcp_client_status != IPERF_TCP_CLIENT_TXRUNNING) {
246                     if (iperf_tcp_client_status >= IPERF_TCP_CLIENT_CONNECTING) {
247                         iperf_printf("iperf tcp client already running, please terminate it before run again!\r\n");
248                         continue;
249                     }
250                     txperf_init();
251                     if (start_txperf_application(&(iperf_config.ipaddr), iperf_config.port) != 0) {
252                         iperf_printf("iperf tcp connect fail!\n");
253                         continue;
254                     }
255                     count = 0;
256                     if (iperf_tcp_client_status == IPERF_TCP_CLIENT_TXRUNNING) {
257                         break;
258                     }
259                     while (iperf_tcp_client_status < IPERF_TCP_CLIENT_STARTING) { //wait for tcp connect
260                         lega_rtos_delay_milliseconds(100);
261                         if (++count > 100) {
262                             iperf_printf("iperf connect to %s:%d fail!\n", ip4addr_ntoa((const ip4_addr_t *) & (iperf_config.ipaddr)),
263                                          iperf_config.port);
264                             break;
265                         }
266                     }
267                     if (count > 100) {
268                         continue;
269                     }
270                     iperf_tcp_client_status = IPERF_TCP_CLIENT_TXRUNNING;
271                 }
272 
273                 transfer_txperf_data();
274             } else if (iperf_config.protocol == IPERF_PROTOCOL_UDP) {
275                 if (iperf_config.termFlag == 1) {
276                     do_iperf_terminate("udp client", &utxperf_outinfo, disconnect_utxperf);
277                     continue;
278                 }
279                 if (iperf_udp_client_status >= IPERF_UDP_CLIENT_START) {
280                     iperf_printf("iperf udp client already running status:%d,please terminate it before run again!\r\n",
281                                  iperf_udp_client_status);
282                     continue;
283                 }
284                 utxperf_init();
285                 if (start_utxperf_application(&(iperf_config.ipaddr), iperf_config.port) != 0) {
286                     continue;
287                 }
288                 while (transfer_utxperf_data() != -2) {
289                     lega_rtos_delay_milliseconds(iperf_config.tx_delay_ms);
290                     if (iperf_config.termFlag) {
291                         break;
292                     }
293                 }
294                 if (iperf_config.termFlag) {
295                     continue;
296                 }
297             }
298         }
299     }
300 }
301 
302 lega_thread_t iper_handler = NULL;
303 #define     IPERF_CLIENT_THREAD_NAME    "iperf-client"
304 #define     IPERF_CLIENT_PRIORITY       (28)
305 #define     IPERF_CLIENT_STACK_SIZE     4096
lega_wifi_iperf_init(void)306 void lega_wifi_iperf_init(void)
307 {
308     int i = 0;
309 
310     rxperf_init();
311 
312     urxperf_init();
313     utxperf_init();
314 
315     if (iperf_Semaphore == NULL) {
316         lega_rtos_init_semaphore(&iperf_Semaphore, 0);
317     }
318 
319     /* initialize data buffer being sent */
320     for (i = 0; i < SEND_BUFSIZE; i++) {
321         iperf_send_buf[i] = (i % 10) + '0';
322     }
323 
324     memset(&iperf_config, 0, sizeof(iperf_config));
325     iperf_config.termFlag = 1;
326 
327     lega_rtos_create_thread(&iper_handler, IPERF_CLIENT_PRIORITY, IPERF_CLIENT_THREAD_NAME, lega_wifi_iperf_client_start,
328                             IPERF_CLIENT_STACK_SIZE, 0);
329 }
330 #endif
331