1 /*
2  * Copyright (C) 2017-2019 Alibaba Group Holding Limited
3  */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include "lwip/opt.h"
10 #include "iperf_wrapper.h"
11 #ifdef AOS_NETMGR_WITH_MODERN
12 #ifdef AOS_NET_WITH_WIFI
13 #include "wifi_service.h"
14 #endif /* AOS_NET_WITH_WIFI */
15 #endif /* AOS_NETMGR_WITH_MODERN */
16 #include "lwip/debug.h"
17 #include "lwip/sockets.h"
18 #include "lwip/apps/iperf_task.h"
19 #include "lwip/apps/iperf_debug.h"
20 #include "aos/cli.h"
21 /******************************************************
22  *                      Macros
23  ******************************************************/
24 #define IPERF_DEBUG_INTERNAL
25 #define DBGPRINT_IPERF(FEATURE, ...)  do {          \
26             if (g_iperf_debug_feature & FEATURE) {  \
27                 LWIP_DEBUGF( IPERF_DEBUG, (__VA_ARGS__));             \
28             }                                       \
29         } while(0)
30 
31 /******************************************************
32  *                    Constants
33  ******************************************************/
34 
35 #define MAX_WIN_SIZE (1024*1024)
36 
37 /* Private macro */
38 #define IPERF_DEFAULT_PORT  5001 //Port to listen
39 
40 #define IPERF_HEADER_VERSION1 0x80000000
41 #define IPERF_DEFAULT_UDP_RATE (1024 * 1024)
42 #define IPERF_TEST_BUFFER_SIZE (2048)
43 
44 /******************************************************
45  *                   Enumerations
46  ******************************************************/
47 
48 /******************************************************
49  *                 Type Definitions
50  ******************************************************/
51 
52 // Private typedef -------------------------------------------------------------
53 typedef struct count_s
54 {
55     unsigned Bytes;
56     unsigned KBytes;
57     unsigned MBytes;
58     unsigned GBytes;
59     unsigned times;
60 } count_t;
61 
62 // used to reference the 4 byte ID number we place in UDP datagrams
63 // use int32_t if possible, otherwise a 32 bit bitfield (e.g. on J90)
64 typedef struct UDP_datagram
65 {
66     int32_t id;
67     unsigned int tv_sec;
68     unsigned int tv_usec;
69 } UDP_datagram;
70 
71 /*
72  * The client_hdr structure is sent from clients
73  * to servers to alert them of things that need
74  * to happen. Order must be perserved in all
75  * future releases for backward compatibility.
76  * 1.7 has flags, num_threads, port, and buffer_len
77  */
78 typedef struct client_hdr
79 {
80     /*
81      * flags is a bitmap for different options
82      * the most significant bits are for determining
83      * which information is available. So 1.7 uses
84      * 0x80000000 and the next time information is added
85      * the 1.7 bit will be set and 0x40000000 will be
86      * set signifying additional information. If no
87      * information bits are set then the header is ignored.
88      * The lowest order diferentiates between dualtest and
89      * tradeoff modes, wheither the speaker needs to start
90      * immediately or after the audience finishes.
91      */
92     int32_t flags;
93     int32_t num_threads;
94     int32_t port;
95     int32_t buffer_len;
96     int32_t win_band;
97     int32_t amount;
98 } client_hdr;
99 
100 /*
101  * The server_hdr structure facilitates the server
102  * report of jitter and loss on the client side.
103  * It piggy_backs on the existing clear to close
104  * packet.
105  */
106 typedef struct server_hdr
107 {
108     /*
109      * flags is a bitmap for different options
110      * the most significant bits are for determining
111      * which information is available. So 1.7 uses
112      * 0x80000000 and the next time information is added
113      * the 1.7 bit will be set and 0x40000000 will be
114      * set signifying additional information. If no
115      * information bits are set then the header is ignored.
116      */
117     int32_t flags;
118     int32_t total_len1;
119     int32_t total_len2;
120     int32_t stop_sec;
121     int32_t stop_usec;
122     int32_t error_cnt;
123     int32_t outorder_cnt;
124     int32_t datagrams;
125     int32_t jitter1;
126     int32_t jitter2;
127 } server_hdr;
128 
129 /******************************************************
130  *                    Structures
131  ******************************************************/
132 
133 /******************************************************
134  *               Function Declarations
135  ******************************************************/
136 
137 count_t iperf_calculate_result( int pkt_size, count_t pkt_count, int need_to_convert );
138 void iperf_display_report( char *report_title, unsigned time, unsigned h_ms_time, count_t pkt_count );
139 count_t iperf_reset_count( count_t pkt_count );
140 count_t iperf_copy_count( count_t pkt_count, count_t tmp_count );
141 count_t iperf_diff_count( count_t pkt_count, count_t tmp_count );
142 int iperf_format_transform( char *param );
143 
144 /******************************************************
145  *               Variables Definitions
146  ******************************************************/
147 
148 uint32_t g_iperf_debug_feature = 0;
149 int g_iperf_is_tradeoff_test_client = 0;
150 int g_iperf_is_tradeoff_test_server = 0;
151 uint32_t g_iperf_server_addr = 0;
152 
153 /******************************************************
154  *               Function Definitions
155  ******************************************************/
156 /* members are in network byte order */
iperf_udp_run_server(char * parameters[])157 void iperf_udp_run_server( char *parameters[] )
158 {
159 
160     int sockfd;
161     struct sockaddr_in servaddr;
162     struct sockaddr_in cliaddr;
163     int cli_len;
164     struct ip_mreq group;
165     int server_port;
166     int i;
167     count_t pkt_count = {0};
168     count_t tmp_count = {0};
169     int nbytes = 0; /* the number of read */
170     int total_send = 0; /* the total number of send  */
171     int mcast_tag = 0; /* the tag of parameter "-B"  */
172     int interval_tag = 0; /* the tag of parameter "-i"  */
173     int interval_time = 10; /* the interval time of "-i"  */
174     char *mcast;
175 #if defined(IPERF_DEBUG_ENABLE)
176     int send_bytes = 0; /* the number of send */
177     int tmp = 0;
178 #endif
179     char *buffer = (char*) iperf_wrapper_malloc( IPERF_TEST_BUFFER_SIZE );
180 
181     uint32_t t1 = 0;
182     uint32_t t2 = 0;
183     uint32_t curr_t = 0;
184     uint32_t curr_h_ms = 0;
185     uint32_t t2_h_ms = 0;
186     uint32_t t1_h_ms = 0;
187     uint32_t tmp_t = 0;
188     uint32_t tmp_h_ms = 0;
189     uint32_t offset_t1 = 0;
190     uint32_t offset_t2 = 0;
191     uint32_t offset_time = 0;
192     UDP_datagram *udp_h = NULL;
193     client_hdr *client_h = NULL;
194     client_hdr client_h_trans = {0};
195     struct timeval timeout = {0};
196     timeout.tv_sec = 20; //set recvive timeout = 20(sec)
197     int is_test_started = 0;
198     int udp_h_id = 0;
199 
200     memset( buffer, 0, IPERF_TEST_BUFFER_SIZE );
201     //Statistics init
202     pkt_count = iperf_reset_count( pkt_count );
203     tmp_count = iperf_reset_count( tmp_count );
204     server_port = 0;
205     t1 = 0;
206     t2 = 0;
207     int offset = IPERF_COMMAND_BUFFER_SIZE / sizeof(char *);
208 
209     //Handle input parameters
210     if ( g_iperf_is_tradeoff_test_client == 0 ) {
211         for ( i = 0; i < 13; i++ ) {
212             if ( strcmp( (char *) &parameters[i * offset], "-p" ) == 0 ) {
213                 i++;
214                 server_port = atoi( (char *) &parameters[i * offset] );
215             } else if ( strcmp( (char *) &parameters[i * offset], "-n" ) == 0 ) {
216                 i++;
217                 total_send = iperf_format_transform( (char *) &parameters[i * offset] );
218                 LWIP_DEBUGF( IPERF_DEBUG, ("Set number to transmit = %d Bytes\n", total_send ));
219             } else if ( strcmp( (char *) &parameters[i * offset], "-B" ) == 0 ) {
220                 i++;
221                 mcast = (char *) &parameters[i * offset];
222                 mcast_tag = 1;
223                 LWIP_DEBUGF( IPERF_DEBUG, ("Join Multicast %s\n", mcast) );
224             } else if ( strcmp( (char *) &parameters[i * offset], "-i" ) == 0 ) {
225                 interval_tag = 1;
226                 i++;
227                 if((interval_time = atoi((char*) &parameters[i * offset])) == 0) {
228                     interval_time = 10;
229                     i--;
230                 }
231                 LWIP_DEBUGF( IPERF_DEBUG, ( "Set %d seconds between periodic bandwidth reports\n" , interval_time));
232             }
233         }
234     }
235 
236     // Create a new UDP connection handle
237     if ( (sockfd = lwip_socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) {
238         LWIP_DEBUGF( IPERF_DEBUG, ("[%s:%d] sockfd = %d\n", __FUNCTION__, __LINE__, sockfd ));
239         if ( parameters ) {
240             iperf_wrapper_free( parameters );
241         }
242         aos_task_exit(0);
243         return;
244     }
245 
246     // Bind to port and any IP address
247     memset( &servaddr, 0, sizeof(servaddr) );
248     servaddr.sin_family = AF_INET;
249     servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
250     if ( server_port == 0 ) {
251         servaddr.sin_port = htons( IPERF_DEFAULT_PORT );
252         LWIP_DEBUGF( IPERF_DEBUG, ("Default server port = %d\n", IPERF_DEFAULT_PORT ));
253     } else {
254         servaddr.sin_port = htons( server_port );
255         LWIP_DEBUGF( IPERF_DEBUG, ("Set server port = %d\n", server_port ));
256     }
257 
258     //Multicast settings
259     if ( mcast_tag == 1 ) {
260         group.imr_multiaddr.s_addr = inet_addr( mcast );
261         group.imr_interface.s_addr = htonl( INADDR_ANY );
262 
263         if ( lwip_setsockopt( sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &group, sizeof(struct ip_mreq) ) < 0 ) {
264             LWIP_DEBUGF( IPERF_DEBUG, ("Setsockopt failed - multicast settings\n" ));
265         }
266     }
267 
268     if ( (lwip_bind( sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr) )) < 0 ) {
269         LWIP_DEBUGF( IPERF_DEBUG, ("[%s:%d]\n", __FUNCTION__, __LINE__ ));
270         if ( parameters ) {
271             iperf_wrapper_free( parameters );
272         }
273         lwip_close(sockfd);
274         aos_task_exit(0);
275         return;
276     }
277 
278     socklen_t len = sizeof(timeout);
279     if ( lwip_setsockopt( sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, len ) < 0 ) {
280         LWIP_DEBUGF( IPERF_DEBUG, ("Setsockopt failed - cancel receive timeout\n" ));
281     }
282 
283     cli_len = sizeof(cliaddr);
284 
285     // Wait and check the request
286     do {
287         // Handles request
288         do {
289             iperf_get_current_time( &offset_t1, 0 );
290             nbytes = lwip_recvfrom( sockfd, buffer, IPERF_TEST_BUFFER_SIZE, 0, (struct sockaddr *) &cliaddr,
291                                (socklen_t *) &cli_len );
292             iperf_get_current_time( &offset_t2, 0 );
293 
294             //if connected to iperf v2.0.1, there is no end package sent from client side
295             if ( (offset_t2 > (offset_t1 + 2)) && (nbytes <= 0) && (pkt_count.times >= 1) ) {
296                 offset_time = offset_t2 - offset_t1;
297             } else if ( offset_time != 0 ) {
298                 offset_time = 0;
299             }
300 
301             udp_h = (UDP_datagram *) buffer;
302             udp_h_id = (int) ntohl( udp_h->id );
303 
304 #if defined(IPERF_DEBUG_INTERNAL)
305             client_h = (client_hdr *)&buffer[12];
306             client_h_trans.flags = (int32_t)(ntohl(client_h->flags));
307             client_h_trans.num_threads = (int32_t)(ntohl(client_h->num_threads));
308             client_h_trans.port = (int32_t)(ntohl(client_h->port));
309             client_h_trans.buffer_len = (int32_t)(ntohl(client_h->buffer_len));
310             client_h_trans.win_band = (int32_t)(ntohl(client_h->win_band));
311             client_h_trans.amount = (int32_t)(ntohl(client_h->amount));
312 
313             DBGPRINT_IPERF(IPERF_DEBUG_RECEIVE, "UDP server, receive from sockfd \"%d\", id is \"%d\", tv_sec is \"%"U32_F"\", tv_usec is \"%"U32_F"\", nbytes is \"%d\"",
314                     sockfd, udp_h_id, ntohl(udp_h->tv_sec), ntohl(udp_h->tv_usec), nbytes);
315             DBGPRINT_IPERF(IPERF_DEBUG_RECEIVE, "UDP server, receive from sin_len = %d, sin_family = %d , port = %d, s_addr = 0x%"X32_F"", cliaddr.sin_len, cliaddr.sin_family,
316                     cliaddr.sin_port, cliaddr.sin_addr.s_addr);
317             DBGPRINT_IPERF(IPERF_DEBUG_RECEIVE, "[%s:%d] t1 = %"U32_F", t2 = %"U32_F"", __FUNCTION__, __LINE__, t1, t2);
318 
319             DBGPRINT_IPERF(IPERF_DEBUG_RECEIVE, "[%s:%d], client_h_trans.flag = %d, num_threads = %d, port = %d, buffer_len = %d, win_band = %d, amount = %d"
320                     , __FUNCTION__, __LINE__, client_h_trans.flags, client_h_trans.num_threads, client_h_trans.port, client_h_trans.buffer_len, client_h_trans.win_band, client_h_trans.amount);
321 #endif
322 
323 #if defined(IPERF_DEBUG_ENABLE)
324             if (tmp != nbytes) {
325                 DBGPRINT_IPERF(IPERF_DEBUG_RECEIVE, "[%s:%d] nbytes=%d ", __FUNCTION__, __LINE__, nbytes);
326             } else {
327                 DBGPRINT_IPERF(IPERF_DEBUG_RECEIVE, ".");
328             }
329             tmp = nbytes;
330 #endif
331 
332             pkt_count = iperf_calculate_result( nbytes, pkt_count, 0 );
333 
334             if ( pkt_count.times == 1 ) {
335                 iperf_get_current_time( &t1, &t1_h_ms );
336                 t1_h_ms = (t1_h_ms / 100) % interval_time;
337             }
338 
339             // Report by second
340             if ( (pkt_count.times >= 1 && interval_tag > 0) ) {
341                 iperf_get_current_time( &curr_t, &curr_h_ms );
342                 curr_h_ms = (curr_h_ms / 100) % interval_time;
343 
344                 if ( offset_time > 0 ) {
345                     curr_t -= offset_time;
346                 }
347 
348                 if ( curr_h_ms >= t1_h_ms ) {
349                     tmp_h_ms = curr_h_ms - t1_h_ms;
350                     tmp_t = curr_t - t1;
351                 } else {
352                     tmp_h_ms = curr_h_ms + interval_time - t1_h_ms;
353                     tmp_t = curr_t - t1 - 1;
354                 }
355 
356                 if ( (((int)(curr_t - t1) / interval_time) == interval_tag) && ((curr_h_ms >= t1_h_ms) || ((curr_t - t1) % 10) >= 1) ) {
357                     aos_cli_printf("Interval: %d.0 - %d.0 sec   ", (int) (curr_t - t1) / interval_time * interval_time - interval_time,
358                             (int) (curr_t - t1) / interval_time * interval_time );
359                     iperf_display_report( "UDP Server", interval_time, 0, iperf_diff_count( pkt_count, tmp_count ) );
360                     tmp_count = iperf_copy_count( pkt_count, tmp_count );
361                     interval_tag++;
362                 } else if ( ((udp_h_id < 0) || (nbytes <= 0)) && (((tmp_t) % interval_time) != 0) && (is_test_started == 1) ) {
363                     aos_cli_printf("Interval: %d.0 - %d.%d sec   ", (int) (curr_t - t1 + 1) / interval_time * interval_time - interval_time,
364                             (int) tmp_t, (int) tmp_h_ms );
365                     iperf_display_report( "UDP Server", (tmp_t - ((curr_t - t1 + 1) / interval_time * interval_time - interval_time)), tmp_h_ms,
366                                           iperf_diff_count( pkt_count, tmp_count ) );
367                     tmp_count = iperf_copy_count( pkt_count, tmp_count );
368                     interval_tag++;
369                 }
370             }
371 
372             if ( (is_test_started == 0) && (udp_h_id > 0) && (nbytes > 0) ) {
373                 is_test_started = 1;
374             } else if ( ((udp_h_id < 0) || (nbytes <= 0)) && (is_test_started == 1) ) { // the last package
375                 int32_t old_flag = 0;
376 
377                 // test end, save the current time to "t2"
378                 if ( pkt_count.times >= 1 ) {
379                     /* sync the time if report by second */
380                     if ( interval_tag > 0 ) {
381                         t2 = curr_t;
382                         t2_h_ms = curr_h_ms;
383                     } else {
384                         iperf_get_current_time( &t2, &t2_h_ms );
385                         t2_h_ms = (t2_h_ms / 100) % interval_time;
386                         if ( offset_time > 0 ) {
387                             t2 -= offset_time;
388                         }
389                     }
390                 }
391 
392                 // Calculate time: second
393                 if ( t2_h_ms >= t1_h_ms ) {
394                     t2_h_ms = t2_h_ms - t1_h_ms;
395                     t2 = t2 - t1;
396                 } else {
397                     t2_h_ms = t2_h_ms + interval_time - t1_h_ms;
398                     t2 = t2 - t1 - 1;
399                 }
400                 // print out result
401                 iperf_display_report( "[Total]UDP Server", t2, t2_h_ms, pkt_count );
402 
403                 //TODO: need to send the correct report to client-side, flag = 0 means the report is ignored.
404                 if ( udp_h_id < 0 ) {
405                     old_flag = client_h_trans.flags;
406                     client_h_trans.flags = (int32_t) 0;
407 
408                     // send the server report to client-side
409 #if defined(IPERF_DEBUG_ENABLE)
410                     send_bytes =
411 #endif
412                     lwip_sendto( sockfd, buffer, nbytes, 0, (struct sockaddr *) &cliaddr, cli_len );
413                     client_h_trans.flags = old_flag;
414                 }
415 
416 #if defined(IPERF_DEBUG_ENABLE)
417                 DBGPRINT_IPERF(IPERF_DEBUG_RECEIVE, "[%s:%d]send_bytes = %d, nbytes = %d,", __FUNCTION__, __LINE__, send_bytes, nbytes);
418 #endif
419 
420                 client_h = (client_hdr *) &buffer[12];
421                 client_h_trans.flags = (int32_t) (ntohl( client_h->flags ));
422 
423                 // Tradeoff mode
424                 if ( IPERF_HEADER_VERSION1 & client_h_trans.flags ) {
425                     LWIP_DEBUGF( IPERF_DEBUG, ("Tradeoff mode, client-side start.\n" ));
426 
427                     g_iperf_is_tradeoff_test_server = 1;
428                     g_iperf_server_addr = cliaddr.sin_addr.s_addr;
429                     iperf_udp_run_client( NULL );
430                     g_iperf_is_tradeoff_test_server = 0;
431 
432                 }
433 
434                 LWIP_DEBUGF( IPERF_DEBUG, ("Data transfer is finished.\n" ));
435                 //TODO: send report to other side
436                 break;
437             }
438         } while ( nbytes > 0 );
439 
440 #if defined(IPERF_DEBUG_ENABLE)
441         DBGPRINT_IPERF(IPERF_DEBUG_RECEIVE, "[%s:%d] Interval = %"U32_F".%"U32_F" (secs)", __FUNCTION__, __LINE__, t2, t2_h_ms); //sec.
442 #endif
443 
444     } while ( 0 );
445 
446     LWIP_DEBUGF( IPERF_DEBUG, (" UDP server close socket!\n" ));
447     lwip_close( sockfd );
448 
449     LWIP_DEBUGF( IPERF_DEBUG, ("If you want to execute iperf server again, please enter \"iperf -s -u\".\n" ));
450 
451     if ( parameters ) {
452         iperf_wrapper_free( parameters );
453     }
454     iperf_wrapper_free( buffer );
455     // For tradeoff mode, task will be deleted in iperf_udp_run_client
456     if ( g_iperf_is_tradeoff_test_client == 0 ) {
457         aos_task_exit(0);
458         return;
459     }
460 }
461 
iperf_tcp_run_server(char * parameters[])462 void iperf_tcp_run_server( char *parameters[] )
463 {
464     int listenfd, connfd;
465     struct sockaddr_in servaddr, cliaddr;
466     socklen_t clilen;
467     int server_port;
468     int i;
469     count_t pkt_count = {0};
470     count_t tmp_count = {0};
471     int nbytes = 0; /* the number of read */
472     int total_rcv = 0; /* the total number of receive  */
473     int num_tag = 0; /* the tag of parameter "-n"  */
474     int interval_tag = 0; /* the tag of parameter "-i"  */
475     int interval_time = 10; /* the interval time of "-i"  */
476 #if defined(IPERF_DEBUG_ENABLE)
477     int tmp = 0;
478 #endif
479     uint32_t t1, t2, curr_t;
480     int offset = IPERF_COMMAND_BUFFER_SIZE / sizeof(char *);
481     char *buffer = (char*) iperf_wrapper_malloc( IPERF_TEST_BUFFER_SIZE );
482     struct timeval timeout = {0};
483     timeout.tv_sec = 20; //set recvive timeout = 20(sec)
484 
485     memset( buffer, 0, IPERF_TEST_BUFFER_SIZE );
486     //Statistics init
487     pkt_count = iperf_reset_count( pkt_count );
488     tmp_count = iperf_reset_count( tmp_count );
489     server_port = 0;
490 
491     //Handle input parameters
492     for ( i = 0; i < 9; i++ ) {
493         if ( strcmp( (char *) &parameters[i * offset], "-p" ) == 0 ) {
494             i++;
495             server_port = atoi( (char *) &parameters[i * offset] );
496         } else if ( strcmp( (char *) &parameters[i * offset], "-n" ) == 0 ) {
497             i++;
498             total_rcv = iperf_format_transform( (char *) &parameters[i * offset] );
499             num_tag = 1;
500             LWIP_DEBUGF( IPERF_DEBUG, ("Set number to receive = %d Bytes\n", total_rcv ));
501         } else {
502             if ( strcmp( (char *) &parameters[i * offset], "-i" ) == 0 ) {
503                 interval_tag = 1;
504                 i++;
505                 if((interval_time = atoi((char*) &parameters[i * offset])) == 0) {
506                     interval_time = 10;
507                     i--;
508                 }
509                 LWIP_DEBUGF( IPERF_DEBUG, ( "Set %d seconds between periodic bandwidth reports\n" , interval_time));
510             }
511         }
512     }
513 
514     // Create a new TCP connection handle
515     if ( (listenfd = lwip_socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
516         LWIP_DEBUGF( IPERF_DEBUG, ("[%s:%d] listenfd = %d\n", __FUNCTION__, __LINE__, listenfd ));
517         if ( parameters ) {
518             iperf_wrapper_free( parameters );
519         }
520         aos_task_exit(0);
521         return;
522     }
523 
524     do {
525         // Bind to port and any IP address
526         memset( &servaddr, 0, sizeof(servaddr) );
527         servaddr.sin_family = AF_INET;
528         servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
529         if ( server_port == 0 ) {
530             servaddr.sin_port = htons( IPERF_DEFAULT_PORT );
531             LWIP_DEBUGF( IPERF_DEBUG, ("Default server port = %d\n", IPERF_DEFAULT_PORT ));
532         }
533         else {
534             servaddr.sin_port = htons( server_port );
535             LWIP_DEBUGF( IPERF_DEBUG, ("Set server port = %d\n", server_port ));
536         }
537 
538         if ( (lwip_bind( listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr) )) < 0 ) {
539             LWIP_DEBUGF( IPERF_DEBUG, ("[%s:%d] \n", __FUNCTION__, __LINE__ ));
540             break;
541         }
542 
543         // Put the connection into LISTEN state
544         if ( (lwip_listen( listenfd, 1024 )) < 0 ) {
545             LWIP_DEBUGF( IPERF_DEBUG, ("[%s:%d] \n", __FUNCTION__, __LINE__ ));
546             break;
547         }
548 
549         int buflen = 64240;
550         if ( lwip_setsockopt( listenfd, SOL_SOCKET, SO_RCVBUF, (char *) &buflen, sizeof(buflen) ) < 0 ) {
551                 LWIP_DEBUGF( IPERF_DEBUG, ("Setsockopt failed - cancel receive buf len\n" ));
552         }
553 
554         do {
555             if ( server_port != 0 ) {
556                 LWIP_DEBUGF( IPERF_DEBUG, ("Listen...(port = %d)\n", server_port ));
557             } else {
558                 LWIP_DEBUGF( IPERF_DEBUG, ("Listen...(port = %d)\n", IPERF_DEFAULT_PORT ));
559             }
560             // Block and wait for an incoming connection
561             if ( (connfd = lwip_accept( listenfd, (struct sockaddr *) &cliaddr, &clilen )) != -1 ) {
562                 socklen_t len = sizeof(timeout);
563 
564                 LWIP_DEBUGF( IPERF_DEBUG, ("[%s:%d] Accept... (sockfd=%d)\n", __FUNCTION__, __LINE__, connfd ));
565                 if ( lwip_setsockopt( connfd, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, len ) < 0 ) {
566                     LWIP_DEBUGF( IPERF_DEBUG, ("Setsockopt failed - cancel receive timeout\n" ));
567                 }
568 
569                 //Connection
570                 do {
571                     nbytes = lwip_recv( connfd, buffer, IPERF_TEST_BUFFER_SIZE, 0 );
572                     pkt_count = iperf_calculate_result( nbytes, pkt_count, 0 );
573                     if ( pkt_count.times == 1 ) {
574                         iperf_get_current_time( &t1, 0 );
575                     }
576 #if defined(IPERF_DEBUG_ENABLE)
577                     if (tmp != nbytes) {
578                         DBGPRINT_IPERF(IPERF_DEBUG_RECEIVE, "[%s:%d] nbytes=%d ", __FUNCTION__, __LINE__, nbytes);
579                     } else {
580                         DBGPRINT_IPERF(IPERF_DEBUG_RECEIVE, ".");
581                     }
582                     tmp = nbytes;
583 #endif
584                     if ( num_tag == 1 ) {
585                         total_rcv -= nbytes;
586                     }
587 
588                     //Reach total receive number "-n"
589                     if ( total_rcv < 0 ) {
590                         LWIP_DEBUGF( IPERF_DEBUG, ("Finish Receiving\n" ));
591                         break;
592                     }
593                     if ( pkt_count.times >= 1 && interval_tag > 0 ) {
594                         iperf_get_current_time( &curr_t, 0 );
595                         if ( ((int)(curr_t - t1) / interval_time) == interval_tag ) {
596                             aos_cli_printf("Interval: %d - %d sec   ", (int) (curr_t - t1) / interval_time * interval_time - interval_time,
597                                     (int) (curr_t - t1) / interval_time * interval_time );
598                             iperf_display_report( "TCP Server", interval_time, 0, iperf_diff_count( pkt_count, tmp_count ) );
599                             tmp_count = iperf_copy_count( pkt_count, tmp_count );
600                             interval_tag++;
601                         }
602                     }
603                 } while ( nbytes > 0 );
604 
605                 if ( pkt_count.times >= 1 ) {
606                     iperf_get_current_time( &t2, 0 );
607                 }
608 
609                 LWIP_DEBUGF( IPERF_DEBUG, ("Close socket!\n" ));
610                 //Get report
611                 iperf_display_report( "[Total]TCP Server", t2 - t1, 0, pkt_count );
612 
613                 //Statistics init
614                 pkt_count = iperf_reset_count( pkt_count );
615                 tmp_count = iperf_reset_count( tmp_count );
616                 if ( interval_tag > 0 ) {
617                     interval_tag = 1;
618                 } else {
619                     interval_tag = 0;
620                 }
621                 lwip_close( connfd );
622             }
623         } while ( connfd != -1 && num_tag == 0 );
624 
625         if ( num_tag == 0 ) {
626             LWIP_DEBUGF( IPERF_DEBUG, ("Close socket!\n" ));
627             iperf_display_report( "[Total]TCP Server ", t2 - t1, 0, pkt_count );
628         }
629     } while ( 0 ); //Loop just once
630 
631     lwip_close( listenfd );
632     LWIP_DEBUGF( IPERF_DEBUG, ("If you want to execute iperf server again, please enter \"iperf -s\".\n" ));
633 
634     if ( parameters ) {
635         iperf_wrapper_free( parameters );
636     }
637 
638     iperf_wrapper_free( buffer );
639     aos_task_exit(0);
640     return;
641 }
642 
iperf_tcp_run_client(char * parameters[])643 void iperf_tcp_run_client( char *parameters[] )
644 {
645     int sockfd;
646     struct sockaddr_in servaddr;
647     char *Server_IP;
648     count_t pkt_count = {0};
649     count_t tmp_count = {0};
650     int nbytes = 0; /* the number of send */
651     int total_send = 0; /* the total number of transmit  */
652     int num_tag = 0; /* the tag of parameter "-n"  */
653     int interval_tag = 0; /* the tag of parameter "-i"  */
654     int interval_time = 10; /* the interval time of "-i"  */
655     int i;
656     int win_size, send_time, server_port, pkt_delay, tos;
657     uint32_t t1, t2, curr_t;
658     int offset = IPERF_COMMAND_BUFFER_SIZE / sizeof(char *);
659     char *buffer = (char*) iperf_wrapper_malloc( IPERF_TEST_BUFFER_SIZE );
660     pkt_count = iperf_reset_count( pkt_count );
661     tmp_count = iperf_reset_count( tmp_count );
662     win_size = 0;
663     send_time = 0;
664     server_port = 0;
665     pkt_delay = 0;
666     tos = 0;
667     memset( buffer, 0, IPERF_TEST_BUFFER_SIZE );
668     //Handle input parameters
669     Server_IP = (char *) &parameters[0];
670 
671     LWIP_DEBUGF( IPERF_DEBUG, ("Servr IP %s \n", Server_IP ));
672     for ( i = 1; i < 18; i++ ) {
673         if ( strcmp( (char *) &parameters[i * offset], "-w" ) == 0 ) {
674             i++;
675             win_size = iperf_format_transform( (char *) &parameters[i * offset] );
676             if ( win_size > MAX_WIN_SIZE ) {
677                 LWIP_DEBUGF( IPERF_DEBUG, ("Win size too big, set to %d \n", MAX_WIN_SIZE ));
678                 win_size = MAX_WIN_SIZE;
679             }
680             LWIP_DEBUGF( IPERF_DEBUG, ("Set window size = %d Bytes\n", win_size ));
681         }
682 
683         else if ( strcmp( (char *) &parameters[i * offset], "-t" ) == 0 ) {
684             i++;
685             send_time = atoi( (char *) &parameters[i * offset] );
686             LWIP_DEBUGF( IPERF_DEBUG, ("Set send times = %d (secs)\n", atoi( (char *) &parameters[i * offset] ) ));
687         }
688         else if ( strcmp( (char *) &parameters[i * offset], "-p" ) == 0 ) {
689             i++;
690             server_port = atoi( (char *) &parameters[i * offset] );
691         }
692         else if ( strcmp( (char *) &parameters[i * offset], "-d" ) == 0 ) {
693             i++;
694             pkt_delay = atoi( (char *) &parameters[i * offset] );
695             LWIP_DEBUGF( IPERF_DEBUG, ("Set packet delay = %d (ms)\n", atoi( (char *) &parameters[i * offset] ) ));
696         } else if ( strcmp( (char *) &parameters[i * offset], "-n" ) == 0 ) {
697             i++;
698             total_send = iperf_format_transform( (char *) &parameters[i * offset] );
699             num_tag = 1;
700             LWIP_DEBUGF( IPERF_DEBUG, ("Set number to transmit = %d Bytes\n", total_send ));
701         } else if ( strcmp( (char *) &parameters[i * offset], "-S" ) == 0 ) {
702             i++;
703             tos = atoi( (char *) &parameters[i * offset] );
704             LWIP_DEBUGF( IPERF_DEBUG, ("Set TOS = %d\n", atoi( (char *) &parameters[i * offset] ) ));
705         } else if ( strcmp( (char *) &parameters[i * offset], "-i" ) == 0 ) {
706             interval_tag = 1;
707             i++;
708             if((interval_time = atoi((char*) &parameters[i * offset])) == 0) {
709                 interval_time = 10;
710                 i--;
711             }
712             LWIP_DEBUGF( IPERF_DEBUG, ( "Set %d seconds between periodic bandwidth reports\n" , interval_time));
713         }
714     }
715 
716     if ( win_size == 0 ) {
717         win_size = 1460;
718         LWIP_DEBUGF( IPERF_DEBUG, ("Default window size = %d Bytes\n", win_size ));
719     }
720     if ( send_time == 0 ) {
721         if ( num_tag == 1 ) {
722             send_time = 999999;
723         }
724         else {
725             send_time = 10;
726             LWIP_DEBUGF( IPERF_DEBUG, ("Default send times = %d (secs)\n", send_time ));
727         }
728     }
729 
730     // Create a new TCP connection handle
731     if ( (sockfd = lwip_socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
732         LWIP_DEBUGF( IPERF_DEBUG, ("[%s:%d] sockfd = %d\n", __FUNCTION__, __LINE__, sockfd ));
733         if ( parameters ) {
734             iperf_wrapper_free( parameters );
735         }
736         aos_task_exit(0);
737         return;
738     }
739 
740     if ( lwip_setsockopt( sockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos) ) < 0 ) {
741         LWIP_DEBUGF( IPERF_DEBUG, ("Set TOS: fail!\n" ));
742     }
743     // Bind to port and IP
744     memset( &servaddr, 0, sizeof(servaddr) );
745     servaddr.sin_family = AF_INET;
746     servaddr.sin_addr.s_addr = inet_addr( Server_IP );
747     if ( server_port == 0 ) {
748         servaddr.sin_port = htons( IPERF_DEFAULT_PORT );
749         LWIP_DEBUGF( IPERF_DEBUG, ("Default server port = %d\n", IPERF_DEFAULT_PORT ));
750     } else {
751         servaddr.sin_port = htons( server_port );
752         LWIP_DEBUGF( IPERF_DEBUG, ("Set server port = %d\n", server_port ));
753     }
754 
755     if ( (lwip_connect( sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr) )) < 0 ) {
756         LWIP_DEBUGF( IPERF_DEBUG, ("Connect failed, sockfd is %d, addr is \"%s\"\n", (int) sockfd,
757                 ((struct sockaddr *) &servaddr)->sa_data ));
758         lwip_close( sockfd );
759         if ( parameters ) {
760             iperf_wrapper_free( parameters );
761         }
762         aos_task_exit(0);
763         return;
764     }
765 
766     iperf_get_current_time( &t1, 0 );
767 
768     do {
769         nbytes = lwip_send( sockfd, buffer, win_size, 0 );
770         if (nbytes < 0) {
771             LWIP_DEBUGF( IPERF_DEBUG, ("Send failed\n" ));
772             break;
773         }
774 
775         pkt_count = iperf_calculate_result( nbytes, pkt_count, 0 );
776 #if defined(IPERF_DEBUG_ENABLE)
777         DBGPRINT_IPERF(IPERF_DEBUG_SEND, "[%s:%d]nbytes=%d ", __FUNCTION__, __LINE__, nbytes);
778 #endif
779         aos_msleep( pkt_delay );
780 
781         if ( num_tag == 1 ) {
782             total_send -= nbytes;
783         }
784         //Reach total receive number "-n"
785         if ( total_send < 0 ) {
786             LWIP_DEBUGF( IPERF_DEBUG, ("Finish Sending\n" ));
787             break;
788         }
789 
790         if ( interval_tag > 0 ) {
791             iperf_get_current_time( &curr_t, 0 );
792 
793             if ( ((int)(curr_t - t1) / interval_time) == interval_tag ) {
794                 aos_cli_printf("Interval: %d - %d sec   ", (int) (curr_t - t1) / interval_time * interval_time - interval_time,
795                         (int) (curr_t - t1) / interval_time * interval_time );
796                 iperf_display_report( "TCP Client", interval_time, 0, iperf_diff_count( pkt_count, tmp_count ) );
797                 tmp_count = iperf_copy_count( pkt_count, tmp_count );
798                 interval_tag++;
799             }
800         }
801 
802         iperf_get_current_time( &curr_t, 0 );
803     } while ( (int)(curr_t - t1) < send_time );
804 
805     iperf_get_current_time( &t2, 0 );
806 
807     lwip_close( sockfd );
808     LWIP_DEBUGF( IPERF_DEBUG, ("Close socket!\n" ));
809     iperf_wrapper_free( buffer );
810     iperf_display_report( "[Total]TCP Client", t2 - t1, 0, pkt_count );
811 
812     if ( parameters ) {
813         iperf_wrapper_free( parameters );
814     }
815     aos_task_exit(0);
816     return;
817 }
818 
iperf_udp_run_client(char * parameters[])819 void iperf_udp_run_client( char *parameters[] )
820 {
821     int sockfd;
822     struct sockaddr_in servaddr;
823     char *Server_IP = 0;
824     count_t pkt_count = {0};
825     count_t tmp_count = {0};
826     int nbytes = 0; /* the number of send */
827     int total_send = 0; /* the total number of transmit  */
828     int num_tag = 0; /* the tag of parameter "-n"  */
829     int interval_tag = 0; /* the tag of parameter "-i"  */
830     int interval_time = 10; /* the interval time of "-i"  */
831     int tradeoff_tag = 0; /* the tag of parameter "-r"  */
832     int i;
833     int data_size, send_time, server_port, pkt_delay, pkt_delay_offset, tos, bw;
834     uint32_t t1, t2, curr_t, t1_ms, last_tick, current_tick, last_sleep, current_sleep;
835     UDP_datagram *udp_h;
836     client_hdr *client_h;
837     int udp_h_id = 0;
838     int offset = IPERF_COMMAND_BUFFER_SIZE / sizeof(char *);
839     char *buffer = (char*) iperf_wrapper_malloc( IPERF_TEST_BUFFER_SIZE );
840     // test data init
841     for ( i = 0; i < IPERF_TEST_BUFFER_SIZE; i++ ) {
842         buffer[i] = (i % 10 + '0');
843     }
844     memset( buffer, 0, IPERF_TEST_BUFFER_SIZE );
845     //Statistics init
846     pkt_count = iperf_reset_count( pkt_count );
847     tmp_count = iperf_reset_count( tmp_count );
848     data_size = 0;
849     send_time = 0;
850     server_port = 0;
851     pkt_delay = 0;
852     pkt_delay_offset = 0;
853     tos = 0;
854     bw = 15728640; /* Change from 2621440 to 15728640 */
855 
856     //Handle input parameters
857     if ( g_iperf_is_tradeoff_test_server == 0 ) {
858         Server_IP = (char *) &parameters[0];
859         for ( i = 1; i < 18; i++ ) {
860             if ( strcmp( (char *) &parameters[i * offset], "-l" ) == 0 ) {
861                 i++;
862                 data_size = iperf_format_transform( (char *) &parameters[i * offset] );
863                 LWIP_DEBUGF( IPERF_DEBUG, ("Set datagram size = %d Bytes\n", data_size ));
864             } else if ( strcmp( (char *) &parameters[i * offset], "-t" ) == 0 ) {
865                 i++;
866                 send_time = atoi( (char *) &parameters[i * offset] );
867                 LWIP_DEBUGF( IPERF_DEBUG, ("Set send times = %d (secs)\n", atoi( (char *) &parameters[i * offset] ) ));
868             } else if ( strcmp( (char *) &parameters[i * offset], "-p" ) == 0 ) {
869                 i++;
870                 server_port = atoi( (char *) &parameters[i * offset] );
871             } else if ( strcmp( (char *) &parameters[i * offset], "-d" ) == 0 ) {
872                 i++;
873                 pkt_delay = atoi( (char *) &parameters[i * offset] );
874                 LWIP_DEBUGF( IPERF_DEBUG, ("Set packet delay = %d (ms)\n", atoi( (char *) &parameters[i * offset] ) ));
875             } else if ( strcmp( (char *) &parameters[i * offset], "-n" ) == 0 ) {
876                 i++;
877                 total_send = iperf_format_transform( (char *) &parameters[i * offset] );
878                 num_tag = 1;
879                 LWIP_DEBUGF( IPERF_DEBUG, ("Set number to transmit = %d Bytes\n", total_send ));
880             } else if ( strcmp( (char *) &parameters[i * offset], "-S" ) == 0 ) {
881                 i++;
882                 tos = atoi( (char *) &parameters[i * offset] );
883                 LWIP_DEBUGF( IPERF_DEBUG, ("Set TOS = %d\n", atoi( (char *) &parameters[i * offset] ) ));
884             } else if ( strcmp( (char *) &parameters[i * offset], "-b" ) == 0 ) {
885                 i++;
886                 LWIP_DEBUGF( IPERF_DEBUG, ("Set bandwidth = %s\n", (char *) &parameters[i * offset] ));
887                 bw = iperf_format_transform( (char *) &parameters[i * offset] );
888                 if ( bw > 15728640 || bw <= 0 ) {
889                     bw = 15728640; /* Change from 2621440 to 15728640 */
890                     LWIP_DEBUGF( IPERF_DEBUG, ("Upper limit of bandwith setting = 60Mbits/sec\n" ));
891                 }
892                 LWIP_DEBUGF( IPERF_DEBUG, ("bandwidth = %d\n", bw ));
893             } else if ( strcmp( (char *) &parameters[i * offset], "-i" ) == 0 ) {
894                 interval_tag = 1;
895                 i++;
896                 if((interval_time = atoi((char*) &parameters[i * offset])) == 0) {
897                     interval_time = 10;
898                     i--;
899                 }
900                 LWIP_DEBUGF( IPERF_DEBUG, ( "Set %d seconds between periodic bandwidth reports\n" , interval_time));
901             } else if ( strcmp( (char *) &parameters[i * offset], "-r" ) == 0 ) {
902                 tradeoff_tag = 1;
903                 LWIP_DEBUGF( IPERF_DEBUG, ( "Set to tradeoff mode\n" ));
904             }
905         }
906     }
907 
908     if ( data_size == 0 ) {
909         data_size = 1460;
910         LWIP_DEBUGF( IPERF_DEBUG, ("Default datagram size = %d Bytes\n", data_size ));
911     }
912 
913     if ( bw > 0 ) {
914         pkt_delay = (1000 * data_size) / bw;
915 
916         // pkt_dalay add 1ms regularly to reduce the offset
917         pkt_delay_offset = (((1000 * data_size) % bw) * 60 / bw);
918         if ( pkt_delay_offset ) {
919             pkt_delay_offset = 10 / pkt_delay_offset;
920         }
921     }
922 
923     if ( send_time == 0 ) {
924         if ( num_tag == 1 ) {
925             send_time = 999999;
926         } else {
927             send_time = 10;
928             LWIP_DEBUGF( IPERF_DEBUG, ("Default send times = %d (secs)\n", send_time ));
929         }
930     }
931 
932     // Create a new TCP connection handle
933     if ( (sockfd = lwip_socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) {
934         LWIP_DEBUGF( IPERF_DEBUG, ("[%s:%d] sockfd = %d\n", __FUNCTION__, __LINE__, sockfd ));
935         if ( parameters ) {
936             iperf_wrapper_free( parameters );
937         }
938         aos_task_exit(0);
939         return;
940     }
941 
942     if ( lwip_setsockopt( sockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos) ) < 0 ) {
943         LWIP_DEBUGF( IPERF_DEBUG, ("Set TOS: fail!\n" ));
944     }
945 
946     // Bind to port and IP
947     memset( &servaddr, 0, sizeof(servaddr) );
948     servaddr.sin_family = AF_INET;
949 
950     if ( g_iperf_is_tradeoff_test_server == 0 ) {
951         servaddr.sin_addr.s_addr = inet_addr( Server_IP );
952     } else {
953         servaddr.sin_addr.s_addr = g_iperf_server_addr;
954     }
955     LWIP_DEBUGF( IPERF_DEBUG, ("Server address = %x\n", (unsigned int) servaddr.sin_addr.s_addr ));
956 
957     if ( server_port == 0 ) {
958         servaddr.sin_port = htons( IPERF_DEFAULT_PORT );
959         LWIP_DEBUGF( IPERF_DEBUG, ("Default server port = %d\n", IPERF_DEFAULT_PORT ));
960     } else {
961         servaddr.sin_port = htons( server_port );
962         LWIP_DEBUGF( IPERF_DEBUG, ("Set server port = %d\n", server_port ));
963     }
964 
965     if ( (lwip_connect( sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr) )) < 0 ) {
966         LWIP_DEBUGF( IPERF_DEBUG, ( "Connect failed\n" ));
967         lwip_close( sockfd );
968         if ( parameters ) {
969             iperf_wrapper_free( parameters );
970         }
971         aos_task_exit(0);
972         return;
973     }
974 
975     // Init UDP data header
976     udp_h = (UDP_datagram *) &buffer[0];
977     client_h = (client_hdr *) &buffer[12];
978     if ( tradeoff_tag == 1 ) {
979         client_h->flags = htonl( IPERF_HEADER_VERSION1 );
980     } else {
981         client_h->flags = 0;
982     }
983     client_h->num_threads = htonl( 1 );
984     client_h->port = htonl( IPERF_DEFAULT_PORT );
985     client_h->buffer_len = 0;
986     client_h->win_band = htonl( IPERF_DEFAULT_UDP_RATE );
987     if ( num_tag != 1 ) { // time mode
988         client_h->amount = htonl( ~(long )(send_time * 100) );
989     } else {
990         client_h->amount = htonl( (long )(send_time * 100) );
991         client_h->amount &= htonl( 0x7FFFFFFF );
992     }
993 
994     iperf_get_current_time( &t1, &t1_ms );
995     last_tick = t1_ms;
996     last_sleep = 0;
997 
998     do {
999         udp_h->id = htonl( udp_h_id );
1000         udp_h->tv_sec = htonl( (last_tick + last_sleep) / 1000 );
1001         udp_h->tv_usec = htonl( last_tick + last_sleep );
1002 
1003         udp_h_id++;
1004 
1005         nbytes = lwip_send( sockfd, buffer, data_size, 0 );
1006         if (nbytes < 0) {
1007             LWIP_DEBUGF( IPERF_DEBUG, ("Send failed\n" ));
1008             break;
1009         }
1010 
1011         pkt_count = iperf_calculate_result( nbytes, pkt_count, 0 );
1012 
1013         iperf_get_current_time( &curr_t, &current_tick );
1014 
1015         if ( (pkt_delay_offset != 0) && ((udp_h_id % pkt_delay_offset) == 0) ) {
1016             current_sleep = pkt_delay - (current_tick - last_tick - last_sleep) + 1;
1017         } else {
1018             current_sleep = pkt_delay - (current_tick - last_tick - last_sleep);
1019         }
1020 
1021         if ( (int) current_sleep > 0 ) {
1022             aos_msleep( current_sleep );
1023         } else {
1024             current_sleep = 0;
1025         }
1026 
1027         last_tick = current_tick;
1028         last_sleep = current_sleep;
1029 
1030 #if defined(IPERF_DEBUG_INTERNAL)
1031         // show the debug info per second
1032         if (((bw == 0) && ((udp_h_id % 5000 == 0))) || (udp_h_id % (bw / nbytes) == 0)) {
1033             DBGPRINT_IPERF(IPERF_DEBUG_SEND, "[%s:%d] nbytes = %d, udp_h_id = %d, pkt_delay = %d, current_tick = %"U32_F", current_sleep = %"U32_F"",
1034                     __FUNCTION__, __LINE__, nbytes, udp_h_id, pkt_delay, current_tick, current_sleep);
1035         }
1036 #endif
1037 
1038         if ( num_tag == 1 ) {
1039             total_send -= nbytes;
1040         }
1041 
1042         //Reach total receive number "-n"
1043         if ( total_send < 0 ) {
1044             LWIP_DEBUGF( IPERF_DEBUG, ("Finish Sending\n" ));
1045             break;
1046         }
1047 
1048         if ( interval_tag > 0 ) {
1049             if ( ((int)(current_tick - t1_ms) / (interval_time * 1000)) == interval_tag ) {
1050                 aos_cli_printf("Interval: %d - %d sec   ", (int) (current_tick - t1_ms) / (interval_time * 1000) * interval_time - interval_time,
1051                         (int) (current_tick - t1_ms) / (interval_time * 1000) * interval_time );
1052                 iperf_display_report( "UDP Client", interval_time, 0, iperf_diff_count( pkt_count, tmp_count ) );
1053                 tmp_count = iperf_copy_count( pkt_count, tmp_count );
1054                 interval_tag++;
1055             }
1056             iperf_get_current_time( &curr_t, &current_tick );
1057         }
1058     } while ( (int)(current_tick + (uint32_t)pkt_delay - t1_ms)/1000 < send_time );
1059 
1060     iperf_get_current_time( &t2, 0 );
1061     iperf_display_report( "[Total]UDP Client", t2 - t1, 0, pkt_count );
1062 
1063     // send the last datagram
1064     udp_h_id = (-udp_h_id);
1065     udp_h->id = htonl( udp_h_id );
1066     iperf_get_current_time( &curr_t, 0 );
1067     udp_h->tv_sec = htonl( curr_t );
1068     udp_h->tv_usec = htonl( curr_t * 1000 );
1069 
1070     nbytes = lwip_send( sockfd, buffer, data_size, 0 );
1071     if (nbytes < 0) {
1072         LWIP_DEBUGF( IPERF_DEBUG, ("Send failed\n" ));
1073     }
1074 
1075     //TODO: receive the report from server side and print out
1076 
1077     LWIP_DEBUGF( IPERF_DEBUG, ("UDP Client close socket!\n" ));
1078     lwip_close( sockfd );
1079 
1080     // tradeoff testing
1081     if ( tradeoff_tag == 1 ) {
1082         LWIP_DEBUGF( IPERF_DEBUG, ("Tradoff test, start server-side.\n" ));
1083         g_iperf_is_tradeoff_test_client = 1;
1084         iperf_udp_run_server( NULL );
1085         g_iperf_is_tradeoff_test_client = 0;
1086     }
1087 
1088     if ( parameters ) {
1089         iperf_wrapper_free( parameters );
1090     }
1091 
1092     iperf_wrapper_free( buffer );
1093     // For tradeoff mode, task will be deleted in iperf_udp_run_server
1094     if ( g_iperf_is_tradeoff_test_server == 0 ) {
1095         aos_task_exit(0);
1096     }
1097     return;
1098 }
1099 
iperf_calculate_result(int pkt_size,count_t pkt_count,int need_to_convert)1100 count_t iperf_calculate_result( int pkt_size, count_t pkt_count, int need_to_convert )
1101 {
1102     if ( pkt_size > 0 ) {
1103         pkt_count.Bytes += pkt_size;
1104         pkt_count.times++;
1105     }
1106 
1107     if ( need_to_convert == 1 ) {
1108         if ( pkt_count.Bytes >= 1024 ) {
1109             pkt_count.KBytes += (pkt_count.Bytes / 1024);
1110             pkt_count.Bytes = pkt_count.Bytes % 1024;
1111         }
1112 
1113         if ( pkt_count.KBytes >= 1024 ) {
1114             pkt_count.MBytes += (pkt_count.KBytes / 1024);
1115             pkt_count.KBytes = pkt_count.KBytes % 1024;
1116         }
1117 
1118         if ( pkt_count.MBytes >= 1024 ) {
1119             pkt_count.GBytes += (pkt_count.MBytes / 1024);
1120             pkt_count.MBytes = pkt_count.MBytes % 1024;
1121         }
1122     }
1123 
1124     return pkt_count;
1125 }
1126 
iperf_display_report(char * report_title,unsigned time,unsigned h_ms_time,count_t pkt_count)1127 void iperf_display_report( char *report_title, unsigned time, unsigned h_ms_time, count_t pkt_count )
1128 {
1129     unsigned tmp_time = (time * 10) + h_ms_time;
1130 
1131 #if defined(IPERF_DEBUG_ENABLE)
1132     DBGPRINT_IPERF(IPERF_DEBUG_REPORT, "\nTransfer in %d.%d seconds: ", time, h_ms_time);
1133     if (pkt_count.GBytes != 0) {
1134         DBGPRINT_IPERF(IPERF_DEBUG_REPORT, "%d GBytes ", pkt_count.GBytes);
1135     }
1136 
1137     if (pkt_count.MBytes != 0) {
1138         DBGPRINT_IPERF(IPERF_DEBUG_REPORT, "%d MBytes ", pkt_count.MBytes);
1139     }
1140 
1141     if (pkt_count.KBytes != 0) {
1142         DBGPRINT_IPERF(IPERF_DEBUG_REPORT, "%d KBytes ", pkt_count.KBytes);
1143     }
1144 
1145     DBGPRINT_IPERF(IPERF_DEBUG_REPORT, "[%s:%d], time = %d, h_ms_time = %d, GBytes = %d, MBytes = %d, KBytes= %d, Bytes= %d ", __FUNCTION__, __LINE__, time, h_ms_time, pkt_count.GBytes, pkt_count.MBytes, pkt_count.KBytes, pkt_count.Bytes);
1146 #endif
1147 
1148     aos_cli_printf("%s Bandwidth: ", report_title );
1149 
1150     if ( tmp_time != 0 ) {
1151         //Calculate Bandwidth
1152         pkt_count.Bytes = (((pkt_count.KBytes * 8 * 10) % tmp_time) * 1024 + pkt_count.Bytes * 8 * 10) / tmp_time;
1153         pkt_count.KBytes = (((pkt_count.MBytes * 8 * 10) % tmp_time) * 1024 + pkt_count.KBytes * 8 * 10) / tmp_time;
1154         pkt_count.MBytes = (((pkt_count.GBytes * 8 * 10) % tmp_time) * 1024 + pkt_count.MBytes * 8 * 10) / tmp_time;
1155         pkt_count.GBytes = pkt_count.GBytes * 8 * 10 / tmp_time;
1156     } else {
1157         pkt_count.Bytes = 0;
1158         pkt_count.KBytes = 0;
1159         pkt_count.MBytes = 0;
1160         pkt_count.GBytes = 0;
1161     }
1162 
1163     pkt_count = iperf_calculate_result( 0, pkt_count, 1 );
1164 
1165     if ( pkt_count.GBytes != 0 ) {
1166         aos_cli_printf("%d Gbits ", pkt_count.GBytes );
1167     }
1168 
1169     if ( pkt_count.MBytes != 0 ) {
1170         aos_cli_printf("%d Mbits ", pkt_count.MBytes );
1171     }
1172 
1173     if ( pkt_count.KBytes != 0 ) {
1174         aos_cli_printf("%d Kbits ", pkt_count.KBytes );
1175     }
1176     aos_cli_printf("%d bits/sec", pkt_count.Bytes );
1177 
1178 #ifdef AOS_NETMGR_WITH_MODERN
1179 #ifdef AOS_NET_WITH_WIFI
1180     int rssi;
1181     wifi_service_get_rssi(&rssi);
1182     aos_cli_printf(" rssi: %d dBm",  rssi);
1183 #endif /* AOS_NET_WITH_WIFI */
1184 #endif /* AOS_NETMGR_WITH_MODERN */
1185 
1186    aos_cli_printf("\n");
1187 #if defined(IPERF_DEBUG_ENABLE)
1188     DBGPRINT_IPERF(IPERF_DEBUG_REPORT, "Receive times: %d", pkt_count.times);
1189 #endif
1190 
1191 }
1192 
iperf_reset_count(count_t pkt_count)1193 count_t iperf_reset_count( count_t pkt_count )
1194 {
1195     pkt_count.Bytes = 0;
1196     pkt_count.KBytes = 0;
1197     pkt_count.MBytes = 0;
1198     pkt_count.GBytes = 0;
1199     pkt_count.times = 0;
1200 
1201     return pkt_count;
1202 }
1203 
iperf_copy_count(count_t pkt_count,count_t tmp_count)1204 count_t iperf_copy_count( count_t pkt_count, count_t tmp_count )
1205 {
1206 
1207     tmp_count.Bytes = pkt_count.Bytes;
1208     tmp_count.KBytes = pkt_count.KBytes;
1209     tmp_count.MBytes = pkt_count.MBytes;
1210     tmp_count.GBytes = pkt_count.GBytes;
1211     tmp_count.times = pkt_count.times;
1212 
1213     return tmp_count;
1214 }
1215 
iperf_diff_count(count_t pkt_count,count_t tmp_count)1216 count_t iperf_diff_count( count_t pkt_count, count_t tmp_count )
1217 {
1218     /* pkt_count > tmp_count */
1219     tmp_count.times = pkt_count.times - tmp_count.times;
1220 
1221     if ( pkt_count.Bytes >= tmp_count.Bytes ) {
1222         tmp_count.Bytes = pkt_count.Bytes - tmp_count.Bytes;
1223     } else {
1224         tmp_count.Bytes = pkt_count.Bytes + 1024 - tmp_count.Bytes;
1225         if ( pkt_count.KBytes > 0 ) {
1226             pkt_count.KBytes--;
1227         } else if ( pkt_count.MBytes > 0 ) {
1228             pkt_count.MBytes--;
1229             pkt_count.KBytes = 1023;
1230         } else if ( pkt_count.GBytes > 0 ) {
1231             pkt_count.GBytes--;
1232             pkt_count.MBytes = 1023;
1233             pkt_count.KBytes = 1023;
1234         } else {
1235             LWIP_DEBUGF( IPERF_DEBUG, ("Warning: Diff data is wrong.\n" ));
1236         }
1237     }
1238 
1239     if ( pkt_count.KBytes >= tmp_count.KBytes ) {
1240         tmp_count.KBytes = pkt_count.KBytes - tmp_count.KBytes;
1241     } else {
1242         tmp_count.KBytes = pkt_count.KBytes + 1024 - tmp_count.KBytes;
1243         if ( pkt_count.MBytes > 0 ) {
1244             pkt_count.MBytes--;
1245         } else if ( pkt_count.GBytes > 0 ) {
1246             pkt_count.GBytes--;
1247             pkt_count.MBytes = 1023;
1248         } else {
1249             LWIP_DEBUGF( IPERF_DEBUG, ("Warning: Diff data is wrong.\n" ));
1250         }
1251     }
1252 
1253     if ( pkt_count.MBytes >= tmp_count.MBytes ) {
1254         tmp_count.MBytes = pkt_count.MBytes - tmp_count.MBytes;
1255     } else {
1256         tmp_count.MBytes = pkt_count.MBytes + 1024 - tmp_count.MBytes;
1257         if ( pkt_count.GBytes > 0 ) {
1258             pkt_count.GBytes--;
1259         } else {
1260             LWIP_DEBUGF( IPERF_DEBUG, ("Warning: Diff data is wrong.\n" ));
1261         }
1262     }
1263 
1264 #if defined(IPERF_DEBUG_INTERNAL)
1265     DBGPRINT_IPERF(IPERF_DEBUG_REPORT, "\niperf_diff_count: ret.times = %d, ret.GBytes = %d, ret.MBytes = %d, ret.KBytes = %d, ret.Bytes = %d",
1266             tmp_count.times, tmp_count.GBytes, tmp_count.MBytes, tmp_count.KBytes, tmp_count.Bytes);
1267 #endif
1268 
1269     return tmp_count;
1270 }
1271 
iperf_get_current_time(uint32_t * s,uint32_t * ms)1272 void iperf_get_current_time( uint32_t *s, uint32_t *ms )
1273 {
1274     uint64_t now = aos_now_ms();
1275     if ( s ) {
1276         *s = (uint32_t)(now/1000);
1277     }
1278 
1279     if ( ms ) {
1280         *ms = (uint32_t)(now);
1281     }
1282 }
1283 
iperf_set_debug_mode(uint32_t debug)1284 void iperf_set_debug_mode( uint32_t debug )
1285 {
1286     g_iperf_debug_feature = debug;
1287 }
1288 
iperf_format_transform(char * param)1289 int iperf_format_transform( char *param )
1290 {
1291     char *temp;
1292     int win_size = 0;
1293     int i;
1294 
1295     temp = param;
1296 
1297     for ( i = 0; temp[i] != '\0'; i++ ) {
1298         if ( temp[i] == 'k' ) {
1299             temp[i] = '\0';
1300             win_size = (1000 * atoi( temp ));
1301         } else if ( temp[i] == 'm' ) {
1302             temp[i] = '\0';
1303             win_size = (1000 * 1000 * atoi( temp ));
1304         } else if ( temp[i] == 'K' ) {
1305             temp[i] = '\0';
1306             win_size = 1024 * atoi( temp );
1307         } else if ( temp[i] == 'M' ) {
1308             temp[i] = '\0';
1309             win_size = 1024 * 1024 * atoi( temp );
1310         } else {
1311             win_size = atoi( param );
1312         }
1313     }
1314 
1315     return win_size;
1316 }
1317 
1318