[修改] 增加freeRTOS

1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
2023-05-06 16:43:01 +00:00
commit a345df017b
20944 changed files with 11094377 additions and 0 deletions

View File

@ -0,0 +1,100 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*
* dump_packets.c
* Used in the PC/Win project to dump Ethernet packets, along with some description.
*/
#ifndef DUMP_PACKETS_H
#define DUMP_PACKETS_H
#ifndef dumpMAX_DUMP_ENTRIES
#define dumpMAX_DUMP_ENTRIES 16
#endif
#define flag_ICMP4 0x00000001UL
#define flag_ICMP6 0x00000002UL
#define flag_UDP 0x00000004UL
#define flag_TCP 0x00000008UL
#define flag_DNS 0x00000010UL
#define flag_REPLY 0x00000020UL
#define flag_REQUEST 0x00000040UL
#define flag_SYN 0x00000080UL
#define flag_FIN 0x00000100UL
#define flag_RST 0x00000200UL
#define flag_ACK 0x00000400UL
#define flag_IN 0x00000800UL
#define flag_OUT 0x00001000UL
#define flag_FRAME_ARP 0x00002000UL
#define flag_ARP 0x00004000UL
#define flag_UNKNOWN 0x00008000UL
#define flag_FRAME_4 0x00010000UL
#define flag_FRAME_6 0x00020000UL
#define flag_Unknown_FRAME 0x00040000UL
/**
* Structure to hold information about one dump entry.
*/
typedef struct xDumpEntry
{
uint32_t ulMask; /**< The mask of the entry */
size_t uxMax; /**< The max value of the entry */
size_t uxCount; /**< The count of the entry */
} DumpEntry_t;
/**
* Structure to hold information of all the entries in this data dump.
*/
typedef struct xDumpEntries
{
size_t uxEntryCount; /**< The number of entries*/
DumpEntry_t xEntries[ dumpMAX_DUMP_ENTRIES ]; /**< Array of struct for all the entries */
} DumpEntries_t;
/*
*
*/
#if ( ipconfigUSE_DUMP_PACKETS != 0 )
extern void dump_packet_init( const char * pcFileName,
DumpEntries_t * pxEntries );
#define iptraceDUMP_INIT( pcFileName, pxEntries ) \
dump_packet_init( pcFileName, pxEntries )
extern void dump_packet( const uint8_t * pucBuffer,
size_t uxLength,
BaseType_t xIncoming );
#define iptraceDUMP_PACKET( pucBuffer, uxLength, xIncoming ) \
dump_packet( pucBuffer, uxLength, xIncoming )
#endif /* if ( ipconfigUSE_DUMP_PACKETS != 0 ) */
#endif /* ifndef DUMP_PACKETS_H */

View File

@ -0,0 +1,80 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*
* tcp_mem_stats.h
*/
#ifndef TCP_MEM_STATS_H
#define TCP_MEM_STATS_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum xTCP_MEMORY
{
tcpSOCKET_TCP,
tcpSOCKET_UDP,
tcpSOCKET_SET,
tcpSEMAPHORE,
tcpRX_STREAM_BUFFER,
tcpTX_STREAM_BUFFER,
tcpNETWORK_BUFFER,
} TCP_MEMORY_t;
#if ( ipconfigUSE_TCP_MEM_STATS != 0 )
void vTCPMemStatCreate( TCP_MEMORY_t xMemType,
void * pxObject,
size_t uxSize );
void vTCPMemStatDelete( void * pxObject );
void vTCPMemStatClose( void );
#define iptraceMEM_STATS_CREATE( xMemType, pxObject, uxSize ) \
vTCPMemStatCreate( xMemType, pxObject, uxSize )
#define iptraceMEM_STATS_DELETE( pxObject ) \
vTCPMemStatDelete( pxObject )
#define iptraceMEM_STATS_CLOSE() \
vTCPMemStatClose()
#else /* if ( ipconfigUSE_TCP_MEM_STATS != 0 ) */
/* The header file 'IPTraceMacroDefaults.h' will define the default empty macro's. */
#endif /* ipconfigUSE_TCP_MEM_STATS != 0 */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* TCP_MEM_STATS_H */

View File

@ -0,0 +1,120 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*
* TCP_NETSTAT.c
* Some function to get a list of sockets and active port numbers.
*/
#ifndef TCP_NETSTAT_H
#define TCP_NETSTAT_H
#ifndef nstatMAX_UDP_PORTS
#define nstatMAX_UDP_PORTS 12U
#endif
#ifndef nstatMAX_TCP_PORTS
#define nstatMAX_TCP_PORTS 12U
#endif
#ifndef nstatMAX_UDP_SOCKETS
#define nstatMAX_UDP_SOCKETS 12U
#endif
#ifndef nstatMAX_TCP_SOCKETS
#define nstatMAX_TCP_SOCKETS 12U
#endif
typedef struct xIOCounters
{
size_t uxByteCount;
size_t uxPacketCount;
} IOCounters_t;
extern IOCounters_t xInputCounters, xOutputCounters;
typedef struct
{
uint16_t usUDPPortList[ nstatMAX_UDP_PORTS ];
size_t uxCount;
} UDPPortList_t;
typedef struct
{
uint16_t usTCPPortList[ nstatMAX_TCP_PORTS ];
size_t uxCount;
} TCPPortList_t;
typedef struct
{
uint16_t usLocalPort;
uint16_t usRemotePort;
uint32_t ulRemoteIP;
} TCPEntry_t;
typedef struct
{
TCPEntry_t xTCPList[ nstatMAX_TCP_SOCKETS ];
size_t uxCount;
} TCPSocketList_t;
typedef struct
{
uint16_t usLocalPort;
} UDPEntry_t;
typedef struct
{
UDPEntry_t xUDPList[ nstatMAX_UDP_SOCKETS ];
size_t uxCount;
} UDPSocketList_t;
typedef struct
{
UDPPortList_t xUDPPortList;
TCPPortList_t xTCPPortList;
TCPSocketList_t xTCPSocketList;
UDPSocketList_t xUDPSocketList;
IOCounters_t xInput;
IOCounters_t xOutput;
} MetricsType_t;
extern BaseType_t vGetMetrics( MetricsType_t * pxMetrics );
extern void vShowMetrics( const MetricsType_t * pxMetrics );
#define iptraceNETWORK_INTERFACE_INPUT( uxDataLength, pucEthernetBuffer ) \
xInputCounters.uxByteCount += uxDataLength; \
xInputCounters.uxPacketCount++;
#define iptraceNETWORK_INTERFACE_OUTPUT( uxDataLength, pucEthernetBuffer ) \
xOutputCounters.uxByteCount += uxDataLength; \
xOutputCounters.uxPacketCount++;
#endif /* TCP_NETSTAT_H */

View File

