MAX_CARLINK_A270S/MXC_A27-PCB4.5-270S/FreeRTOS-Plus/FreeRTOS-Plus-TCP/iperf_task.c

984 lines
29 KiB
C
Raw Permalink Blame History

/*
A FreeRTOS+TCP demo program:
A simple example of a TCP/UDP iperf server, see https://iperf.fr
It uses a single task which will store some client information in a:
List_t xTCPClientList;
The task will sleep constantly by calling:
xResult = FreeRTOS_select( xSocketSet, xBlockingTime );
Command examples for testing:
iperf3 -c 192.168.2.114 --port 5001 --bytes 100M
iperf3 -c 192.168.2.114 --port 5001 --bytes 100M -R
iperf3 -c fe80::8d11:cd9b:8b66:4a80 --port 5001 --bytes 1M
iperf3 -c fe80::8d11:cd9b:8b66:4a81 --port 5001 --bytes 1M
iperf3 -c fe80::6802:9887:8670:b37c --port 5001 --bytes 1M
ping fe80::8d11:cd9b:8b66:4a80
ping fe80::8d11:cd9b:8b66:4a81
iperf3 -s --port 5001
iperf3 -c zynq --port 5001 --bytes 1024
iperf3 -c laptop --port 5001 --bytes 1024
fe80::8d11:cd9b:8b66:4a80
TCP : iperf3 -c 192.168.2.116 --port 5001 --bytes 1024
UDP : iperf3 -c 192.168.2.116 --port 5001 --udp --bandwidth 50M --mss 1460 --bytes 1024
*/
/* Standard includes. */
#include <stdio.h>
#include <time.h>
/* FreeRTOS includes. */
#include <FreeRTOS.h>
#include "task.h"
#include "timers.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_TCP_IP.h"
#include "iperf_task.h"
/* Put the TCP server at this port number: */
#ifndef ipconfigIPERF_TCP_ECHO_PORT
/* 5001 seems to be the standard TCP server port number. */
#define ipconfigIPERF_TCP_ECHO_PORT 5001
#endif
/* Put the TCP server at this port number: */
#ifndef ipconfigIPERF_UDP_ECHO_PORT
/* 5001 seems to be the standard UDP server port number. */
#define ipconfigIPERF_UDP_ECHO_PORT 5001
#endif
#ifndef ipconfigIPERF_STACK_SIZE_IPERF_TASK
/* Stack size needed for vIPerfTask(), a bit of a guess: */
#define ipconfigIPERF_STACK_SIZE_IPERF_TASK 340
#endif
#ifndef ipconfigIPERF_PRIORITY_IPERF_TASK
/* The priority of vIPerfTask(). Should be lower than the IP-task
and the task running in NetworkInterface.c. */
#define ipconfigIPERF_PRIORITY_IPERF_TASK 3
#endif
#ifndef ipconfigIPERF_RECV_BUFFER_SIZE
/* Only used when ipconfigIPERF_USE_ZERO_COPY = 0.
Buffer size when reading from the sockets. */
#define ipconfigIPERF_RECV_BUFFER_SIZE ( 4 * ipconfigTCP_MSS )
#endif
#ifndef ipconfigIPERF_LOOP_BLOCKING_TIME_MS
/* Let the mainloop wake-up so now and then. */
#define ipconfigIPERF_LOOP_BLOCKING_TIME_MS 5000UL
#endif
#ifndef ipconfigIPERF_HAS_TCP
/* A TCP server socket will be created. */
#define ipconfigIPERF_HAS_TCP 1
#endif
#ifndef ipconfigIPERF_HAS_UDP
/* A UDP server socket will be created. */
#define ipconfigIPERF_HAS_UDP 1
#endif
#ifndef ipconfigIPERF_DOES_ECHO_UDP
/* By default, this server will echo UDP data as required by iperf. */
#define ipconfigIPERF_DOES_ECHO_UDP 1
#endif
#ifndef ipconfigIPERF_USE_ZERO_COPY
#define ipconfigIPERF_USE_ZERO_COPY 1
#endif
#ifndef ipconfigIPERF_TX_BUFSIZE
#define ipconfigIPERF_TX_BUFSIZE ( 65 * 1024 ) /* Units of bytes. */
#define ipconfigIPERF_TX_WINSIZE ( 4 ) /* Size in units of MSS */
#define ipconfigIPERF_RX_BUFSIZE ( ( 65 * 1024 ) - 1 ) /* Units of bytes. */
#define ipconfigIPERF_RX_WINSIZE ( 8 ) /* Size in units of MSS */
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (BaseType_t)(sizeof(x)/sizeof(x)[0])
#endif
void vIPerfTask( void *pvParameter );
/* As for now, still defined in 'FreeRTOS-Plus-TCP\FreeRTOS_TCP_WIN.c' : */
extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere );
static portINLINE void vListInsertFifo( List_t * const pxList, ListItem_t * const pxNewListItem )
{
vListInsertGeneric( pxList, pxNewListItem, &pxList->xListEnd );
}
#if( ipconfigIPERF_VERSION == 3 )
typedef enum
{
eTCP_0_WaitName, /* Expect a text like "osboxes.1460335312.612572.527642c36f" */
eTCP_1_WaitCount,
eTCP_2_WaitHeader,
eTCP_3_WaitOneTwo,
eTCP_4_WaitCount2,
eTCP_5_WaitHeader2,
eTCP_6_WaitDone,
eTCP_7_WaitTransfer
} eTCP_Server_Status_t;
#endif
typedef struct
{
Socket_t xServerSocket;
#if( ipconfigIPERF_VERSION == 3 )
struct {
uint32_t
bIsControl : 1,
bReverse : 1,
bTimed : 1, /* Reverse role, limited time. */
bTimedOut : 1, /* TIme is up. */
bHasShutdown : 1;
} bits;
eTCP_Server_Status_t eTCP_Status;
uint32_t ulSkipCount, ulAmount;
uint32_t xRemainingTime;
TimeOut_t xTimeOut;
#endif /* ipconfigIPERF_VERSION == 3 */
#if( ipconfigUSE_IPv6 != 0 )
struct freertos_sockaddr6 xRemoteAddr;
#else
struct freertos_sockaddr xRemoteAddr;
#endif
uint32_t ulRecvCount;
struct xLIST_ITEM xListItem; /* With this item the client will be bound to a List_t. */
} TcpClient_t;
#if( ipconfigIPERF_USE_ZERO_COPY != 0 )
struct xRawBuffer {
char pcBuffer[ ipconfigIPERF_RECV_BUFFER_SIZE ];
} *pxRawBuffer;
#define pcSendBuffer ( pxRawBuffer->pcBuffer )
static char *pcRecvBuffer;
#else
struct xRawBuffer {
char pcBuffer[ ipconfigIPERF_RECV_BUFFER_SIZE ];
} *pxRawBuffer;
#define pcRecvBuffer ( pxRawBuffer->pcBuffer )
#define pcSendBuffer ( pxRawBuffer->pcBuffer )
#endif
#if( ipconfigIPERF_VERSION == 3 )
char pcExpectedClient[ 80 ];
TcpClient_t *pxControlClient, *pxDataClient;
/*{"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}]} */
#endif
static List_t xTCPClientList;
#if( ipconfigIPERF_HAS_UDP != 0 )
static uint32_t ulUDPRecvCount = 0, ulUDPRecvCountShown = 0, ulUDPRecvCountSeen = 0;
#endif
static SocketSet_t xSocketSet;
static TaskHandle_t pxIperfTask;
void vIPerfInstall( void )
{
if( pxRawBuffer == NULL )
{
pxRawBuffer = ( struct xRawBuffer * ) pvPortMalloc( sizeof *pxRawBuffer );
if( pxRawBuffer == NULL )
{
FreeRTOS_printf( ( "vIPerfInstall: malloc %u bytes failed.\n", (unsigned)sizeof *pxRawBuffer ) ) ;
return;
}
}
if( pxIperfTask == NULL )
{printf("start iperf\r\n");
/* Call this function once to start the test with FreeRTOS_accept(). */
xTaskCreate( vIPerfTask, "IPerf", ipconfigIPERF_STACK_SIZE_IPERF_TASK, NULL, ipconfigIPERF_PRIORITY_IPERF_TASK, &pxIperfTask );
}
}
static void vIPerfServerWork( Socket_t xSocket )
{
struct freertos_sockaddr xAddress;
socklen_t xSocketLength;
Socket_t xNexSocket;
xNexSocket = FreeRTOS_accept( xSocket, &xAddress, &xSocketLength);
if( ( xNexSocket != NULL ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) )
{
char pucBuffer[ 16 ];
TcpClient_t *pxClient;
pxClient = ( TcpClient_t * )pvPortMalloc( sizeof *pxClient );
memset( pxClient, '\0', sizeof *pxClient );
pxClient->xServerSocket = xNexSocket;
listSET_LIST_ITEM_OWNER( &( pxClient->xListItem ), ( void* ) pxClient );
#if( ipconfigUSE_IPv6 != 0 )
FreeRTOS_GetRemoteAddress( xNexSocket, ( struct freertos_sockaddr6 * ) &pxClient->xRemoteAddr );
#else
FreeRTOS_GetRemoteAddress( xNexSocket, ( struct freertos_sockaddr * ) &pxClient->xRemoteAddr );
FreeRTOS_inet_ntoa( pxClient->xRemoteAddr.sin_addr, pucBuffer );
FreeRTOS_printf( ( "vIPerfTask: Received a connection from %s:%u\n",
pucBuffer,
FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ) ) );
#endif
FreeRTOS_FD_SET( xNexSocket, xSocketSet, eSELECT_READ );
vListInsertFifo( &xTCPClientList, &( pxClient->xListItem ) );
}
}
static void vIPerfTCPClose( TcpClient_t *pxClient )
{
if( pxControlClient == pxClient )
{
pxControlClient = NULL;
}
if( pxDataClient == pxClient )
{
pxDataClient = NULL;
}
/* Remove server socket from the socket set. */
if( pxClient->xServerSocket != NULL )
{
char pucBuffer[ 16 ];
#if( ipconfigUSE_IPv6 == 0 )
FreeRTOS_inet_ntoa( pxClient->xRemoteAddr.sin_addr, pucBuffer );
FreeRTOS_printf( ( "vIPerfTCPClose: Closing server socket %s:%u after %lu bytes\n",
pucBuffer,
FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ),
pxClient->ulRecvCount ) );
#endif
FreeRTOS_FD_CLR( pxClient->xServerSocket, xSocketSet, eSELECT_ALL );
FreeRTOS_closesocket( pxClient->xServerSocket );
pxClient->xServerSocket = NULL;
}
/* Remove client socket from the socket set. */
{
if( pxClient->xServerSocket == NULL )
{
/* Remove this socket from the list. */
uxListRemove( &( pxClient->xListItem ) );
vPortFree( ( void * ) pxClient );
}
}
}
static int vIPerfTCPSend( TcpClient_t *pxClient )
{
BaseType_t xResult = 0;
do
{
size_t uxMaxSpace = (size_t) FreeRTOS_tx_space( pxClient->xServerSocket );
size_t uxSize = (size_t)FreeRTOS_min_uint32( uxMaxSpace, ( int32_t )sizeof( pcSendBuffer ) );
if( pxClient->bits.bTimed != pdFALSE_UNSIGNED )
{
if( xTaskCheckForTimeOut( &( pxClient->xTimeOut ), &( pxClient->xRemainingTime ) ) != pdFALSE )
{
/* Time is up. */
if( pxClient->bits.bTimedOut == pdFALSE_UNSIGNED )
{
FreeRTOS_shutdown( pxClient->xServerSocket, FREERTOS_SHUT_RDWR );
pxClient->bits.bTimedOut = pdTRUE_UNSIGNED;
}
break;
}
}
uxSize = FreeRTOS_min_uint32( uxSize, pxClient->ulAmount );
if( uxSize <= 0 )
{
break;
}
xResult = FreeRTOS_send( pxClient->xServerSocket, (const void *)pcSendBuffer, uxSize, 0 );
if( xResult < 0 )
{
break;
}
if( pxClient->bits.bTimed == pdFALSE_UNSIGNED )
{
pxClient->ulAmount -= uxSize;
if( pxClient->ulAmount == 0ul )
{
/* All data have been sent. No longer interested in eSELECT_WRITE events. */
FreeRTOS_FD_CLR( pxClient->xServerSocket, xSocketSet, eSELECT_WRITE );
}
}
if( uxSize > 0 )
{
xResult += uxSize;
}
}
while( 0 );
return xResult;
}
#if( ipconfigIPERF_VERSION == 3 )
static void handleRecvPacket( TcpClient_t *pxClient, char *pcReadBuffer, BaseType_t xRecvResult )
{
BaseType_t xRemaining = xRecvResult;
if( pxClient->eTCP_Status < eTCP_7_WaitTransfer )
{
FreeRTOS_printf( ( "TCP[ port %d ] recv[ %d ] %d\n", FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ), ( int ) pxClient->eTCP_Status, ( int )xRecvResult ) );
}
/*
2016-04-11 09:26:55.533 192.168.2.106 16.926.349 [] TCP recv[ 1 ] 4
2016-04-11 09:26:55.539 192.168.2.106 16.926.365 [] TCP skipcount 83 xRecvResult 4
2016-04-11 09:26:55.546 192.168.2.106 16.926.402 [] TCP recv[ 2 ] 4
2016-04-11 09:26:55.552 192.168.2.106 16.927.015 [] ipTCP_FLAG_PSH received
2016-04-11 09:26:55.560 192.168.2.106 16.927.085 [] TCP recv[ 2 ] 83
*/
switch( pxClient->eTCP_Status )
{
case eTCP_0_WaitName:
{
int rc;
if( pcExpectedClient[ 0 ] != '\0' )
{
/* Get a string like 'LAPTOP.1463928623.162445.0fbe105c6eb',
where 'LAPTOP' is the hostname. */
rc = strncmp( pcExpectedClient, pcReadBuffer, sizeof( pcExpectedClient ) );
}
else
{
rc = -1;
}
{
unsigned char tab[ 1 ] = { '\t' };
FreeRTOS_send( pxClient->xServerSocket, (const void *)tab, 1, 0 );
}
if( rc != 0 )
{
FreeRTOS_printf( ( "Got Control Socket: rc %d: exp: '%s' got: '%s'\n", rc, pcExpectedClient, pcReadBuffer ) );
strncpy( pcExpectedClient, pcReadBuffer, sizeof( pcExpectedClient ) );
pxControlClient = pxClient;
pxClient->bits.bIsControl = pdTRUE_UNSIGNED;
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
else
{
FreeRTOS_printf( ( "Got expected client: rc %d: '%s'\n", rc, pcExpectedClient ) );
pcExpectedClient[ 0 ] = '\0';
pxDataClient = pxClient;
if( pxControlClient != NULL )
{
/* Transfer all properties to the data client. */
memcpy( &( pxDataClient->bits ), &( pxControlClient->bits ), sizeof( pxDataClient->bits ) );
pxDataClient->ulAmount = pxControlClient->ulAmount;
pxDataClient->xRemainingTime = pxControlClient->xRemainingTime;
vTaskSetTimeOutState( &( pxDataClient->xTimeOut ) );
if( pxDataClient->bits.bReverse != pdFALSE_UNSIGNED )
{
/* As this socket will only write data, set the WRITE select flag. */
FreeRTOS_FD_SET( pxClient->xServerSocket, xSocketSet, eSELECT_WRITE );
}
pxControlClient->bits.bIsControl = pdTRUE_UNSIGNED;
pxDataClient->bits.bIsControl = pdFALSE_UNSIGNED;
}
pxDataClient->eTCP_Status = eTCP_7_WaitTransfer;
}
}
break;
case eTCP_1_WaitCount:
if( xRemaining < 4 )
{
break;
}
{
pxClient->ulSkipCount =
( ( ( uint32_t ) pcReadBuffer[ 0 ] ) << 24 ) |
( ( ( uint32_t ) pcReadBuffer[ 1 ] ) << 16 ) |
( ( ( uint32_t ) pcReadBuffer[ 2 ] ) << 8 ) |
( ( ( uint32_t ) pcReadBuffer[ 3 ] ) << 0 );
/* Receive a number: an amount of bytes to be skipped. */
FreeRTOS_printf( ( "TCP skipcount %u xRecvResult %d\n", ( unsigned )pxClient->ulSkipCount, ( int )xRemaining ) );
pcReadBuffer += 4;
xRemaining -= 4;
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
if( xRemaining == 0 )
{
break;
}
/* fall through */
case eTCP_2_WaitHeader:
{
if (xRemaining > 0) {
char *pcPtr;
pcReadBuffer[ xRemaining ] = '\0';
FreeRTOS_printf( ( "Control string: %s\n", pcReadBuffer ) );
for( pcPtr = pcReadBuffer; *pcPtr; pcPtr++ )
{
if( strncmp( pcPtr, "\"reverse\"", 9 ) == 0 )
{
pxClient->bits.bReverse = pcPtr[ 10 ] == 't';
}
else if( strncmp( pcPtr, "\"num\"", 5 ) == 0 )
{
uint32_t ulAmount;
if( sscanf( pcPtr + 6, "%lu", &( ulAmount ) ) > 0 )
{
pxClient->ulAmount = ulAmount;
}
}
else if( strncmp( pcPtr, "\"time\"", 6 ) == 0 )
{
uint32_t ulSeconds;
if( sscanf( pcPtr + 7, "%lu", &( ulSeconds ) ) > 0 )
{
pxClient->xRemainingTime = ulSeconds * 1000ul;
pxClient->bits.bTimed = pdTRUE_UNSIGNED;
}
}
}
if( pxClient->bits.bReverse != pdFALSE_UNSIGNED )
{
FreeRTOS_printf( ( "Reverse %d send %lu bytes timed %d: %lu\n",
pxClient->bits.bReverse, pxClient->ulAmount,
pxClient->bits.bTimed,
pxClient->xRemainingTime ) );
}
}
if( pxClient->ulSkipCount > ( uint32_t ) xRemaining )
{
pxClient->ulSkipCount -= ( uint32_t ) xRemaining;
}
else
{
unsigned char newline[ 1 ] = { '\n' };
unsigned char onetwo[ 2 ] = { '\1', '\2' };
FreeRTOS_send( pxClient->xServerSocket, (const void *)newline, sizeof( newline ), 0 );
FreeRTOS_send( pxClient->xServerSocket, (const void *)onetwo, sizeof( onetwo ), 0 );
pxClient->ulSkipCount = 0;
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
}
break;
case eTCP_3_WaitOneTwo:
{
unsigned char ch = pcReadBuffer[ 0 ];
unsigned char cr[ 1 ] = { '\r' };
FreeRTOS_printf( ( "TCP[ port %d ] recv %d bytes: 0x%02X\n",
FreeRTOS_ntohs( pxClient->xRemoteAddr.sin_port ), ( int )xRecvResult, ch ) );
ch = ch;
FreeRTOS_send( pxClient->xServerSocket, (const void *)cr, sizeof( cr ), 0 );
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
break;
case eTCP_4_WaitCount2:
if( xRemaining < 4 )
{
break;
}
{
pxClient->ulSkipCount =
( ( ( uint32_t ) pcReadBuffer[ 0 ] ) << 24 ) |
( ( ( uint32_t ) pcReadBuffer[ 1 ] ) << 16 ) |
( ( ( uint32_t ) pcReadBuffer[ 2 ] ) << 8 ) |
( ( ( uint32_t ) pcReadBuffer[ 3 ] ) << 0 );
FreeRTOS_printf( ( "TCP skipcount %lu xRecvResult %ld\n", pxClient->ulSkipCount, xRemaining ) );
pcReadBuffer += 4;
xRemaining -= 4;
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
if( xRemaining == 0 )
{
break;
}
/* fall through */
case eTCP_5_WaitHeader2:
{
if( pxClient->ulSkipCount > ( uint32_t ) xRemaining )
{
pxClient->ulSkipCount -= xRemaining;
}
else
{
char pcResponse[ 200 ];
uint32_t ulLength, ulStore, ulCount = 0;
if( pxDataClient != NULL )
{
ulCount = pxDataClient->ulRecvCount;
}
ulLength = snprintf( pcResponse + 4, sizeof( pcResponse ) - 4,
"{"
"\"cpu_util_total\":0,"
"\"cpu_util_user\":0,"
"\"cpu_util_system\":0,"
"\"sender_has_retransmits\":-1,"
"\"streams\":["
"{"
"\"id\":1,"
"\"bytes\":%lu,"
"\"retransmits\":-1,"
"\"jitter\":0,"
"\"errors\":0,"
"\"packets\":0"
"}"
"]"
"}\xe",
ulCount );
ulStore = FreeRTOS_htonl( ulLength - 1 );
memcpy( pcResponse, &( ulStore ), sizeof ( ulStore ) );
FreeRTOS_send( pxClient->xServerSocket, (const void *)pcResponse, ulLength + 4, 0 );
pxClient->ulSkipCount = 0;
pxClient->eTCP_Status = ( eTCP_Server_Status_t ) ( ( ( int ) pxClient->eTCP_Status ) + 1 );
}
}
break;
case eTCP_6_WaitDone:
break;
case eTCP_7_WaitTransfer:
break;
}
}
#endif /* ipconfigIPERF_VERSION == 3 */
static void vIPerfTCPWork( TcpClient_t *pxClient )
{
BaseType_t xRecvResult;
//#warning take away
//BaseType_t xLogged = pdFALSE;
if( pxClient->xServerSocket == NULL )
{
vIPerfTCPClose( pxClient );
return;
}
#if( ipconfigIPERF_VERSION == 3 )
/* Is this a data client with the -R reverse option ? */
if( ( pxClient->bits.bIsControl == pdFALSE_UNSIGNED ) && ( pxClient->bits.bReverse != pdFALSE_UNSIGNED ) )
{
if( ( pxClient->bits.bTimed == pdFALSE_UNSIGNED ) && ( pxClient->bits.bHasShutdown == pdFALSE_UNSIGNED ) && ( pxClient->ulAmount == (uint32_t)0u ) )
{
FreeRTOS_printf( ( "Shutdown connection\n" ) );
FreeRTOS_shutdown( pxClient->xServerSocket, FREERTOS_SHUT_RDWR );
pxClient->bits.bHasShutdown = pdTRUE_UNSIGNED;
}
}
#endif
for( ;; )
{
#if( ipconfigIPERF_USE_ZERO_COPY != 0 )
{
const BaseType_t xRecvSize = 0x10000;
xRecvResult = FreeRTOS_recv( pxClient->xServerSocket, /* The socket being received from. */
&pcRecvBuffer, /* The buffer into which the received data will be written. */
xRecvSize, /* Any size is OK here. */
FREERTOS_ZERO_COPY );
}
#else
{
const BaseType_t xRecvSize = sizeof pcRecvBuffer;
xRecvResult = FreeRTOS_recv( pxClient->xServerSocket, /* The socket being received from. */
pcRecvBuffer, /* The buffer into which the received data will be written. */
sizeof pcRecvBuffer, /* The size of the buffer provided to receive the data. */
0 );
}
#endif
if( xRecvResult <= 0 )
{
break;
}
pxClient->ulRecvCount += xRecvResult;
#if( ipconfigIPERF_VERSION == 3 )
if( pxClient->eTCP_Status < eTCP_6_WaitDone )
{
handleRecvPacket(pxClient, pcRecvBuffer, xRecvResult);
}
#endif /* ipconfigIPERF_VERSION == 3 */
#if( ipconfigIPERF_USE_ZERO_COPY != 0 )
{
FreeRTOS_recv( pxClient->xServerSocket, /* The socket being received from. */
NULL, /* The buffer into which the received data will be written. */
xRecvResult, /* This is important now. */
0 );
}
#endif
} /* for( ;; ) */
if( ( xRecvResult == 0 ) && ( pxClient->bits.bIsControl == pdFALSE_UNSIGNED ) && ( pxClient->bits.bReverse != pdFALSE_UNSIGNED ) )
{
xRecvResult = vIPerfTCPSend( pxClient );
}
if( ( xRecvResult < 0 ) && ( xRecvResult != -pdFREERTOS_ERRNO_EAGAIN ) )
{
vIPerfTCPClose( pxClient );
}
}
#if( ipconfigUSE_CALLBACKS == 0 ) && ( ipconfigIPERF_HAS_UDP != 0 )
static void vIPerfUDPWork( Socket_t xSocket )
{
BaseType_t xRecvResult;
struct freertos_sockaddr xAddress;
uint32_t xAddressLength;
#if( ipconfigIPERF_USE_ZERO_COPY != 0 )
{
xRecvResult = FreeRTOS_recvfrom( xSocket, ( void * ) &pcRecvBuffer, sizeof( pcRecvBuffer ),
FREERTOS_ZERO_COPY, &xAddress, &xAddressLength );
}
#else
{
xRecvResult = FreeRTOS_recvfrom( xSocket, ( void * ) pcRecvBuffer, sizeof( pcRecvBuffer ),
0, &xAddress, &xAddressLength );
}
#endif /* ipconfigIPERF_USE_ZERO_COPY */
if( xRecvResult > 0 )
{
ulUDPRecvCount += xRecvResult;
#if( ipconfigIPERF_DOES_ECHO_UDP != 0 )
{
FreeRTOS_sendto( xSocket, (const void *)pcRecvBuffer, xRecvResult, 0, &xAddress, sizeof( xAddress ) );
}
#endif /* ipconfigIPERF_DOES_ECHO_UDP */
#if( ipconfigIPERF_USE_ZERO_COPY != 0 )
{
FreeRTOS_ReleaseUDPPayloadBuffer( pcRecvBuffer );
}
#endif /* ipconfigIPERF_USE_ZERO_COPY */
}
}
#endif /* ipconfigUSE_CALLBACKS == 0 */
#if( ipconfigUSE_CALLBACKS != 0 ) && ( ipconfigIPERF_HAS_UDP != 0 )
static BaseType_t xOnUdpReceive( Socket_t xSocket, void * pvData, size_t xLength,
const struct freertos_sockaddr *pxFrom, const struct freertos_sockaddr *pxDest )
{
( void ) pvData;
( void ) pxFrom;
ulUDPRecvCount += xLength;
#if( ipconfigIPERF_DOES_ECHO_UDP != 0 )
{
FreeRTOS_sendto( xSocket, (const void *)pcRecvBuffer, xLength, 0, pxFrom, sizeof( *pxFrom ) );
}
#else /* ipconfigIPERF_DOES_ECHO_UDP */
{
( void ) xSocket;
}
#endif
/* Tell the driver not to store the RX data */
return 1;
}
#endif /* ipconfigUSE_CALLBACKS != 0 */
#if( ipconfigIPERF_HAS_TCP != 0 )
static Socket_t xCreateTCPServerSocket()
{
BaseType_t xBindResult, xListenResult;
struct freertos_sockaddr xEchoServerAddress;
Socket_t xTCPServerSocket;
TickType_t xNoTimeOut = 0;
xTCPServerSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
configASSERT( ( xTCPServerSocket != FREERTOS_INVALID_SOCKET ) && ( xTCPServerSocket != NULL ) );
memset( &xEchoServerAddress, '\0', sizeof xEchoServerAddress );
xEchoServerAddress.sin_port = FreeRTOS_htons( ipconfigIPERF_TCP_ECHO_PORT );
/* Set the receive time out to portMAX_DELAY.
Note that any TCP child connections will inherit this reception time-out. */
FreeRTOS_setsockopt( xTCPServerSocket, 0, FREERTOS_SO_RCVTIMEO, &xNoTimeOut, sizeof( xNoTimeOut ) );
{
WinProperties_t xWinProperties;
memset(&xWinProperties, '\0', sizeof xWinProperties);
xWinProperties.lTxBufSize = ipconfigIPERF_TX_BUFSIZE; /* Units of bytes. */
xWinProperties.lTxWinSize = ipconfigIPERF_TX_WINSIZE; /* Size in units of MSS */
xWinProperties.lRxBufSize = ipconfigIPERF_RX_BUFSIZE; /* Units of bytes. */
xWinProperties.lRxWinSize = ipconfigIPERF_RX_WINSIZE; /* Size in units of MSS */
FreeRTOS_setsockopt( xTCPServerSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProperties, sizeof( xWinProperties ) );
}
xBindResult = FreeRTOS_bind( xTCPServerSocket, &xEchoServerAddress, sizeof xEchoServerAddress );
xListenResult = FreeRTOS_listen( xTCPServerSocket, 4 );
FreeRTOS_FD_SET( xTCPServerSocket, xSocketSet, eSELECT_READ );
FreeRTOS_printf( ( "vIPerfTask: created TCP server socket %p bind port %u: %ld listen %ld\n",
xTCPServerSocket, ipconfigIPERF_TCP_ECHO_PORT, xBindResult, xListenResult ) );
xBindResult = xBindResult;
xListenResult = xListenResult;
return xTCPServerSocket;
}
#endif /* ipconfigIPERF_HAS_TCP */
#if( ipconfigIPERF_HAS_UDP != 0 )
static Socket_t xCreateUDPServerSocket()
{
BaseType_t xBindResult;
struct freertos_sockaddr xEchoServerAddress;
TickType_t xNoTimeOut = 0;
Socket_t xUDPServerSocket;
xUDPServerSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
configASSERT( ( xUDPServerSocket != FREERTOS_INVALID_SOCKET ) && ( xUDPServerSocket != NULL ) );
xEchoServerAddress.sin_port = FreeRTOS_htons( ipconfigIPERF_UDP_ECHO_PORT );
FreeRTOS_setsockopt( xUDPServerSocket, 0, FREERTOS_SO_RCVTIMEO, &xNoTimeOut, sizeof( xNoTimeOut ) );
xBindResult = FreeRTOS_bind( xUDPServerSocket, &xEchoServerAddress, sizeof xEchoServerAddress );
FreeRTOS_printf( ( "vIPerfTask: created UDP server socket %p bind port %u: %ld\n",
xUDPServerSocket, ipconfigIPERF_UDP_ECHO_PORT, xBindResult ) );
xBindResult = xBindResult;
#if( ipconfigUSE_CALLBACKS == 0 )
{
FreeRTOS_FD_SET( xUDPServerSocket, xSocketSet, eSELECT_READ );
}
#else
{
F_TCP_UDP_Handler_t xHandler;
memset( &xHandler, '\0', sizeof ( xHandler ) );
xHandler.pOnUdpReceive = xOnUdpReceive;
FreeRTOS_setsockopt( xUDPServerSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) );
}
#endif /* ipconfigUSE_CALLBACKS */
return xUDPServerSocket;
}
#endif /* ipconfigIPERF_HAS_UDP */
void vIPerfTask( void *pvParameter )
{
#if( ipconfigIPERF_HAS_TCP != 0 )
Socket_t xTCPServerSocket;
#endif /* ipconfigIPERF_HAS_TCP */
#if( ipconfigIPERF_HAS_UDP != 0 )
Socket_t xUDPServerSocket;
#endif /* ipconfigIPERF_HAS_UDP */
( void ) pvParameter;
xSocketSet = FreeRTOS_CreateSocketSet( );
vListInitialise( &xTCPClientList );
#if( ipconfigIPERF_HAS_TCP != 0 )
{
xTCPServerSocket = xCreateTCPServerSocket();
}
#endif /* ipconfigIPERF_HAS_TCP */
#if( ipconfigIPERF_HAS_UDP != 0 )
{
xUDPServerSocket = xCreateUDPServerSocket();
(void)xUDPServerSocket;
}
#endif /* ipconfigIPERF_HAS_UDP */
FreeRTOS_printf( ( "Use for example:\n" ) );
FreeRTOS_printf( ( "iperf3 -c %lxip --port %u --bytes 100M [ -R ]\n",
FreeRTOS_htonl( FreeRTOS_GetIPAddress() ), ipconfigIPERF_UDP_ECHO_PORT ) );
#define HUNDREDTH_MB ( ( 1024 * 1024 ) / 100 )
for( ;; )
{
BaseType_t xResult;
const TickType_t xBlockingTime = pdMS_TO_TICKS( ipconfigIPERF_LOOP_BLOCKING_TIME_MS );
/* Wait at most 5 seconds. */
xResult = FreeRTOS_select( xSocketSet, xBlockingTime );
#if( ipconfigIPERF_HAS_TCP != 0 )
if( xResult != 0 )
{
const MiniListItem_t* pxEnd;
const ListItem_t *pxIterator;
pxEnd = ( const MiniListItem_t* ) listGET_END_MARKER( &xTCPClientList );
vIPerfServerWork( xTCPServerSocket );
/* Check all TCP clients: */
for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd );
pxIterator != ( const ListItem_t * ) pxEnd;
)
{
TcpClient_t *pxClient;
pxClient = ( TcpClient_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
/* Let the iterator point to the next element before the current element
removes itself from the list. */
pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator );
vIPerfTCPWork( pxClient );
}
}
#endif /* ipconfigIPERF_HAS_TCP */
#if( ipconfigIPERF_HAS_UDP != 0 )
#if( ipconfigUSE_CALLBACKS == 0 )
if( xResult != 0 )
{
vIPerfUDPWork( xUDPServerSocket );
}
else
#endif /* ipconfigUSE_CALLBACKS */
{
if( ulUDPRecvCountSeen != ulUDPRecvCount )
{
/* The amount is still changing, do not show it yet. */
ulUDPRecvCountSeen = ulUDPRecvCount;
}
else if( ulUDPRecvCountShown != ulUDPRecvCount )
{
uint32_t ulNewBytes = ulUDPRecvCount - ulUDPRecvCountShown;
uint32_t ulMB = (ulNewBytes + HUNDREDTH_MB/2) / HUNDREDTH_MB;
FreeRTOS_printf( ( "UDP received %lu + %lu (%lu.%02lu MB) = %lu\n",
ulUDPRecvCountShown,
ulNewBytes,
ulMB / 100,
ulMB % 100,
ulUDPRecvCount ) );
ulUDPRecvCountShown = ulUDPRecvCount;
ulMB = ulMB;
}
}
#endif /* ipconfigIPERF_HAS_UDP */
}
}
//<2F><><EFBFBD><EFBFBD>ͨWiFi<46><69>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>
#define IPERF_BUFSZ (4 * 1024)
typedef unsigned int u32_t;
static TaskHandle_t iperf_task_handle = NULL;
static int flag_start_iperf = 0;
static char gaddr[4] = {0};
static int gport = 0;
static u32_t sys_now(void)
{
return xTaskGetTickCount() * portTICK_PERIOD_MS;
}
static void iperf_client(const char * ipaddr, int port)
{
Socket_t sock;
int i;
//struct sockaddr_in client_addr;
struct freertos_sockaddr client_addr;
uint8_t* send_buf;
u32_t tick1, tick2;
uint64_t sentlen;
(void)ipaddr;
(void)port;
send_buf = (uint8_t *) pvPortMalloc(IPERF_BUFSZ);
if (!send_buf)
return ;
for(i = 0; i < IPERF_BUFSZ; i ++)
send_buf[i] = i & 0xff;
while(flag_start_iperf) {
sock = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
if (sock == FREERTOS_INVALID_SOCKET) {
printf("Socket error\r\n");
vTaskDelay(pdMS_TO_TICKS(100));
continue;
}
client_addr.sin_port = FreeRTOS_htons( gport );
client_addr.sin_addr = FreeRTOS_inet_addr_quick( gaddr[0],
gaddr[1],
gaddr[2],
gaddr[3] );
//memset(&(client_addr.sin_zero), 0, sizeof(client_addr.sin_zero));
if (FreeRTOS_connect(sock, &client_addr, sizeof( struct freertos_sockaddr )) != 0) {
printf("Connect failed!\r\n");
FreeRTOS_closesocket(sock);
vTaskDelay(10);
continue;
}
printf("Connect to iperf server successful!\r\n");
tick1 = sys_now();
while (flag_start_iperf) {
tick2 = sys_now();
if(tick2 - tick1 >= configTICK_RATE_HZ * 5) {
float f;
f = (float)(sentlen * configTICK_RATE_HZ/125/(tick2 - tick1));
f /= 1000.0f;
printf("\r\nsend speed = %.4f Mbps!\r\n", f);
tick1 = tick2;
sentlen = 0;
}
if(FreeRTOS_send(sock, send_buf, IPERF_BUFSZ, 0) < 0) {
printf("FreeRTOS_send failed\r\n");
break;
} else {
sentlen += IPERF_BUFSZ;
}
}
FreeRTOS_closesocket(sock);
}
if (send_buf) {
vPortFree(send_buf);
}
}
static void iperf_task_proc(void* arg)
{
iperf_client(NULL, 0);
vTaskDelete(NULL);
}
void start_iperf_client(const char* ip, int port)
{
if (flag_start_iperf) {
printf("iperf client has been started");
return;
}
if (iperf_task_handle == NULL) {
sscanf(ip, "%d.%d.%d.%d", (int*)&gaddr[0], (int*)&gaddr[1], (int*)&gaddr[2], (int*)&gaddr[3]);
gport = port;
flag_start_iperf = 1;
xTaskCreate(iperf_task_proc, "iperf task task", 512, NULL, configMAX_PRIORITIES / 3, &iperf_task_handle);
}
}