iperf_task.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. /*
  2. A FreeRTOS+TCP demo program:
  3. A simple example of a TCP/UDP iperf server, see https://iperf.fr
  4. It uses a single task which will store some client information in a:
  5. List_t xTCPClientList;
  6. The task will sleep constantly by calling:
  7. xResult = FreeRTOS_select( xSocketSet, xBlockingTime );
  8. Command examples for testing:
  9. iperf3 -c 192.168.2.114 --port 5001 --bytes 100M
  10. iperf3 -c 192.168.2.114 --port 5001 --bytes 100M -R
  11. iperf3 -c fe80::8d11:cd9b:8b66:4a80 --port 5001 --bytes 1M
  12. iperf3 -c fe80::8d11:cd9b:8b66:4a81 --port 5001 --bytes 1M
  13. iperf3 -c fe80::6802:9887:8670:b37c --port 5001 --bytes 1M
  14. ping fe80::8d11:cd9b:8b66:4a80
  15. ping fe80::8d11:cd9b:8b66:4a81
  16. iperf3 -s --port 5001
  17. iperf3 -c zynq --port 5001 --bytes 1024
  18. iperf3 -c laptop --port 5001 --bytes 1024
  19. fe80::8d11:cd9b:8b66:4a80
  20. TCP : iperf3 -c 192.168.2.116 --port 5001 --bytes 1024
  21. UDP : iperf3 -c 192.168.2.116 --port 5001 --udp --bandwidth 50M --mss 1460 --bytes 1024
  22. */
  23. /* Standard includes. */
  24. #include <stdio.h>
  25. #include <time.h>
  26. /* FreeRTOS includes. */
  27. #include <FreeRTOS.h>
  28. #include "task.h"
  29. #include "timers.h"
  30. /* FreeRTOS+TCP includes. */
  31. #include "FreeRTOS_IP.h"
  32. #include "FreeRTOS_Sockets.h"
  33. #include "FreeRTOS_TCP_IP.h"
  34. #include "iperf_task.h"
  35. /* Put the TCP server at this port number: */
  36. #ifndef ipconfigIPERF_TCP_ECHO_PORT
  37. /* 5001 seems to be the standard TCP server port number. */
  38. #define ipconfigIPERF_TCP_ECHO_PORT 5001
  39. #endif
  40. /* Put the TCP server at this port number: */
  41. #ifndef ipconfigIPERF_UDP_ECHO_PORT
  42. /* 5001 seems to be the standard UDP server port number. */
  43. #define ipconfigIPERF_UDP_ECHO_PORT 5001
  44. #endif
  45. #ifndef ipconfigIPERF_STACK_SIZE_IPERF_TASK
  46. /* Stack size needed for vIPerfTask(), a bit of a guess: */
  47. #define ipconfigIPERF_STACK_SIZE_IPERF_TASK 340
  48. #endif
  49. #ifndef ipconfigIPERF_PRIORITY_IPERF_TASK
  50. /* The priority of vIPerfTask(). Should be lower than the IP-task
  51. and the task running in NetworkInterface.c. */
  52. #define ipconfigIPERF_PRIORITY_IPERF_TASK 3
  53. #endif
  54. #ifndef ipconfigIPERF_RECV_BUFFER_SIZE
  55. /* Only used when ipconfigIPERF_USE_ZERO_COPY = 0.
  56. Buffer size when reading from the sockets. */
  57. #define ipconfigIPERF_RECV_BUFFER_SIZE ( 4 * ipconfigTCP_MSS )
  58. #endif
  59. #ifndef ipconfigIPERF_LOOP_BLOCKING_TIME_MS
  60. /* Let the mainloop wake-up so now and then. */
  61. #define ipconfigIPERF_LOOP_BLOCKING_TIME_MS 5000UL
  62. #endif
  63. #ifndef ipconfigIPERF_HAS_TCP
  64. /* A TCP server socket will be created. */
  65. #define ipconfigIPERF_HAS_TCP 1
  66. #endif
  67. #ifndef ipconfigIPERF_HAS_UDP
  68. /* A UDP server socket will be created. */
  69. #define ipconfigIPERF_HAS_UDP 1
  70. #endif
  71. #ifndef ipconfigIPERF_DOES_ECHO_UDP
  72. /* By default, this server will echo UDP data as required by iperf. */
  73. #define ipconfigIPERF_DOES_ECHO_UDP 1
  74. #endif
  75. #ifndef ipconfigIPERF_USE_ZERO_COPY
  76. #define ipconfigIPERF_USE_ZERO_COPY 1
  77. #endif
  78. #ifndef ipconfigIPERF_TX_BUFSIZE
  79. #define ipconfigIPERF_TX_BUFSIZE ( 65 * 1024 ) /* Units of bytes. */
  80. #define ipconfigIPERF_TX_WINSIZE ( 4 ) /* Size in units of MSS */
  81. #define ipconfigIPERF_RX_BUFSIZE ( ( 65 * 1024 ) - 1 ) /* Units of bytes. */
  82. #define ipconfigIPERF_RX_WINSIZE ( 8 ) /* Size in units of MSS */
  83. #endif
  84. #ifndef ARRAY_SIZE
  85. #define ARRAY_SIZE(x) (BaseType_t)(sizeof(x)/sizeof(x)[0])
  86. #endif
  87. void vIPerfTask( void *pvParameter );
  88. /* As for now, still defined in 'FreeRTOS-Plus-TCP\FreeRTOS_TCP_WIN.c' : */
  89. extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere );
  90. static portINLINE void vListInsertFifo( List_t * const pxList, ListItem_t * const pxNewListItem )
  91. {
  92. vListInsertGeneric( pxList, pxNewListItem, &pxList->xListEnd );
  93. }
  94. #if( ipconfigIPERF_VERSION == 3 )
  95. typedef enum
  96. {
  97. eTCP_0_WaitName, /* Expect a text like "osboxes.1460335312.612572.527642c36f" */
  98. eTCP_1_WaitCount,
  99. eTCP_2_WaitHeader,
  100. eTCP_3_WaitOneTwo,
  101. eTCP_4_WaitCount2,
  102. eTCP_5_WaitHeader2,
  103. eTCP_6_WaitDone,
  104. eTCP_7_WaitTransfer
  105. } eTCP_Server_Status_t;
  106. #endif
  107. typedef struct
  108. {
  109. Socket_t xServerSocket;
  110. #if( ipconfigIPERF_VERSION == 3 )
  111. struct {
  112. uint32_t
  113. bIsControl : 1,
  114. bReverse : 1,
  115. bTimed : 1, /* Reverse role, limited time. */
  116. bTimedOut : 1, /* TIme is up. */
  117. bHasShutdown : 1;
  118. } bits;
  119. eTCP_Server_Status_t eTCP_Status;
  120. uint32_t ulSkipCount, ulAmount;
  121. uint32_t xRemainingTime;
  122. TimeOut_t xTimeOut;
  123. #endif /* ipconfigIPERF_VERSION == 3 */
  124. #if( ipconfigUSE_IPv6 != 0 )
  125. struct freertos_sockaddr6 xRemoteAddr;
  126. #else
  127. struct freertos_sockaddr xRemoteAddr;
  128. #endif
  129. uint32_t ulRecvCount;
  130. struct xLIST_ITEM xListItem; /* With this item the client will be bound to a List_t. */
  131. } TcpClient_t;
  132. #if( ipconfigIPERF_USE_ZERO_COPY != 0 )
  133. struct xRawBuffer {
  134. char pcBuffer[ ipconfigIPERF_RECV_BUFFER_SIZE ];
  135. } *pxRawBuffer;
  136. #define pcSendBuffer ( pxRawBuffer->pcBuffer )
  137. static char *pcRecvBuffer;
  138. #else
  139. struct xRawBuffer {
  140. char pcBuffer[ ipconfigIPERF_RECV_BUFFER_SIZE ];
  141. } *pxRawBuffer;
  142. #define pcRecvBuffer ( pxRawBuffer->pcBuffer )
  143. #define pcSendBuffer ( pxRawBuffer->pcBuffer )
  144. #endif
  145. #if( ipconfigIPERF_VERSION == 3 )
  146. char pcExpectedClient[ 80 ];
  147. TcpClient_t *pxControlClient, *pxDataClient;
  148. /*{"cpu_util_total":0,"cpu_util_user":0,"cpu_util_system":0,"sender_has_retransmits":-1,"streams":[{"id":1,"bytes":8760,"retransmits":-1,"jitter":0,"errors":0,"packets":0}]} */
  149. #endif
  150. static List_t xTCPClientList;
  151. #if( ipconfigIPERF_HAS_UDP != 0 )
  152. static uint32_t ulUDPRecvCount = 0, ulUDPRecvCountShown = 0, ulUDPRecvCountSeen = 0;
  153. #endif
  154. static SocketSet_t xSocketSet;
  155. static TaskHandle_t pxIperfTask;
  156. void vIPerfInstall( void )
  157. {
  158. if( pxRawBuffer == NULL )
  159. {
  160. pxRawBuffer = ( struct xRawBuffer * ) pvPortMalloc( sizeof *pxRawBuffer );
  161. if( pxRawBuffer == NULL )
  162. {
  163. FreeRTOS_printf( ( "vIPerfInstall: malloc %u bytes failed.\n", (unsigned)sizeof *pxRawBuffer ) ) ;
  164. return;
  165. }
  166. }
  167. if( pxIperfTask == NULL )
  168. {printf("start iperf\r\n");
  169. /* Call this function once to start the test with FreeRTOS_accept(). */
  170. xTaskCreate( vIPerfTask, "IPerf", ipconfigIPERF_STACK_SIZE_IPERF_TASK, NULL, ipconfigIPERF_PRIORITY_IPERF_TASK, &pxIperfTask );
  171. }
  172. }
  173. static void vIPerfServerWork( Socket_t xSocket )
  174. {
  175. struct freertos_sockaddr xAddress;
  176. socklen_t xSocketLength;
  177. Socket_t xNexSocket;
  178. xNexSocket = FreeRTOS_accept( xSocket, &xAddress, &xSocketLength);
  179. if( ( xNexSocket != NULL ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) )
  180. {
  181. char pucBuffer[ 16 ];
  182. TcpClient_t *pxClient;
  183. pxClient = ( TcpClient_t * )pvPortMalloc( sizeof *pxClient );
  184. memset( pxClient, '\0', sizeof *pxClient );
  185. pxClient->xServerSocket = xNexSocket;
  186. listSET_LIST_ITEM_OWNER( &( pxClient->xListItem ), ( void* ) pxClient );
  187. #if( ipconfigUSE_IPv6 != 0 )
  188. FreeRTOS_GetRemoteAddress( xNexSocket, ( struct freertos_sockaddr6 * ) &pxClient->xRemoteAddr );
  189. #else
  190. FreeRTOS_GetRemoteAddress( xNexSocket, ( struct freertos_sockaddr * ) &pxClient->xRemoteAddr );
  191. FreeRTOS_inet_ntoa( pxClient->xRemoteAddr.sin_addr, pucBuffer );
  192. FreeRTOS_printf( ( "vIPerfTask: Received a connection from %s:%u\n",
  193. pucBuffer,
  194. FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ) ) );
  195. #endif
  196. FreeRTOS_FD_SET( xNexSocket, xSocketSet, eSELECT_READ );
  197. vListInsertFifo( &xTCPClientList, &( pxClient->xListItem ) );
  198. }
  199. }
  200. static void vIPerfTCPClose( TcpClient_t *pxClient )
  201. {
  202. if( pxControlClient == pxClient )
  203. {
  204. pxControlClient = NULL;
  205. }
  206. if( pxDataClient == pxClient )
  207. {
  208. pxDataClient = NULL;
  209. }
  210. /* Remove server socket from the socket set. */
  211. if( pxClient->xServerSocket != NULL )
  212. {
  213. char pucBuffer[ 16 ];
  214. #if( ipconfigUSE_IPv6 == 0 )
  215. FreeRTOS_inet_ntoa( pxClient->xRemoteAddr.sin_addr, pucBuffer );
  216. FreeRTOS_printf( ( "vIPerfTCPClose: Closing server socket %s:%u after %lu bytes\n",
  217. pucBuffer,
  218. FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ),
  219. pxClient->ulRecvCount ) );
  220. #endif
  221. FreeRTOS_FD_CLR( pxClient->xServerSocket, xSocketSet, eSELECT_ALL );
  222. FreeRTOS_closesocket( pxClient->xServerSocket );
  223. pxClient->xServerSocket = NULL;
  224. }
  225. /* Remove client socket from the socket set. */
  226. {
  227. if( pxClient->xServerSocket == NULL )
  228. {
  229. /* Remove this socket from the list. */
  230. uxListRemove( &( pxClient->xListItem ) );
  231. vPortFree( ( void * ) pxClient );
  232. }
  233. }
  234. }
  235. static int vIPerfTCPSend( TcpClient_t *pxClient )
  236. {
  237. BaseType_t xResult = 0;
  238. do
  239. {
  240. size_t uxMaxSpace = (size_t) FreeRTOS_tx_space( pxClient->xServerSocket );
  241. size_t uxSize = (size_t)FreeRTOS_min_uint32( uxMaxSpace, ( int32_t )sizeof( pcSendBuffer ) );
  242. if( pxClient->bits.bTimed != pdFALSE_UNSIGNED )
  243. {
  244. if( xTaskCheckForTimeOut( &( pxClient->xTimeOut ), &( pxClient->xRemainingTime ) ) != pdFALSE )
  245. {
  246. /* Time is up. */
  247. if( pxClient->bits.bTimedOut == pdFALSE_UNSIGNED )
  248. {
  249. FreeRTOS_shutdown( pxClient->xServerSocket, FREERTOS_SHUT_RDWR );
  250. pxClient->bits.bTimedOut = pdTRUE_UNSIGNED;
  251. }
  252. break;
  253. }
  254. }
  255. uxSize = FreeRTOS_min_uint32( uxSize, pxClient->ulAmount );
  256. if( uxSize <= 0 )
  257. {
  258. break;
  259. }
  260. xResult = FreeRTOS_send( pxClient->xServerSocket, (const void *)pcSendBuffer, uxSize, 0 );
  261. if( xResult < 0 )
  262. {
  263. break;
  264. }
  265. if( pxClient->bits.bTimed == pdFALSE_UNSIGNED )
  266. {
  267. pxClient->ulAmount -= uxSize;
  268. if( pxClient->ulAmount == 0ul )
  269. {
  270. /* All data have been sent. No longer interested in eSELECT_WRITE events. */
  271. FreeRTOS_FD_CLR( pxClient->xServerSocket, xSocketSet, eSELECT_WRITE );
  272. }
  273. }
  274. if( uxSize > 0 )
  275. {
  276. xResult += uxSize;
  277. }
  278. }
  279. while( 0 );
  280. return xResult;
  281. }
  282. #if( ipconfigIPERF_VERSION == 3 )
  283. static void handleRecvPacket( TcpClient_t *pxClient, char *pcReadBuffer, BaseType_t xRecvResult )
  284. {
  285. BaseType_t xRemaining = xRecvResult;
  286. if( pxClient->eTCP_Status < eTCP_7_WaitTransfer )
  287. {
  288. FreeRTOS_printf( ( "TCP[ port %d ] recv[ %d ] %d\n", FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ), ( int ) pxClient->eTCP_Status, ( int )xRecvResult ) );
  289. }
  290. /*
  291. 2016-04-11 09:26:55.533 192.168.2.106 16.926.349 [] TCP recv[ 1 ] 4
  292. 2016-04-11 09:26:55.539 192.168.2.106 16.926.365 [] TCP skipcount 83 xRecvResult 4
  293. 2016-04-11 09:26:55.546 192.168.2.106 16.926.402 [] TCP recv[ 2 ] 4
  294. 2016-04-11 09:26:55.552 192.168.2.106 16.927.015 [] ipTCP_FLAG_PSH received
  295. 2016-04-11 09:26:55.560 192.168.2.106 16.927.085 [] TCP recv[ 2 ] 83
  296. */
  297. switch( pxClient->eTCP_Status )
  298. {
  299. case eTCP_0_WaitName:
  300. {
  301. int rc;
  302. if( pcExpectedClient[ 0 ] != '\0' )
  303. {
  304. /* Get a string like 'LAPTOP.1463928623.162445.0fbe105c6eb',
  305. where 'LAPTOP' is the hostname. */
  306. rc = strncmp( pcExpectedClient, pcReadBuffer, sizeof( pcExpectedClient ) );
  307. }
  308. else
  309. {
  310. rc = -1;
  311. }
  312. {
  313. unsigned char tab[ 1 ] = { '\t' };
  314. FreeRTOS_send( pxClient->xServerSocket, (const void *)tab, 1, 0 );
  315. }
  316. if( rc != 0 )
  317. {
  318. FreeRTOS_printf( ( "Got Control Socket: rc %d: exp: '%s' got: '%s'\n", rc, pcExpectedClient, pcReadBuffer ) );
  319. strncpy( pcExpectedClient, pcReadBuffer, sizeof( pcExpectedClient ) );
  320. pxControlClient = pxClient;
  321. pxClient->bits.bIsControl = pdTRUE_UNSIGNED;
  322. pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
  323. }
  324. else
  325. {
  326. FreeRTOS_printf( ( "Got expected client: rc %d: '%s'\n", rc, pcExpectedClient ) );
  327. pcExpectedClient[ 0 ] = '\0';
  328. pxDataClient = pxClient;
  329. if( pxControlClient != NULL )
  330. {
  331. /* Transfer all properties to the data client. */
  332. memcpy( &( pxDataClient->bits ), &( pxControlClient->bits ), sizeof( pxDataClient->bits ) );
  333. pxDataClient->ulAmount = pxControlClient->ulAmount;
  334. pxDataClient->xRemainingTime = pxControlClient->xRemainingTime;
  335. vTaskSetTimeOutState( &( pxDataClient->xTimeOut ) );
  336. if( pxDataClient->bits.bReverse != pdFALSE_UNSIGNED )
  337. {
  338. /* As this socket will only write data, set the WRITE select flag. */
  339. FreeRTOS_FD_SET( pxClient->xServerSocket, xSocketSet, eSELECT_WRITE );
  340. }
  341. pxControlClient->bits.bIsControl = pdTRUE_UNSIGNED;
  342. pxDataClient->bits.bIsControl = pdFALSE_UNSIGNED;
  343. }
  344. pxDataClient->eTCP_Status = eTCP_7_WaitTransfer;
  345. }
  346. }
  347. break;
  348. case eTCP_1_WaitCount:
  349. if( xRemaining < 4 )
  350. {
  351. break;
  352. }
  353. {
  354. pxClient->ulSkipCount =
  355. ( ( ( uint32_t ) pcReadBuffer[ 0 ] ) << 24 ) |
  356. ( ( ( uint32_t ) pcReadBuffer[ 1 ] ) << 16 ) |
  357. ( ( ( uint32_t ) pcReadBuffer[ 2 ] ) << 8 ) |
  358. ( ( ( uint32_t ) pcReadBuffer[ 3 ] ) << 0 );
  359. /* Receive a number: an amount of bytes to be skipped. */
  360. FreeRTOS_printf( ( "TCP skipcount %u xRecvResult %d\n", ( unsigned )pxClient->ulSkipCount, ( int )xRemaining ) );
  361. pcReadBuffer += 4;
  362. xRemaining -= 4;
  363. pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
  364. }
  365. if( xRemaining == 0 )
  366. {
  367. break;
  368. }
  369. /* fall through */
  370. case eTCP_2_WaitHeader:
  371. {
  372. if (xRemaining > 0) {
  373. char *pcPtr;
  374. pcReadBuffer[ xRemaining ] = '\0';
  375. FreeRTOS_printf( ( "Control string: %s\n", pcReadBuffer ) );
  376. for( pcPtr = pcReadBuffer; *pcPtr; pcPtr++ )
  377. {
  378. if( strncmp( pcPtr, "\"reverse\"", 9 ) == 0 )
  379. {
  380. pxClient->bits.bReverse = pcPtr[ 10 ] == 't';
  381. }
  382. else if( strncmp( pcPtr, "\"num\"", 5 ) == 0 )
  383. {
  384. uint32_t ulAmount;
  385. if( sscanf( pcPtr + 6, "%lu", &( ulAmount ) ) > 0 )
  386. {
  387. pxClient->ulAmount = ulAmount;
  388. }
  389. }
  390. else if( strncmp( pcPtr, "\"time\"", 6 ) == 0 )
  391. {
  392. uint32_t ulSeconds;
  393. if( sscanf( pcPtr + 7, "%lu", &( ulSeconds ) ) > 0 )
  394. {
  395. pxClient->xRemainingTime = ulSeconds * 1000ul;
  396. pxClient->bits.bTimed = pdTRUE_UNSIGNED;
  397. }
  398. }
  399. }
  400. if( pxClient->bits.bReverse != pdFALSE_UNSIGNED )
  401. {
  402. FreeRTOS_printf( ( "Reverse %d send %lu bytes timed %d: %lu\n",
  403. pxClient->bits.bReverse, pxClient->ulAmount,
  404. pxClient->bits.bTimed,
  405. pxClient->xRemainingTime ) );
  406. }
  407. }
  408. if( pxClient->ulSkipCount > ( uint32_t ) xRemaining )
  409. {
  410. pxClient->ulSkipCount -= ( uint32_t ) xRemaining;
  411. }
  412. else
  413. {
  414. unsigned char newline[ 1 ] = { '\n' };
  415. unsigned char onetwo[ 2 ] = { '\1', '\2' };
  416. FreeRTOS_send( pxClient->xServerSocket, (const void *)newline, sizeof( newline ), 0 );
  417. FreeRTOS_send( pxClient->xServerSocket, (const void *)onetwo, sizeof( onetwo ), 0 );
  418. pxClient->ulSkipCount = 0;
  419. pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
  420. }
  421. }
  422. break;
  423. case eTCP_3_WaitOneTwo:
  424. {
  425. unsigned char ch = pcReadBuffer[ 0 ];
  426. unsigned char cr[ 1 ] = { '\r' };
  427. FreeRTOS_printf( ( "TCP[ port %d ] recv %d bytes: 0x%02X\n",
  428. FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ), ( int )xRecvResult, ch ) );
  429. ch = ch;
  430. FreeRTOS_send( pxClient->xServerSocket, (const void *)cr, sizeof( cr ), 0 );
  431. pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
  432. }
  433. break;
  434. case eTCP_4_WaitCount2:
  435. if( xRemaining < 4 )
  436. {
  437. break;
  438. }
  439. {
  440. pxClient->ulSkipCount =
  441. ( ( ( uint32_t ) pcReadBuffer[ 0 ] ) << 24 ) |
  442. ( ( ( uint32_t ) pcReadBuffer[ 1 ] ) << 16 ) |
  443. ( ( ( uint32_t ) pcReadBuffer[ 2 ] ) << 8 ) |
  444. ( ( ( uint32_t ) pcReadBuffer[ 3 ] ) << 0 );
  445. FreeRTOS_printf( ( "TCP skipcount %lu xRecvResult %ld\n", pxClient->ulSkipCount, xRemaining ) );
  446. pcReadBuffer += 4;
  447. xRemaining -= 4;
  448. pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
  449. }
  450. if( xRemaining == 0 )
  451. {
  452. break;
  453. }
  454. /* fall through */
  455. case eTCP_5_WaitHeader2:
  456. {
  457. if( pxClient->ulSkipCount > ( uint32_t ) xRemaining )
  458. {
  459. pxClient->ulSkipCount -= xRemaining;
  460. }
  461. else
  462. {
  463. char pcResponse[ 200 ];
  464. uint32_t ulLength, ulStore, ulCount = 0;
  465. if( pxDataClient != NULL )
  466. {
  467. ulCount = pxDataClient->ulRecvCount;
  468. }
  469. ulLength = snprintf( pcResponse + 4, sizeof( pcResponse ) - 4,
  470. "{"
  471. "\"cpu_util_total\":0,"
  472. "\"cpu_util_user\":0,"
  473. "\"cpu_util_system\":0,"
  474. "\"sender_has_retransmits\":-1,"
  475. "\"streams\":["
  476. "{"
  477. "\"id\":1,"
  478. "\"bytes\":%lu,"
  479. "\"retransmits\":-1,"
  480. "\"jitter\":0,"
  481. "\"errors\":0,"
  482. "\"packets\":0"
  483. "}"
  484. "]"
  485. "}\xe",
  486. ulCount );
  487. ulStore = FreeRTOS_htonl( ulLength - 1 );
  488. memcpy( pcResponse, &( ulStore ), sizeof ( ulStore ) );
  489. FreeRTOS_send( pxClient->xServerSocket, (const void *)pcResponse, ulLength + 4, 0 );
  490. pxClient->ulSkipCount = 0;
  491. pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
  492. }
  493. }
  494. break;
  495. case eTCP_6_WaitDone:
  496. break;
  497. case eTCP_7_WaitTransfer:
  498. break;
  499. }
  500. }
  501. #endif /* ipconfigIPERF_VERSION == 3 */
  502. static void vIPerfTCPWork( TcpClient_t *pxClient )
  503. {
  504. BaseType_t xRecvResult;
  505. //#warning take away
  506. //BaseType_t xLogged = pdFALSE;
  507. if( pxClient->xServerSocket == NULL )
  508. {
  509. vIPerfTCPClose( pxClient );
  510. return;
  511. }
  512. #if( ipconfigIPERF_VERSION == 3 )
  513. /* Is this a data client with the -R reverse option ? */
  514. if( ( pxClient->bits.bIsControl == pdFALSE_UNSIGNED ) && ( pxClient->bits.bReverse != pdFALSE_UNSIGNED ) )
  515. {
  516. if( ( pxClient->bits.bTimed == pdFALSE_UNSIGNED ) && ( pxClient->bits.bHasShutdown == pdFALSE_UNSIGNED ) && ( pxClient->ulAmount == (uint32_t)0u ) )
  517. {
  518. FreeRTOS_printf( ( "Shutdown connection\n" ) );
  519. FreeRTOS_shutdown( pxClient->xServerSocket, FREERTOS_SHUT_RDWR );
  520. pxClient->bits.bHasShutdown = pdTRUE_UNSIGNED;
  521. }
  522. }
  523. #endif
  524. for( ;; )
  525. {
  526. #if( ipconfigIPERF_USE_ZERO_COPY != 0 )
  527. {
  528. const BaseType_t xRecvSize = 0x10000;
  529. xRecvResult = FreeRTOS_recv( pxClient->xServerSocket, /* The socket being received from. */
  530. &pcRecvBuffer, /* The buffer into which the received data will be written. */
  531. xRecvSize, /* Any size is OK here. */
  532. FREERTOS_ZERO_COPY );
  533. }
  534. #else
  535. {
  536. const BaseType_t xRecvSize = sizeof pcRecvBuffer;
  537. xRecvResult = FreeRTOS_recv( pxClient->xServerSocket, /* The socket being received from. */
  538. pcRecvBuffer, /* The buffer into which the received data will be written. */
  539. sizeof pcRecvBuffer, /* The size of the buffer provided to receive the data. */
  540. 0 );
  541. }
  542. #endif
  543. if( xRecvResult <= 0 )
  544. {
  545. break;
  546. }
  547. pxClient->ulRecvCount += xRecvResult;
  548. #if( ipconfigIPERF_VERSION == 3 )
  549. if( pxClient->eTCP_Status < eTCP_6_WaitDone )
  550. {
  551. handleRecvPacket(pxClient, pcRecvBuffer, xRecvResult);
  552. }
  553. #endif /* ipconfigIPERF_VERSION == 3 */
  554. #if( ipconfigIPERF_USE_ZERO_COPY != 0 )
  555. {
  556. FreeRTOS_recv( pxClient->xServerSocket, /* The socket being received from. */
  557. NULL, /* The buffer into which the received data will be written. */
  558. xRecvResult, /* This is important now. */
  559. 0 );
  560. }
  561. #endif
  562. } /* for( ;; ) */
  563. if( ( xRecvResult == 0 ) && ( pxClient->bits.bIsControl == pdFALSE_UNSIGNED ) && ( pxClient->bits.bReverse != pdFALSE_UNSIGNED ) )
  564. {
  565. xRecvResult = vIPerfTCPSend( pxClient );
  566. }
  567. if( ( xRecvResult < 0 ) && ( xRecvResult != -pdFREERTOS_ERRNO_EAGAIN ) )
  568. {
  569. vIPerfTCPClose( pxClient );
  570. }
  571. }
  572. #if( ipconfigUSE_CALLBACKS == 0 ) && ( ipconfigIPERF_HAS_UDP != 0 )
  573. static void vIPerfUDPWork( Socket_t xSocket )
  574. {
  575. BaseType_t xRecvResult;
  576. struct freertos_sockaddr xAddress;
  577. uint32_t xAddressLength;
  578. #if( ipconfigIPERF_USE_ZERO_COPY != 0 )
  579. {
  580. xRecvResult = FreeRTOS_recvfrom( xSocket, ( void * ) &pcRecvBuffer, sizeof( pcRecvBuffer ),
  581. FREERTOS_ZERO_COPY, &xAddress, &xAddressLength );
  582. }
  583. #else
  584. {
  585. xRecvResult = FreeRTOS_recvfrom( xSocket, ( void * ) pcRecvBuffer, sizeof( pcRecvBuffer ),
  586. 0, &xAddress, &xAddressLength );
  587. }
  588. #endif /* ipconfigIPERF_USE_ZERO_COPY */
  589. if( xRecvResult > 0 )
  590. {
  591. ulUDPRecvCount += xRecvResult;
  592. #if( ipconfigIPERF_DOES_ECHO_UDP != 0 )
  593. {
  594. FreeRTOS_sendto( xSocket, (const void *)pcRecvBuffer, xRecvResult, 0, &xAddress, sizeof( xAddress ) );
  595. }
  596. #endif /* ipconfigIPERF_DOES_ECHO_UDP */
  597. #if( ipconfigIPERF_USE_ZERO_COPY != 0 )
  598. {
  599. FreeRTOS_ReleaseUDPPayloadBuffer( pcRecvBuffer );
  600. }
  601. #endif /* ipconfigIPERF_USE_ZERO_COPY */
  602. }
  603. }
  604. #endif /* ipconfigUSE_CALLBACKS == 0 */
  605. #if( ipconfigUSE_CALLBACKS != 0 ) && ( ipconfigIPERF_HAS_UDP != 0 )
  606. static BaseType_t xOnUdpReceive( Socket_t xSocket, void * pvData, size_t xLength,
  607. const struct freertos_sockaddr *pxFrom, const struct freertos_sockaddr *pxDest )
  608. {
  609. ( void ) pvData;
  610. ( void ) pxFrom;
  611. ulUDPRecvCount += xLength;
  612. #if( ipconfigIPERF_DOES_ECHO_UDP != 0 )
  613. {
  614. FreeRTOS_sendto( xSocket, (const void *)pcRecvBuffer, xLength, 0, pxFrom, sizeof( *pxFrom ) );
  615. }
  616. #else /* ipconfigIPERF_DOES_ECHO_UDP */
  617. {
  618. ( void ) xSocket;
  619. }
  620. #endif
  621. /* Tell the driver not to store the RX data */
  622. return 1;
  623. }
  624. #endif /* ipconfigUSE_CALLBACKS != 0 */
  625. #if( ipconfigIPERF_HAS_TCP != 0 )
  626. static Socket_t xCreateTCPServerSocket()
  627. {
  628. BaseType_t xBindResult, xListenResult;
  629. struct freertos_sockaddr xEchoServerAddress;
  630. Socket_t xTCPServerSocket;
  631. TickType_t xNoTimeOut = 0;
  632. xTCPServerSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
  633. configASSERT( ( xTCPServerSocket != FREERTOS_INVALID_SOCKET ) && ( xTCPServerSocket != NULL ) );
  634. memset( &xEchoServerAddress, '\0', sizeof xEchoServerAddress );
  635. xEchoServerAddress.sin_port = FreeRTOS_htons( ipconfigIPERF_TCP_ECHO_PORT );
  636. /* Set the receive time out to portMAX_DELAY.
  637. Note that any TCP child connections will inherit this reception time-out. */
  638. FreeRTOS_setsockopt( xTCPServerSocket, 0, FREERTOS_SO_RCVTIMEO, &xNoTimeOut, sizeof( xNoTimeOut ) );
  639. {
  640. WinProperties_t xWinProperties;
  641. memset(&xWinProperties, '\0', sizeof xWinProperties);
  642. xWinProperties.lTxBufSize = ipconfigIPERF_TX_BUFSIZE; /* Units of bytes. */
  643. xWinProperties.lTxWinSize = ipconfigIPERF_TX_WINSIZE; /* Size in units of MSS */
  644. xWinProperties.lRxBufSize = ipconfigIPERF_RX_BUFSIZE; /* Units of bytes. */
  645. xWinProperties.lRxWinSize = ipconfigIPERF_RX_WINSIZE; /* Size in units of MSS */
  646. FreeRTOS_setsockopt( xTCPServerSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProperties, sizeof( xWinProperties ) );
  647. }
  648. xBindResult = FreeRTOS_bind( xTCPServerSocket, &xEchoServerAddress, sizeof xEchoServerAddress );
  649. xListenResult = FreeRTOS_listen( xTCPServerSocket, 4 );
  650. FreeRTOS_FD_SET( xTCPServerSocket, xSocketSet, eSELECT_READ );
  651. FreeRTOS_printf( ( "vIPerfTask: created TCP server socket %p bind port %u: %ld listen %ld\n",
  652. xTCPServerSocket, ipconfigIPERF_TCP_ECHO_PORT, xBindResult, xListenResult ) );
  653. xBindResult = xBindResult;
  654. xListenResult = xListenResult;
  655. return xTCPServerSocket;
  656. }
  657. #endif /* ipconfigIPERF_HAS_TCP */
  658. #if( ipconfigIPERF_HAS_UDP != 0 )
  659. static Socket_t xCreateUDPServerSocket()
  660. {
  661. BaseType_t xBindResult;
  662. struct freertos_sockaddr xEchoServerAddress;
  663. TickType_t xNoTimeOut = 0;
  664. Socket_t xUDPServerSocket;
  665. xUDPServerSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
  666. configASSERT( ( xUDPServerSocket != FREERTOS_INVALID_SOCKET ) && ( xUDPServerSocket != NULL ) );
  667. xEchoServerAddress.sin_port = FreeRTOS_htons( ipconfigIPERF_UDP_ECHO_PORT );
  668. FreeRTOS_setsockopt( xUDPServerSocket, 0, FREERTOS_SO_RCVTIMEO, &xNoTimeOut, sizeof( xNoTimeOut ) );
  669. xBindResult = FreeRTOS_bind( xUDPServerSocket, &xEchoServerAddress, sizeof xEchoServerAddress );
  670. FreeRTOS_printf( ( "vIPerfTask: created UDP server socket %p bind port %u: %ld\n",
  671. xUDPServerSocket, ipconfigIPERF_UDP_ECHO_PORT, xBindResult ) );
  672. xBindResult = xBindResult;
  673. #if( ipconfigUSE_CALLBACKS == 0 )
  674. {
  675. FreeRTOS_FD_SET( xUDPServerSocket, xSocketSet, eSELECT_READ );
  676. }
  677. #else
  678. {
  679. F_TCP_UDP_Handler_t xHandler;
  680. memset( &xHandler, '\0', sizeof ( xHandler ) );
  681. xHandler.pOnUdpReceive = xOnUdpReceive;
  682. FreeRTOS_setsockopt( xUDPServerSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) );
  683. }
  684. #endif /* ipconfigUSE_CALLBACKS */
  685. return xUDPServerSocket;
  686. }
  687. #endif /* ipconfigIPERF_HAS_UDP */
  688. void vIPerfTask( void *pvParameter )
  689. {
  690. #if( ipconfigIPERF_HAS_TCP != 0 )
  691. Socket_t xTCPServerSocket;
  692. #endif /* ipconfigIPERF_HAS_TCP */
  693. #if( ipconfigIPERF_HAS_UDP != 0 )
  694. Socket_t xUDPServerSocket;
  695. #endif /* ipconfigIPERF_HAS_UDP */
  696. ( void ) pvParameter;
  697. xSocketSet = FreeRTOS_CreateSocketSet( );
  698. vListInitialise( &xTCPClientList );
  699. #if( ipconfigIPERF_HAS_TCP != 0 )
  700. {
  701. xTCPServerSocket = xCreateTCPServerSocket();
  702. }
  703. #endif /* ipconfigIPERF_HAS_TCP */
  704. #if( ipconfigIPERF_HAS_UDP != 0 )
  705. {
  706. xUDPServerSocket = xCreateUDPServerSocket();
  707. (void)xUDPServerSocket;
  708. }
  709. #endif /* ipconfigIPERF_HAS_UDP */
  710. FreeRTOS_printf( ( "Use for example:\n" ) );
  711. FreeRTOS_printf( ( "iperf3 -c %lxip --port %u --bytes 100M [ -R ]\n",
  712. FreeRTOS_htonl( FreeRTOS_GetIPAddress() ), ipconfigIPERF_UDP_ECHO_PORT ) );
  713. #define HUNDREDTH_MB ( ( 1024 * 1024 ) / 100 )
  714. for( ;; )
  715. {
  716. BaseType_t xResult;
  717. const TickType_t xBlockingTime = pdMS_TO_TICKS( ipconfigIPERF_LOOP_BLOCKING_TIME_MS );
  718. /* Wait at most 5 seconds. */
  719. xResult = FreeRTOS_select( xSocketSet, xBlockingTime );
  720. #if( ipconfigIPERF_HAS_TCP != 0 )
  721. if( xResult != 0 )
  722. {
  723. const MiniListItem_t* pxEnd;
  724. const ListItem_t *pxIterator;
  725. pxEnd = ( const MiniListItem_t* ) listGET_END_MARKER( &xTCPClientList );
  726. vIPerfServerWork( xTCPServerSocket );
  727. /* Check all TCP clients: */
  728. for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
  729. pxIterator != ( const ListItem_t * ) pxEnd;
  730. )
  731. {
  732. TcpClient_t *pxClient;
  733. pxClient = ( TcpClient_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
  734. /* Let the iterator point to the next element before the current element
  735. removes itself from the list. */
  736. pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator );
  737. vIPerfTCPWork( pxClient );
  738. }
  739. }
  740. #endif /* ipconfigIPERF_HAS_TCP */
  741. #if( ipconfigIPERF_HAS_UDP != 0 )
  742. #if( ipconfigUSE_CALLBACKS == 0 )
  743. if( xResult != 0 )
  744. {
  745. vIPerfUDPWork( xUDPServerSocket );
  746. }
  747. else
  748. #endif /* ipconfigUSE_CALLBACKS */
  749. {
  750. if( ulUDPRecvCountSeen != ulUDPRecvCount )
  751. {
  752. /* The amount is still changing, do not show it yet. */
  753. ulUDPRecvCountSeen = ulUDPRecvCount;
  754. }
  755. else if( ulUDPRecvCountShown != ulUDPRecvCount )
  756. {
  757. uint32_t ulNewBytes = ulUDPRecvCount - ulUDPRecvCountShown;
  758. uint32_t ulMB = (ulNewBytes + HUNDREDTH_MB/2) / HUNDREDTH_MB;
  759. FreeRTOS_printf( ( "UDP received %lu + %lu (%lu.%02lu MB) = %lu\n",
  760. ulUDPRecvCountShown,
  761. ulNewBytes,
  762. ulMB / 100,
  763. ulMB % 100,
  764. ulUDPRecvCount ) );
  765. ulUDPRecvCountShown = ulUDPRecvCount;
  766. ulMB = ulMB;
  767. }
  768. }
  769. #endif /* ipconfigIPERF_HAS_UDP */
  770. }
  771. }
  772. //?¡è¡§|¡§¡ã?¨¢¡§a?¡ìWiFi??¡ì?|¨¬2a¡§o?
  773. #define IPERF_BUFSZ (4 * 1024)
  774. typedef unsigned int u32_t;
  775. static TaskHandle_t iperf_task_handle = NULL;
  776. static int flag_start_iperf = 0;
  777. static char gaddr[4] = {0};
  778. static int gport = 0;
  779. static u32_t sys_now(void)
  780. {
  781. return xTaskGetTickCount() * portTICK_PERIOD_MS;
  782. }
  783. static void iperf_client(const char * ipaddr, int port)
  784. {
  785. Socket_t sock;
  786. int i;
  787. //struct sockaddr_in client_addr;
  788. struct freertos_sockaddr client_addr;
  789. uint8_t* send_buf;
  790. u32_t tick1, tick2;
  791. uint64_t sentlen;
  792. (void)ipaddr;
  793. (void)port;
  794. send_buf = (uint8_t *) pvPortMalloc(IPERF_BUFSZ);
  795. if (!send_buf)
  796. return ;
  797. for(i = 0; i < IPERF_BUFSZ; i ++)
  798. send_buf[i] = i & 0xff;
  799. while(flag_start_iperf) {
  800. sock = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
  801. if (sock == FREERTOS_INVALID_SOCKET) {
  802. printf("Socket error\r\n");
  803. vTaskDelay(pdMS_TO_TICKS(100));
  804. continue;
  805. }
  806. client_addr.sin_port = FreeRTOS_htons( gport );
  807. client_addr.sin_addr = FreeRTOS_inet_addr_quick( gaddr[0],
  808. gaddr[1],
  809. gaddr[2],
  810. gaddr[3] );
  811. //memset(&(client_addr.sin_zero), 0, sizeof(client_addr.sin_zero));
  812. if (FreeRTOS_connect(sock, &client_addr, sizeof( struct freertos_sockaddr )) != 0) {
  813. printf("Connect failed!\r\n");
  814. FreeRTOS_closesocket(sock);
  815. vTaskDelay(10);
  816. continue;
  817. }
  818. printf("Connect to iperf server successful!\r\n");
  819. tick1 = sys_now();
  820. while (flag_start_iperf) {
  821. tick2 = sys_now();
  822. if(tick2 - tick1 >= configTICK_RATE_HZ * 5) {
  823. float f;
  824. f = (float)(sentlen * configTICK_RATE_HZ/125/(tick2 - tick1));
  825. f /= 1000.0f;
  826. printf("\r\nsend speed = %.4f Mbps!\r\n", f);
  827. tick1 = tick2;
  828. sentlen = 0;
  829. }
  830. if(FreeRTOS_send(sock, send_buf, IPERF_BUFSZ, 0) < 0) {
  831. printf("FreeRTOS_send failed\r\n");
  832. break;
  833. } else {
  834. sentlen += IPERF_BUFSZ;
  835. }
  836. }
  837. FreeRTOS_closesocket(sock);
  838. }
  839. if (send_buf) {
  840. vPortFree(send_buf);
  841. }
  842. }
  843. static void iperf_task_proc(void* arg)
  844. {
  845. iperf_client(NULL, 0);
  846. vTaskDelete(NULL);
  847. }
  848. void start_iperf_client(const char* ip, int port)
  849. {
  850. if (flag_start_iperf) {
  851. printf("iperf client has been started");
  852. return;
  853. }
  854. if (iperf_task_handle == NULL) {
  855. sscanf(ip, "%d.%d.%d.%d", (int*)&gaddr[0], (int*)&gaddr[1], (int*)&gaddr[2], (int*)&gaddr[3]);
  856. gport = port;
  857. flag_start_iperf = 1;
  858. xTaskCreate(iperf_task_proc, "iperf task task", 512, NULL, configMAX_PRIORITIES / 3, &iperf_task_handle);
  859. }
  860. }