@ -0,0 +1,706 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*
* tcp_dump_packets.c
* Used in the PC/Win project to dump Ethernet packets, along with some description.
* See tools/tcp_dump_packets.md for further description.
*/
/* Standard includes. */
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <ctype.h>
/* FreeRTOS includes. */
#include <FreeRTOS.h>
#include "task.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_Stream_Buffer.h"
#include "FreeRTOS_IP_Private.h"
#if ( ipconfigUSE_DUMP_PACKETS != 0 )
#include "tcp_dump_packets.h"
/* The priority of the windows thread. */
#define dumpPROCESS_THREAD_PRIORITY THREAD_PRIORITY_NORMAL
/* There is a stream buffer between the FreeRTOS tasks sending network packets,
* and the Windows thread that writes these packets to disk. The macro 'dumpITEM_COUNT'
* determines the number of full-size packets that can be stored in this stream buffer. */
#ifndef dumpITEM_COUNT
#define dumpITEM_COUNT 32
#endif
/* Packets are written in hex notation, no more than 16 bytes on a row. */
#ifndef dumpBYTES_PER_ROW
#define dumpBYTES_PER_ROW 16
#endif
/* The TCP port number reserved for a DNS server. */
#define dnsDNS_PORT 0x0035u
/* Some const values describing the 'flags' in a TCP packet. */
#define tcpTCP_FLAG_FIN 0x0001u /* No more data from sender */
#define tcpTCP_FLAG_SYN 0x0002u /* Synchronize sequence numbers */
#define tcpTCP_FLAG_RST 0x0004u /* Reset the connection */
#define tcpTCP_FLAG_PSH 0x0008u /* Push function: please push buffered data to the recv application */
#define tcpTCP_FLAG_ACK 0x0010u /* Acknowledgment field is significant */
/* A macro to add a type, both as a numeric value, as well as a string. */
#define ADD_TYPE( FLAGS ) \
vAddType( flag_ ## FLAGS, # FLAGS )
/*-----------------------------------------------------------*/
static char pcTypeString[ 255 ];
static uint32_t ulTypeMask;
/* The name of the C source file to be written. */
static char pcCodeFileName[ MAX_PATH ];
/* The name of the header file to be written. */
static char pcHeaderFileName[ MAX_PATH ];
/* A stream buffer between the FreeRTOS tasks and the Windows thread. */
static StreamBuffer_t * xPacketBuffer;
/* A process handle of the Windows thread. */
static HANDLE pvProcessHandle;
static UBaseType_t uxNextPacketNumber;
static BaseType_t xFirstPacket = 1;
/* Boolean 'xDumpingReady' becomes true once all desired packet have been collected.
* Further packets will be dropped (ignored). */
static volatile BaseType_t xDumpingReady = pdFALSE;
static DumpEntries_t * pxCurrentEntries;
static uint16_t usSourcePort;
static uint16_t usDestinationPort;
typedef struct xBufferheader
{
size_t uxLength;
UBaseType_t bIncoming : 1;
} Bufferheader_t;
static DumpEntries_t xExampleEntries =
{
.uxEntryCount = 4, /* No more than 'dumpMAX_DUMP_ENTRIES' elements. */
.xEntries =
{
{ .ulMask = flag_IN | flag_UDP, .uxMax = 2u },
{ .ulMask = flag_IN | flag_ARP, .uxMax = 2u },
{ .ulMask = flag_IN | flag_TCP, .uxMax = 5u },
{ .ulMask = flag_IN | flag_SYN, .uxMax = 1u },
}
};
const char pcHeaderCode[] =
"/*\n"
" * This file was created automatically by 'dump_packets.c'\n"
" */\n"
"\n"
"/* Standard includes. */\n"
"#include <stdio.h>\n"
"#include <stdint.h>\n"
"#include <stdarg.h>\n"
"#include <io.h>\n"
"#include <ctype.h>\n"
"\n"
"/* FreeRTOS includes. */\n"
"#include <FreeRTOS.h>\n"
"#include <task.h>\n\n"
"#include \"%s\"\n\n";
const char pcHeaderHeader[] =
"/*\n"
" * This file was created automatically by 'dump_packets.c'\n"
" */\n"
"\n"
"#ifndef PACKET_LIST_H\n\n"
"#define PACKET_LIST_H\n\n"
"typedef struct xDumpPacket\n"
"{\n"
" const uint8_t *pucData;\n"
" size_t uxLength;\n"
" uint32_t ulType;\n"
" uint16_t usSource;\n"
" uint16_t usDestination;\n"
"} DumpPacket_t;\n\n";
/*-----------------------------------------------------------*/
/* The Windows thread that actually writes the network packets to a C source and header file. */
static DWORD WINAPI prvWritePackets( LPVOID lpParameter );
static void vAddProtocolTags( uint8_t * pucEthernetBuffer,
BaseType_t xIPType );
static void vDetermineMessageType( uint8_t * pucBuffer,
BaseType_t xIncoming );
static void vActualDump( uint8_t * pucBuffer,
size_t uxLength,
BaseType_t xIncoming );
static void vAddType( uint32_t ulFlags,
const char * pcFlagName );
static void vWriteHeaderFile( void );
/*-----------------------------------------------------------*/
void dump_packet_init( const char * pcFileName,
DumpEntries_t * pxEntries )
{
size_t uxIndex;
snprintf( pcCodeFileName, sizeof pcCodeFileName, "%s.c", pcFileName );
snprintf( pcHeaderFileName, sizeof pcHeaderFileName, "%s.h", pcFileName );
if( pxEntries == NULL )
{
pxEntries = &( xExampleEntries );
}
configASSERT( pxEntries->uxEntryCount > 0 );
configASSERT( pxEntries->uxEntryCount <= dumpMAX_DUMP_ENTRIES );
for( uxIndex = 0; uxIndex < pxEntries->uxEntryCount; uxIndex++ )
{
pxEntries->xEntries[ uxIndex ].uxCount = 0;
}
pxCurrentEntries = pxEntries;
if( xPacketBuffer == NULL )
{
size_t uxLength, uxSize;
/* Enough space for e.g. 32 buffers and length words. */
uxLength = dumpITEM_COUNT * ( sizeof( void * ) + ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER );
uxSize = ( sizeof( *xPacketBuffer ) + uxLength ) - sizeof( xPacketBuffer->ucArray );
xPacketBuffer = ( StreamBuffer_t * ) pvPortMalloc( uxSize );
configASSERT( xPacketBuffer != NULL );
vStreamBufferClear( xPacketBuffer );
xPacketBuffer->LENGTH = uxLength;
}
if( pvProcessHandle == NULL )
{
pvProcessHandle = CreateThread( NULL, 0, prvWritePackets, NULL, CREATE_SUSPENDED, NULL );
if( pvProcessHandle != NULL )
{
SetThreadPriority( pvProcessHandle, dumpPROCESS_THREAD_PRIORITY );
SetThreadPriorityBoost( pvProcessHandle, TRUE );
SetThreadAffinityMask( pvProcessHandle, 0x0E );
ResumeThread( pvProcessHandle );
}
}
}
/*-----------------------------------------------------------*/
void dump_packet( const uint8_t * pucBuffer,
size_t uxLength,
BaseType_t xIncoming )
{
/* This function shall be called from a normal FreeRTOS task only. */
if( xPacketBuffer != NULL )
{
if( xDumpingReady == pdFALSE )
{
size_t uxSpace = uxStreamBufferGetSpace( xPacketBuffer );
size_t uxNeeded = uxLength + sizeof( size_t );
if( uxNeeded < uxSpace )
{
Bufferheader_t xheader;
xheader.uxLength = uxLength;
xheader.bIncoming = xIncoming;
uxStreamBufferAdd( xPacketBuffer, 0u, ( const uint8_t * ) &( xheader ), sizeof( xheader ) );
uxStreamBufferAdd( xPacketBuffer, 0u, pucBuffer, uxLength );
}
else
{
/* Drop this packet. */
}
}
else
{
/* The Windows thread 'prvWritePackets()' had received enough packets.
* The packet buffer may be freed. */
vPortFree( xPacketBuffer );
xPacketBuffer = NULL;
}
}
}
/*-----------------------------------------------------------*/
static DWORD WINAPI prvWritePackets( LPVOID lpParameter )
{
/* This is a Windows thread, not a FreeRTOS task. FreeRTOS API's may not be called. */
for( ; ; )
{
Sleep( 100 );
while( ( xPacketBuffer != NULL ) && ( xDumpingReady == pdFALSE ) )
{
Bufferheader_t xHeader;
size_t uxBytes = uxStreamBufferGetSize( xPacketBuffer );
if( uxBytes <= sizeof( xHeader ) )
{
break;
}
/* Peek the number of bytes available. */
uxStreamBufferGet( xPacketBuffer, 0u, ( uint8_t * ) &( xHeader ), sizeof( xHeader ), pdTRUE );
if( uxBytes >= sizeof( xHeader ) + xHeader.uxLength )
{
}
{
size_t xBytesRead;
uint8_t pcBuffer[ ipconfigNETWORK_MTU ];
size_t xActualCount;
uxStreamBufferGet( xPacketBuffer, 0u, NULL, sizeof( xHeader ), pdFALSE );
xActualCount = uxStreamBufferGet( xPacketBuffer, 0u, pcBuffer, xHeader.uxLength, pdFALSE );
vActualDump( pcBuffer, xActualCount, xHeader.bIncoming );
}
}
}
}
/*-----------------------------------------------------------*/
static int _fprintf( FILE * pxHandle,
const char * pcFormat,
... )
{
char pcString[ 255 ];
BaseType_t iCount;
va_list args;
va_start( args, pcFormat );
iCount = vsnprintf( pcString, sizeof pcString, pcFormat, args );
va_end( args );
fwrite( pcString, 1u, iCount, pxHandle );
return iCount;
}
/*-----------------------------------------------------------*/
static void vWriteHeaderFile( void )
{
FILE * outfile;
outfile = fopen( pcHeaderFileName, "w" );
if( outfile != NULL )
{
fwrite( pcHeaderHeader, 1u, sizeof( pcHeaderHeader ) - 1u, outfile );
_fprintf( outfile, "#define dumpPACKET_COUNT %lu\n\n",
( uxNextPacketNumber < 1u ) ? 1u : uxNextPacketNumber );
_fprintf( outfile, "extern DumpPacket_t *xPacketList[ dumpPACKET_COUNT ];\n\n" );
_fprintf( outfile, "#endif PACKET_LIST_H\n" );
fclose( outfile );
}
}
/*-----------------------------------------------------------*/
static void vAddType( uint32_t ulFlags,
const char * pcFlagName )
{
size_t uxLength = strlen( pcTypeString );
char pcString[ 64 ];
BaseType_t iCount;
ulTypeMask |= ulFlags;
if( uxLength == 0 )
{
snprintf( pcTypeString, sizeof pcTypeString, "%s", pcFlagName );
}
else
{
snprintf( pcTypeString + uxLength, sizeof pcTypeString - 1, " | %s", pcFlagName );
}
}
/*-----------------------------------------------------------*/
static void vAddProtocolTags( uint8_t * pucEthernetBuffer,
BaseType_t xIPType )
{
ProtocolHeaders_t * pxProtocolHeaders;
#if ( ipconfigUSE_IPv6 != 0 )
const IPHeader_IPv6_t * pxIPHeader_IPv6;
#endif
UBaseType_t uxHeaderLength;
uint8_t ucProtocol;
IPPacket_t * pxIPPacket;
IPHeader_t * pxIPHeader;
pxIPPacket = ( IPPacket_t * ) pucEthernetBuffer;
pxIPHeader = &( pxIPPacket->xIPHeader );
#if ( ipconfigUSE_IPv6 != 0 )
pxIPHeader_IPv6 = ( const IPHeader_IPv6_t * ) &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] );
if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv6_FRAME_TYPE )
{
uxHeaderLength = ipSIZE_OF_IPv6_HEADER;
ucProtocol = pxIPHeader_IPv6->ucNextHeader;
pxProtocolHeaders = ( ProtocolHeaders_t * ) &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv6_HEADER ] );
}
else
#endif
{
size_t uxLength = ( size_t ) pxIPHeader->ucVersionHeaderLength;
/* Check if the IP headers are acceptable and if it has our destination.
* The lowest four bits of 'ucVersionHeaderLength' indicate the IP-header
* length in multiples of 4. */
uxHeaderLength = ( size_t ) ( ( uxLength & 0x0Fu ) << 2 );
ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
pxProtocolHeaders = ( ProtocolHeaders_t * ) &( pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxHeaderLength ] );
}
switch( ucProtocol )
{
case ipPROTOCOL_ICMP:
ADD_TYPE( ICMP4 );
break;
#if ( ipconfigUSE_IPv6 != 0 )
case ipPROTOCOL_ICMP_IPv6:
ADD_TYPE( ICMP6 );
break;
#endif
case ipPROTOCOL_UDP:
ADD_TYPE( UDP );
usSourcePort = pxProtocolHeaders->xUDPHeader.usSourcePort;
usDestinationPort = pxProtocolHeaders->xUDPHeader.usDestinationPort;
if( usSourcePort == FreeRTOS_htons( dnsDNS_PORT ) )
{
ADD_TYPE( DNS );
ADD_TYPE( REPLY );
}
else if( usDestinationPort == FreeRTOS_htons( dnsDNS_PORT ) )
{
ADD_TYPE( DNS );
ADD_TYPE( REQUEST );
}
break;
#if ipconfigUSE_TCP == 1
case ipPROTOCOL_TCP:
ADD_TYPE( TCP );
usSourcePort = pxProtocolHeaders->xTCPHeader.usSourcePort;
usDestinationPort = pxProtocolHeaders->xTCPHeader.usDestinationPort;
if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_SYN ) != 0u )
{
ADD_TYPE( SYN );
}
if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_FIN ) != 0u )
{
ADD_TYPE( FIN );
}
if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_RST ) != 0u )
{
ADD_TYPE( RST );
}
if( ( pxProtocolHeaders->xTCPHeader.ucTCPFlags & tcpTCP_FLAG_ACK ) != 0u )
{
ADD_TYPE( ACK );
}
break;
#endif /* if ipconfigUSE_TCP == 1 */
}
}
/*-----------------------------------------------------------*/
static void vDetermineMessageType( uint8_t * pucBuffer,
BaseType_t xIncoming )
{
EthernetHeader_t * pxEthernetHeader;
if( xIncoming != 0 )
{
ADD_TYPE( IN );
}
else
{
ADD_TYPE( OUT );
}
pxEthernetHeader = ( EthernetHeader_t * ) pucBuffer;
/* Interpret the received Ethernet packet. */
switch( pxEthernetHeader->usFrameType )
{
case ipARP_FRAME_TYPE:
{
ARPPacket_t * pxARPFrame;
ARPHeader_t * pxARPHeader;
/* The Ethernet frame contains an ARP packet. */
ADD_TYPE( FRAME_ARP );
pxARPFrame = ( ARPPacket_t * ) pucBuffer;
pxARPHeader = &( pxARPFrame->xARPHeader );
ADD_TYPE( ARP );
switch( pxARPHeader->usOperation )
{
case ipARP_REQUEST:
ADD_TYPE( REQUEST );
break;
case ipARP_REPLY:
ADD_TYPE( REPLY );
break;
default:
ADD_TYPE( UNKNOWN );
break;
}
}
break;
case ipIPv4_FRAME_TYPE:
ADD_TYPE( FRAME_4 );
vAddProtocolTags( pucBuffer, 4 );
break;
#if ( ipconfigUSE_IPv6 != 0 )
case ipIPv6_FRAME_TYPE:
ADD_TYPE( FRAME_6 );
vAddProtocolTags( pucBuffer, 6 );
break;
#endif
default:
/* No other packet types are handled. Nothing to do. */
ADD_TYPE( Unknown_FRAME );
break;
}
}
/*-----------------------------------------------------------*/
static void vActualDump( uint8_t * pucBuffer,
size_t uxLength,
BaseType_t xIncoming )
{
char pcString[ 513 ];
size_t uxOffset;
size_t uxIndex;
size_t uxCompleteCount = 0;
BaseType_t xUseIt = pdFALSE;
usSourcePort = 0u;
usDestinationPort = 0u;
pcTypeString[ 0 ] = 0;
ulTypeMask = 0uL;
if( pxCurrentEntries == NULL )
{
return;
}
vDetermineMessageType( pucBuffer, xIncoming );
for( uxIndex = 0; uxIndex < pxCurrentEntries->uxEntryCount; uxIndex++ )
{
if( pxCurrentEntries->xEntries[ uxIndex ].uxCount < pxCurrentEntries->xEntries[ uxIndex ].uxMax )
{
uint32_t ulMask = pxCurrentEntries->xEntries[ uxIndex ].ulMask;
if( ( ulMask & ulTypeMask ) == ulMask )
{
pxCurrentEntries->xEntries[ uxIndex ].uxCount++;
xUseIt = pdTRUE;
}
}
else
{
uxCompleteCount++;
}
}
FreeRTOS_printf( ( "prvWritePackets: done %d/%d : (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n",
uxCompleteCount,
pxCurrentEntries->uxEntryCount,
pxCurrentEntries->xEntries[ 0 ].uxCount, pxCurrentEntries->xEntries[ 0 ].uxMax,
pxCurrentEntries->xEntries[ 1 ].uxCount, pxCurrentEntries->xEntries[ 1 ].uxMax,
pxCurrentEntries->xEntries[ 2 ].uxCount, pxCurrentEntries->xEntries[ 2 ].uxMax,
pxCurrentEntries->xEntries[ 3 ].uxCount, pxCurrentEntries->xEntries[ 3 ].uxMax ) );
if( uxCompleteCount >= pxCurrentEntries->uxEntryCount )
{
FreeRTOS_printf( ( "prvWritePackets: all %lu packets have been collected\n", pxCurrentEntries->uxEntryCount ) );
if( pxCurrentEntries != NULL )
{
FILE * outfile = fopen( pcCodeFileName, ( xFirstPacket != 0 ) ? "w" : "a+" );
if( outfile == NULL )
{
FreeRTOS_printf( ( "Can not create '%s'\n", pcCodeFileName ) );
}
else
{
/*
* Create a list with pointers to each network packet.
* DumpPacket_t *xPacketList[ dumpPACKET_COUNT ] =
* {
* &xPacket_0000,
* &xPacket_0001,
* &xPacket_0002,
* &xPacket_0003,
* }
*/
_fprintf( outfile, "\nDumpPacket_t *xPacketList[ dumpPACKET_COUNT ] =\n{\n" );
for( uxIndex = 0; uxIndex < uxNextPacketNumber; uxIndex++ )
{
_fprintf( outfile, "\t&xPacket_%04lu,\n", uxIndex );
}
_fprintf( outfile, "};\n" );
fclose( outfile );
vWriteHeaderFile();
}
pxCurrentEntries = NULL;
/* Tell the thread and the function dump_packet() that packet
* dumping is ready. */
xDumpingReady = pdTRUE;
}
return;
}
if( xUseIt == pdFALSE )
{
return;
}
printf( "prvWritePackets: Read %lu bytes, type %s\n", uxLength, pcTypeString );
FILE * outfile = fopen( pcCodeFileName, ( xFirstPacket != 0 ) ? "w" : "a+" );
if( outfile == NULL )
{
FreeRTOS_printf( ( "Can not create '%s'\n", pcCodeFileName ) );
return;
}
if( xFirstPacket != 0 )
{
char * pcPtr;
size_t xLength;
vWriteHeaderFile( pcHeaderFileName );
xLength = snprintf( pcString, sizeof pcString, pcHeaderCode, pcHeaderFileName );
fwrite( pcString, 1u, xLength, outfile );
xFirstPacket = pdFALSE;
}
_fprintf( outfile, "\n/* Packet_%04d */\n", uxNextPacketNumber );
_fprintf( outfile, "uint8_t ucPacket_%04lx[ %lu ] =\n{\n", uxNextPacketNumber, uxLength );
for( uxOffset = 0u; uxOffset < uxLength; )
{
size_t uxCurLength = 0u;
size_t uxLast = uxOffset + dumpBYTES_PER_ROW;
BaseType_t xFirst = pdTRUE;
if( uxLast > uxLength )
{
uxLast = uxLength;
}
while( uxOffset < uxLast )
{
uxCurLength += snprintf( pcString + uxCurLength, sizeof pcString - uxCurLength, "%s0x%02x",
( uxCurLength == 0 ) ? "\t" : ", ", pucBuffer[ uxOffset ] );
uxOffset++;
}
if( uxCurLength != 0u )
{
uxCurLength += snprintf( pcString + uxCurLength, sizeof pcString - uxCurLength, "%s\n",
( uxOffset == uxLength ) ? "\n};" : "," );
fwrite( pcString, 1u, uxCurLength, outfile );
}
}
_fprintf( outfile, "\n" );
_fprintf( outfile,
"DumpPacket_t xPacket_%04lx =\n{\n"
"\t.pucData = ucPacket_%04lx,\n"
"\t.uxLength = %lu,\n"
"\t.ulType = 0x%lX, /* %s */\n",
uxNextPacketNumber, uxNextPacketNumber, uxLength, ulTypeMask, pcTypeString );
if( usSourcePort != 0u )
{
_fprintf( outfile,
"\t.usSource = %u,\n", FreeRTOS_ntohs( usSourcePort ) );
}
if( usSourcePort != 0u )
{
_fprintf( outfile,
"\t.usDestination = %u,\n", FreeRTOS_ntohs( usDestinationPort ) );
}
_fprintf( outfile,
"};\n"
"/*-----------------------------------------------------------*/\n\n" );
fclose( outfile );
uxNextPacketNumber++;
}
/*-----------------------------------------------------------*/
#endif /* ( ipconfigUSE_DUMP_PACKETS != 0 ) */

View File

@ -0,0 +1,72 @@
tcp_dump_packets.c dumps network packets in a C source file.
It is written to be added to the "pc" project ( Windows simulator ). It uses the file system to write 2 C source files:
PacketList.c
PacketList.h
How to include 'tcp_dump_packets' into a project:
● Make sure that tools/tcp_dump_packets.c is added to the source files
● See if Network Interface has been adapted to call:
`iptraceDUMP_PACKET( ucBuffer, xLength, pdTRUE ); /* Incoming packet. */`
`iptraceDUMP_PACKET( ucBuffer, xLength, pdFALSE ); /* Outgoing packet. */`
● Once the network is up, call `dump_packet_init()` with a file name and a pointer to
`DumpEntries_t`, which contains the requirements. For instance like this:
static DumpEntries_t xExampleEntries = {
.uxEntryCount = 4, /* No more than 'dumpMAX_DUMP_ENTRIES' elements. */
.xEntries = {
{ .ulMask = flag_IN | flag_UDP, .uxMax = 2u },
{ .ulMask = flag_IN | flag_ARP, .uxMax = 2u },
{ .ulMask = flag_IN | flag_TCP, .uxMax = 5u },
{ .ulMask = flag_IN | flag_SYN, .uxMax = 1u },
}
};
● Add the following lines to FreeRTOSIPConfig.h :
#define ipconfigUSE_DUMP_PACKETS ( 1 )
#include "../tools/tcp_dump_packets.h"
Later on, the module can disabled by simply setting `ipconfigUSE_DUMP_PACKETS` to `0`.
Here is some contents of the output file:
/* Packet_0001 */
uint8_t ucPacket_0001[ 60 ] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x74, 0xb5, 0x7e, 0xf0, 0x47, 0xee, 0x08, 0x06, 0x00, 0x01,
0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x74, 0xb5, 0x7e, 0xf0, 0x47, 0xee, 0xc0, 0xa8, 0x02, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
DumpPacket_t xPacket_0001 =
{
.pucData = ucPacket_0001,
.uxLength = 60,
.ulType = 0x6840, /* IN | FRAME_ARP | ARP | REQUEST */
};
/*-----------------------------------------------------------*/
tcp_dump_packets has an enum of all possible properties of network packets:
ICMP4, ICMP6, UDP, TCP, DNS, REPLY, REQUEST, SYN,
FIN, RST, ACK, IN, OUT, ARP, FRAME_ARP, FRAME_4, and FRAME_6
Each property is defined as a bit so they can be combined as in:
.ulType = 0x6840, /* IN | FRAME_ARP | ARP | REQUEST */
Finishing: when there are enough packets of all required types, an array is added to the C-source output:
DumpPacket_t *xPacketList[ dumpPACKET_COUNT ] =
{
&xPacket_0000,
&xPacket_0001,
&xPacket_0002,
&xPacket_0003,
&xPacket_0004,
&xPacket_0005,
&xPacket_0006,
&xPacket_0007,
&xPacket_0008,
};
The new source file PacketList.{c, h} can be used in testing software as sample packets.

View File

@ -0,0 +1,465 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/*
* tcp_mem_stats.c
* Used to create a CSV file with detailed information about the memory usage of FreeRTOS+TCP.
* See tools/tcp_mem_stats.md for further description.
*/
/* Standard includes. */
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
/* FreeRTOS includes. */
#include <FreeRTOS.h>
#include "task.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_Stream_Buffer.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_IP_Private.h"
#include "tcp_mem_stats.h"
#if ( ipconfigUSE_TCP_MEM_STATS != 0 )
#ifndef ipconfigTCP_MEM_STATS_MAX_ALLOCATION
/* Define the maximum number of objects ( memory allocations by
* the IP-stack ) that will be recorded. */
#define ipconfigTCP_MEM_STATS_MAX_ALLOCATION 128u
/* If you don't want to see this pragma message, you can either
* remove it or define 'ipconfigTCP_MEM_STATS_MAX_ALLOCATION' in
* your freeRTOSIPConfig.h. */
#pragma message ("ipconfigTCP_MEM_STATS_MAX_ALLOCATION undefined?")
#endif
/* When a streambuffer is allocated, 4 extra bytes will be reserved. */
#define STREAM_BUFFER_ROUNDUP_BYTES 4
#define STATS_PRINTF( MSG ) \
xCurrentLine++; \
configPRINTF( MSG )
#define ETH_MAX_PACKET_SIZE ( ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER + ipBUFFER_PADDING + 31 ) & ~0x1FuL )
/*-----------------------------------------------------------*/
/* Objects are allocated and deleted. This structure stores the type
* and the size of the object. */
typedef struct xTCP_ALLOCATION
{
TCP_MEMORY_t xMemType;
void * pxObject;
UBaseType_t uxNumber;
size_t uxSize;
} TCP_ALLOCATION_t;
/*-----------------------------------------------------------*/
static void vWriteHeader( void );
static size_t uxCurrentMallocSize;
static TCP_ALLOCATION_t xAllocations[ ipconfigTCP_MEM_STATS_MAX_ALLOCATION ];
static size_t uxAllocationCount;
static BaseType_t xFirstItem = pdTRUE;
UBaseType_t uxNextObjectNumber;
static BaseType_t xCurrentLine = 0;
static BaseType_t xFirstDumpLine = 0;
static BaseType_t xLastHeaderLineNr = 0;
static BaseType_t xLoggingStopped = 0;
/*-----------------------------------------------------------*/
static void vAddAllocation( TCP_MEMORY_t xMemType,
void * pxObject,
size_t uxSize )
{
size_t uxIndex;
vTaskSuspendAll();
{
for( uxIndex = 0; uxIndex < uxAllocationCount; uxIndex++ )
{
if( xAllocations[ uxIndex ].pxObject == pxObject )
{
/* Already added, strange. */
FreeRTOS_printf( ( "vAddAllocation: Pointer %p already added\n", pxObject ) );
break;
}
}
/* If the object has not been found,
* and if there is still space, add the object. */
if( ( uxIndex == uxAllocationCount ) &&
( uxAllocationCount < ipconfigTCP_MEM_STATS_MAX_ALLOCATION ) )
{
xAllocations[ uxIndex ].pxObject = pxObject;
xAllocations[ uxIndex ].xMemType = xMemType;
xAllocations[ uxIndex ].uxSize = uxSize;
xAllocations[ uxIndex ].uxNumber = uxNextObjectNumber++;
uxAllocationCount++;
}
}
xTaskResumeAll();
}
/*-----------------------------------------------------------*/
static TCP_ALLOCATION_t * pxRemoveAllocation( void * pxObject )
{
size_t uxSource = 0, uxTarget = 0;
static TCP_ALLOCATION_t xAllocation = { 0 };
BaseType_t xFound = pdFALSE;
TCP_ALLOCATION_t * pxReturn;
vTaskSuspendAll();
{
for( ; uxSource < uxAllocationCount; uxSource++ )
{
if( xAllocations[ uxSource ].pxObject == pxObject )
{
/* This is entry will be removed. */
( void ) memcpy( &( xAllocation ), &( xAllocations[ uxSource ] ), sizeof xAllocation );
xFound = pdTRUE;
}
else
{
xAllocations[ uxTarget ] = xAllocations[ uxSource ];
uxTarget++;
}
}
if( xFound != pdFALSE )
{
uxAllocationCount--;
pxReturn = &( xAllocation );
}
else
{
pxReturn = NULL;
}
}
xTaskResumeAll();
return pxReturn;
}
/*-----------------------------------------------------------*/
static const char * pcTypeName( TCP_MEMORY_t xMemType )
{
switch( xMemType )
{
case tcpSOCKET_TCP:
return "TCP-Socket";
case tcpSOCKET_UDP:
return "UDP-Socket";
case tcpSOCKET_SET:
return "SocketSet";
case tcpSEMAPHORE:
return "Semaphore";
case tcpRX_STREAM_BUFFER:
return "RX-Buffer";
case tcpTX_STREAM_BUFFER:
return "TX-Buffer";
case tcpNETWORK_BUFFER:
return "networkBuffer";
}
return "Unknown object";
}
/*-----------------------------------------------------------*/
static void vWriteHeader()
{
size_t uxPacketSize;
size_t uxTXSize;
size_t uxStaticSize = 0;
BaseType_t xFirstLineNr = 0;
char pucComment[ 64 ] = "";
StreamBuffer_t * pxBuffer = NULL;
size_t uxTara = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray );
/* The approximate size of a buffer for a Network Packet. */
STATS_PRINTF( ( "TCPMemStat,Some important ipconfig items:\n" ) );
STATS_PRINTF( ( "TCPMemStat,ipconfig item,Value,Comment\n" ) );
STATS_PRINTF( ( "TCPMemStat,NETWORK_MTU,%u\n", ipconfigNETWORK_MTU ) );
STATS_PRINTF( ( "TCPMemStat,TCP_MSS,%u\n", ipconfigTCP_MSS ) );
STATS_PRINTF( ( "TCPMemStat,USE_TCP,%u\n", ipconfigUSE_TCP ) );
STATS_PRINTF( ( "TCPMemStat,USE_TCP_WIN,%u\n", ipconfigUSE_TCP_WIN ) );
uxTXSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );
STATS_PRINTF( ( "TCPMemStat,TCP_RX_BUFFER_LENGTH,%u,Plus %u bytes\n", ipconfigTCP_RX_BUFFER_LENGTH, uxTara + STREAM_BUFFER_ROUNDUP_BYTES ) );
if( uxTXSize > ipconfigTCP_TX_BUFFER_LENGTH )
{
snprintf( pucComment, sizeof pucComment, ",Rounded up to %u x MSS (plus %u bytes)", uxTXSize / ipconfigTCP_MSS, uxTara + STREAM_BUFFER_ROUNDUP_BYTES );
}
STATS_PRINTF( ( "TCPMemStat,TCP_TX_BUFFER_LENGTH,%u%s\n", ipconfigTCP_TX_BUFFER_LENGTH, pucComment ) );
STATS_PRINTF( ( "TCPMemStat,USE_DHCP,%u\n", ipconfigUSE_DHCP ) );
/*
* Start of fixed RAM allocations.
*/
STATS_PRINTF( ( "TCPMemStat,\n" ) );
STATS_PRINTF( ( "TCPMemStat,RAM that is always allocated either statically or on the heap:\n" ) );
STATS_PRINTF( ( "TCPMemStat,ipconfig item,Value,PerUnit,Total\n" ) );
xFirstLineNr = xCurrentLine;
if( xBufferAllocFixedSize != 0 )
{
size_t uxBytes;
/* Using BufferAllocation_1.c */
uxPacketSize = ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER + ipBUFFER_PADDING + 31 ) & ~0x1FuL;
uxBytes = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ( uxPacketSize + sizeof( NetworkBufferDescriptor_t ) );
STATS_PRINTF( ( "TCPMemStat,NUM_NETWORK_BUFFER_DESCRIPTORS,%u,%u,=B%d*C%d,Descriptors + buffers\n",
ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS,
uxPacketSize + sizeof( NetworkBufferDescriptor_t ),
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
}
else
{
size_t uxBytes;
/* Using BufferAllocation_2.c */
uxBytes = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * sizeof( NetworkBufferDescriptor_t );
STATS_PRINTF( ( "TCPMemStat,NUM_NETWORK_BUFFER_DESCRIPTORS,%u,%u,=B%d*C%d,Descriptors only\n",
ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS,
sizeof( NetworkBufferDescriptor_t ),
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
}
{
#if ( ipconfigUSE_TCP_WIN != 0 )
{
STATS_PRINTF( ( "TCPMemStat,TCP_WIN_SEG_COUNT,%u,%u,=B%d*C%d\n",
ipconfigTCP_WIN_SEG_COUNT, sizeof( TCPSegment_t ), xCurrentLine, xCurrentLine ) );
}
#else
{
STATS_PRINTF( ( "TCPMemStat,TCP_WIN_SEG_COUNT,%u,%u\n", 0, 0 ) );
}
#endif
}
{
size_t uxBytes;
size_t uxEntrySize;
uxBytes = ipconfigEVENT_QUEUE_LENGTH * sizeof( IPStackEvent_t );
STATS_PRINTF( ( "TCPMemStat,EVENT_QUEUE_LENGTH,%u,%u,=B%d*C%d\n",
ipconfigEVENT_QUEUE_LENGTH,
sizeof( IPStackEvent_t ),
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
uxBytes = ipconfigIP_TASK_STACK_SIZE_WORDS * sizeof( void * );
STATS_PRINTF( ( "TCPMemStat,IP_TASK_STACK_SIZE_WORDS,%u,%u,=B%d*C%d\n",
ipconfigIP_TASK_STACK_SIZE_WORDS,
sizeof( void * ),
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
uxBytes = ipconfigARP_CACHE_ENTRIES * sizeof( ARPCacheRow_t );
STATS_PRINTF( ( "TCPMemStat,ARP_CACHE_ENTRIES,%u,%u,=B%d*C%d\n",
ipconfigARP_CACHE_ENTRIES,
sizeof( ARPCacheRow_t ),
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
#if ( ipconfigUSE_DNS_CACHE == 1 )
{
uxEntrySize = 3u * sizeof( uint32_t ) + ( ( ipconfigDNS_CACHE_NAME_LENGTH + 3 ) & ~0x3u );
STATS_PRINTF( ( "TCPMemStat,DNS_CACHE_ENTRIES,%u,%u,=B%d*C%d\n",
ipconfigDNS_CACHE_ENTRIES,
uxEntrySize,
xCurrentLine,
xCurrentLine ) );
}
#endif
}
/*
* End of fixed RAM allocations.
*/
if( xBufferAllocFixedSize != 0 )
{
pucComment[ 0 ] = 0;
}
else
{
size_t uxBytes;
/* BufferAllocation_2.c uses HEAP to store network packets. */
uxPacketSize = ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER + ipBUFFER_PADDING + 3 ) & ~0x03uL;
uxBytes = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * uxPacketSize;
STATS_PRINTF( ( "TCPMemStat,Network buffers in HEAP,%u,%u,=B%d*C%d\n",
ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS,
uxPacketSize,
xCurrentLine,
xCurrentLine ) );
uxStaticSize += uxBytes;
snprintf( pucComment, sizeof pucComment, "Actual size fluctuates because BufferAllocation_2.c is used" );
}
xLastHeaderLineNr = xCurrentLine;
STATS_PRINTF( ( "TCPMemStat,Total,,,=SUM(D%d:D%d),%s\n", xFirstLineNr + 1, xLastHeaderLineNr, pucComment ) );
STATS_PRINTF( ( "TCPMemStat,\n" ) );
STATS_PRINTF( ( "TCPMemStat,\n" ) );
STATS_PRINTF( ( "TCPMemStat,The following allocations are done on the heap while running:\n" ) );
STATS_PRINTF( ( "TCPMemStat,Create/Remove,Object,Size,Heap use,Pointer,Heap-min,Heap-Cur,comment\n" ) );
}
/*-----------------------------------------------------------*/
void vTCPMemStatCreate( TCP_MEMORY_t xMemType,
void * pxObject,
size_t uxSize )
{
if( xLoggingStopped == pdFALSE )
{
StreamBuffer_t * pxBuffer = NULL;
char pcExtra[ 81 ] = "";
if( xFirstItem != pdFALSE )
{
xFirstItem = pdFALSE;
vWriteHeader();
}
if( ( xMemType == tcpRX_STREAM_BUFFER ) || ( xMemType == tcpTX_STREAM_BUFFER ) )
{
size_t uxTara = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray );
size_t uxNett = uxSize - uxTara;
snprintf( pcExtra, sizeof pcExtra, ",%u nett", uxNett );
}
if( xFirstDumpLine == 0 )
{
xFirstDumpLine = xCurrentLine + 1;
}
xCurrentLine++;
configPRINTF( ( "TCPMemStat,CREATE,%s,%lu,%lu,%u,%u,%u%s\n",
pcTypeName( xMemType ),
uxSize,
uxCurrentMallocSize + uxSize,
uxNextObjectNumber,
xPortGetMinimumEverFreeHeapSize(),
xPortGetFreeHeapSize(),
pcExtra ) );
uxCurrentMallocSize += uxSize;
vAddAllocation( xMemType, pxObject, uxSize );
}
}
/*-----------------------------------------------------------*/
void vTCPMemStatDelete( void * pxObject )
{
if( xLoggingStopped == pdFALSE )
{
TCP_ALLOCATION_t * pxFound = pxRemoveAllocation( pxObject );
if( xFirstDumpLine == 0 )
{
xFirstDumpLine = xCurrentLine + 1;
}
if( pxFound == NULL )
{
FreeRTOS_printf( ( "TCPMemStat: can not find pointer %p\n", pxObject ) );
}
else
{
xCurrentLine++;
configPRINTF( ( "TCPMemStat,REMOVE,%s,-%lu,%lu,%x,%u,%u\n",
pcTypeName( pxFound->xMemType ),
pxFound->uxSize,
uxCurrentMallocSize - pxFound->uxSize,
pxFound->uxNumber,
xPortGetMinimumEverFreeHeapSize(),
xPortGetFreeHeapSize() ) );
if( uxCurrentMallocSize < pxFound->uxSize )
{
uxCurrentMallocSize = 0uL;
}
else
{
uxCurrentMallocSize -= pxFound->uxSize;
}
}
}
}
/*-----------------------------------------------------------*/
void vTCPMemStatClose()
{
if( xLoggingStopped == pdFALSE )
{
/* name;object;size;Heap;Ppointer;HeapMin;HeapDur;Comment */
BaseType_t xLastLineNr = xCurrentLine;
xLoggingStopped = pdTRUE;
STATS_PRINTF( ( "TCPMemStat,Totals,,,=MAX(D%d:D%d),,=MIN(F%d:F%d),=MAX(G%d:G%d)\n",
xFirstDumpLine,
xLastLineNr,
xFirstDumpLine,
xLastLineNr,
xFirstDumpLine,
xLastLineNr ) );
STATS_PRINTF( ( "TCPMemStat,Maximum RAM usage:,,,=SUM(D%d;D%d)\n",
xLastHeaderLineNr + 1,
xLastLineNr + 1 ) );
}
}
/*-----------------------------------------------------------*/
#endif /* ( ipconfigUSE_TCP_MEM_STATS != 0 ) */

View File

@ -0,0 +1,45 @@
tcp_mem_stats.c : FreeRTOS+TCP Memory Statistics
This module can be used in any project on any platform that uses FreeRTOS+TCP.
It creates an overview of the memory usage of FreeRTOS+TCP.
It reports the static use of RAM, and also the dynamic usage ( heap ).
It relates these numbers to the macro's defined `FreeRTOSIPConfig.h`.
It writes CSV records to the logging with configPRINTF().
The resulting log can be filtered by e.g.:
cat logging.txt | grep ".*TCPMemStat," | sed "s/.*TCPMemStat,//"
The resulting text can be imported into any spreadsheet at cell "A1" ( top-left ):
ipconfig item,Value,PerUnit,Total
NUM_NETWORK_BUFFER_DESCRIPTORS,12,60,=B13*C13,Descriptors only
TCP_WIN_SEG_COUNT,32,64,=B14*C14
EVENT_QUEUE_LENGTH,17,8,=B15*C15
IP_TASK_STACK_SIZE_WORDS,300,4,=B16*C16
When the CSV-records are imported at another row or column than "A1", the formulas will be incorrect.
How to include 'tcp_mem_stats' into a project:
● Add tools/tcp_sources/tcp_mem_stats.c to the sources
● Add the following lines to FreeRTOSIPConfig.h :
#define ipconfigUSE_TCP_MEM_STATS ( 1 )
#define ipconfigTCP_MEM_STATS_MAX_ALLOCATION ( 128 )
#include "tools/tcp_sources/include/tcp_mem_stats.h"
Later on, the module can disabled by setting `#define ipconfigUSE_TCP_MEM_STATS 0`.
`ipconfigTCP_MEM_STATS_MAX_ALLOCATION` is the maximum number of objects that can be followed at any time.
A socket that has 2 stream buffers counts as 3 objects ( needing 3 x 16 = 48 bytes to store their properties ).
The **summary** at the bottom will only be written when `iptraceMEM_STATS_CLOSE()` is called.
The application is responsible for calling `iptraceMEM_STATS_CLOSE()`.
The summary at the bottom looks like this:
Totals,,,=MAX(D25:D31),,=MIN(F25:F31),=MAX(G25:G31)
Maximum RAM usage:,,,=SUM(D20;D32)
The spreadsheet can be edited further to make estimations with different macro values.

View File

@ -0,0 +1,197 @@
/*
* FreeRTOS+TCP V3.1.0
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "tcp_netstat.h"
extern List_t xBoundUDPSocketsList;
#if ( ipconfigUSE_TCP == 1 )
extern List_t xBoundTCPSocketsList;
#endif /* ipconfigUSE_TCP == 1 */
IOCounters_t xInputCounters = { 0U };
IOCounters_t xOutputCounters = { 0U };
BaseType_t vGetMetrics( MetricsType_t * pxMetrics )
{
BaseType_t xResult = 0;
/* Show a simple listing of all created sockets and their connections */
const ListItem_t * pxIterator;
uint16_t usLastPort;
memset( pxMetrics, 0, sizeof *pxMetrics );
pxMetrics->xInput = xInputCounters;
pxMetrics->xOutput = xOutputCounters;
if( !listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) )
{
FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );
xResult = -1;
}
else
{
#if ( ipconfigUSE_TCP == 1 )
const ListItem_t * pxEndTCP = listGET_END_MARKER( &xBoundTCPSocketsList );
#endif
const ListItem_t * pxEndUDP = listGET_END_MARKER( &xBoundUDPSocketsList );
usLastPort = 0U;
#if ( ipconfigUSE_TCP == 1 )
{
vTaskSuspendAll();
{
for( pxIterator = listGET_HEAD_ENTRY( &xBoundTCPSocketsList );
pxIterator != pxEndTCP;
pxIterator = listGET_NEXT( pxIterator ) )
{
const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
if( pxMetrics->xTCPPortList.uxCount < nstatMAX_TCP_PORTS )
{
if( usLastPort != pxSocket->usLocalPort )
{
pxMetrics->xTCPPortList.usTCPPortList[ pxMetrics->xTCPPortList.uxCount ] = pxSocket->usLocalPort;
pxMetrics->xTCPPortList.uxCount++;
usLastPort = pxSocket->usLocalPort;
}
}
if( pxMetrics->xTCPSocketList.uxCount < nstatMAX_TCP_PORTS )
{
size_t uxCount = pxMetrics->xTCPSocketList.uxCount;
pxMetrics->xTCPSocketList.xTCPList[ uxCount ].usLocalPort = pxSocket->usLocalPort;
pxMetrics->xTCPSocketList.xTCPList[ uxCount ].ulRemoteIP = pxSocket->u.xTCP.ulRemoteIP;
pxMetrics->xTCPSocketList.xTCPList[ uxCount ].usRemotePort = pxSocket->u.xTCP.usRemotePort;
pxMetrics->xTCPSocketList.uxCount++;
}
}
}
if( xTaskResumeAll() == 0 )
{
taskYIELD();
}
}
#endif /* ( ipconfigUSE_TCP == 1 ) */
vTaskSuspendAll();
{
for( pxIterator = listGET_HEAD_ENTRY( &xBoundUDPSocketsList );
pxIterator != pxEndUDP;
pxIterator = listGET_NEXT( pxIterator ) )
{
const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
if( pxMetrics->xUDPPortList.uxCount < nstatMAX_UDP_PORTS )
{
pxMetrics->xUDPPortList.usUDPPortList[ pxMetrics->xUDPPortList.uxCount ] = pxSocket->usLocalPort;
pxMetrics->xUDPPortList.uxCount++;
}
if( pxMetrics->xUDPSocketList.uxCount < nstatMAX_UDP_PORTS )
{
size_t uxCount = pxMetrics->xUDPSocketList.uxCount;
pxMetrics->xUDPSocketList.xUDPList[ uxCount ].usLocalPort = pxSocket->usLocalPort;
pxMetrics->xUDPSocketList.uxCount++;
}
}
}
( void ) xTaskResumeAll();
}
return xResult;
}
void vShowMetrics( const MetricsType_t * pxMetrics )
{
size_t uxIndex;
FreeRTOS_printf( ( "Bytes in/out:\n" ) );
FreeRTOS_printf( ( " Input : %5lu packets, %5lu bytes\n",
pxMetrics->xInput.uxPacketCount,
pxMetrics->xInput.uxByteCount ) );
FreeRTOS_printf( ( " Output : %5lu packets, %5lu bytes\n",
pxMetrics->xOutput.uxPacketCount,
pxMetrics->xOutput.uxByteCount ) );
#if ( ipconfigUSE_TCP == 1 )
{
FreeRTOS_printf( ( "TCP ports:\n" ) );
for( uxIndex = 0; uxIndex < pxMetrics->xTCPPortList.uxCount; uxIndex++ )
{
FreeRTOS_printf( ( " local port: %u\n",
pxMetrics->xTCPPortList.usTCPPortList[ uxIndex ] ) );
}
FreeRTOS_printf( ( "TCP sockets:\n" ) );
for( uxIndex = 0; uxIndex < pxMetrics->xTCPSocketList.uxCount; uxIndex++ )
{
FreeRTOS_printf( ( " local port: %u remote IP %xip:%u\n",
pxMetrics->xTCPSocketList.xTCPList[ uxIndex ].usLocalPort,
pxMetrics->xTCPSocketList.xTCPList[ uxIndex ].ulRemoteIP,
pxMetrics->xTCPSocketList.xTCPList[ uxIndex ].usRemotePort ) );
}
}
#endif /* ( ipconfigUSE_TCP == 1 ) */
FreeRTOS_printf( ( "UDP ports:\n" ) );
for( uxIndex = 0; uxIndex < pxMetrics->xUDPPortList.uxCount; uxIndex++ )
{
FreeRTOS_printf( ( " local port: %u\n",
pxMetrics->xUDPPortList.usUDPPortList[ uxIndex ] ) );
}
FreeRTOS_printf( ( "UDP sockets:\n" ) );
for( uxIndex = 0; uxIndex < pxMetrics->xUDPSocketList.uxCount; uxIndex++ )
{
FreeRTOS_printf( ( " local port: %u\n",
pxMetrics->xUDPSocketList.xUDPList[ uxIndex ].usLocalPort ) );
}
}

View File

@ -0,0 +1,19 @@
tcp_netstat.c : it introduces the following function:
`BaseType_t vGetMetrics( MetricsType_t * pxMetrics )`
It collects information: all port numbers in use, all UDP sockets, all TCP sockets and their connections.
Make sure that your FreeRTOSIPConfig.h includes tools/tcp_utilities/include/tcp_netstat.h:
`@include "tcp_netstat.h"`
because it will define 2 important macro's:
#define iptraceNETWORK_INTERFACE_INPUT( uxDataLength, pucEthernetBuffer )
#define iptraceNETWORK_INTERFACE_OUTPUT( uxDataLength, pucEthernetBuffer )
These macro's will be called when an Ethernet packet has been received or sent.
When collecting socket and port information, it will iterate through the list of sockets, filling arrays of structures.