Sync with a:FR (#75)

* AFR sync

* AFR sync: CBMC

* AFR sync: CBMC: remove .bak files

* AFR sync: CBMC: more cleanup

* Corrected CBMC proofs

* Corrected CBMC patches

* Corrected CBMC patches-1

* Corrected CBMC patches-2

* remove .bak files (3)

Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com>
This commit is contained in:
Aniruddha Kanhere 2020-05-28 10:11:58 -07:00 committed by GitHub
parent 6557291e54
commit cb7edd2323
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
99 changed files with 6475 additions and 4241 deletions

View file

@ -43,18 +43,18 @@
#if( ipconfigUSE_LLMNR == 1 ) #if( ipconfigUSE_LLMNR == 1 )
#include "FreeRTOS_DNS.h" #include "FreeRTOS_DNS.h"
#endif /* ipconfigUSE_LLMNR */ #endif /* ipconfigUSE_LLMNR */
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
/* When the age of an entry in the ARP table reaches this value (it counts down /* When the age of an entry in the ARP table reaches this value (it counts down
* to zero, so this is an old entry) an ARP request will be sent to see if the to zero, so this is an old entry) an ARP request will be sent to see if the
* entry is still valid and can therefore be refreshed. */ entry is still valid and can therefore be refreshed. */
#define arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST ( 3 ) #define arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST ( 3 )
/* The time between gratuitous ARPs. */ /* The time between gratuitous ARPs. */
#ifndef arpGRATUITOUS_ARP_PERIOD #ifndef arpGRATUITOUS_ARP_PERIOD
#define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS( 20000 ) ) #define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS( 20000U ) )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -70,7 +70,7 @@ static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress
static ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ]; static ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ];
/* The time at which the last gratuitous ARP was sent. Gratuitous ARPs are used /* The time at which the last gratuitous ARP was sent. Gratuitous ARPs are used
* to ensure ARP tables are up to date and to detect IP address conflicts. */ to ensure ARP tables are up to date and to detect IP address conflicts. */
static TickType_t xLastGratuitousARPTime = ( TickType_t ) 0; static TickType_t xLastGratuitousARPTime = ( TickType_t ) 0;
/* /*
@ -96,28 +96,28 @@ uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
pxARPHeader = &( pxARPFrame->xARPHeader ); pxARPHeader = &( pxARPFrame->xARPHeader );
/* The field ulSenderProtocolAddress is badly aligned, copy byte-by-byte. */ /* The field ulSenderProtocolAddress is badly aligned, copy byte-by-byte. */
( void ) memcpy( ( void * )&( ulSenderProtocolAddress ), ( const void * ) pxARPHeader->ucSenderProtocolAddress, sizeof( ulSenderProtocolAddress ) ); ( void ) memcpy( &( ulSenderProtocolAddress ), pxARPHeader->ucSenderProtocolAddress, sizeof( ulSenderProtocolAddress ) );
/* The field ulTargetProtocolAddress is well-aligned, a 32-bits copy. */ /* The field ulTargetProtocolAddress is well-aligned, a 32-bits copy. */
ulTargetProtocolAddress = pxARPHeader->ulTargetProtocolAddress; ulTargetProtocolAddress = pxARPHeader->ulTargetProtocolAddress;
traceARP_PACKET_RECEIVED(); traceARP_PACKET_RECEIVED();
/* Don't do anything if the local IP address is zero because /* Don't do anything if the local IP address is zero because
* that means a DHCP request has not completed. */ that means a DHCP request has not completed. */
if( *ipLOCAL_IP_ADDRESS_POINTER != 0UL ) if( *ipLOCAL_IP_ADDRESS_POINTER != 0UL )
{ {
switch( pxARPHeader->usOperation ) switch( pxARPHeader->usOperation )
{ {
case ipARP_REQUEST : case ipARP_REQUEST :
/* The packet contained an ARP request. Was it for the IP /* The packet contained an ARP request. Was it for the IP
* address of the node running this code? */ address of the node running this code? */
if( ulTargetProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER ) if( ulTargetProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )
{ {
iptraceSENDING_ARP_REPLY( ulSenderProtocolAddress ); iptraceSENDING_ARP_REPLY( ulSenderProtocolAddress );
/* The request is for the address of this node. Add the /* The request is for the address of this node. Add the
* entry into the ARP cache, or refresh the entry if it entry into the ARP cache, or refresh the entry if it
* already exists. */ already exists. */
vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress ); vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );
/* Generate a reply payload in the same buffer. */ /* Generate a reply payload in the same buffer. */
@ -126,17 +126,17 @@ uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
{ {
/* A double IP address is detected! */ /* A double IP address is detected! */
/* Give the sources MAC address the value of the broadcast address, will be swapped later */ /* Give the sources MAC address the value of the broadcast address, will be swapped later */
( void ) memcpy( ( void * ) pxARPFrame->xEthernetHeader.xSourceAddress.ucBytes, ( const void * ) xBroadcastMACAddress.ucBytes, sizeof( xBroadcastMACAddress ) ); ( void ) memcpy( pxARPFrame->xEthernetHeader.xSourceAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( xBroadcastMACAddress ) );
( void ) memset( pxARPHeader->xTargetHardwareAddress.ucBytes, 0, sizeof( MACAddress_t ) ); ( void ) memset( pxARPHeader->xTargetHardwareAddress.ucBytes, 0, sizeof( MACAddress_t ) );
pxARPHeader->ulTargetProtocolAddress = 0UL; pxARPHeader->ulTargetProtocolAddress = 0UL;
} }
else else
{ {
( void ) memcpy( ( void * ) pxARPHeader->xTargetHardwareAddress.ucBytes, ( const void * ) pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( MACAddress_t ) ); ( void ) memcpy( pxARPHeader->xTargetHardwareAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( MACAddress_t ) );
pxARPHeader->ulTargetProtocolAddress = ulSenderProtocolAddress; pxARPHeader->ulTargetProtocolAddress = ulSenderProtocolAddress;
} }
( void ) memcpy( ( void * ) pxARPHeader->xSenderHardwareAddress.ucBytes, ( const void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); ( void ) memcpy( pxARPHeader->xSenderHardwareAddress.ucBytes, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
( void ) memcpy( ( void * ) pxARPHeader->ucSenderProtocolAddress, ( const void * ) ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPHeader->ucSenderProtocolAddress ) ); ( void ) memcpy( pxARPHeader->ucSenderProtocolAddress, ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPHeader->ucSenderProtocolAddress ) );
eReturn = eReturnEthernetFrame; eReturn = eReturnEthernetFrame;
} }
@ -151,7 +151,8 @@ uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
if( ulSenderProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER ) if( ulSenderProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )
{ {
xARPHadIPClash = pdTRUE; xARPHadIPClash = pdTRUE;
( void ) memcpy( ( void * ) xARPClashMacAddress.ucBytes, ( const void * ) pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( xARPClashMacAddress.ucBytes ) ); /* Remember the MAC-address of the other device which has the same IP-address. */
( void ) memcpy( xARPClashMacAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( xARPClashMacAddress.ucBytes ) );
} }
} }
#endif /* ipconfigARP_USE_CLASH_DETECTION */ #endif /* ipconfigARP_USE_CLASH_DETECTION */
@ -201,17 +202,18 @@ uint8_t ucMinAgeFound = 0U;
#if( ipconfigARP_STORES_REMOTE_ADDRESSES == 0 ) #if( ipconfigARP_STORES_REMOTE_ADDRESSES == 0 )
/* Only process the IP address if it is on the local network. /* Only process the IP address if it is on the local network.
* Unless: when '*ipLOCAL_IP_ADDRESS_POINTER' equals zero, the IP-address Unless: when '*ipLOCAL_IP_ADDRESS_POINTER' equals zero, the IP-address
* and netmask are still unknown. */ and netmask are still unknown. */
if( ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ) || if( ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ) ||
( *ipLOCAL_IP_ADDRESS_POINTER == 0UL ) ) ( *ipLOCAL_IP_ADDRESS_POINTER == 0UL ) )
#else #else
/* If ipconfigARP_STORES_REMOTE_ADDRESSES is non-zero, IP addresses with /* If ipconfigARP_STORES_REMOTE_ADDRESSES is non-zero, IP addresses with
* a different netmask will also be stored. After when replying to a UDP a different netmask will also be stored. After when replying to a UDP
* message from a different netmask, the IP address can be looped up and a message from a different netmask, the IP address can be looped up and a
* reply sent. This option is useful for systems with multiple gateways, reply sent. This option is useful for systems with multiple gateways,
* the reply will surely arrive. If ipconfigARP_STORES_REMOTE_ADDRESSES is the reply will surely arrive. If ipconfigARP_STORES_REMOTE_ADDRESSES is
* zero the the gateway address is the only option. */ zero the the gateway address is the only option. */
if( pdTRUE ) if( pdTRUE )
#endif #endif
{ {
@ -221,47 +223,64 @@ uint8_t ucMinAgeFound = 0U;
/* For each entry in the ARP cache table. */ /* For each entry in the ARP cache table. */
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ ) for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{ {
BaseType_t xMatchingMAC;
if( pxMACAddress != NULL )
{
if( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 )
{
xMatchingMAC = pdTRUE;
}
else
{
xMatchingMAC = pdFALSE;
}
}
else
{
xMatchingMAC = pdFALSE;
}
/* Does this line in the cache table hold an entry for the IP /* Does this line in the cache table hold an entry for the IP
* address being queried? */ address being queried? */
if( xARPCache[ x ].ulIPAddress == ulIPAddress ) if( xARPCache[ x ].ulIPAddress == ulIPAddress )
{ {
if( pxMACAddress == NULL ) if( pxMACAddress == NULL )
{ {
/* In case the parameter pxMACAddress is NULL, an entry will be reserved to /* In case the parameter pxMACAddress is NULL, an entry will be reserved to
* indicate that there is an outstanding ARP request, This entry will have indicate that there is an outstanding ARP request, This entry will have
* "ucValid == pdFALSE". */ "ucValid == pdFALSE". */
xIpEntry = x; xIpEntry = x;
break; break;
} }
/* See if the MAC-address also matches. */ /* See if the MAC-address also matches. */
if( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) if( xMatchingMAC != pdFALSE )
{ {
/* This function will be called for each received packet /* This function will be called for each received packet
* As this is by far the most common path the coding standard As this is by far the most common path the coding standard
* is relaxed in this case and a return is permitted as an is relaxed in this case and a return is permitted as an
* optimisation. */ optimisation. */
xARPCache[ x ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE; xARPCache[ x ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
xARPCache[ x ].ucValid = ( uint8_t ) pdTRUE; xARPCache[ x ].ucValid = ( uint8_t ) pdTRUE;
return; return;
} }
/* Found an entry containing ulIPAddress, but the MAC address /* Found an entry containing ulIPAddress, but the MAC address
* doesn't match. Might be an entry with ucValid==pdFALSE, waiting doesn't match. Might be an entry with ucValid=pdFALSE, waiting
* for an ARP reply. Still want to see if there is match with the for an ARP reply. Still want to see if there is match with the
* given MAC address.ucBytes. If found, either of the two entries given MAC address.ucBytes. If found, either of the two entries
* must be cleared. */ must be cleared. */
xIpEntry = x; xIpEntry = x;
} }
else if( ( pxMACAddress != NULL ) && ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) ) else if( xMatchingMAC != pdFALSE )
{ {
/* Found an entry with the given MAC-address, but the IP-address /* Found an entry with the given MAC-address, but the IP-address
* is different. Continue looping to find a possible match with is different. Continue looping to find a possible match with
* ulIPAddress. */ ulIPAddress. */
#if( ipconfigARP_STORES_REMOTE_ADDRESSES != 0 ) #if( ipconfigARP_STORES_REMOTE_ADDRESSES != 0 )
/* If ARP stores the MAC address of IP addresses outside the /* If ARP stores the MAC address of IP addresses outside the
* network, than the MAC address of the gateway should not be network, than the MAC address of the gateway should not be
* overwritten. */ overwritten. */
BaseType_t bIsLocal[ 2 ]; BaseType_t bIsLocal[ 2 ];
bIsLocal[ 0 ] = ( ( xARPCache[ x ].ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ); bIsLocal[ 0 ] = ( ( xARPCache[ x ].ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) );
bIsLocal[ 1 ] = ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ); bIsLocal[ 1 ] = ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) );
@ -274,19 +293,19 @@ uint8_t ucMinAgeFound = 0U;
#endif #endif
} }
/* _HT_ /* _HT_
* Shouldn't we test for xARPCache[ x ].ucValid == pdFALSE here ? */ Shouldn't we test for xARPCache[ x ].ucValid == pdFALSE here ? */
else if( xARPCache[ x ].ucAge < ucMinAgeFound ) else if( xARPCache[ x ].ucAge < ucMinAgeFound )
{ {
/* As the table is traversed, remember the table row that /* As the table is traversed, remember the table row that
* contains the oldest entry (the lowest age count, as ages are contains the oldest entry (the lowest age count, as ages are
* decremented to zero) so the row can be re-used if this function decremented to zero) so the row can be re-used if this function
* needs to add an entry that does not already exist. */ needs to add an entry that does not already exist. */
ucMinAgeFound = xARPCache[ x ].ucAge; ucMinAgeFound = xARPCache[ x ].ucAge;
xUseEntry = x; xUseEntry = x;
} }
else else
{ {
/* Do nothing. */ /* Nothing happes to this cache entry for now. */
} }
} }
@ -297,9 +316,9 @@ uint8_t ucMinAgeFound = 0U;
if( xIpEntry >= 0 ) if( xIpEntry >= 0 )
{ {
/* Both the MAC address as well as the IP address were found in /* Both the MAC address as well as the IP address were found in
* different locations: clear the entry which matches the different locations: clear the entry which matches the
* IP-address */ IP-address */
( void ) memset( &xARPCache[ xIpEntry ], 0, sizeof( xARPCache[ xIpEntry ] ) ); ( void ) memset( &( xARPCache[ xIpEntry ] ), 0, sizeof( ARPCacheRow_t ) );
} }
} }
else if( xIpEntry >= 0 ) else if( xIpEntry >= 0 )
@ -309,7 +328,7 @@ uint8_t ucMinAgeFound = 0U;
} }
else else
{ {
/* Do nothing! xUseEntry retains its value */ /* No matching entry found. */
} }
/* If the entry was not found, we use the oldest entry and set the IPaddress */ /* If the entry was not found, we use the oldest entry and set the IPaddress */
@ -317,7 +336,7 @@ uint8_t ucMinAgeFound = 0U;
if( pxMACAddress != NULL ) if( pxMACAddress != NULL )
{ {
( void ) memcpy( ( void * ) xARPCache[ xUseEntry ].xMACAddress.ucBytes, ( const void * ) pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ); ( void ) memcpy( xARPCache[ xUseEntry ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) );
iptraceARP_TABLE_ENTRY_CREATED( ulIPAddress, (*pxMACAddress) ); iptraceARP_TABLE_ENTRY_CREATED( ulIPAddress, (*pxMACAddress) );
/* And this entry does not need immediate attention */ /* And this entry does not need immediate attention */
@ -331,9 +350,7 @@ uint8_t ucMinAgeFound = 0U;
} }
else else
{ {
/* Do nothing. (pxMACAddress == NULL) and (xIPEntry > 0) /* Nothing will be stored. */
* Implies that an IP address was found but we don't have
* a MAC address for it. Therefore, no action required */
} }
} }
} }
@ -349,8 +366,8 @@ uint8_t ucMinAgeFound = 0U;
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ ) for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{ {
/* Does this row in the ARP cache table hold an entry for the MAC /* Does this row in the ARP cache table hold an entry for the MAC
* address being searched? */ address being searched? */
if( memcmp( ( void * ) pxMACAddress->ucBytes, ( const void * ) xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 ) if( memcmp( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
{ {
*pulIPAddress = xARPCache[ x ].ulIPAddress; *pulIPAddress = xARPCache[ x ].ulIPAddress;
eReturn = eARPCacheHit; eReturn = eARPCacheHit;
@ -368,27 +385,35 @@ eARPLookupResult_t eARPGetCacheEntry( uint32_t *pulIPAddress, MACAddress_t * con
{ {
eARPLookupResult_t eReturn; eARPLookupResult_t eReturn;
uint32_t ulAddressToLookup; uint32_t ulAddressToLookup;
ulAddressToLookup = *pulIPAddress;
#if( ipconfigUSE_LLMNR == 1 ) #if( ipconfigUSE_LLMNR == 1 )
if( *pulIPAddress == ipLLMNR_IP_ADDR ) /* Is in network byte order. */ if( ulAddressToLookup == ipLLMNR_IP_ADDR ) /* Is in network byte order. */
{ {
/* The LLMNR IP-address has a fixed virtual MAC address. */ /* The LLMNR IP-address has a fixed virtual MAC address. */
( void ) memcpy( ( void * ) pxMACAddress->ucBytes, ( const void * ) xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) ); ( void ) memcpy( pxMACAddress->ucBytes, xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit; eReturn = eARPCacheHit;
} }
else else
#endif #endif
if( ( *pulIPAddress == ipBROADCAST_IP_ADDRESS ) || /* Is it the general broadcast address 255.255.255.255? */ if( xIsIPv4Multicast( ulAddressToLookup ) != 0 )
{
/* Get the lowest 23 bits of the IP-address. */
vSetMultiCastIPv4MacAddress( ulAddressToLookup, pxMACAddress );
eReturn = eARPCacheHit;
}
else if( ( *pulIPAddress == ipBROADCAST_IP_ADDRESS ) || /* Is it the general broadcast address 255.255.255.255? */
( *pulIPAddress == xNetworkAddressing.ulBroadcastAddress ) )/* Or a local broadcast address, eg 192.168.1.255? */ ( *pulIPAddress == xNetworkAddressing.ulBroadcastAddress ) )/* Or a local broadcast address, eg 192.168.1.255? */
{ {
/* This is a broadcast so uses the broadcast MAC address. */ /* This is a broadcast so it uses the broadcast MAC address. */
( void ) memcpy( ( void * ) pxMACAddress->ucBytes, ( const void * ) xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) ); ( void ) memcpy( pxMACAddress->ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit; eReturn = eARPCacheHit;
} }
else if( *ipLOCAL_IP_ADDRESS_POINTER == 0UL ) else if( *ipLOCAL_IP_ADDRESS_POINTER == 0UL )
{ {
/* The IP address has not yet been assigned, so there is nothing that /* The IP address has not yet been assigned, so there is nothing that
* can be done. */ can be done. */
eReturn = eCantSendPacket; eReturn = eCantSendPacket;
} }
else else
@ -397,21 +422,22 @@ uint32_t ulAddressToLookup;
if( ( *pulIPAddress & xNetworkAddressing.ulNetMask ) != ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ) if( ( *pulIPAddress & xNetworkAddressing.ulNetMask ) != ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) )
{ {
/* No matching end-point is found, look for a gateway. */
#if( ipconfigARP_STORES_REMOTE_ADDRESSES == 1 ) #if( ipconfigARP_STORES_REMOTE_ADDRESSES == 1 )
eReturn = prvCacheLookup( *pulIPAddress, pxMACAddress ); eReturn = prvCacheLookup( *pulIPAddress, pxMACAddress );
if( eReturn == eARPCacheHit ) if( eReturn == eARPCacheHit )
{ {
/* The stack is configured to store 'remote IP addresses', i.e. addresses /* The stack is configured to store 'remote IP addresses', i.e. addresses
* belonging to a different the netmask. prvCacheLookup() returned a hit, so belonging to a different the netmask. prvCacheLookup() returned a hit, so
* the MAC address is known */ the MAC address is known. */
} }
else else
#endif #endif
{ {
/* The IP address is off the local network, so look up the /* The IP address is off the local network, so look up the
* hardware address of the router, if any. */ hardware address of the router, if any. */
if( xNetworkAddressing.ulGatewayAddress != ( uint32_t )0u ) if( xNetworkAddressing.ulGatewayAddress != ( uint32_t ) 0U )
{ {
ulAddressToLookup = xNetworkAddressing.ulGatewayAddress; ulAddressToLookup = xNetworkAddressing.ulGatewayAddress;
} }
@ -424,16 +450,20 @@ uint32_t ulAddressToLookup;
else else
{ {
/* The IP address is on the local network, so lookup the requested /* The IP address is on the local network, so lookup the requested
* IP address directly. */ IP address directly. */
ulAddressToLookup = *pulIPAddress; ulAddressToLookup = *pulIPAddress;
} }
if( eReturn == eARPCacheMiss ) #if( ipconfigARP_STORES_REMOTE_ADDRESSES == 1 )
if( eReturn == eARPCacheMiss ) /*lint !e774: (Info -- Boolean within 'if' always evaluates to True, depending on configuration. */
#else
/* No cache look-up was done, so the result is still 'eARPCacheMiss'. */
#endif
{ {
if( ulAddressToLookup == 0UL ) if( ulAddressToLookup == 0UL )
{ {
/* The address is not on the local network, and there is not a /* The address is not on the local network, and there is not a
* router. */ router. */
eReturn = eCantSendPacket; eReturn = eCantSendPacket;
} }
else else
@ -463,7 +493,7 @@ eARPLookupResult_t eReturn = eARPCacheMiss;
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ ) for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{ {
/* Does this row in the ARP cache table hold an entry for the IP address /* Does this row in the ARP cache table hold an entry for the IP address
* being queried? */ being queried? */
if( xARPCache[ x ].ulIPAddress == ulAddressToLookup ) if( xARPCache[ x ].ulIPAddress == ulAddressToLookup )
{ {
/* A matching valid entry was found. */ /* A matching valid entry was found. */
@ -475,7 +505,7 @@ eARPLookupResult_t eReturn = eARPCacheMiss;
else else
{ {
/* A valid entry was found. */ /* A valid entry was found. */
( void ) memcpy( ( void * ) pxMACAddress->ucBytes, ( const void * ) xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) ); ( void ) memcpy( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) );
eReturn = eARPCacheHit; eReturn = eARPCacheHit;
} }
break; break;
@ -498,11 +528,11 @@ TickType_t xTimeNow;
if( xARPCache[ x ].ucAge > 0U ) if( xARPCache[ x ].ucAge > 0U )
{ {
/* Decrement the age value of the entry in this ARP cache table row. /* Decrement the age value of the entry in this ARP cache table row.
* When the age reaches zero it is no longer considered valid. */ When the age reaches zero it is no longer considered valid. */
( xARPCache[ x ].ucAge )--; ( xARPCache[ x ].ucAge )--;
/* If the entry is not yet valid, then it is waiting an ARP /* If the entry is not yet valid, then it is waiting an ARP
* reply, and the ARP request should be retransmitted. */ reply, and the ARP request should be retransmitted. */
if( xARPCache[ x ].ucValid == ( uint8_t ) pdFALSE ) if( xARPCache[ x ].ucValid == ( uint8_t ) pdFALSE )
{ {
FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress ); FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress );
@ -510,7 +540,7 @@ TickType_t xTimeNow;
else if( xARPCache[ x ].ucAge <= ( uint8_t ) arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST ) else if( xARPCache[ x ].ucAge <= ( uint8_t ) arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST )
{ {
/* This entry will get removed soon. See if the MAC address is /* This entry will get removed soon. See if the MAC address is
* still valid to prevent this happening. */ still valid to prevent this happening. */
iptraceARP_TABLE_ENTRY_WILL_EXPIRE( xARPCache[ x ].ulIPAddress ); iptraceARP_TABLE_ENTRY_WILL_EXPIRE( xARPCache[ x ].ulIPAddress );
FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress ); FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress );
} }
@ -519,7 +549,7 @@ TickType_t xTimeNow;
/* The age has just ticked down, with nothing to do. */ /* The age has just ticked down, with nothing to do. */
} }
if( xARPCache[ x ].ucAge == 0u ) if( xARPCache[ x ].ucAge == 0U )
{ {
/* The entry is no longer valid. Wipe it out. */ /* The entry is no longer valid. Wipe it out. */
iptraceARP_TABLE_ENTRY_EXPIRED( xARPCache[ x ].ulIPAddress ); iptraceARP_TABLE_ENTRY_EXPIRED( xARPCache[ x ].ulIPAddress );
@ -541,7 +571,7 @@ TickType_t xTimeNow;
void vARPSendGratuitous( void ) void vARPSendGratuitous( void )
{ {
/* Setting xLastGratuitousARPTime to 0 will force a gratuitous ARP the next /* Setting xLastGratuitousARPTime to 0 will force a gratuitous ARP the next
* time vARPAgeCache() is called. */ time vARPAgeCache() is called. */
xLastGratuitousARPTime = ( TickType_t ) 0; xLastGratuitousARPTime = ( TickType_t ) 0;
/* Let the IP-task call vARPAgeCache(). */ /* Let the IP-task call vARPAgeCache(). */
@ -554,8 +584,8 @@ void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress )
NetworkBufferDescriptor_t *pxNetworkBuffer; NetworkBufferDescriptor_t *pxNetworkBuffer;
/* This is called from the context of the IP event task, so a block time /* This is called from the context of the IP event task, so a block time
* must not be used. */ must not be used. */
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( ARPPacket_t ), ( TickType_t )0 ); pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( ARPPacket_t ), ( TickType_t ) 0U );
if( pxNetworkBuffer != NULL ) if( pxNetworkBuffer != NULL )
{ {
@ -570,24 +600,17 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ ) for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
{ {
pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u; pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0U;
} }
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
} }
} }
#endif #endif
if( xIsCallingFromIPTask() != 0 ) if( xIsCallingFromIPTask() != 0 )
{ {
/* Only the IP-task is allowed to call this function directly. */ /* Only the IP-task is allowed to call this function directly. */
if( xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE ) != pdTRUE ) ( void ) xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
{
/* Not sent? Bad news. Maybe link is down? */
#if ( ipconfigHAS_DEBUG_PRINTF != 0 )
FreeRTOS_printf( ( "xNetworkInterfaceOutput failed. Link down?\n" ) );
#else
; /* Do nothing */
#endif
}
} }
else else
{ {
@ -595,7 +618,7 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
/* Send a message to the IP-task to send this ARP packet. */ /* Send a message to the IP-task to send this ARP packet. */
xSendEvent.eEventType = eNetworkTxEvent; xSendEvent.eEventType = eNetworkTxEvent;
xSendEvent.pvData = ( void * ) pxNetworkBuffer; xSendEvent.pvData = pxNetworkBuffer;
if( xSendEventStructToIPTask( &xSendEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL ) if( xSendEventStructToIPTask( &xSendEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )
{ {
/* Failed to send the message, so release the network buffer. */ /* Failed to send the message, so release the network buffer. */
@ -607,11 +630,9 @@ NetworkBufferDescriptor_t *pxNetworkBuffer;
void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer ) void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{ {
ARPPacket_t *pxARPPacket;
/* Part of the Ethernet and ARP headers are always constant when sending an IPv4 /* Part of the Ethernet and ARP headers are always constant when sending an IPv4
* ARP packet. This array defines the constant parts, allowing this part of the ARP packet. This array defines the constant parts, allowing this part of the
* packet to be filled in using a simple memcpy() instead of individual writes. */ packet to be filled in using a simple memcpy() instead of individual writes. */
static const uint8_t xDefaultPartARPPacketHeader[] = static const uint8_t xDefaultPartARPPacketHeader[] =
{ {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Ethernet destination address. */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Ethernet destination address. */
@ -627,31 +648,32 @@ static const uint8_t xDefaultPartARPPacketHeader[] =
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* xTargetHardwareAddress. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* xTargetHardwareAddress. */
}; };
ARPPacket_t *pxARPPacket;
/* Buffer allocation ensures that buffers always have space /* Buffer allocation ensures that buffers always have space
* for an ARP packet. See buffer allocation implementations 1 for an ARP packet. See buffer allocation implementations 1
* and 2 under portable/BufferManagement. */ and 2 under portable/BufferManagement. */
configASSERT( pxNetworkBuffer != NULL ); configASSERT( pxNetworkBuffer != NULL );
configASSERT( pxNetworkBuffer->xDataLength >= sizeof(ARPPacket_t) ); configASSERT( pxNetworkBuffer->xDataLength >= sizeof(ARPPacket_t) );
pxARPPacket = ( ARPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; pxARPPacket = ipPOINTER_CAST( ARPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
/* memcpy the const part of the header information into the correct /* memcpy the const part of the header information into the correct
* location in the packet. This copies: location in the packet. This copies:
* xEthernetHeader.ulDestinationAddress xEthernetHeader.ulDestinationAddress
* xEthernetHeader.usFrameType; xEthernetHeader.usFrameType;
* xARPHeader.usHardwareType; xARPHeader.usHardwareType;
* xARPHeader.usProtocolType; xARPHeader.usProtocolType;
* xARPHeader.ucHardwareAddressLength; xARPHeader.ucHardwareAddressLength;
* xARPHeader.ucProtocolAddressLength; xARPHeader.ucProtocolAddressLength;
* xARPHeader.usOperation; xARPHeader.usOperation;
* xARPHeader.xTargetHardwareAddress; xARPHeader.xTargetHardwareAddress;
*/ */
( void ) memcpy( pxARPPacket, xDefaultPartARPPacketHeader, sizeof( xDefaultPartARPPacketHeader ) );
( void ) memcpy( pxARPPacket->xEthernetHeader.xSourceAddress.ucBytes , ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
( void ) memcpy( pxARPPacket->xARPHeader.xSenderHardwareAddress.ucBytes, ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
( void ) memcpy( ( void * ) pxARPPacket, ( const void * )xDefaultPartARPPacketHeader, sizeof( xDefaultPartARPPacketHeader ) ); ( void ) memcpy( pxARPPacket->xARPHeader.ucSenderProtocolAddress, ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPPacket->xARPHeader.ucSenderProtocolAddress ) );
( void ) memcpy( ( void * ) pxARPPacket->xEthernetHeader.xSourceAddress.ucBytes, ( const void * ) ipLOCAL_MAC_ADDRESS, ( size_t )ipMAC_ADDRESS_LENGTH_BYTES );
( void ) memcpy( ( void * ) pxARPPacket->xARPHeader.xSenderHardwareAddress.ucBytes, ( const void * )ipLOCAL_MAC_ADDRESS, ( size_t )ipMAC_ADDRESS_LENGTH_BYTES );
( void ) memcpy( ( void * )pxARPPacket->xARPHeader.ucSenderProtocolAddress, ( const void * )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPPacket->xARPHeader.ucSenderProtocolAddress ) );
pxARPPacket->xARPHeader.ulTargetProtocolAddress = pxNetworkBuffer->ulIPAddress; pxARPPacket->xARPHeader.ulTargetProtocolAddress = pxNetworkBuffer->ulIPAddress;
pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t ); pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t );
@ -666,11 +688,53 @@ void FreeRTOS_ClearARP( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if 1
BaseType_t xCheckLoopback( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
{
BaseType_t xResult = pdFALSE;
NetworkBufferDescriptor_t * pxUseDescriptor = pxDescriptor;
const IPPacket_t *pxIPPacket = ipPOINTER_CAST( IPPacket_t *, pxUseDescriptor->pucEthernetBuffer );
/* This function will check if the target IP-address belongs to this device.
* If so, the packet will be passed to the IP-stack, who will answer it.
* The function is to be called within the function xNetworkInterfaceOutput().
*/
if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )
{
if( memcmp( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, ipLOCAL_MAC_ADDRESS, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 )
{
xResult = pdTRUE;
if( bReleaseAfterSend == pdFALSE )
{
/* Driver is not allowed to transfer the ownership
of descriptor, so make a copy of it */
pxUseDescriptor =
pxDuplicateNetworkBufferWithDescriptor( pxDescriptor, pxDescriptor->xDataLength );
}
if( pxUseDescriptor != NULL )
{
IPStackEvent_t xRxEvent;
xRxEvent.eEventType = eNetworkRxEvent;
xRxEvent.pvData = pxUseDescriptor;
if( xSendEventStructToIPTask( &xRxEvent, 0U ) != pdTRUE )
{
vReleaseNetworkBufferAndDescriptor( pxUseDescriptor );
iptraceETHERNET_RX_EVENT_LOST();
FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );
}
}
}
}
return xResult;
}
#endif /* 0 */
/*-----------------------------------------------------------*/
#if( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 ) #if( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 )
/* MISRA c 2012 rule 8.7 relaxed since this function can be
* called from external location when debugging is enabled */
/* coverity[misra_c_2012_rule_8_7_violation] */
void FreeRTOS_PrintARPCache( void ) void FreeRTOS_PrintARPCache( void )
{ {
BaseType_t x, xCount = 0; BaseType_t x, xCount = 0;
@ -678,7 +742,7 @@ void FreeRTOS_ClearARP( void )
/* Loop through each entry in the ARP cache. */ /* Loop through each entry in the ARP cache. */
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ ) for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{ {
if( ( xARPCache[ x ].ulIPAddress != 0UL ) && ( xARPCache[ x ].ucAge > 0U ) ) if( ( xARPCache[ x ].ulIPAddress != 0UL ) && ( xARPCache[ x ].ucAge > ( uint8_t ) 0U ) )
{ {
/* See if the MAC-address also matches, and we're all happy */ /* See if the MAC-address also matches, and we're all happy */
FreeRTOS_printf( ( "Arp %2ld: %3u - %16lxip : %02x:%02x:%02x : %02x:%02x:%02x\n", FreeRTOS_printf( ( "Arp %2ld: %3u - %16lxip : %02x:%02x:%02x : %02x:%02x:%02x\n",

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -44,9 +44,10 @@
* will be used when TCP data is received while earlier data is still missing. * will be used when TCP data is received while earlier data is still missing.
* If 'pucData' equals NULL, the function is called to advance 'uxHead' only. * If 'pucData' equals NULL, the function is called to advance 'uxHead' only.
*/ */
size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount ) size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxByteCount )
{ {
size_t uxSpace, uxNextHead, uxFirst; size_t uxSpace, uxNextHead, uxFirst;
size_t uxCount = uxByteCount;
uxSpace = uxStreamBufferGetSpace( pxBuffer ); uxSpace = uxStreamBufferGetSpace( pxBuffer );
@ -57,18 +58,18 @@ size_t uxSpace, uxNextHead, uxFirst;
} }
else else
{ {
uxSpace = 0u; uxSpace = 0U;
} }
/* The number of bytes that can be written is the minimum of the number of /* The number of bytes that can be written is the minimum of the number of
bytes requested and the number available. */ bytes requested and the number available. */
uxCount = FreeRTOS_min_uint32( uxSpace, uxCount ); uxCount = FreeRTOS_min_uint32( uxSpace, uxCount );
if( uxCount != 0u ) if( uxCount != 0U )
{ {
uxNextHead = pxBuffer->uxHead; uxNextHead = pxBuffer->uxHead;
if( uxOffset != 0u ) if( uxOffset != 0U )
{ {
/* ( uxOffset > 0 ) means: write in front if the uxHead marker */ /* ( uxOffset > 0 ) means: write in front if the uxHead marker */
uxNextHead += uxOffset; uxNextHead += uxOffset;
@ -86,7 +87,7 @@ size_t uxSpace, uxNextHead, uxFirst;
uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextHead, uxCount ); uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextHead, uxCount );
/* Write as many bytes as can be written in the first write. */ /* Write as many bytes as can be written in the first write. */
memcpy( ( void* ) ( pxBuffer->ucArray + uxNextHead ), pucData, uxFirst ); ( void ) memcpy( &( pxBuffer->ucArray[ uxNextHead ] ), pucData, uxFirst );
/* If the number of bytes written was less than the number that /* If the number of bytes written was less than the number that
could be written in the first write... */ could be written in the first write... */
@ -94,11 +95,11 @@ size_t uxSpace, uxNextHead, uxFirst;
{ {
/* ...then write the remaining bytes to the start of the /* ...then write the remaining bytes to the start of the
buffer. */ buffer. */
memcpy( ( void * )pxBuffer->ucArray, pucData + uxFirst, uxCount - uxFirst ); ( void ) memcpy( pxBuffer->ucArray, &( pucData[ uxFirst ] ), uxCount - uxFirst );
} }
} }
if( uxOffset == 0u ) if( uxOffset == 0U )
{ {
/* ( uxOffset == 0 ) means: write at uxHead position */ /* ( uxOffset == 0 ) means: write at uxHead position */
uxNextHead += uxCount; uxNextHead += uxCount;
@ -140,17 +141,17 @@ size_t uxSize, uxCount, uxFirst, uxNextTail;
} }
else else
{ {
uxSize = 0u; uxSize = 0U;
} }
/* Use the minimum of the wanted bytes and the available bytes. */ /* Use the minimum of the wanted bytes and the available bytes. */
uxCount = FreeRTOS_min_uint32( uxSize, uxMaxCount ); uxCount = FreeRTOS_min_uint32( uxSize, uxMaxCount );
if( uxCount > 0u ) if( uxCount > 0U )
{ {
uxNextTail = pxBuffer->uxTail; uxNextTail = pxBuffer->uxTail;
if( uxOffset != 0u ) if( uxOffset != 0U )
{ {
uxNextTail += uxOffset; uxNextTail += uxOffset;
if( uxNextTail >= pxBuffer->LENGTH ) if( uxNextTail >= pxBuffer->LENGTH )
@ -168,14 +169,14 @@ size_t uxSize, uxCount, uxFirst, uxNextTail;
/* Obtain the number of bytes it is possible to obtain in the first /* Obtain the number of bytes it is possible to obtain in the first
read. */ read. */
memcpy( pucData, pxBuffer->ucArray + uxNextTail, uxFirst ); ( void ) memcpy( pucData, &( pxBuffer->ucArray[ uxNextTail ] ), uxFirst );
/* If the total number of wanted bytes is greater than the number /* If the total number of wanted bytes is greater than the number
that could be read in the first read... */ that could be read in the first read... */
if( uxCount > uxFirst ) if( uxCount > uxFirst )
{ {
/*...then read the remaining bytes from the start of the buffer. */ /*...then read the remaining bytes from the start of the buffer. */
memcpy( pucData + uxFirst, pxBuffer->ucArray, uxCount - uxFirst ); ( void ) memcpy( &( pucData[ uxFirst ] ), pxBuffer->ucArray, uxCount - uxFirst );
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -39,16 +39,12 @@
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_UDP_IP.h" #include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
#include "FreeRTOS_TCP_WIN.h"
/* Constants used for Smoothed Round Trip Time (SRTT). */ /* Constants used for Smoothed Round Trip Time (SRTT). */
#define winSRTT_INCREMENT_NEW 2 #define winSRTT_INCREMENT_NEW 2
@ -80,12 +76,12 @@
* by the peer, it is very unlikely a current packet will ever arrive. * by the peer, it is very unlikely a current packet will ever arrive.
* It will be retransmitted far before the RTO. * It will be retransmitted far before the RTO.
*/ */
#define DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT ( 3u ) #define DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT ( 3U )
/* If there have been several retransmissions (4), decrease the /* If there have been several retransmissions (4), decrease the
* size of the transmission window to at most 2 times MSS. * size of the transmission window to at most 2 times MSS.
*/ */
#define MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW ( 4u ) #define MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW ( 4U )
#endif /* configUSE_TCP_WIN */ #endif /* configUSE_TCP_WIN */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -109,7 +105,7 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
* segments: 'pxWindow->xRxSegments'. * segments: 'pxWindow->xRxSegments'.
*/ */
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
static TCPSegment_t *xTCPWindowRxFind( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber ); static TCPSegment_t *xTCPWindowRxFind( const TCPWindow_t *pxWindow, uint32_t ulSequenceNumber );
#endif /* ipconfigUSE_TCP_WIN == 1 */ #endif /* ipconfigUSE_TCP_WIN == 1 */
/* /*
@ -121,28 +117,18 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
static TCPSegment_t *xTCPWindowNew( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, int32_t lCount, BaseType_t xIsForRx ); static TCPSegment_t *xTCPWindowNew( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, int32_t lCount, BaseType_t xIsForRx );
#endif /* ipconfigUSE_TCP_WIN == 1 */ #endif /* ipconfigUSE_TCP_WIN == 1 */
/* When the peer has a close request (FIN flag), the driver will check if
* there are missing packets in the Rx-queue
* It will accept the closure of the connection if both conditions are true:
* - the Rx-queue is empty
* - we've ACK'd the highest Rx sequence number seen
*/
#if( ipconfigUSE_TCP_WIN == 1 )
BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow );
#endif /* ipconfigUSE_TCP_WIN == 1 */
/* /*
* Detaches and returns the head of a queue * Detaches and returns the head of a queue
*/ */
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
static TCPSegment_t *xTCPWindowGetHead( List_t *pxList ); static TCPSegment_t *xTCPWindowGetHead( const List_t *pxList );
#endif /* ipconfigUSE_TCP_WIN == 1 */ #endif /* ipconfigUSE_TCP_WIN == 1 */
/* /*
* Returns the head of a queue but it won't be detached * Returns the head of a queue but it won't be detached
*/ */
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
static TCPSegment_t *xTCPWindowPeekHead( List_t *pxList ); static TCPSegment_t *xTCPWindowPeekHead( const List_t *pxList );
#endif /* ipconfigUSE_TCP_WIN == 1 */ #endif /* ipconfigUSE_TCP_WIN == 1 */
/* /*
@ -162,7 +148,7 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
* segment should have a sequence number equal to '(ulSequenceNumber+xLength)'. * segment should have a sequence number equal to '(ulSequenceNumber+xLength)'.
*/ */
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
static TCPSegment_t *xTCPWindowRxConfirm( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength ); static TCPSegment_t *xTCPWindowRxConfirm( const TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength );
#endif /* ipconfigUSE_TCP_WIN == 1 */ #endif /* ipconfigUSE_TCP_WIN == 1 */
/* /*
@ -178,7 +164,7 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
* true if there is data to be sent. * true if there is data to be sent.
*/ */
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize ); static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow, uint32_t ulWindowSize );
#endif /* ipconfigUSE_TCP_WIN == 1 */ #endif /* ipconfigUSE_TCP_WIN == 1 */
/* /*
@ -217,10 +203,20 @@ BaseType_t xTCPWindowLoggingLevel = 0;
static portINLINE BaseType_t xSequenceLessThanOrEqual( uint32_t a, uint32_t b ); static portINLINE BaseType_t xSequenceLessThanOrEqual( uint32_t a, uint32_t b );
static portINLINE BaseType_t xSequenceLessThanOrEqual( uint32_t a, uint32_t b ) static portINLINE BaseType_t xSequenceLessThanOrEqual( uint32_t a, uint32_t b )
{ {
BaseType_t xResult;
/* Test if a <= b /* Test if a <= b
Return true if the unsigned subtraction of (b-a) doesn't generate an Return true if the unsigned subtraction of (b-a) doesn't generate an
arithmetic overflow. */ arithmetic overflow. */
return ( ( b - a ) & 0x80000000UL ) == 0UL; if( ( ( b - a ) & 0x80000000UL ) == 0UL )
{
xResult = pdTRUE;
}
else
{
xResult = pdFALSE;
}
return xResult;
} }
#endif /* ipconfigUSE_TCP_WIN */ #endif /* ipconfigUSE_TCP_WIN */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -229,8 +225,18 @@ BaseType_t xTCPWindowLoggingLevel = 0;
static portINLINE BaseType_t xSequenceLessThan( uint32_t a, uint32_t b ); static portINLINE BaseType_t xSequenceLessThan( uint32_t a, uint32_t b );
static portINLINE BaseType_t xSequenceLessThan( uint32_t a, uint32_t b ) static portINLINE BaseType_t xSequenceLessThan( uint32_t a, uint32_t b )
{ {
BaseType_t xResult;
/* Test if a < b */ /* Test if a < b */
return ( ( b - a - 1UL ) & 0x80000000UL ) == 0UL; if( ( ( b - ( a + 1UL ) ) & 0x80000000UL ) == 0UL )
{
xResult = pdTRUE;
}
else
{
xResult = pdFALSE;
}
return xResult;
} }
#endif /* ipconfigUSE_TCP_WIN */ #endif /* ipconfigUSE_TCP_WIN */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -239,8 +245,18 @@ BaseType_t xTCPWindowLoggingLevel = 0;
static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a, uint32_t b ); static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a, uint32_t b );
static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a, uint32_t b ) static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a, uint32_t b )
{ {
BaseType_t xResult;
/* Test if a > b */ /* Test if a > b */
return ( ( a - b - 1UL ) & 0x80000000UL ) == 0UL; if( ( ( a - ( b + 1UL ) ) & 0x80000000UL ) == 0UL )
{
xResult = pdTRUE;
}
else
{
xResult = pdFALSE;
}
return xResult;
} }
#endif /* ipconfigUSE_TCP_WIN */ #endif /* ipconfigUSE_TCP_WIN */
@ -248,8 +264,18 @@ BaseType_t xTCPWindowLoggingLevel = 0;
static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a, uint32_t b ); static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a, uint32_t b );
static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a, uint32_t b ) static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a, uint32_t b )
{ {
BaseType_t xResult;
/* Test if a >= b */ /* Test if a >= b */
return ( ( a - b ) & 0x80000000UL ) == 0UL; if( ( ( a - b ) & 0x80000000UL ) == 0UL )
{
xResult = pdTRUE;
}
else
{
xResult = pdFALSE;
}
return xResult;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -269,30 +295,25 @@ static portINLINE void vTCPTimerSet( TCPTimer_t *pxTimer )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static portINLINE uint32_t ulTimerGetAge( TCPTimer_t *pxTimer ); static portINLINE uint32_t ulTimerGetAge( const TCPTimer_t *pxTimer );
static portINLINE uint32_t ulTimerGetAge( TCPTimer_t *pxTimer ) static portINLINE uint32_t ulTimerGetAge( const TCPTimer_t *pxTimer )
{ {
return ( ( xTaskGetTickCount() - pxTimer->ulBorn ) * portTICK_PERIOD_MS ); return ( ( xTaskGetTickCount() - ( ( TickType_t ) pxTimer->ulBorn ) ) * portTICK_PERIOD_MS );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* _HT_ GCC (using the settings that I'm using) checks for every public function if it is
preceded by a prototype. Later this prototype will be located in list.h? */
extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere );
void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere ) void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere )
{ {
/* Insert a new list item into pxList, it does not sort the list, /* Insert a new list item into pxList, it does not sort the list,
but it puts the item just before xListEnd, so it will be the last item but it puts the item just before xListEnd, so it will be the last item
returned by listGET_HEAD_ENTRY() */ returned by listGET_HEAD_ENTRY() */
pxNewListItem->pxNext = (struct xLIST_ITEM * configLIST_VOLATILE)pxWhere; pxNewListItem->pxNext = ipPOINTER_CAST(struct xLIST_ITEM * configLIST_VOLATILE, pxWhere );
pxNewListItem->pxPrevious = pxWhere->pxPrevious; pxNewListItem->pxPrevious = pxWhere->pxPrevious;
pxWhere->pxPrevious->pxNext = pxNewListItem; pxWhere->pxPrevious->pxNext = pxNewListItem;
pxWhere->pxPrevious = pxNewListItem; pxWhere->pxPrevious = pxNewListItem;
/* Remember which list the item is in. */ /* Remember which list the item is in. */
listLIST_ITEM_CONTAINER( pxNewListItem ) = ( void * ) pxList; listLIST_ITEM_CONTAINER( pxNewListItem ) = ( struct xLIST * configLIST_VOLATILE )pxList;
( pxList->uxNumberOfItems )++; ( pxList->uxNumberOfItems )++;
} }
@ -307,29 +328,29 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
/* Allocate space for 'xTCPSegments' and store them in 'xSegmentList'. */ /* Allocate space for 'xTCPSegments' and store them in 'xSegmentList'. */
vListInitialise( &xSegmentList ); vListInitialise( &xSegmentList );
xTCPSegments = ( TCPSegment_t * ) pvPortMallocLarge( ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ); xTCPSegments = ipPOINTER_CAST( TCPSegment_t *, pvPortMallocLarge( ( size_t ) ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ) );
if( xTCPSegments == NULL ) if( xTCPSegments == NULL )
{ {
FreeRTOS_debug_printf( ( "prvCreateSectors: malloc %lu failed\n", FreeRTOS_debug_printf( ( "prvCreateSectors: malloc %u failed\n",
ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ) ); ( unsigned ) ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ) );
xReturn = pdFAIL; xReturn = pdFAIL;
} }
else else
{ {
/* Clear the allocated space. */ /* Clear the allocated space. */
memset( xTCPSegments, '\0', ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ); ( void ) memset( xTCPSegments, 0, ( size_t ) ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) );
for( xIndex = 0; xIndex < ipconfigTCP_WIN_SEG_COUNT; xIndex++ ) for( xIndex = 0; xIndex < ipconfigTCP_WIN_SEG_COUNT; xIndex++ )
{ {
/* Could call vListInitialiseItem here but all data has been /* Could call vListInitialiseItem here but all data has been
nulled already. Set the owner to a segment descriptor. */ nulled already. Set the owner to a segment descriptor. */
listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xListItem ), ( void* ) &( xTCPSegments[ xIndex ] ) ); listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xSegmentItem ), ipPOINTER_CAST( void *, &( xTCPSegments[ xIndex ] ) ) );
listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xQueueItem ), ( void* ) &( xTCPSegments[ xIndex ] ) ); listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xQueueItem ), ipPOINTER_CAST( void *, &( xTCPSegments[ xIndex ] ) ) );
/* And add it to the pool of available segments */ /* And add it to the pool of available segments */
vListInsertFifo( &xSegmentList, &( xTCPSegments[xIndex].xListItem ) ); vListInsertFifo( &xSegmentList, &( xTCPSegments[xIndex].xSegmentItem ) );
} }
xReturn = pdPASS; xReturn = pdPASS;
@ -343,22 +364,22 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
static TCPSegment_t *xTCPWindowRxFind( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber ) static TCPSegment_t *xTCPWindowRxFind( const TCPWindow_t *pxWindow, uint32_t ulSequenceNumber )
{ {
const ListItem_t *pxIterator; const ListItem_t *pxIterator;
const MiniListItem_t* pxEnd; const ListItem_t* pxEnd;
TCPSegment_t *pxSegment, *pxReturn = NULL; TCPSegment_t *pxSegment, *pxReturn = NULL;
/* Find a segment with a given sequence number in the list of received /* Find a segment with a given sequence number in the list of received
segments. */ segments. */
pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &pxWindow->xRxSegments ); pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &pxWindow->xRxSegments ) );
for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd ); for( pxIterator = listGET_NEXT( pxEnd );
pxIterator != ( const ListItem_t * ) pxEnd; pxIterator != pxEnd;
pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) ) pxIterator = listGET_NEXT( pxIterator ) )
{ {
pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
if( pxSegment->ulSequenceNumber == ulSequenceNumber ) if( pxSegment->ulSequenceNumber == ulSequenceNumber )
{ {
@ -386,7 +407,7 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
{ {
/* If the TCP-stack runs out of segments, you might consider /* If the TCP-stack runs out of segments, you might consider
increasing 'ipconfigTCP_WIN_SEG_COUNT'. */ increasing 'ipconfigTCP_WIN_SEG_COUNT'. */
FreeRTOS_debug_printf( ( "xTCPWindow%cxNew: Error: all segments occupied\n", xIsForRx ? 'R' : 'T' ) ); FreeRTOS_debug_printf( ( "xTCPWindow%cxNew: Error: all segments occupied\n", ( xIsForRx != 0 ) ? 'R' : 'T' ) );
pxSegment = NULL; pxSegment = NULL;
} }
else else
@ -394,22 +415,29 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
/* Pop the item at the head of the list. Semaphore protection is /* Pop the item at the head of the list. Semaphore protection is
not required as only the IP task will call these functions. */ not required as only the IP task will call these functions. */
pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( &xSegmentList ); pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( &xSegmentList );
pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxItem ); pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxItem ) );
configASSERT( pxItem != NULL ); configASSERT( pxItem != NULL );
configASSERT( pxSegment != NULL ); configASSERT( pxSegment != NULL );
/* Remove the item from xSegmentList. */ /* Remove the item from xSegmentList. */
uxListRemove( pxItem ); ( void ) uxListRemove( pxItem );
/* Add it to either the connections' Rx or Tx queue. */ /* Add it to either the connections' Rx or Tx queue. */
vListInsertFifo( xIsForRx ? &pxWindow->xRxSegments : &pxWindow->xTxSegments, pxItem ); if( xIsForRx != 0 )
{
vListInsertFifo( &pxWindow->xRxSegments, pxItem );
}
else
{
vListInsertFifo( &pxWindow->xTxSegments, pxItem );
}
/* And set the segment's timer to zero */ /* And set the segment's timer to zero */
vTCPTimerSet( &pxSegment->xTransmitTimer ); vTCPTimerSet( &pxSegment->xTransmitTimer );
pxSegment->u.ulFlags = 0; pxSegment->u.ulFlags = 0;
pxSegment->u.bits.bIsForRx = ( xIsForRx != 0 ); pxSegment->u.bits.bIsForRx = ( xIsForRx != 0 ) ? 1U : 0U;
pxSegment->lMaxLength = lCount; pxSegment->lMaxLength = lCount;
pxSegment->lDataLength = lCount; pxSegment->lDataLength = lCount;
pxSegment->ulSequenceNumber = ulSequenceNumber; pxSegment->ulSequenceNumber = ulSequenceNumber;
@ -434,7 +462,7 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow ) BaseType_t xTCPWindowRxEmpty( const TCPWindow_t *pxWindow )
{ {
BaseType_t xReturn; BaseType_t xReturn;
@ -470,7 +498,7 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
static TCPSegment_t *xTCPWindowGetHead( List_t *pxList ) static TCPSegment_t *xTCPWindowGetHead( const List_t *pxList )
{ {
TCPSegment_t *pxSegment; TCPSegment_t *pxSegment;
ListItem_t * pxItem; ListItem_t * pxItem;
@ -483,9 +511,9 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
else else
{ {
pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( pxList ); pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( pxList );
pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxItem ); pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxItem ) );
uxListRemove( pxItem ); ( void ) uxListRemove( pxItem );
} }
return pxSegment; return pxSegment;
@ -496,9 +524,9 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
static TCPSegment_t *xTCPWindowPeekHead( List_t *pxList ) static TCPSegment_t *xTCPWindowPeekHead( const List_t *pxList )
{ {
ListItem_t *pxItem; const ListItem_t *pxItem;
TCPSegment_t *pxReturn; TCPSegment_t *pxReturn;
/* Returns the head of a queue but it won't be detached. */ /* Returns the head of a queue but it won't be detached. */
@ -509,7 +537,7 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
else else
{ {
pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( pxList ); pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( pxList );
pxReturn = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxItem ); pxReturn = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxItem ) );
} }
return pxReturn; return pxReturn;
@ -528,21 +556,21 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
Unlink it from one of the queues, if any. */ Unlink it from one of the queues, if any. */
if( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) != NULL ) if( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) != NULL )
{ {
uxListRemove( &( pxSegment->xQueueItem ) ); ( void ) uxListRemove( &( pxSegment->xQueueItem ) );
} }
pxSegment->ulSequenceNumber = 0u; pxSegment->ulSequenceNumber = 0UL;
pxSegment->lDataLength = 0l; pxSegment->lDataLength = 0L;
pxSegment->u.ulFlags = 0u; pxSegment->u.ulFlags = 0UL;
/* Take it out of xRxSegments/xTxSegments */ /* Take it out of xRxSegments/xTxSegments */
if( listLIST_ITEM_CONTAINER( &( pxSegment->xListItem ) ) != NULL ) if( listLIST_ITEM_CONTAINER( &( pxSegment->xSegmentItem ) ) != NULL )
{ {
uxListRemove( &( pxSegment->xListItem ) ); ( void ) uxListRemove( &( pxSegment->xSegmentItem ) );
} }
/* Return it to xSegmentList */ /* Return it to xSegmentList */
vListInsertFifo( &xSegmentList, &( pxSegment->xListItem ) ); vListInsertFifo( &xSegmentList, &( pxSegment->xSegmentItem ) );
} }
#endif /* ipconfigUSE_TCP_WIN == 1 */ #endif /* ipconfigUSE_TCP_WIN == 1 */
@ -550,9 +578,9 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
void vTCPWindowDestroy( TCPWindow_t *pxWindow ) void vTCPWindowDestroy( TCPWindow_t const * pxWindow )
{ {
List_t * pxSegments; const List_t * pxSegments;
BaseType_t xRound; BaseType_t xRound;
TCPSegment_t *pxSegment; TCPSegment_t *pxSegment;
@ -571,11 +599,11 @@ void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem
pxSegments = &( pxWindow->xTxSegments ); pxSegments = &( pxWindow->xTxSegments );
} }
if( listLIST_IS_INITIALISED( pxSegments ) != pdFALSE ) if( listLIST_IS_INITIALISED( pxSegments ) )
{ {
while( listCURRENT_LIST_LENGTH( pxSegments ) > 0U ) while( listCURRENT_LIST_LENGTH( pxSegments ) > 0U )
{ {
pxSegment = ( TCPSegment_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxSegments ); pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_OWNER_OF_HEAD_ENTRY( pxSegments ) );
vTCPWindowFree( pxSegment ); vTCPWindowFree( pxSegment );
} }
} }
@ -594,15 +622,15 @@ void vTCPWindowCreate( TCPWindow_t *pxWindow, uint32_t ulRxWindowLength,
{ {
if( xTCPSegments == NULL ) if( xTCPSegments == NULL )
{ {
prvCreateSectors(); ( void ) prvCreateSectors();
} }
vListInitialise( &pxWindow->xTxSegments ); vListInitialise( &( pxWindow->xTxSegments ) );
vListInitialise( &pxWindow->xRxSegments ); vListInitialise( &( pxWindow->xRxSegments ) );
vListInitialise( &pxWindow->xPriorityQueue ); /* Priority queue: segments which must be sent immediately */ vListInitialise( &( pxWindow->xPriorityQueue ) ); /* Priority queue: segments which must be sent immediately */
vListInitialise( &pxWindow->xTxQueue ); /* Transmit queue: segments queued for transmission */ vListInitialise( &( pxWindow->xTxQueue ) ); /* Transmit queue: segments queued for transmission */
vListInitialise( &pxWindow->xWaitQueue ); /* Waiting queue: outstanding segments */ vListInitialise( &( pxWindow->xWaitQueue ) ); /* Waiting queue: outstanding segments */
} }
#endif /* ipconfigUSE_TCP_WIN == 1 */ #endif /* ipconfigUSE_TCP_WIN == 1 */
@ -623,17 +651,17 @@ void vTCPWindowInit( TCPWindow_t *pxWindow, uint32_t ulAckNumber, uint32_t ulSeq
{ {
const int32_t l500ms = 500; const int32_t l500ms = 500;
pxWindow->u.ulFlags = 0ul; pxWindow->u.ulFlags = 0UL;
pxWindow->u.bits.bHasInit = pdTRUE_UNSIGNED; pxWindow->u.bits.bHasInit = pdTRUE_UNSIGNED;
if( ulMSS != 0ul ) if( ulMSS != 0UL )
{ {
if( pxWindow->usMSSInit != 0u ) if( pxWindow->usMSSInit != 0U )
{ {
pxWindow->usMSSInit = ( uint16_t ) ulMSS; pxWindow->usMSSInit = ( uint16_t ) ulMSS;
} }
if( ( ulMSS < ( uint32_t ) pxWindow->usMSS ) || ( pxWindow->usMSS == 0u ) ) if( ( ulMSS < ( uint32_t ) pxWindow->usMSS ) || ( pxWindow->usMSS == 0U ) )
{ {
pxWindow->xSize.ulRxWindowLength = ( pxWindow->xSize.ulRxWindowLength / ulMSS ) * ulMSS; pxWindow->xSize.ulRxWindowLength = ( pxWindow->xSize.ulRxWindowLength / ulMSS ) * ulMSS;
pxWindow->usMSS = ( uint16_t ) ulMSS; pxWindow->usMSS = ( uint16_t ) ulMSS;
@ -707,12 +735,12 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
static TCPSegment_t *xTCPWindowRxConfirm( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength ) static TCPSegment_t *xTCPWindowRxConfirm( const TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength )
{ {
TCPSegment_t *pxBest = NULL; TCPSegment_t *pxBest = NULL;
const ListItem_t *pxIterator; const ListItem_t *pxIterator;
uint32_t ulNextSequenceNumber = ulSequenceNumber + ulLength; uint32_t ulNextSequenceNumber = ulSequenceNumber + ulLength;
const MiniListItem_t* pxEnd = ( const MiniListItem_t* ) listGET_END_MARKER( &pxWindow->xRxSegments ); const ListItem_t * pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &pxWindow->xRxSegments ) );
TCPSegment_t *pxSegment; TCPSegment_t *pxSegment;
/* A segment has been received with sequence number 'ulSequenceNumber', /* A segment has been received with sequence number 'ulSequenceNumber',
@ -724,11 +752,11 @@ const int32_t l500ms = 500;
'(ulSequenceNumber+ulLength)'. */ '(ulSequenceNumber+ulLength)'. */
/* Iterate through all RX segments that are stored: */ /* Iterate through all RX segments that are stored: */
for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd ); for( pxIterator = listGET_NEXT( pxEnd );
pxIterator != ( const ListItem_t * ) pxEnd; pxIterator != pxEnd;
pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) ) pxIterator = listGET_NEXT( pxIterator ) )
{ {
pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
/* And see if there is a segment for which: /* And see if there is a segment for which:
'ulSequenceNumber' <= 'pxSegment->ulSequenceNumber' < 'ulNextSequenceNumber' 'ulSequenceNumber' <= 'pxSegment->ulSequenceNumber' < 'ulNextSequenceNumber'
If there are more matching segments, the one with the lowest sequence number If there are more matching segments, the one with the lowest sequence number
@ -746,7 +774,6 @@ const int32_t l500ms = 500;
if( ( pxBest != NULL ) && if( ( pxBest != NULL ) &&
( ( pxBest->ulSequenceNumber != ulSequenceNumber ) || ( pxBest->lDataLength != ( int32_t ) ulLength ) ) ) ( ( pxBest->ulSequenceNumber != ulSequenceNumber ) || ( pxBest->lDataLength != ( int32_t ) ulLength ) ) )
{ {
FreeRTOS_flush_logging();
FreeRTOS_debug_printf( ( "xTCPWindowRxConfirm[%u]: search %lu (+%ld=%lu) found %lu (+%ld=%lu)\n", FreeRTOS_debug_printf( ( "xTCPWindowRxConfirm[%u]: search %lu (+%ld=%lu) found %lu (+%ld=%lu)\n",
pxWindow->usPeerPortNumber, pxWindow->usPeerPortNumber,
ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber, ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
@ -783,10 +810,10 @@ const int32_t l500ms = 500;
ulCurrentSequenceNumber = pxWindow->rx.ulCurrentSequenceNumber; ulCurrentSequenceNumber = pxWindow->rx.ulCurrentSequenceNumber;
/* For Selective Ack (SACK), used when out-of-sequence data come in. */ /* For Selective Ack (SACK), used when out-of-sequence data come in. */
pxWindow->ucOptionLength = 0u; pxWindow->ucOptionLength = 0U;
/* Non-zero if TCP-windows contains data which must be popped. */ /* Non-zero if TCP-windows contains data which must be popped. */
pxWindow->ulUserDataLength = 0ul; pxWindow->ulUserDataLength = 0UL;
if( ulCurrentSequenceNumber == ulSequenceNumber ) if( ulCurrentSequenceNumber == ulSequenceNumber )
{ {
@ -801,7 +828,7 @@ const int32_t l500ms = 500;
{ {
ulCurrentSequenceNumber += ulLength; ulCurrentSequenceNumber += ulLength;
if( listCURRENT_LIST_LENGTH( &( pxWindow->xRxSegments ) ) != 0 ) if( listCURRENT_LIST_LENGTH( &( pxWindow->xRxSegments ) ) != 0U )
{ {
ulSavedSequenceNumber = ulCurrentSequenceNumber; ulSavedSequenceNumber = ulCurrentSequenceNumber;
@ -818,12 +845,17 @@ const int32_t l500ms = 500;
/* Remove it because it will be passed to user directly. */ /* Remove it because it will be passed to user directly. */
vTCPWindowFree( pxFound ); vTCPWindowFree( pxFound );
} }
} while ( pxFound ); } while ( pxFound != NULL );
/* Check for following segments that are already in the /* Check for following segments that are already in the
queue and increment ulCurrentSequenceNumber. */ queue and increment ulCurrentSequenceNumber. */
while( ( pxFound = xTCPWindowRxFind( pxWindow, ulCurrentSequenceNumber ) ) != NULL ) for( ;; )
{ {
pxFound = xTCPWindowRxFind( pxWindow, ulCurrentSequenceNumber );
if( pxFound == NULL )
{
break;
}
ulCurrentSequenceNumber += ( uint32_t ) pxFound->lDataLength; ulCurrentSequenceNumber += ( uint32_t ) pxFound->lDataLength;
/* As all packet below this one have been passed to the /* As all packet below this one have been passed to the
@ -870,7 +902,9 @@ const int32_t l500ms = 500;
/* An "out-of-sequence" segment was received, must have missed one. /* An "out-of-sequence" segment was received, must have missed one.
Prepare a SACK (Selective ACK). */ Prepare a SACK (Selective ACK). */
ulLast = ulSequenceNumber + ulLength; ulLast = ulSequenceNumber + ulLength;
lDistance = ( int32_t ) ( ulLast - ulCurrentSequenceNumber ); /* The cast from unsigned long to signed long is on purpose.
The macro 'ipNUMERIC_CAST' will prevent PC-lint from complaining. */
lDistance = ipNUMERIC_CAST( int32_t, ulLast - ulCurrentSequenceNumber );
if( lDistance <= 0 ) if( lDistance <= 0 )
{ {
@ -895,19 +929,25 @@ const int32_t l500ms = 500;
* This is useful because subsequent packets will be SACK'd with * This is useful because subsequent packets will be SACK'd with
* single one message * single one message
*/ */
while( ( pxFound = xTCPWindowRxFind( pxWindow, ulLast ) ) != NULL ) for( ;; )
{ {
pxFound = xTCPWindowRxFind( pxWindow, ulLast );
if( pxFound == NULL )
{
break;
}
ulLast += ( uint32_t ) pxFound->lDataLength; ulLast += ( uint32_t ) pxFound->lDataLength;
} }
if( xTCPWindowLoggingLevel >= 1 ) if( xTCPWindowLoggingLevel >= 1 )
{ {
FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%d,%d]: seqnr %lu exp %lu (dist %ld) SACK to %lu\n", FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%d,%d]: seqnr %u exp %u (dist %d) SACK to %u\n",
pxWindow->usPeerPortNumber, pxWindow->usOurPortNumber, ( int ) pxWindow->usPeerPortNumber,
ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber, ( int ) pxWindow->usOurPortNumber,
ulCurrentSequenceNumber - pxWindow->rx.ulFirstSequenceNumber, ( unsigned ) ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
( BaseType_t ) ( ulSequenceNumber - ulCurrentSequenceNumber ), /* want this signed */ ( unsigned ) ulCurrentSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,
ulLast - pxWindow->rx.ulFirstSequenceNumber ) ); ( unsigned ) ( ulSequenceNumber - ulCurrentSequenceNumber ), /* want this signed */
( unsigned ) ( ulLast - pxWindow->rx.ulFirstSequenceNumber ) ) );
} }
/* Now prepare the SACK message. /* Now prepare the SACK message.
@ -921,7 +961,7 @@ const int32_t l500ms = 500;
pxWindow->ulOptionsData[2] = FreeRTOS_htonl( ulLast ); pxWindow->ulOptionsData[2] = FreeRTOS_htonl( ulLast );
/* Which make 12 (3*4) option bytes. */ /* Which make 12 (3*4) option bytes. */
pxWindow->ucOptionLength = 3 * sizeof( pxWindow->ulOptionsData[ 0 ] ); pxWindow->ucOptionLength = ( uint8_t ) ( 3U * sizeof( pxWindow->ulOptionsData[ 0 ] ) );
pxFound = xTCPWindowRxFind( pxWindow, ulSequenceNumber ); pxFound = xTCPWindowRxFind( pxWindow, ulSequenceNumber );
@ -940,7 +980,7 @@ const int32_t l500ms = 500;
{ {
/* Can not send a SACK, because the segment cannot be /* Can not send a SACK, because the segment cannot be
stored. */ stored. */
pxWindow->ucOptionLength = 0u; pxWindow->ucOptionLength = 0U;
/* Needs to be stored but there is no segment /* Needs to be stored but there is no segment
available. */ available. */
@ -958,7 +998,7 @@ const int32_t l500ms = 500;
/* Return a positive value. The packet may be accepted /* Return a positive value. The packet may be accepted
and stored but an earlier packet is still missing. */ and stored but an earlier packet is still missing. */
lReturn = ( int32_t ) ( ulSequenceNumber - ulCurrentSequenceNumber ); lReturn = ipNUMERIC_CAST( int32_t, ulSequenceNumber - ulCurrentSequenceNumber );
} }
} }
} }
@ -990,15 +1030,17 @@ const int32_t l500ms = 500;
static int32_t lTCPIncrementTxPosition( int32_t lPosition, int32_t lMax, int32_t lCount ) static int32_t lTCPIncrementTxPosition( int32_t lPosition, int32_t lMax, int32_t lCount )
{ {
int32_t lReturn;
/* +TCP stores data in circular buffers. Calculate the next position to /* +TCP stores data in circular buffers. Calculate the next position to
store. */ store. */
lPosition += lCount; lReturn = lPosition + lCount;
if( lPosition >= lMax ) if( lReturn >= lMax )
{ {
lPosition -= lMax; lReturn -= lMax;
} }
return lPosition; return lReturn;
} }
#endif /* ipconfigUSE_TCP_WIN == 1 */ #endif /* ipconfigUSE_TCP_WIN == 1 */
@ -1010,6 +1052,7 @@ const int32_t l500ms = 500;
{ {
int32_t lBytesLeft = ( int32_t ) ulLength, lToWrite; int32_t lBytesLeft = ( int32_t ) ulLength, lToWrite;
int32_t lDone = 0; int32_t lDone = 0;
int32_t lBufferIndex = lPosition;
TCPSegment_t *pxSegment = pxWindow->pxHeadSegment; TCPSegment_t *pxSegment = pxWindow->pxHeadSegment;
/* Puts a message in the Tx-window (after buffer size has been /* Puts a message in the Tx-window (after buffer size has been
@ -1042,7 +1085,7 @@ const int32_t l500ms = 500;
lDone += lToWrite; lDone += lToWrite;
/* Some detailed logging, for those who're interested. */ /* Some detailed logging, for those who're interested. */
if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != 0 ) ) if( ( xTCPWindowLoggingLevel >= 2 ) && ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) )
{ {
FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: Add %4lu bytes for seqNr %lu len %4lu (nxt %lu) pos %lu\n", FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: Add %4lu bytes for seqNr %lu len %4lu (nxt %lu) pos %lu\n",
ulLength, ulLength,
@ -1055,7 +1098,7 @@ const int32_t l500ms = 500;
/* Calculate the next position in the circular data buffer, knowing /* Calculate the next position in the circular data buffer, knowing
its maximum length 'lMax'. */ its maximum length 'lMax'. */
lPosition = lTCPIncrementTxPosition( lPosition, lMax, lToWrite ); lBufferIndex = lTCPIncrementTxPosition( lBufferIndex, lMax, lToWrite );
} }
} }
} }
@ -1064,7 +1107,7 @@ const int32_t l500ms = 500;
{ {
/* The current transmission segment is full, create new segments as /* The current transmission segment is full, create new segments as
needed. */ needed. */
pxSegment = xTCPWindowTxNew( pxWindow, pxWindow->ulNextTxSequenceNumber, pxWindow->usMSS ); pxSegment = xTCPWindowTxNew( pxWindow, pxWindow->ulNextTxSequenceNumber, ( int32_t ) pxWindow->usMSS );
if( pxSegment != NULL ) if( pxSegment != NULL )
{ {
@ -1073,9 +1116,9 @@ const int32_t l500ms = 500;
lToWrite = FreeRTOS_min_int32( lBytesLeft, pxSegment->lMaxLength ); lToWrite = FreeRTOS_min_int32( lBytesLeft, pxSegment->lMaxLength );
pxSegment->lDataLength = lToWrite; pxSegment->lDataLength = lToWrite;
pxSegment->lStreamPos = lPosition; pxSegment->lStreamPos = lBufferIndex;
lBytesLeft -= lToWrite; lBytesLeft -= lToWrite;
lPosition = lTCPIncrementTxPosition( lPosition, lMax, lToWrite ); lBufferIndex = lTCPIncrementTxPosition( lBufferIndex, lMax, lToWrite );
pxWindow->ulNextTxSequenceNumber += ( uint32_t ) lToWrite; pxWindow->ulNextTxSequenceNumber += ( uint32_t ) lToWrite;
lDone += lToWrite; lDone += lToWrite;
@ -1093,7 +1136,7 @@ const int32_t l500ms = 500;
pxWindow->pxHeadSegment = NULL; pxWindow->pxHeadSegment = NULL;
} }
if( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != 0 ) if( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) )
{ {
if( ( xTCPWindowLoggingLevel >= 3 ) || if( ( xTCPWindowLoggingLevel >= 3 ) ||
( ( xTCPWindowLoggingLevel >= 2 ) && ( pxWindow->pxHeadSegment != NULL ) ) ) ( ( xTCPWindowLoggingLevel >= 2 ) && ( pxWindow->pxHeadSegment != NULL ) ) )
@ -1128,7 +1171,7 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow ) BaseType_t xTCPWindowTxDone( const TCPWindow_t *pxWindow )
{ {
return listLIST_IS_EMPTY( ( &pxWindow->xTxSegments) ); return listLIST_IS_EMPTY( ( &pxWindow->xTxSegments) );
} }
@ -1138,11 +1181,12 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize ) static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t const * pxWindow, uint32_t ulWindowSize )
{ {
uint32_t ulTxOutstanding; uint32_t ulTxOutstanding;
BaseType_t xHasSpace; BaseType_t xHasSpace;
TCPSegment_t *pxSegment; const TCPSegment_t *pxSegment;
uint32_t ulNettSize;
/* This function will look if there is new transmission data. It will /* This function will look if there is new transmission data. It will
return true if there is data to be sent. */ return true if there is data to be sent. */
@ -1167,10 +1211,10 @@ const int32_t l500ms = 500;
} }
/* Subtract this from the peer's space. */ /* Subtract this from the peer's space. */
ulWindowSize -= FreeRTOS_min_uint32( ulWindowSize, ulTxOutstanding ); ulNettSize = ulWindowSize - FreeRTOS_min_uint32( ulWindowSize, ulTxOutstanding );
/* See if the next segment may be sent. */ /* See if the next segment may be sent. */
if( ulWindowSize >= ( uint32_t ) pxSegment->lDataLength ) if( ulNettSize >= ( uint32_t ) pxSegment->lDataLength )
{ {
xHasSpace = pdTRUE; xHasSpace = pdTRUE;
} }
@ -1183,7 +1227,7 @@ const int32_t l500ms = 500;
more new segment of size MSS. xSize.ulTxWindowLength is the self-imposed more new segment of size MSS. xSize.ulTxWindowLength is the self-imposed
limitation of the transmission window (in case of many resends it limitation of the transmission window (in case of many resends it
may be decreased). */ may be decreased). */
if( ( ulTxOutstanding != 0UL ) && ( pxWindow->xSize.ulTxWindowLength < ulTxOutstanding + ( ( uint32_t ) pxSegment->lDataLength ) ) ) if( ( ulTxOutstanding != 0UL ) && ( pxWindow->xSize.ulTxWindowLength < ( ulTxOutstanding + ( ( uint32_t ) pxSegment->lDataLength ) ) ) )
{ {
xHasSpace = pdFALSE; xHasSpace = pdFALSE;
} }
@ -1197,13 +1241,13 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay ) BaseType_t xTCPWindowTxHasData( TCPWindow_t const * pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay )
{ {
TCPSegment_t *pxSegment; TCPSegment_t const * pxSegment;
BaseType_t xReturn; BaseType_t xReturn;
TickType_t ulAge, ulMaxAge; TickType_t ulAge, ulMaxAge;
*pulDelay = 0u; *pulDelay = 0U;
if( listLIST_IS_EMPTY( &pxWindow->xPriorityQueue ) == pdFALSE ) if( listLIST_IS_EMPTY( &pxWindow->xPriorityQueue ) == pdFALSE )
{ {
@ -1225,7 +1269,7 @@ const int32_t l500ms = 500;
/* After a packet has been sent for the first time, it will wait /* After a packet has been sent for the first time, it will wait
'1 * lSRTT' ms for an ACK. A second time it will wait '2 * lSRTT' ms, '1 * lSRTT' ms for an ACK. A second time it will wait '2 * lSRTT' ms,
each time doubling the time-out */ each time doubling the time-out */
ulMaxAge = ( 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT ); ulMaxAge = ( 1UL << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
if( ulMaxAge > ulAge ) if( ulMaxAge > ulAge )
{ {
@ -1297,17 +1341,17 @@ const int32_t l500ms = 500;
if( pxSegment != NULL ) if( pxSegment != NULL )
{ {
/* Do check the timing. */ /* Do check the timing. */
ulMaxTime = ( 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT ); ulMaxTime = ( 1UL << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
if( ulTimerGetAge( &pxSegment->xTransmitTimer ) > ulMaxTime ) if( ulTimerGetAge( &pxSegment->xTransmitTimer ) > ulMaxTime )
{ {
/* A normal (non-fast) retransmission. Move it from the /* A normal (non-fast) retransmission. Move it from the
head of the waiting queue. */ head of the waiting queue. */
pxSegment = xTCPWindowGetHead( &( pxWindow->xWaitQueue ) ); pxSegment = xTCPWindowGetHead( &( pxWindow->xWaitQueue ) );
pxSegment->u.bits.ucDupAckCount = pdFALSE_UNSIGNED; pxSegment->u.bits.ucDupAckCount = ( uint8_t ) pdFALSE_UNSIGNED;
/* Some detailed logging. */ /* Some detailed logging. */
if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != 0 ) ) if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
{ {
FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: WaitQueue %ld bytes for sequence number %lu (%lX)\n", FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: WaitQueue %ld bytes for sequence number %lu (%lX)\n",
pxWindow->usPeerPortNumber, pxWindow->usPeerPortNumber,
@ -1363,7 +1407,7 @@ const int32_t l500ms = 500;
pxWindow->tx.ulHighestSequenceNumber = pxSegment->ulSequenceNumber + ( ( uint32_t ) pxSegment->lDataLength ); pxWindow->tx.ulHighestSequenceNumber = pxSegment->ulSequenceNumber + ( ( uint32_t ) pxSegment->lDataLength );
/* ...and more detailed logging */ /* ...and more detailed logging */
if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) ) if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
{ {
FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: XmitQueue %ld bytes for sequence number %lu (ws %lu)\n", FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: XmitQueue %ld bytes for sequence number %lu (ws %lu)\n",
pxWindow->usPeerPortNumber, pxWindow->usPeerPortNumber,
@ -1395,6 +1439,8 @@ const int32_t l500ms = 500;
/* See if it has already been determined to return 0. */ /* See if it has already been determined to return 0. */
if( ulReturn != 0UL ) if( ulReturn != 0UL )
{ {
/* pxSegment is not NULL when ulReturn != 0UL. */
configASSERT( pxSegment != NULL );
configASSERT( listLIST_ITEM_CONTAINER( &(pxSegment->xQueueItem ) ) == NULL ); configASSERT( listLIST_ITEM_CONTAINER( &(pxSegment->xQueueItem ) ) == NULL );
/* Now that the segment will be transmitted, add it to the tail of /* Now that the segment will be transmitted, add it to the tail of
@ -1412,11 +1458,13 @@ const int32_t l500ms = 500;
size of the transmission window to at most 2 times MSS. */ size of the transmission window to at most 2 times MSS. */
if( pxSegment->u.bits.ucTransmitCount == MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW ) if( pxSegment->u.bits.ucTransmitCount == MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW )
{ {
if( pxWindow->xSize.ulTxWindowLength > ( 2U * pxWindow->usMSS ) ) if( pxWindow->xSize.ulTxWindowLength > ( 2U * ( ( uint32_t ) pxWindow->usMSS ) ) )
{ {
FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u - %d]: Change Tx window: %lu -> %u\n", FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u - %d]: Change Tx window: %lu -> %u\n",
pxWindow->usPeerPortNumber, pxWindow->usOurPortNumber, pxWindow->usPeerPortNumber,
pxWindow->xSize.ulTxWindowLength, 2 * pxWindow->usMSS ) ); pxWindow->usOurPortNumber,
pxWindow->xSize.ulTxWindowLength,
2U * pxWindow->usMSS ) );
pxWindow->xSize.ulTxWindowLength = ( 2UL * pxWindow->usMSS ); pxWindow->xSize.ulTxWindowLength = ( 2UL * pxWindow->usMSS );
} }
} }
@ -1443,10 +1491,10 @@ const int32_t l500ms = 500;
static uint32_t prvTCPWindowTxCheckAck( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast ) static uint32_t prvTCPWindowTxCheckAck( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast )
{ {
uint32_t ulBytesConfirmed = 0u; uint32_t ulBytesConfirmed = 0U;
uint32_t ulSequenceNumber = ulFirst, ulDataLength; uint32_t ulSequenceNumber = ulFirst, ulDataLength;
const ListItem_t *pxIterator; const ListItem_t *pxIterator;
const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &pxWindow->xTxSegments ); const ListItem_t *pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &pxWindow->xTxSegments ) );
BaseType_t xDoUnlink; BaseType_t xDoUnlink;
TCPSegment_t *pxSegment; TCPSegment_t *pxSegment;
/* An acknowledgement or a selective ACK (SACK) was received. See if some outstanding data /* An acknowledgement or a selective ACK (SACK) was received. See if some outstanding data
@ -1470,13 +1518,11 @@ const int32_t l500ms = 500;
A Smoothed RTT will increase quickly, but it is conservative when A Smoothed RTT will increase quickly, but it is conservative when
becoming smaller. */ becoming smaller. */
for( pxIterator = listGET_NEXT( pxEnd );
pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd ); while( ( pxIterator != pxEnd ) && ( xSequenceLessThan( ulSequenceNumber, ulLast ) != 0 ) )
( pxIterator != ( const ListItem_t * ) pxEnd ) && ( xSequenceLessThan( ulSequenceNumber, ulLast ) != 0 );
)
{ {
xDoUnlink = pdFALSE; xDoUnlink = pdFALSE;
pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
/* Move to the next item because the current item might get /* Move to the next item because the current item might get
removed. */ removed. */
@ -1491,6 +1537,7 @@ const int32_t l500ms = 500;
/* Is it ready? */ /* Is it ready? */
if( ulSequenceNumber != pxSegment->ulSequenceNumber ) if( ulSequenceNumber != pxSegment->ulSequenceNumber )
{ {
/* coverity[break_stmt] : Break statement terminating the loop */
break; break;
} }
@ -1520,11 +1567,11 @@ const int32_t l500ms = 500;
} }
/* This segment is fully ACK'd, set the flag. */ /* This segment is fully ACK'd, set the flag. */
pxSegment->u.bits.bAcked = pdTRUE_UNSIGNED; pxSegment->u.bits.bAcked = pdTRUE;
/* Calculate the RTT only if the segment was sent-out for the /* Calculate the RTT only if the segment was sent-out for the
first time and if this is the last ACK'd segment in a range. */ first time and if this is the last ACK'd segment in a range. */
if( ( pxSegment->u.bits.ucTransmitCount == 1 ) && ( ( pxSegment->ulSequenceNumber + ulDataLength ) == ulLast ) ) if( ( pxSegment->u.bits.ucTransmitCount == 1U ) && ( ( pxSegment->ulSequenceNumber + ulDataLength ) == ulLast ) )
{ {
int32_t mS = ( int32_t ) ulTimerGetAge( &( pxSegment->xTransmitTimer ) ); int32_t mS = ( int32_t ) ulTimerGetAge( &( pxSegment->xTransmitTimer ) );
@ -1554,7 +1601,7 @@ const int32_t l500ms = 500;
side of the transmission queue? If so, it may be freed. */ side of the transmission queue? If so, it may be freed. */
if( ulSequenceNumber == pxWindow->tx.ulCurrentSequenceNumber ) if( ulSequenceNumber == pxWindow->tx.ulCurrentSequenceNumber )
{ {
if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) ) if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
{ {
FreeRTOS_debug_printf( ( "prvTCPWindowTxCheckAck: %lu - %lu Ready sequence number %lu\n", FreeRTOS_debug_printf( ( "prvTCPWindowTxCheckAck: %lu - %lu Ready sequence number %lu\n",
ulFirst - pxWindow->tx.ulFirstSequenceNumber, ulFirst - pxWindow->tx.ulFirstSequenceNumber,
@ -1579,7 +1626,7 @@ const int32_t l500ms = 500;
if( ( xDoUnlink != pdFALSE ) && ( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) != NULL ) ) if( ( xDoUnlink != pdFALSE ) && ( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) != NULL ) )
{ {
/* Remove item from its queues. */ /* Remove item from its queues. */
uxListRemove( &pxSegment->xQueueItem ); ( void ) uxListRemove( &pxSegment->xQueueItem );
} }
ulSequenceNumber += ulDataLength; ulSequenceNumber += ulDataLength;
@ -1595,37 +1642,41 @@ const int32_t l500ms = 500;
static uint32_t prvTCPWindowFastRetransmit( TCPWindow_t *pxWindow, uint32_t ulFirst ) static uint32_t prvTCPWindowFastRetransmit( TCPWindow_t *pxWindow, uint32_t ulFirst )
{ {
const ListItem_t * pxIterator; const ListItem_t * pxIterator;
const MiniListItem_t* pxEnd; const ListItem_t * pxEnd;
TCPSegment_t *pxSegment; TCPSegment_t *pxSegment;
uint32_t ulCount = 0UL; uint32_t ulCount = 0UL;
/* A higher Tx block has been acknowledged. Now iterate through the /* A higher Tx block has been acknowledged. Now iterate through the
xWaitQueue to find a possible condition for a FAST retransmission. */ xWaitQueue to find a possible condition for a FAST retransmission. */
pxEnd = ( const MiniListItem_t* ) listGET_END_MARKER( &( pxWindow->xWaitQueue ) ); pxEnd = ipPOINTER_CAST( const ListItem_t *, listGET_END_MARKER( &( pxWindow->xWaitQueue ) ) );
for( pxIterator = ( const ListItem_t * ) listGET_NEXT( pxEnd ); pxIterator = listGET_NEXT( pxEnd );
pxIterator != ( const ListItem_t * ) pxEnd; )
while( pxIterator != pxEnd )
{ {
/* Get the owner, which is a TCP segment. */ /* Get the owner, which is a TCP segment. */
pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); pxSegment = ipPOINTER_CAST( TCPSegment_t *, listGET_LIST_ITEM_OWNER( pxIterator ) );
/* Hop to the next item before the current gets unlinked. */ /* Hop to the next item before the current gets unlinked. */
pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ); pxIterator = listGET_NEXT( pxIterator );
/* Fast retransmission: /* Fast retransmission:
When 3 packets with a higher sequence number have been acknowledged When 3 packets with a higher sequence number have been acknowledged
by the peer, it is very unlikely a current packet will ever arrive. by the peer, it is very unlikely a current packet will ever arrive.
It will be retransmitted far before the RTO. */ It will be retransmitted far before the RTO. */
if( ( pxSegment->u.bits.bAcked == pdFALSE_UNSIGNED ) && if( pxSegment->u.bits.bAcked == pdFALSE_UNSIGNED )
( xSequenceLessThan( pxSegment->ulSequenceNumber, ulFirst ) != pdFALSE ) &&
( ++( pxSegment->u.bits.ucDupAckCount ) == DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT ) )
{ {
pxSegment->u.bits.ucTransmitCount = pdFALSE_UNSIGNED; if( xSequenceLessThan( pxSegment->ulSequenceNumber, ulFirst ) != pdFALSE )
{
pxSegment->u.bits.ucDupAckCount++;
if( pxSegment->u.bits.ucDupAckCount == DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT )
{
pxSegment->u.bits.ucTransmitCount = ( uint8_t ) pdFALSE;
/* Not clearing 'ucDupAckCount' yet as more SACK's might come in /* Not clearing 'ucDupAckCount' yet as more SACK's might come in
which might lead to a second fast rexmit. */ which might lead to a second fast rexmit. */
if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) ) if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) ) )
{ {
FreeRTOS_debug_printf( ( "prvTCPWindowFastRetransmit: Requeue sequence number %lu < %lu\n", FreeRTOS_debug_printf( ( "prvTCPWindowFastRetransmit: Requeue sequence number %lu < %lu\n",
pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber, pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,
@ -1634,14 +1685,15 @@ const int32_t l500ms = 500;
} }
/* Remove it from xWaitQueue. */ /* Remove it from xWaitQueue. */
uxListRemove( &pxSegment->xQueueItem ); ( void ) uxListRemove( &pxSegment->xQueueItem );
/* Add this segment to the priority queue so it gets /* Add this segment to the priority queue so it gets
retransmitted immediately. */ retransmitted immediately. */
vListInsertFifo( &( pxWindow->xPriorityQueue ), &( pxSegment->xQueueItem ) ); vListInsertFifo( &( pxWindow->xPriorityQueue ), &( pxSegment->xQueueItem ) );
ulCount++; ulCount++;
} }
} }
}
}
return ulCount; return ulCount;
} }
@ -1677,12 +1729,12 @@ const int32_t l500ms = 500;
uint32_t ulTCPWindowTxSack( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast ) uint32_t ulTCPWindowTxSack( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast )
{ {
uint32_t ulAckCount = 0UL; uint32_t ulAckCount;
uint32_t ulCurrentSequenceNumber = pxWindow->tx.ulCurrentSequenceNumber; uint32_t ulCurrentSequenceNumber = pxWindow->tx.ulCurrentSequenceNumber;
/* Receive a SACK option. */ /* Receive a SACK option. */
ulAckCount = prvTCPWindowTxCheckAck( pxWindow, ulFirst, ulLast ); ulAckCount = prvTCPWindowTxCheckAck( pxWindow, ulFirst, ulLast );
prvTCPWindowFastRetransmit( pxWindow, ulFirst ); ( void ) prvTCPWindowFastRetransmit( pxWindow, ulFirst );
if( ( xTCPWindowLoggingLevel >= 1 ) && ( xSequenceGreaterThan( ulFirst, ulCurrentSequenceNumber ) != pdFALSE ) ) if( ( xTCPWindowLoggingLevel >= 1 ) && ( xSequenceGreaterThan( ulFirst, ulCurrentSequenceNumber ) != pdFALSE ) )
{ {
@ -1810,15 +1862,15 @@ const int32_t l500ms = 500;
if( pxSegment->u.bits.bOutstanding != pdFALSE_UNSIGNED ) if( pxSegment->u.bits.bOutstanding != pdFALSE_UNSIGNED )
{ {
/* As 'ucTransmitCount' has a minimum of 1, take 2 * RTT */ /* As 'ucTransmitCount' has a minimum of 1, take 2 * RTT */
ulMaxTime = ( ( uint32_t ) 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT ); ulMaxTime = ( ( uint32_t ) 1U << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
if( ulTimerGetAge( &( pxSegment->xTransmitTimer ) ) < ulMaxTime ) if( ulTimerGetAge( &( pxSegment->xTransmitTimer ) ) < ulMaxTime )
{ {
ulLength = 0ul; ulLength = 0UL;
} }
} }
if( ulLength != 0ul ) if( ulLength != 0UL )
{ {
pxSegment->u.bits.bOutstanding = pdTRUE_UNSIGNED; pxSegment->u.bits.bOutstanding = pdTRUE_UNSIGNED;
pxSegment->u.bits.ucTransmitCount++; pxSegment->u.bits.ucTransmitCount++;
@ -1836,7 +1888,7 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 0 ) #if( ipconfigUSE_TCP_WIN == 0 )
BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow ) BaseType_t xTCPWindowTxDone( const TCPWindow_t *pxWindow )
{ {
BaseType_t xReturn; BaseType_t xReturn;
@ -1880,7 +1932,7 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 0 ) #if( ipconfigUSE_TCP_WIN == 0 )
BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay ) BaseType_t xTCPWindowTxHasData( TCPWindow_t const *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay )
{ {
TCPSegment_t *pxSegment = &( pxWindow->xTxSegment ); TCPSegment_t *pxSegment = &( pxWindow->xTxSegment );
BaseType_t xReturn; BaseType_t xReturn;
@ -1898,7 +1950,7 @@ const int32_t l500ms = 500;
if( pxSegment->u.bits.bOutstanding != pdFALSE_UNSIGNED ) if( pxSegment->u.bits.bOutstanding != pdFALSE_UNSIGNED )
{ {
ulAge = ulTimerGetAge ( &pxSegment->xTransmitTimer ); ulAge = ulTimerGetAge ( &pxSegment->xTransmitTimer );
ulMaxAge = ( ( TickType_t ) 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT ); ulMaxAge = ( ( TickType_t ) 1U << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );
if( ulMaxAge > ulAge ) if( ulMaxAge > ulAge )
{ {
@ -1933,7 +1985,7 @@ const int32_t l500ms = 500;
/* Receive a normal ACK */ /* Receive a normal ACK */
if( ulDataLength != 0ul ) if( ulDataLength != 0UL )
{ {
if( ulSequenceNumber < ( pxWindow->tx.ulCurrentSequenceNumber + ulDataLength ) ) if( ulSequenceNumber < ( pxWindow->tx.ulCurrentSequenceNumber + ulDataLength ) )
{ {
@ -1946,7 +1998,7 @@ const int32_t l500ms = 500;
} }
/* Nothing to send right now. */ /* Nothing to send right now. */
ulDataLength = 0ul; ulDataLength = 0UL;
} }
else else
{ {
@ -1971,7 +2023,7 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 0 ) #if( ipconfigUSE_TCP_WIN == 0 )
BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow ) BaseType_t xTCPWindowRxEmpty( const TCPWindow_t *pxWindow )
{ {
/* Return true if 'ulCurrentSequenceNumber >= ulHighestSequenceNumber' /* Return true if 'ulCurrentSequenceNumber >= ulHighestSequenceNumber'
'ulCurrentSequenceNumber' is the highest sequence number stored, 'ulCurrentSequenceNumber' is the highest sequence number stored,
@ -1985,7 +2037,7 @@ const int32_t l500ms = 500;
#if( ipconfigUSE_TCP_WIN == 0 ) #if( ipconfigUSE_TCP_WIN == 0 )
/* Destroy a window (always returns NULL) */ /* Destroy a window (always returns NULL) */
void vTCPWindowDestroy( TCPWindow_t *pxWindow ) void vTCPWindowDestroy( const TCPWindow_t *pxWindow )
{ {
/* As in tiny TCP there are no shared segments descriptors, there is /* As in tiny TCP there are no shared segments descriptors, there is
nothing to release. */ nothing to release. */

View file

@ -53,6 +53,7 @@
/* Part of the Ethernet and IP headers are always constant when sending an IPv4 /* Part of the Ethernet and IP headers are always constant when sending an IPv4
UDP packet. This array defines the constant parts, allowing this part of the UDP packet. This array defines the constant parts, allowing this part of the
packet to be filled in using a simple memcpy() instead of individual writes. */ packet to be filled in using a simple memcpy() instead of individual writes. */
/*lint -e708 (Info -- union initialization). */
UDPPacketHeader_t xDefaultPartUDPPacketHeader = UDPPacketHeader_t xDefaultPartUDPPacketHeader =
{ {
/* .ucBytes : */ /* .ucBytes : */
@ -81,10 +82,10 @@ uint32_t ulIPAddress = pxNetworkBuffer->ulIPAddress;
size_t uxPayloadSize; size_t uxPayloadSize;
/* Map the UDP packet onto the start of the frame. */ /* Map the UDP packet onto the start of the frame. */
pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer; pxUDPPacket = ipPOINTER_CAST( UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
#if ipconfigSUPPORT_OUTGOING_PINGS == 1 #if ipconfigSUPPORT_OUTGOING_PINGS == 1
if( pxNetworkBuffer->usPort == ipPACKET_CONTAINS_ICMP_DATA ) if( pxNetworkBuffer->usPort == ( uint16_t ) ipPACKET_CONTAINS_ICMP_DATA )
{ {
uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( ICMPPacket_t ); uxPayloadSize = pxNetworkBuffer->xDataLength - sizeof( ICMPPacket_t );
} }
@ -112,7 +113,7 @@ size_t uxPayloadSize;
#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) #if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
/* Is it possible that the packet is not actually a UDP packet /* Is it possible that the packet is not actually a UDP packet
after all, but an ICMP packet. */ after all, but an ICMP packet. */
if( pxNetworkBuffer->usPort != ipPACKET_CONTAINS_ICMP_DATA ) if( pxNetworkBuffer->usPort != ( uint16_t ) ipPACKET_CONTAINS_ICMP_DATA )
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */ #endif /* ipconfigSUPPORT_OUTGOING_PINGS */
{ {
UDPHeader_t *pxUDPHeader; UDPHeader_t *pxUDPHeader;
@ -123,7 +124,7 @@ size_t uxPayloadSize;
pxUDPHeader->usSourcePort = pxNetworkBuffer->usBoundPort; pxUDPHeader->usSourcePort = pxNetworkBuffer->usBoundPort;
pxUDPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( UDPHeader_t ) ); pxUDPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( UDPHeader_t ) );
pxUDPHeader->usLength = FreeRTOS_htons( pxUDPHeader->usLength ); pxUDPHeader->usLength = FreeRTOS_htons( pxUDPHeader->usLength );
pxUDPHeader->usChecksum = 0u; pxUDPHeader->usChecksum = 0U;
} }
/* memcpy() the constant parts of the header information into /* memcpy() the constant parts of the header information into
@ -140,19 +141,23 @@ size_t uxPayloadSize;
and and
xIPHeader.usHeaderChecksum xIPHeader.usHeaderChecksum
*/ */
/* Save options now, as they will be overwritten by memcpy */ /* Save options now, as they will be overwritten by memcpy */
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
{
ucSocketOptions = pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ]; ucSocketOptions = pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ];
}
#endif #endif
/* /*
* Offset the memcpy by the size of a MAC address to start at the packet's * Offset the memcpy by the size of a MAC address to start at the packet's
* Ethernet header 'source' MAC address; the preceding 'destination' should not be altered. * Ethernet header 'source' MAC address; the preceding 'destination' should not be altered.
*/ */
char *pxUdpSrcAddrOffset = ( char *) pxUDPPacket + sizeof( MACAddress_t ); /* The Ethernet source address is at offset 6. */
memcpy( pxUdpSrcAddrOffset, xDefaultPartUDPPacketHeader.ucBytes, sizeof( xDefaultPartUDPPacketHeader ) ); char *pxUdpSrcAddrOffset = ( char *) ( &( pxNetworkBuffer->pucEthernetBuffer[ sizeof( MACAddress_t ) ] ) );
( void ) memcpy( pxUdpSrcAddrOffset, xDefaultPartUDPPacketHeader.ucBytes, sizeof( xDefaultPartUDPPacketHeader ) );
#if ipconfigSUPPORT_OUTGOING_PINGS == 1 #if ipconfigSUPPORT_OUTGOING_PINGS == 1
if( pxNetworkBuffer->usPort == ipPACKET_CONTAINS_ICMP_DATA ) if( pxNetworkBuffer->usPort == ( uint16_t ) ipPACKET_CONTAINS_ICMP_DATA )
{ {
pxIPHeader->ucProtocol = ipPROTOCOL_ICMP; pxIPHeader->ucProtocol = ipPROTOCOL_ICMP;
pxIPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( IPHeader_t ) + sizeof( ICMPHeader_t ) ); pxIPHeader->usLength = ( uint16_t ) ( uxPayloadSize + sizeof( IPHeader_t ) + sizeof( ICMPHeader_t ) );
@ -164,7 +169,6 @@ size_t uxPayloadSize;
} }
pxIPHeader->usLength = FreeRTOS_htons( pxIPHeader->usLength ); pxIPHeader->usLength = FreeRTOS_htons( pxIPHeader->usLength );
/* HT:endian: changed back to network endian */
pxIPHeader->ulDestinationIPAddress = pxNetworkBuffer->ulIPAddress; pxIPHeader->ulDestinationIPAddress = pxNetworkBuffer->ulIPAddress;
#if( ipconfigUSE_LLMNR == 1 ) #if( ipconfigUSE_LLMNR == 1 )
@ -180,17 +184,17 @@ size_t uxPayloadSize;
#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
{ {
pxIPHeader->usHeaderChecksum = 0u; pxIPHeader->usHeaderChecksum = 0U;
pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER ); pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum ); pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
if( ( ucSocketOptions & ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT ) != 0u ) if( ( ucSocketOptions & ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT ) != 0U )
{ {
usGenerateProtocolChecksum( (uint8_t*)pxUDPPacket, pxNetworkBuffer->xDataLength, pdTRUE ); ( void ) usGenerateProtocolChecksum( ( uint8_t * ) pxUDPPacket, pxNetworkBuffer->xDataLength, pdTRUE );
} }
else else
{ {
pxUDPPacket->xUDPHeader.usChecksum = 0u; pxUDPPacket->xUDPHeader.usChecksum = 0U;
} }
} }
#endif #endif
@ -228,14 +232,14 @@ size_t uxPayloadSize;
for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ ) for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
{ {
pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u; pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0U;
} }
pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
} }
} }
#endif #endif
xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE ); ( void ) xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
} }
else else
{ {
@ -250,16 +254,16 @@ BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer
{ {
BaseType_t xReturn = pdPASS; BaseType_t xReturn = pdPASS;
FreeRTOS_Socket_t *pxSocket; FreeRTOS_Socket_t *pxSocket;
configASSERT(pxNetworkBuffer); configASSERT( pxNetworkBuffer != NULL );
configASSERT(pxNetworkBuffer->pucEthernetBuffer); configASSERT( pxNetworkBuffer->pucEthernetBuffer != NULL );
UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer; const UDPPacket_t *pxUDPPacket = ipPOINTER_CAST( const UDPPacket_t *, pxNetworkBuffer->pucEthernetBuffer );
/* Caller must check for minimum packet size. */ /* Caller must check for minimum packet size. */
pxSocket = pxUDPSocketLookup( usPort ); pxSocket = pxUDPSocketLookup( usPort );
if( pxSocket ) if( pxSocket != NULL )
{ {
/* When refreshing the ARP cache with received UDP packets we must be /* When refreshing the ARP cache with received UDP packets we must be
@ -273,7 +277,7 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleReceive ) ) if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleReceive ) )
{ {
struct freertos_sockaddr xSourceAddress, destinationAddress; struct freertos_sockaddr xSourceAddress, destinationAddress;
void *pcData = ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ); void *pcData = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
FOnUDPReceive_t xHandler = ( FOnUDPReceive_t ) pxSocket->u.xUDP.pxHandleReceive; FOnUDPReceive_t xHandler = ( FOnUDPReceive_t ) pxSocket->u.xUDP.pxHandleReceive;
xSourceAddress.sin_port = pxNetworkBuffer->usPort; xSourceAddress.sin_port = pxNetworkBuffer->usPort;
xSourceAddress.sin_addr = pxNetworkBuffer->ulIPAddress; xSourceAddress.sin_addr = pxNetworkBuffer->ulIPAddress;
@ -281,16 +285,19 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
destinationAddress.sin_addr = pxUDPPacket->xIPHeader.ulDestinationIPAddress; destinationAddress.sin_addr = pxUDPPacket->xIPHeader.ulDestinationIPAddress;
/* The value of 'xDataLength' was proven to be at least the size of a UDP packet in prvProcessIPPacket(). */ /* The value of 'xDataLength' was proven to be at least the size of a UDP packet in prvProcessIPPacket(). */
if( xHandler( ( Socket_t ) pxSocket, ( void* ) pcData, ( size_t ) ( pxNetworkBuffer->xDataLength - ipUDP_PAYLOAD_OFFSET_IPv4 ), if( xHandler( ( Socket_t ) pxSocket,
&xSourceAddress, &destinationAddress ) ) ( void* ) pcData,
( size_t ) ( pxNetworkBuffer->xDataLength - ipUDP_PAYLOAD_OFFSET_IPv4 ),
&( xSourceAddress ),
&( destinationAddress ) ) != 0 )
{ {
xReturn = pdFAIL; /* FAIL means that we did not consume or release the buffer */ xReturn = pdFAIL; /* xHandler has consumed the data, do not add it to .xWaitingPacketsList'. */
} }
} }
} }
#endif /* ipconfigUSE_CALLBACKS */ #endif /* ipconfigUSE_CALLBACKS */
#if( ipconfigUDP_MAX_RX_PACKETS > 0 ) #if( ipconfigUDP_MAX_RX_PACKETS > 0U )
{ {
if( xReturn == pdPASS ) if( xReturn == pdPASS )
{ {
@ -305,11 +312,13 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
} }
#endif #endif
if( xReturn == pdPASS ) #if( ipconfigUSE_CALLBACKS == 1 ) || ( ipconfigUDP_MAX_RX_PACKETS > 0U )
if( xReturn == pdPASS ) /*lint !e774: Boolean within 'if' always evaluates to True, depending on configuration. [MISRA 2012 Rule 14.3, required. */
#else
/* xReturn is still pdPASS. */
#endif
{ {
vTaskSuspendAll(); vTaskSuspendAll();
{
if( xReturn == pdPASS )
{ {
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
@ -319,20 +328,19 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
} }
} ( void ) xTaskResumeAll();
xTaskResumeAll();
/* Set the socket's receive event */ /* Set the socket's receive event */
if( pxSocket->xEventGroup != NULL ) if( pxSocket->xEventGroup != NULL )
{ {
xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE ); ( void ) xEventGroupSetBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_RECEIVE );
} }
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
{ {
if( ( pxSocket->pxSocketSet != NULL ) && ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) ) if( ( pxSocket->pxSocketSet != NULL ) && ( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_READ ) ) != 0U ) )
{ {
xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_READ ); ( void ) xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, ( EventBits_t ) eSELECT_READ );
} }
} }
#endif #endif
@ -341,16 +349,16 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
{ {
if( pxSocket->pxUserSemaphore != NULL ) if( pxSocket->pxUserSemaphore != NULL )
{ {
xSemaphoreGive( pxSocket->pxUserSemaphore ); ( void ) xSemaphoreGive( pxSocket->pxUserSemaphore );
} }
} }
#endif #endif
#if( ipconfigUSE_DHCP == 1 ) #if( ipconfigUSE_DHCP == 1 )
{ {
if( xIsDHCPSocket( pxSocket ) ) if( xIsDHCPSocket( pxSocket ) != 0 )
{ {
xSendEventToIPTask( eDHCPEvent ); ( void ) xSendEventToIPTask( eDHCPEvent );
} }
} }
#endif #endif
@ -366,7 +374,7 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
does open a UDP socket to send a messages, this socket will be does open a UDP socket to send a messages, this socket will be
closed after a short timeout. Messages that come late (after the closed after a short timeout. Messages that come late (after the
socket is closed) will be treated here. */ socket is closed) will be treated here. */
if( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usSourcePort ) == ipDNS_PORT ) if( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usSourcePort ) == ( uint16_t ) ipDNS_PORT )
{ {
vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress ); vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer ); xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer );
@ -375,7 +383,7 @@ UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;
#endif #endif
#if( ipconfigUSE_LLMNR == 1 ) #if( ipconfigUSE_LLMNR == 1 )
/* a LLMNR request, check for the destination port. */ /* A LLMNR request, check for the destination port. */
if( ( usPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) || if( ( usPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) ||
( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) ) ( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) )
{ {

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -157,7 +157,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
* This macro will only be used if FreeRTOS_debug_printf() is defined for logging * This macro will only be used if FreeRTOS_debug_printf() is defined for logging
*/ */
#ifndef ipconfigTCP_MAY_LOG_PORT #ifndef ipconfigTCP_MAY_LOG_PORT
#define ipconfigTCP_MAY_LOG_PORT(xPort) ( ( xPort ) != 23u ) #define ipconfigTCP_MAY_LOG_PORT(xPort) ( ( xPort ) != 23U )
#endif #endif
@ -171,11 +171,11 @@ from the FreeRTOSIPConfig.h configuration header file. */
#ifndef ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS #ifndef ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS
#define ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS pdMS_TO_TICKS( 500u ) #define ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS pdMS_TO_TICKS( 5000U )
#endif #endif
#ifndef ipconfigDNS_SEND_BLOCK_TIME_TICKS #ifndef ipconfigDNS_SEND_BLOCK_TIME_TICKS
#define ipconfigDNS_SEND_BLOCK_TIME_TICKS pdMS_TO_TICKS( 500u ) #define ipconfigDNS_SEND_BLOCK_TIME_TICKS pdMS_TO_TICKS( 500U )
#endif #endif
/* /*
* FreeRTOS debug logging routine (proposal) * FreeRTOS debug logging routine (proposal)
@ -196,7 +196,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif /* ifdef ipconfigHAS_DEBUG_PRINTF */ #endif /* ifdef ipconfigHAS_DEBUG_PRINTF */
#ifndef FreeRTOS_debug_printf #ifndef FreeRTOS_debug_printf
#define FreeRTOS_debug_printf( MSG ) do{} while(0) #define FreeRTOS_debug_printf( MSG ) do{} while( ipFALSE_BOOL )
#define ipconfigHAS_DEBUG_PRINTF 0 #define ipconfigHAS_DEBUG_PRINTF 0
#endif #endif
@ -217,7 +217,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif /* ifdef ipconfigHAS_PRINTF */ #endif /* ifdef ipconfigHAS_PRINTF */
#ifndef FreeRTOS_printf #ifndef FreeRTOS_printf
#define FreeRTOS_printf( MSG ) do{} while(0) #define FreeRTOS_printf( MSG ) do{} while( ipFALSE_BOOL )
#define ipconfigHAS_PRINTF 0 #define ipconfigHAS_PRINTF 0
#endif #endif
@ -227,7 +227,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
* An example of this is the netstat command, which produces many lines of logging * An example of this is the netstat command, which produces many lines of logging
*/ */
#ifndef FreeRTOS_flush_logging #ifndef FreeRTOS_flush_logging
#define FreeRTOS_flush_logging( ) do{} while(0) #define FreeRTOS_flush_logging( ) do{} while( ipFALSE_BOOL )
#endif #endif
/* Malloc functions. Within most applications of FreeRTOS, the couple /* Malloc functions. Within most applications of FreeRTOS, the couple
@ -274,7 +274,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif #endif
#ifndef ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS #ifndef ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS
#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( pdMS_TO_TICKS( 20 ) ) #define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( pdMS_TO_TICKS( 20U ) )
#endif #endif
#ifndef ipconfigARP_CACHE_ENTRIES #ifndef ipconfigARP_CACHE_ENTRIES
@ -282,11 +282,11 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif #endif
#ifndef ipconfigMAX_ARP_RETRANSMISSIONS #ifndef ipconfigMAX_ARP_RETRANSMISSIONS
#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5u ) #define ipconfigMAX_ARP_RETRANSMISSIONS ( 5U )
#endif #endif
#ifndef ipconfigMAX_ARP_AGE #ifndef ipconfigMAX_ARP_AGE
#define ipconfigMAX_ARP_AGE 150u #define ipconfigMAX_ARP_AGE 150U
#endif #endif
#ifndef ipconfigUSE_ARP_REVERSED_LOOKUP #ifndef ipconfigUSE_ARP_REVERSED_LOOKUP
@ -301,6 +301,10 @@ from the FreeRTOSIPConfig.h configuration header file. */
#define ipconfigINCLUDE_FULL_INET_ADDR 1 #define ipconfigINCLUDE_FULL_INET_ADDR 1
#endif #endif
#ifndef ipconfigUSE_LINKED_RX_MESSAGES
#define ipconfigUSE_LINKED_RX_MESSAGES 0
#endif
#ifndef ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS #ifndef ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS
#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 45 #define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 45
#endif #endif
@ -326,7 +330,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
* for each UDP socket. * for each UDP socket.
* Can be overridden with the socket option FREERTOS_SO_UDP_MAX_RX_PACKETS * Can be overridden with the socket option FREERTOS_SO_UDP_MAX_RX_PACKETS
*/ */
#define ipconfigUDP_MAX_RX_PACKETS 0u #define ipconfigUDP_MAX_RX_PACKETS 0U
#endif #endif
#ifndef ipconfigUSE_DHCP #ifndef ipconfigUSE_DHCP
@ -359,7 +363,7 @@ from the FreeRTOSIPConfig.h configuration header file. */
#endif #endif
#ifndef ipconfigTCP_MSS #ifndef ipconfigTCP_MSS
#define ipconfigTCP_MSS ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER - ipSIZE_OF_TCP_HEADER ) #define ipconfigTCP_MSS ( ipconfigNETWORK_MTU - ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) )
#endif #endif
/* Each TCP socket has circular stream buffers for Rx and Tx, which /* Each TCP socket has circular stream buffers for Rx and Tx, which
@ -367,19 +371,19 @@ from the FreeRTOSIPConfig.h configuration header file. */
* The defaults for these size are defined here, although * The defaults for these size are defined here, although
* they can be overridden at runtime by using the setsockopt() call */ * they can be overridden at runtime by using the setsockopt() call */
#ifndef ipconfigTCP_RX_BUFFER_LENGTH #ifndef ipconfigTCP_RX_BUFFER_LENGTH
#define ipconfigTCP_RX_BUFFER_LENGTH ( 4u * ipconfigTCP_MSS ) /* defaults to 5840 bytes */ #define ipconfigTCP_RX_BUFFER_LENGTH ( 4U * ipconfigTCP_MSS ) /* defaults to 5840 bytes */
#endif #endif
/* Define the size of Tx stream buffer for TCP sockets */ /* Define the size of Tx stream buffer for TCP sockets */
#ifndef ipconfigTCP_TX_BUFFER_LENGTH #ifndef ipconfigTCP_TX_BUFFER_LENGTH
# define ipconfigTCP_TX_BUFFER_LENGTH ( 4u * ipconfigTCP_MSS ) /* defaults to 5840 bytes */ # define ipconfigTCP_TX_BUFFER_LENGTH ( 4U * ipconfigTCP_MSS ) /* defaults to 5840 bytes */
#endif #endif
#ifndef ipconfigMAXIMUM_DISCOVER_TX_PERIOD #ifndef ipconfigMAXIMUM_DISCOVER_TX_PERIOD
#ifdef _WINDOWS_ #ifdef _WINDOWS_
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 999 ) ) #define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 999U ) )
#else #else
#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 30000 ) ) #define ipconfigMAXIMUM_DISCOVER_TX_PERIOD ( pdMS_TO_TICKS( 30000U ) )
#endif /* _WINDOWS_ */ #endif /* _WINDOWS_ */
#endif /* ipconfigMAXIMUM_DISCOVER_TX_PERIOD */ #endif /* ipconfigMAXIMUM_DISCOVER_TX_PERIOD */
@ -413,8 +417,16 @@ from the FreeRTOSIPConfig.h configuration header file. */
#ifndef ipconfigDNS_CACHE_ENTRIES #ifndef ipconfigDNS_CACHE_ENTRIES
#define ipconfigDNS_CACHE_ENTRIES 1 #define ipconfigDNS_CACHE_ENTRIES 1
#endif #endif
#endif /* ipconfigUSE_DNS_CACHE != 0 */ #endif /* ipconfigUSE_DNS_CACHE != 0 */
/* When accessing services which have multiple IP addresses, setting this
greater than 1 can improve reliability by returning different IP address
answers on successive calls to FreeRTOS_gethostbyname(). */
#ifndef ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY
#define ipconfigDNS_CACHE_ADDRESSES_PER_ENTRY 1
#endif
#ifndef ipconfigCHECK_IP_QUEUE_SPACE #ifndef ipconfigCHECK_IP_QUEUE_SPACE
#define ipconfigCHECK_IP_QUEUE_SPACE 0 #define ipconfigCHECK_IP_QUEUE_SPACE 0
#endif #endif
@ -544,7 +556,7 @@ connections, hang protection can help reduce the impact of SYN floods. */
/* Non-activity timeout is expressed in seconds. */ /* Non-activity timeout is expressed in seconds. */
#ifndef ipconfigTCP_HANG_PROTECTION_TIME #ifndef ipconfigTCP_HANG_PROTECTION_TIME
#define ipconfigTCP_HANG_PROTECTION_TIME 30 #define ipconfigTCP_HANG_PROTECTION_TIME 30U
#endif #endif
#ifndef ipconfigTCP_IP_SANITY #ifndef ipconfigTCP_IP_SANITY
@ -559,11 +571,15 @@ connections, hang protection can help reduce the impact of SYN floods. */
/* Expert option: define a value for 'ipBUFFER_PADDING'. /* Expert option: define a value for 'ipBUFFER_PADDING'.
When 'ipconfigBUFFER_PADDING' equals 0, When 'ipconfigBUFFER_PADDING' equals 0,
'ipBUFFER_PADDING' will get a default value of 8 + 2 bytes. */ 'ipBUFFER_PADDING' will get a default value of 8 + 2 bytes. */
#define ipconfigBUFFER_PADDING 0 #define ipconfigBUFFER_PADDING 0U
#endif #endif
#ifndef ipconfigPACKET_FILLER_SIZE #ifndef ipconfigPACKET_FILLER_SIZE
#define ipconfigPACKET_FILLER_SIZE 2 #define ipconfigPACKET_FILLER_SIZE 2U
#endif
#ifndef ipconfigSELECT_USES_NOTIFY
#define ipconfigSELECT_USES_NOTIFY 0
#endif #endif
#endif /* FREERTOS_DEFAULT_IP_CONFIG_H */ #endif /* FREERTOS_DEFAULT_IP_CONFIG_H */

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -54,13 +54,6 @@ typedef enum
eCantSendPacket /* 2 There is no IP address, or an ARP is still in progress, so the packet cannot be sent. */ eCantSendPacket /* 2 There is no IP address, or an ARP is still in progress, so the packet cannot be sent. */
} eARPLookupResult_t; } eARPLookupResult_t;
typedef enum
{
eNotFragment = 0, /* The IP packet being sent is not part of a fragment. */
eFirstFragment, /* The IP packet being sent is the first in a set of fragmented packets. */
eFollowingFragment /* The IP packet being sent is part of a set of fragmented packets. */
} eIPFragmentStatus_t;
/* /*
* If ulIPAddress is already in the ARP cache table then reset the age of the * If ulIPAddress is already in the ARP cache table then reset the age of the
* entry back to its maximum value. If ulIPAddress is not already in the ARP * entry back to its maximum value. If ulIPAddress is not already in the ARP
@ -121,6 +114,23 @@ void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffe
*/ */
void vARPSendGratuitous( void ); void vARPSendGratuitous( void );
/* This function will check if the target IP-address belongs to this device.
If so, the packet will be passed to the IP-stack, who will answer it.
The function is to be called within the function xNetworkInterfaceOutput()
in NetworkInterface.c as follows:
if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 )
{
/ * The packet has been sent back to the IP-task.
* The IP-task will further handle it.
* Do not release the descriptor.
* /
return pdTRUE;
}
/ * Send the packet as usual. * /
*/
BaseType_t xCheckLoopback( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend );
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -34,14 +34,12 @@ extern "C" {
#include "FreeRTOSIPConfig.h" #include "FreeRTOSIPConfig.h"
#include "IPTraceMacroDefaults.h" #include "IPTraceMacroDefaults.h"
#if( ipconfigUSE_DHCP_HOOK != 0 )
/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */ /* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
typedef enum eDHCP_PHASE typedef enum eDHCP_PHASE
{ {
eDHCPPhasePreDiscover, /* Driver is about to send a DHCP discovery. */ eDHCPPhasePreDiscover, /* Driver is about to send a DHCP discovery. */
eDHCPPhasePreRequest, /* Driver is about to request DHCP an IP address. */ eDHCPPhasePreRequest /* Driver is about to request DHCP an IP address. */
#if( ipconfigDHCP_SEND_DISCOVER_AFTER_AUTO_IP != 0 )
eDHCPPhasePreLLA, /* Driver is about to try get an LLA address */
#endif /* ipconfigDHCP_SEND_DISCOVER_AFTER_AUTO_IP */
} eDHCPCallbackPhase_t; } eDHCPCallbackPhase_t;
/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */ /* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
@ -51,6 +49,38 @@ typedef enum eDHCP_ANSWERS
eDHCPUseDefaults, /* Stop DHCP and use the static defaults. */ eDHCPUseDefaults, /* Stop DHCP and use the static defaults. */
eDHCPStopNoChanges, /* Stop DHCP and continue with current settings. */ eDHCPStopNoChanges, /* Stop DHCP and continue with current settings. */
} eDHCPCallbackAnswer_t; } eDHCPCallbackAnswer_t;
#endif /* #if( ipconfigUSE_DHCP_HOOK != 0 ) */
/* DHCP state machine states. */
typedef enum
{
eWaitingSendFirstDiscover = 0, /* Initial state. Send a discover the first time it is called, and reset all timers. */
eWaitingOffer, /* Either resend the discover, or, if the offer is forthcoming, send a request. */
eWaitingAcknowledge, /* Either resend the request. */
#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
eGetLinkLayerAddress, /* When DHCP didn't respond, try to obtain a LinkLayer address 168.254.x.x. */
#endif
eLeasedAddress, /* Resend the request at the appropriate time to renew the lease. */
eNotUsingLeasedAddress /* DHCP failed, and a default IP address is being used. */
} eDHCPState_t;
/* Hold information in between steps in the DHCP state machine. */
struct xDHCP_DATA
{
uint32_t ulTransactionId;
uint32_t ulOfferedIPAddress;
uint32_t ulDHCPServerAddress;
uint32_t ulLeaseTime;
/* Hold information on the current timer state. */
TickType_t xDHCPTxTime;
TickType_t xDHCPTxPeriod;
/* Try both without and with the broadcast flag */
BaseType_t xUseBroadcast;
/* Maintains the DHCP state machine state. */
eDHCPState_t eDHCPState;
};
typedef struct xDHCP_DATA DHCPData_t;
/* /*
* NOT A PUBLIC API FUNCTION. * NOT A PUBLIC API FUNCTION.
@ -60,12 +90,14 @@ void vDHCPProcess( BaseType_t xReset );
/* Internal call: returns true if socket is the current DHCP socket */ /* Internal call: returns true if socket is the current DHCP socket */
BaseType_t xIsDHCPSocket( Socket_t xSocket ); BaseType_t xIsDHCPSocket( Socket_t xSocket );
#if( ipconfigUSE_DHCP_HOOK != 0 )
/* Prototype of the hook (or callback) function that must be provided by the /* Prototype of the hook (or callback) function that must be provided by the
application if ipconfigUSE_DHCP_HOOK is set to 1. See the following URL for application if ipconfigUSE_DHCP_HOOK is set to 1. See the following URL for
usage information: usage information:
http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK
*/ */
eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase, uint32_t ulIPAddress ); eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase, uint32_t ulIPAddress );
#endif /* ( ipconfigUSE_DHCP_HOOK != 0 ) */
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -43,9 +43,9 @@ extern "C" {
* The target IP address will be 224.0.0.252 * The target IP address will be 224.0.0.252
*/ */
#if( ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN ) #if( ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )
#define ipLLMNR_IP_ADDR 0xE00000FC #define ipLLMNR_IP_ADDR 0xE00000FCUL
#else #else
#define ipLLMNR_IP_ADDR 0xFC0000E0 #define ipLLMNR_IP_ADDR 0xFC0000E0UL
#endif /* ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN */ #endif /* ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN */
#define ipLLMNR_PORT 5355 /* Standard LLMNR port. */ #define ipLLMNR_PORT 5355 /* Standard LLMNR port. */
@ -55,18 +55,21 @@ extern "C" {
#define ipNBNS_PORT 137 /* NetBIOS Name Service. */ #define ipNBNS_PORT 137 /* NetBIOS Name Service. */
#define ipNBDGM_PORT 138 /* Datagram Service, not included. */ #define ipNBDGM_PORT 138 /* Datagram Service, not included. */
#if( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 )
/* /*
* The following function should be provided by the user and return true if it * The following function should be provided by the user and return true if it
* matches the domain name. * matches the domain name.
*/ */
extern BaseType_t xApplicationDNSQueryHook( const char *pcName ); extern BaseType_t xApplicationDNSQueryHook( const char *pcName );
#endif /* ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_NBNS == 1 ) */
/* /*
* LLMNR is very similar to DNS, so is handled by the DNS routines. * LLMNR is very similar to DNS, so is handled by the DNS routines.
*/ */
uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer ); uint32_t ulDNSHandlePacket( const NetworkBufferDescriptor_t *pxNetworkBuffer );
#if( ipconfigUSE_LLMNR == 1 ) #if( ipconfigUSE_LLMNR == 1 )
/* The LLMNR MAC address is 01:00:5e:00:00:fc */
extern const MACAddress_t xLLMNR_MacAdress; extern const MACAddress_t xLLMNR_MacAdress;
#endif /* ipconfigUSE_LLMNR */ #endif /* ipconfigUSE_LLMNR */
@ -89,7 +92,8 @@ uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer );
uint32_t FreeRTOS_dnslookup( const char *pcHostName ); uint32_t FreeRTOS_dnslookup( const char *pcHostName );
/* Remove all entries from the DNS cache. */ /* Remove all entries from the DNS cache. */
void FreeRTOS_dnsclear(); void FreeRTOS_dnsclear( void );
#endif /* ipconfigUSE_DNS_CACHE != 0 */ #endif /* ipconfigUSE_DNS_CACHE != 0 */
#if( ipconfigDNS_USE_CALLBACKS != 0 ) #if( ipconfigDNS_USE_CALLBACKS != 0 )
@ -104,18 +108,33 @@ uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer );
* Asynchronous version of gethostbyname() * Asynchronous version of gethostbyname()
* xTimeout is in units of ms. * xTimeout is in units of ms.
*/ */
uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName, FOnDNSEvent pCallback, void *pvSearchID, TickType_t xTimeout ); uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName, FOnDNSEvent pCallback, void *pvSearchID, TickType_t uxTimeout );
void FreeRTOS_gethostbyname_cancel( void *pvSearchID ); void FreeRTOS_gethostbyname_cancel( void *pvSearchID );
#endif #endif
/* /*
* FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE * Lookup a IPv4 node in a blocking-way.
* FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL: * It returns a 32-bit IP-address, 0 when not found.
* _TBD_ Add URL * gethostbyname() is already deprecated.
*/ */
uint32_t FreeRTOS_gethostbyname( const char *pcHostName ); uint32_t FreeRTOS_gethostbyname( const char *pcHostName );
#if( ipconfigDNS_USE_CALLBACKS == 1 )
/*
* The function vDNSInitialise() initialises the DNS module.
* It will be called "internally", by the IP-task.
*/
void vDNSInitialise( void );
#endif /* ( ipconfigDNS_USE_CALLBACKS == 1 ) */
#if( ipconfigDNS_USE_CALLBACKS == 1 )
/*
* A function local to the library.
*/
extern void vDNSCheckCallBack( void *pvSearchID );
#endif
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -30,36 +30,73 @@
extern "C" { extern "C" {
#endif #endif
#include "FreeRTOS.h"
#include "task.h"
/* Application level configuration options. */ /* Application level configuration options. */
#include "FreeRTOSIPConfig.h" #include "FreeRTOSIPConfig.h"
#include "FreeRTOSIPConfigDefaults.h" #include "FreeRTOSIPConfigDefaults.h"
#include "IPTraceMacroDefaults.h" #include "IPTraceMacroDefaults.h"
/* Some constants defining the sizes of several parts of a packet */ #ifdef __COVERITY__
#define ipSIZE_OF_ETH_HEADER 14u /* Coverity static checks don't like inlined functions.
#define ipSIZE_OF_IPv4_HEADER 20u As it is up to the users to allow inlining, don't let
#define ipSIZE_OF_IGMP_HEADER 8u let Coverity know about it. */
#define ipSIZE_OF_ICMP_HEADER 8u
#define ipSIZE_OF_UDP_HEADER 8u
#define ipSIZE_OF_TCP_HEADER 20u
#ifdef portINLINE
/* coverity[misra_c_2012_rule_20_5_violation] */
/* The usage of #undef violates the rule. */
#undef portINLINE
#endif
#define portINLINE
#endif
/* Some constants defining the sizes of several parts of a packet.
These defines come before inlucding the configuration header files. */
/* The size of the Ethernet header is 14, meaning that 802.1Q VLAN tags
are not ( yet ) supported. */
#define ipSIZE_OF_ETH_HEADER 14U
#define ipSIZE_OF_IPv4_HEADER 20U
#define ipSIZE_OF_IGMP_HEADER 8U
#define ipSIZE_OF_ICMP_HEADER 8U
#define ipSIZE_OF_UDP_HEADER 8U
#define ipSIZE_OF_TCP_HEADER 20U
#define ipSIZE_OF_IPv4_ADDRESS 4U
/*
* Generate a randomized TCP Initial Sequence Number per RFC.
* This function must be provided by the application builder.
*/
/* coverity[misra_c_2012_rule_8_6_violation] */
/* "ulApplicationGetNextSequenceNumber" is declared but never defined. */
extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
uint16_t usSourcePort,
uint32_t ulDestinationAddress,
uint16_t usDestinationPort );
/* The number of octets in the MAC and IP addresses respectively. */ /* The number of octets in the MAC and IP addresses respectively. */
#define ipMAC_ADDRESS_LENGTH_BYTES ( 6 ) #define ipMAC_ADDRESS_LENGTH_BYTES ( 6 )
#define ipIP_ADDRESS_LENGTH_BYTES ( 4 ) #define ipIP_ADDRESS_LENGTH_BYTES ( 4 )
/* IP protocol definitions. */ /* IP protocol definitions. */
#define ipPROTOCOL_ICMP ( 1 ) #define ipPROTOCOL_ICMP ( 1U )
#define ipPROTOCOL_IGMP ( 2 ) #define ipPROTOCOL_IGMP ( 2U )
#define ipPROTOCOL_TCP ( 6 ) #define ipPROTOCOL_TCP ( 6U )
#define ipPROTOCOL_UDP ( 17 ) #define ipPROTOCOL_UDP ( 17U )
/* The character used to fill ICMP echo requests, and therefore also the
character expected to fill ICMP echo replies. */
#define ipECHO_DATA_FILL_BYTE 'x'
/* Dimensions the buffers that are filled by received Ethernet frames. */ /* Dimensions the buffers that are filled by received Ethernet frames. */
#define ipSIZE_OF_ETH_CRC_BYTES ( 4UL ) #define ipSIZE_OF_ETH_CRC_BYTES ( 4UL )
#define ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES ( 4UL ) #define ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES ( 4UL )
#define ipTOTAL_ETHERNET_FRAME_SIZE ( ( ( uint32_t ) ipconfigNETWORK_MTU ) + ( ( uint32_t ) ipSIZE_OF_ETH_HEADER ) + ipSIZE_OF_ETH_CRC_BYTES + ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES ) #define ipTOTAL_ETHERNET_FRAME_SIZE ( ( ( uint32_t ) ipconfigNETWORK_MTU ) + ( ( uint32_t ) ipSIZE_OF_ETH_HEADER ) + ipSIZE_OF_ETH_CRC_BYTES + ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES )
/*_RB_ Comment may need updating. */
/* Space left at the beginning of a network buffer storage area to store a /* Space left at the beginning of a network buffer storage area to store a
pointer back to the network buffer. Should be a multiple of 8 to ensure 8 byte pointer back to the network buffer. Should be a multiple of 8 to ensure 8 byte
alignment is maintained on architectures that require it. alignment is maintained on architectures that require it.
@ -77,10 +114,11 @@ buffer will have the following contents:
uint8_t ucVersionHeaderLength; uint8_t ucVersionHeaderLength;
etc etc
*/ */
#if( ipconfigBUFFER_PADDING != 0 ) #if( ipconfigBUFFER_PADDING != 0 )
#define ipBUFFER_PADDING ipconfigBUFFER_PADDING #define ipBUFFER_PADDING ipconfigBUFFER_PADDING
#else #else
#define ipBUFFER_PADDING ( 8u + ipconfigPACKET_FILLER_SIZE ) #define ipBUFFER_PADDING ( 8U + ipconfigPACKET_FILLER_SIZE )
#endif #endif
/* The structure used to store buffers and pass them around the network stack. /* The structure used to store buffers and pass them around the network stack.
@ -114,6 +152,8 @@ typedef enum eNETWORK_EVENTS
eNetworkDown /* The network connection has been lost. */ eNetworkDown /* The network connection has been lost. */
} eIPCallbackEvent_t; } eIPCallbackEvent_t;
/* MISRA check: some modules refer to this typedef even though
ipconfigSUPPORT_OUTGOING_PINGS is not enabled. */
typedef enum ePING_REPLY_STATUS typedef enum ePING_REPLY_STATUS
{ {
eSuccess = 0, /* A correct reply has been received for an outgoing ping. */ eSuccess = 0, /* A correct reply has been received for an outgoing ping. */
@ -121,12 +161,15 @@ typedef enum ePING_REPLY_STATUS
eInvalidData /* A reply was received to an outgoing ping but the payload of the reply was not correct. */ eInvalidData /* A reply was received to an outgoing ping but the payload of the reply was not correct. */
} ePingReplyStatus_t; } ePingReplyStatus_t;
typedef enum eNETWORK_ADDRESS_TYPE typedef struct xIP_TIMER
{ {
eNetWorkAddressTypeIPV4, uint32_t
eNetWorkAddressTypeIPV6, bActive : 1, /* This timer is running and must be processed. */
eNetWorkAddressTypeHostName bExpired : 1; /* Timer has expired and a task must be processed. */
} eNetWorkAddressType_t; TimeOut_t xTimeOut;
TickType_t ulRemainingTime;
TickType_t ulReloadTime;
} IPTimer_t;
/* Endian related definitions. */ /* Endian related definitions. */
#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) #if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
@ -169,52 +212,45 @@ typedef enum eNETWORK_ADDRESS_TYPE
static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d); static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d);
static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d); static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d);
static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b); static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b);
static portINLINE BaseType_t FreeRTOS_max_BaseType (BaseType_t a, BaseType_t b);
static portINLINE UBaseType_t FreeRTOS_max_UBaseType (UBaseType_t a, UBaseType_t b);
static portINLINE UBaseType_t FreeRTOS_min_UBaseType (UBaseType_t a, UBaseType_t b);
static portINLINE int32_t FreeRTOS_max_int32 (int32_t a, int32_t b) { return ( a >= b ) ? a : b; }
static portINLINE int32_t FreeRTOS_max_int32 (int32_t a, int32_t b) { return a >= b ? a : b; } static portINLINE uint32_t FreeRTOS_max_uint32 (uint32_t a, uint32_t b) { return ( a >= b ) ? a : b; }
static portINLINE uint32_t FreeRTOS_max_uint32 (uint32_t a, uint32_t b) { return a >= b ? a : b; } static portINLINE int32_t FreeRTOS_min_int32 (int32_t a, int32_t b) { return ( a <= b ) ? a : b; }
static portINLINE int32_t FreeRTOS_min_int32 (int32_t a, int32_t b) { return a <= b ? a : b; } static portINLINE uint32_t FreeRTOS_min_uint32 (uint32_t a, uint32_t b) { return ( a <= b ) ? a : b; }
static portINLINE uint32_t FreeRTOS_min_uint32 (uint32_t a, uint32_t b) { return a <= b ? a : b; } static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d) { return d * ( ( a + d - 1U ) / d ); }
static portINLINE uint32_t FreeRTOS_round_up (uint32_t a, uint32_t d) { return d * ( ( a + d - 1u ) / d ); }
static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d) { return d * ( a / d ); } static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d) { return d * ( a / d ); }
static portINLINE BaseType_t FreeRTOS_max_BaseType (BaseType_t a, BaseType_t b) { return a >= b ? a : b; } static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b) { return ( a <= b ) ? a : b; }
static portINLINE UBaseType_t FreeRTOS_max_UBaseType (UBaseType_t a, UBaseType_t b) { return a >= b ? a : b; }
static portINLINE BaseType_t FreeRTOS_min_BaseType (BaseType_t a, BaseType_t b) { return a <= b ? a : b; }
static portINLINE UBaseType_t FreeRTOS_min_UBaseType (UBaseType_t a, UBaseType_t b) { return a <= b ? a : b; }
#else #else
#define FreeRTOS_max_int32(a,b) ( ( ( int32_t ) ( a ) ) >= ( ( int32_t ) ( b ) ) ? ( ( int32_t ) ( a ) ) : ( ( int32_t ) ( b ) ) ) #define FreeRTOS_max_int32(a,b) ( ( ( ( int32_t ) ( a ) ) >= ( ( int32_t ) ( b ) ) ) ? ( ( int32_t ) ( a ) ) : ( ( int32_t ) ( b ) ) )
#define FreeRTOS_max_uint32(a,b) ( ( ( uint32_t ) ( a ) ) >= ( ( uint32_t ) ( b ) ) ? ( ( uint32_t ) ( a ) ) : ( ( uint32_t ) ( b ) ) ) #define FreeRTOS_max_uint32(a,b) ( ( ( ( uint32_t ) ( a ) ) >= ( ( uint32_t ) ( b ) ) ) ? ( ( uint32_t ) ( a ) ) : ( ( uint32_t ) ( b ) ) )
#define FreeRTOS_min_int32(a,b) ( ( ( int32_t ) a ) <= ( ( int32_t ) b ) ? ( ( int32_t ) a ) : ( ( int32_t ) b ) ) #define FreeRTOS_min_int32(a,b) ( ( ( ( int32_t ) a ) <= ( ( int32_t ) b ) ) ? ( ( int32_t ) a ) : ( ( int32_t ) b ) )
#define FreeRTOS_min_uint32(a,b) ( ( ( uint32_t ) a ) <= ( ( uint32_t ) b ) ? ( ( uint32_t ) a ) : ( ( uint32_t ) b ) ) #define FreeRTOS_min_uint32(a,b) ( ( ( ( uint32_t ) a ) <= ( ( uint32_t ) b ) ) ? ( ( uint32_t ) a ) : ( ( uint32_t ) b ) )
/* Round-up: a = d * ( ( a + d - 1 ) / d ) */ /* Round-up: divide a by d and round=up the result. */
#define FreeRTOS_round_up(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( ( uint32_t ) ( a ) ) + ( ( uint32_t ) ( d ) ) - 1UL ) / ( ( uint32_t ) ( d ) ) ) ) #define FreeRTOS_round_up(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( ( uint32_t ) ( a ) ) + ( ( uint32_t ) ( d ) ) - 1UL ) / ( ( uint32_t ) ( d ) ) ) )
#define FreeRTOS_round_down(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( uint32_t ) ( a ) ) / ( ( uint32_t ) ( d ) ) ) ) #define FreeRTOS_round_down(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( uint32_t ) ( a ) ) / ( ( uint32_t ) ( d ) ) ) )
#define FreeRTOS_ms_to_tick(ms) ( ( ms * configTICK_RATE_HZ + 500 ) / 1000 )
#define FreeRTOS_max_BaseType(a, b) ( ( ( BaseType_t ) ( a ) ) >= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) )
#define FreeRTOS_max_UBaseType(a, b) ( ( ( UBaseType_t ) ( a ) ) >= ( ( UBaseType_t ) ( b ) ) ? ( ( UBaseType_t ) ( a ) ) : ( ( UBaseType_t ) ( b ) ) )
#define FreeRTOS_min_BaseType(a, b) ( ( ( BaseType_t ) ( a ) ) <= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) ) #define FreeRTOS_min_BaseType(a, b) ( ( ( BaseType_t ) ( a ) ) <= ( ( BaseType_t ) ( b ) ) ? ( ( BaseType_t ) ( a ) ) : ( ( BaseType_t ) ( b ) ) )
#define FreeRTOS_min_UBaseType(a, b) ( ( ( UBaseType_t ) ( a ) ) <= ( ( UBaseType_t ) ( b ) ) ? ( ( UBaseType_t ) ( a ) ) : ( ( UBaseType_t ) ( b ) ) )
#endif /* ipconfigHAS_INLINE_FUNCTIONS */ #endif /* ipconfigHAS_INLINE_FUNCTIONS */
#define pdMS_TO_MIN_TICKS( xTimeInMs ) ( pdMS_TO_TICKS( ( xTimeInMs ) ) < ( ( TickType_t ) 1 ) ? ( ( TickType_t ) 1 ) : pdMS_TO_TICKS( ( xTimeInMs ) ) ) #define ipMS_TO_MIN_TICKS( xTimeInMs ) ( ( pdMS_TO_TICKS( ( xTimeInMs ) ) < ( ( TickType_t ) 1U ) ) ? ( ( TickType_t ) 1U ) : pdMS_TO_TICKS( ( xTimeInMs ) ) )
/* For backward compatibility. */
#define pdMS_TO_MIN_TICKS( xTimeInMs ) ipMS_TO_MIN_TICKS( xTimeInMs )
#ifndef pdTRUE_SIGNED #ifndef pdTRUE_SIGNED
/* Temporary solution: eventually the defines below will appear in 'Source\include\projdefs.h' */ /* Temporary solution: eventually the defines below will appear in 'Source\include\projdefs.h' */
#define pdTRUE_SIGNED pdTRUE #define pdTRUE_SIGNED pdTRUE
#define pdFALSE_SIGNED pdFALSE #define pdFALSE_SIGNED pdFALSE
#define pdTRUE_UNSIGNED ( ( UBaseType_t ) 1u ) #define pdTRUE_UNSIGNED ( 1U )
#define pdFALSE_UNSIGNED ( ( UBaseType_t ) 0u ) #define pdFALSE_UNSIGNED ( 0U )
#define ipTRUE_BOOL ( 1 == 1 )
#define ipFALSE_BOOL ( 1 == 2 )
#endif #endif
/* /*
@ -228,15 +264,32 @@ BaseType_t FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES
const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ], const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] ); const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );
void * FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks ); void * FreeRTOS_GetUDPPayloadBuffer( size_t uxRequestedSizeBytes, TickType_t uxBlockTimeTicks );
void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetMask, uint32_t *pulGatewayAddress, uint32_t *pulDNSServerAddress ); void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress,
void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint32_t *pulNetMask, const uint32_t *pulGatewayAddress, const uint32_t *pulDNSServerAddress ); uint32_t *pulNetMask,
BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t xNumberOfBytesToSend, TickType_t xBlockTimeTicks ); uint32_t *pulGatewayAddress,
void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer ); uint32_t *pulDNSServerAddress );
void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress,
const uint32_t *pulNetMask,
const uint32_t *pulGatewayAddress,
const uint32_t *pulDNSServerAddress );
/* MISRA defining 'FreeRTOS_SendPingRequest' should be dependent on 'ipconfigSUPPORT_OUTGOING_PINGS'.
In order not to break some existing project, define it unconditionally. */
BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t uxNumberOfBytesToSend, TickType_t uxBlockTimeTicks );
void FreeRTOS_ReleaseUDPPayloadBuffer( void const * pvBuffer );
const uint8_t * FreeRTOS_GetMACAddress( void ); const uint8_t * FreeRTOS_GetMACAddress( void );
void FreeRTOS_UpdateMACAddress( const uint8_t ucMACAddress[ipMAC_ADDRESS_LENGTH_BYTES] ); void FreeRTOS_UpdateMACAddress( const uint8_t ucMACAddress[ipMAC_ADDRESS_LENGTH_BYTES] );
#if( ipconfigUSE_NETWORK_EVENT_HOOK == 1 )
/* coverity[misra_c_2012_rule_8_6_violation] */
/* This function shall be defined by the application. */
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent ); void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );
#endif
#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier ); void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier );
#endif
uint32_t FreeRTOS_GetIPAddress( void ); uint32_t FreeRTOS_GetIPAddress( void );
void FreeRTOS_SetIPAddress( uint32_t ulIPAddress ); void FreeRTOS_SetIPAddress( uint32_t ulIPAddress );
void FreeRTOS_SetNetmask( uint32_t ulNetmask ); void FreeRTOS_SetNetmask( uint32_t ulNetmask );
@ -264,12 +317,19 @@ const char *FreeRTOS_GetTCPStateName( UBaseType_t ulState);
void FreeRTOS_PrintARPCache( void ); void FreeRTOS_PrintARPCache( void );
void FreeRTOS_ClearARP( void ); void FreeRTOS_ClearARP( void );
/* Return pdTRUE if the IPv4 address is a multicast address. */
BaseType_t xIsIPv4Multicast( uint32_t ulIPAddress );
/* Set the MAC-address that belongs to a given IPv4 multi-cast address. */
void vSetMultiCastIPv4MacAddress( uint32_t ulIPAddress, MACAddress_t *pxMACAddress );
#if( ipconfigDHCP_REGISTER_HOSTNAME == 1 ) #if( ipconfigDHCP_REGISTER_HOSTNAME == 1 )
/* DHCP has an option for clients to register their hostname. It doesn't /* DHCP has an option for clients to register their hostname. It doesn't
have much use, except that a device can be found in a router along with its have much use, except that a device can be found in a router along with its
name. If this option is used the callback below must be provided by the name. If this option is used the callback below must be provided by the
application writer to return a const string, denoting the device's name. */ application writer to return a const string, denoting the device's name. */
/* coverity[misra_c_2012_rule_8_6_violation], typically defined in a user module. */
const char *pcApplicationHostnameHook( void ); const char *pcApplicationHostnameHook( void );
#endif /* ipconfigDHCP_REGISTER_HOSTNAME */ #endif /* ipconfigDHCP_REGISTER_HOSTNAME */
@ -282,7 +342,10 @@ The function is defined in 'iot_secure_sockets.c'.
If that module is not included in the project, the application must provide an If that module is not included in the project, the application must provide an
implementation of it. implementation of it.
The macro's ipconfigRAND32() and configRAND32() are not in use anymore. */ The macro's ipconfigRAND32() and configRAND32() are not in use anymore. */
BaseType_t xApplicationGetRandomNumber( uint32_t *pulNumber ); /* "xApplicationGetRandomNumber" is declared but never defined, because it may
be defined in a user module. */
/* coverity[misra_c_2012_rule_8_6_violation] */
extern BaseType_t xApplicationGetRandomNumber( uint32_t *pulNumber );
/* For backward compatibility define old structure names to the newer equivalent /* For backward compatibility define old structure names to the newer equivalent
structure name. */ structure name. */

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -41,6 +41,8 @@ extern "C" {
#include "FreeRTOS_TCP_IP.h" #include "FreeRTOS_TCP_IP.h"
#endif #endif
#include "semphr.h"
#include "event_groups.h" #include "event_groups.h"
typedef struct xNetworkAddressingParameters typedef struct xNetworkAddressingParameters
@ -53,6 +55,7 @@ typedef struct xNetworkAddressingParameters
} NetworkAddressingParameters_t; } NetworkAddressingParameters_t;
extern BaseType_t xTCPWindowLoggingLevel; extern BaseType_t xTCPWindowLoggingLevel;
extern QueueHandle_t xNetworkEventQueue;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Protocol headers. */ /* Protocol headers. */
@ -101,17 +104,6 @@ struct xIP_HEADER
#include "pack_struct_end.h" #include "pack_struct_end.h"
typedef struct xIP_HEADER IPHeader_t; typedef struct xIP_HEADER IPHeader_t;
#include "pack_struct_start.h"
struct xIGMP_HEADER
{
uint8_t ucVersionType; /* 0 + 1 = 1 */
uint8_t ucMaxResponseTime; /* 1 + 1 = 2 */
uint16_t usChecksum; /* 2 + 2 = 4 */
uint32_t usGroupAddress; /* 4 + 4 = 8 */
}
#include "pack_struct_end.h"
typedef struct xIGMP_HEADER IGMPHeader_t;
#include "pack_struct_start.h" #include "pack_struct_start.h"
struct xICMP_HEADER struct xICMP_HEADER
{ {
@ -155,18 +147,6 @@ struct xTCP_HEADER
#include "pack_struct_end.h" #include "pack_struct_end.h"
typedef struct xTCP_HEADER TCPHeader_t; typedef struct xTCP_HEADER TCPHeader_t;
#include "pack_struct_start.h"
struct xPSEUDO_HEADER
{
uint32_t ulSourceAddress;
uint32_t ulDestinationAddress;
uint8_t ucZeros;
uint8_t ucProtocol;
uint16_t usUDPLength;
}
#include "pack_struct_end.h"
typedef struct xPSEUDO_HEADER PseudoHeader_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Nested protocol packets. */ /* Nested protocol packets. */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -227,6 +207,13 @@ typedef union XPROT_PACKET
ICMPPacket_t xICMPPacket; ICMPPacket_t xICMPPacket;
} ProtocolPacket_t; } ProtocolPacket_t;
typedef union xPROT_HEADERS
{
ICMPHeader_t xICMPHeader;
UDPHeader_t xUDPHeader;
TCPHeader_t xTCPHeader;
} ProtocolHeaders_t;
/* The maximum UDP payload length. */ /* The maximum UDP payload length. */
#define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER ) - ipSIZE_OF_UDP_HEADER ) #define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER ) - ipSIZE_OF_UDP_HEADER )
@ -281,18 +268,6 @@ setting. */
/* The offset into an IP packet into which the IP data (payload) starts. */ /* The offset into an IP packet into which the IP data (payload) starts. */
#define ipIP_PAYLOAD_OFFSET ( sizeof( IPPacket_t ) ) #define ipIP_PAYLOAD_OFFSET ( sizeof( IPPacket_t ) )
#include "pack_struct_start.h"
struct xUDP_IP_FRAGMENT_PARAMETERS
{
uint8_t ucSocketOptions;
uint8_t ucPadFor16BitAlignment;
uint16_t usFragmentedPacketOffset;
uint16_t usFragmentLength;
uint16_t usPayloadChecksum;
}
#include "pack_struct_end.h"
typedef struct xUDP_IP_FRAGMENT_PARAMETERS IPFragmentParameters_t;
#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN ) #if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
/* Ethernet frame types. */ /* Ethernet frame types. */
@ -339,7 +314,8 @@ extern NetworkAddressingParameters_t xNetworkAddressing;
/* Structure that stores the defaults for netmask, gateway address and DNS. /* Structure that stores the defaults for netmask, gateway address and DNS.
These values will be copied to 'xNetworkAddressing' in case DHCP is not used, These values will be copied to 'xNetworkAddressing' in case DHCP is not used,
and also in case DHCP does not lead to a confirmed request. */ and also in case DHCP does not lead to a confirmed request. */
extern NetworkAddressingParameters_t xDefaultAddressing; /*lint -e9003*/
extern NetworkAddressingParameters_t xDefaultAddressing; /*lint !e9003 could define variable 'xDefaultAddressing' at block scope [MISRA 2012 Rule 8.9, advisory]. */
/* True when BufferAllocation_1.c was included, false for BufferAllocation_2.c */ /* True when BufferAllocation_1.c was included, false for BufferAllocation_2.c */
extern const BaseType_t xBufferAllocFixedSize; extern const BaseType_t xBufferAllocFixedSize;
@ -351,11 +327,43 @@ extern const BaseType_t xBufferAllocFixedSize;
/* The local IP address is accessed from within xDefaultPartUDPPacketHeader, /* The local IP address is accessed from within xDefaultPartUDPPacketHeader,
rather than duplicated in its own variable. */ rather than duplicated in its own variable. */
#define ipLOCAL_IP_ADDRESS_POINTER ( ( uint32_t * ) &( xDefaultPartUDPPacketHeader.ulWords[ 20u / sizeof(uint32_t) ] ) ) #define ipLOCAL_IP_ADDRESS_POINTER ( ( uint32_t * ) &( xDefaultPartUDPPacketHeader.ulWords[ 20U / sizeof(uint32_t) ] ) )
/* The local MAC address is accessed from within xDefaultPartUDPPacketHeader, /* The local MAC address is accessed from within xDefaultPartUDPPacketHeader,
rather than duplicated in its own variable. */ rather than duplicated in its own variable. */
#define ipLOCAL_MAC_ADDRESS ( &xDefaultPartUDPPacketHeader.ucBytes[0] ) #define ipLOCAL_MAC_ADDRESS ( xDefaultPartUDPPacketHeader.ucBytes )
/* In this library, there is often a cast from a character pointer
* to a pointer to a struct.
* In order to suppress MISRA warnings, do the cast within a macro,
* which can be exempt from warnings:
*
* 3 required by MISRA:
* -emacro(740,ipPOINTER_CAST) // 750: Unusual pointer cast (incompatible indirect types) [MISRA 2012 Rule 1.3, required])
* -emacro(9005,ipPOINTER_CAST) // 9005: attempt to cast away const/volatile from a pointer or reference [MISRA 2012 Rule 11.8, required]
* -emacro(9087,ipPOINTER_CAST) // 9087: cast performed between a pointer to object type and a pointer to a different object type [MISRA 2012 Rule 11.3, required]
*
* 2 advisory by MISRA:
* -emacro(9079,ipPOINTER_CAST) // 9079: conversion from pointer to void to pointer to other type [MISRA 2012 Rule 11.5, advisory])
* --emacro((826),ipPOINTER_CAST) // 826: Suspicious pointer-to-pointer conversion (area too small)
*
* The MISRA warnings can safely be suppressed because all casts are planned with care.
*/
#define ipPOINTER_CAST( TYPE, pointer ) ( ( TYPE ) ( pointer ) )
/* Sequence and ACK numbers are essentially unsigned (uint32_t). But when
* a distance is calculated, it is useful to use signed numbers:
* int32_t lDistance = ( int32_t ) ( ulSeq1 - ulSeq2 );
*
* 1 required by MISRA:
* -emacro(9033,ipNUMERIC_CAST) // 9033: Impermissible cast of composite expression (different essential type categories) [MISRA 2012 Rule 10.8, required])
*
* 1 advisory by MISRA:
* -emacro(9030,ipNUMERIC_CAST) // 9030: Impermissible cast; cannot cast from 'essentially Boolean' to 'essentially signed' [MISRA 2012 Rule 10.5, advisory])
*/
#define ipNUMERIC_CAST( TYPE, expression ) ( ( TYPE ) ( expression ) )
/* ICMP packets are sent using the same function as UDP packets. The port /* ICMP packets are sent using the same function as UDP packets. The port
number is used to distinguish between the two, as 0 is an invalid UDP port. */ number is used to distinguish between the two, as 0 is an invalid UDP port. */
@ -368,15 +376,15 @@ socket events. */
#define vSetField16( pxBase, xType, xField, usValue ) \ #define vSetField16( pxBase, xType, xField, usValue ) \
{ \ { \
( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( usValue ) >> 8 ); \ ( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( usValue ) >> 8 ); \
( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( usValue ) & 0xff ); \ ( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( usValue ) & 0xffU ); \
} }
#define vSetField32( pxBase, xType, xField, ulValue ) \ #define vSetField32( pxBase, xType, xField, ulValue ) \
{ \ { \
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( ulValue ) >> 24 ); \ ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( ulValue ) >> 24 ); \
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( ( ulValue ) >> 16 ) & 0xff ); \ ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( ( ulValue ) >> 16 ) & 0xffU ); \
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 2 ] = ( uint8_t ) ( ( ( ulValue ) >> 8 ) & 0xff ); \ ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 2 ] = ( uint8_t ) ( ( ( ulValue ) >> 8 ) & 0xffU ); \
( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 3 ] = ( uint8_t ) ( ( ulValue ) & 0xff ); \ ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 3 ] = ( uint8_t ) ( ( ulValue ) & 0xffU ); \
} }
#define vFlip_16( left, right ) \ #define vFlip_16( left, right ) \
@ -384,17 +392,17 @@ socket events. */
uint16_t tmp = (left); \ uint16_t tmp = (left); \
(left) = (right); \ (left) = (right); \
(right) = tmp; \ (right) = tmp; \
} while (0) } while ( ipFALSE_BOOL )
#define vFlip_32( left, right ) \ #define vFlip_32( left, right ) \
do { \ do { \
uint32_t tmp = (left); \ uint32_t tmp = (left); \
(left) = (right); \ (left) = (right); \
(right) = tmp; \ (right) = tmp; \
} while (0) } while ( ipFALSE_BOOL )
#ifndef ARRAY_SIZE #ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (BaseType_t)(sizeof(x)/sizeof(x)[0]) #define ARRAY_SIZE(x) ( ( BaseType_t ) ( sizeof( x ) / sizeof( ( x )[ 0 ] ) ) )
#endif #endif
/* /*
@ -434,7 +442,7 @@ eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucE
/* /*
* Return the checksum generated over xDataLengthBytes from pucNextData. * Return the checksum generated over xDataLengthBytes from pucNextData.
*/ */
uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t uxDataLengthBytes ); uint16_t usGenerateChecksum( uint16_t usSum, const uint8_t * pucNextData, size_t uxByteCount );
/* Socket related private functions. */ /* Socket related private functions. */
@ -448,7 +456,7 @@ BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer
/* /*
* Initialize the socket list data structures for TCP and UDP. * Initialize the socket list data structures for TCP and UDP.
*/ */
BaseType_t vNetworkSocketsInit( void ); void vNetworkSocketsInit( void );
/* /*
* Returns pdTRUE if the IP task has been created and is initialised. Otherwise * Returns pdTRUE if the IP task has been created and is initialised. Otherwise
@ -601,7 +609,8 @@ typedef struct UDPSOCKET
#endif /* ipconfigUSE_CALLBACKS */ #endif /* ipconfigUSE_CALLBACKS */
} IPUDPSocket_t; } IPUDPSocket_t;
typedef enum eSOCKET_EVENT { /* Formally typedef'd as eSocketEvent_t. */
enum eSOCKET_EVENT {
eSOCKET_RECEIVE = 0x0001, eSOCKET_RECEIVE = 0x0001,
eSOCKET_SEND = 0x0002, eSOCKET_SEND = 0x0002,
eSOCKET_ACCEPT = 0x0004, eSOCKET_ACCEPT = 0x0004,
@ -610,7 +619,7 @@ typedef enum eSOCKET_EVENT {
eSOCKET_CLOSED = 0x0020, eSOCKET_CLOSED = 0x0020,
eSOCKET_INTR = 0x0040, eSOCKET_INTR = 0x0040,
eSOCKET_ALL = 0x007F, eSOCKET_ALL = 0x007F,
} eSocketEvent_t; };
typedef struct xSOCKET typedef struct xSOCKET
{ {
@ -695,7 +704,7 @@ void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType
* The TCP driver needs to bind a socket at the moment a listening socket * The TCP driver needs to bind a socket at the moment a listening socket
* creates a new connected socket * creates a new connected socket
*/ */
BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal ); BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxBindAddress, size_t uxAddressLength, BaseType_t xInternal );
/* /*
* Internal function to add streaming data to a TCP socket. If ulIn == true, * Internal function to add streaming data to a TCP socket. If ulIn == true,
@ -714,6 +723,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket );
/* /*
* Some helping function, their meaning should be clear * Some helping function, their meaning should be clear
*/ */
/* coverity[misra_c_2012_rule_2_2_violation] */
static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr); static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr);
static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr) static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr)
{ {
@ -753,13 +763,13 @@ BaseType_t xSendEventToIPTask( eIPEvent_t eEvent );
* eIPEvent_t eEventType; * eIPEvent_t eEventType;
* void *pvData; * void *pvData;
*/ */
BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t xTimeout ); BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t uxTimeout );
/* /*
* Returns a pointer to the original NetworkBuffer from a pointer to a UDP * Returns a pointer to the original NetworkBuffer from a pointer to a UDP
* payload buffer. * payload buffer.
*/ */
NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer ); NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( const void * pvBuffer );
#if( ipconfigZERO_COPY_TX_DRIVER != 0 ) #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
/* /*
@ -778,9 +788,6 @@ NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer )
void vTCPStateChange( FreeRTOS_Socket_t *pxSocket, enum eTCP_STATE eTCPState ); void vTCPStateChange( FreeRTOS_Socket_t *pxSocket, enum eTCP_STATE eTCPState );
#endif /* ipconfigUSE_TCP */ #endif /* ipconfigUSE_TCP */
/*_RB_ Should this be part of the public API? */
void FreeRTOS_netstat( void );
/* Returns pdTRUE is this function is called from the IP-task */ /* Returns pdTRUE is this function is called from the IP-task */
BaseType_t xIsCallingFromIPTask( void ); BaseType_t xIsCallingFromIPTask( void );
@ -789,11 +796,16 @@ BaseType_t xIsCallingFromIPTask( void );
typedef struct xSOCKET_SET typedef struct xSOCKET_SET
{ {
EventGroupHandle_t xSelectGroup; EventGroupHandle_t xSelectGroup;
BaseType_t bApiCalled; /* True if the API was calling the private vSocketSelect */
FreeRTOS_Socket_t *pxSocket;
} SocketSelect_t; } SocketSelect_t;
extern void vSocketSelect( SocketSelect_t *pxSocketSelect ); extern void vSocketSelect( SocketSelect_t *pxSocketSet );
/* Define the data that must be passed for a 'eSocketSelectEvent'. */
typedef struct xSocketSelectMessage
{
TaskHandle_t xTaskhandle;
SocketSelect_t *pxSocketSet;
} SocketSelectMessage_t;
#endif /* ipconfigSUPPORT_SELECT_FUNCTION */ #endif /* ipconfigSUPPORT_SELECT_FUNCTION */

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -180,6 +180,8 @@ struct freertos_sockaddr
uint32_t sin_addr; uint32_t sin_addr;
}; };
extern const char *FreeRTOS_inet_ntoa( uint32_t ulIPAddress, char *pcBuffer );
#if ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN #if ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN
#define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \ #define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \
@ -188,13 +190,6 @@ struct freertos_sockaddr
( ( ( uint32_t ) ( ucOctet1 ) ) << 8UL ) | \ ( ( ( uint32_t ) ( ucOctet1 ) ) << 8UL ) | \
( ( uint32_t ) ( ucOctet0 ) ) ) ( ( uint32_t ) ( ucOctet0 ) ) )
#define FreeRTOS_inet_ntoa( ulIPAddress, pucBuffer ) \
sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u", \
( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ), \
( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \
( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ),\
( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ) )
#else /* ipconfigBYTE_ORDER */ #else /* ipconfigBYTE_ORDER */
#define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \ #define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \
@ -203,23 +198,18 @@ struct freertos_sockaddr
( ( ( uint32_t ) ( ucOctet2 ) ) << 8UL ) | \ ( ( ( uint32_t ) ( ucOctet2 ) ) << 8UL ) | \
( ( uint32_t ) ( ucOctet3 ) ) ) ( ( uint32_t ) ( ucOctet3 ) ) )
#define FreeRTOS_inet_ntoa( ulIPAddress, pucBuffer ) \
sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u", \
( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ), \
( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ),\
( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \
( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ) )
#endif /* ipconfigBYTE_ORDER */ #endif /* ipconfigBYTE_ORDER */
/* The socket type itself. */ /* The socket type itself. */
struct xSOCKET; struct xSOCKET;
typedef struct xSOCKET *Socket_t; typedef struct xSOCKET *Socket_t;
#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
/* The SocketSet_t type is the equivalent to the fd_set type used by the /* The SocketSet_t type is the equivalent to the fd_set type used by the
Berkeley API. */ Berkeley API. */
struct xSOCKET_SET; struct xSOCKET_SET;
typedef struct xSOCKET_SET *SocketSet_t; typedef struct xSOCKET_SET *SocketSet_t;
#endif /* ( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) */
/** /**
* FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE * FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE
@ -227,21 +217,23 @@ typedef struct xSOCKET_SET *SocketSet_t;
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_TCP_API_Functions.html * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_TCP_API_Functions.html
*/ */
Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol ); Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol );
int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength ); int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength );
int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength ); int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t uxTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength );
BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength ); BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr const * pxAddress, socklen_t xAddressLength );
/* function to get the local address and IP port */ /* function to get the local address and IP port */
size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress ); size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress );
/* Made available when ipconfigETHERNET_DRIVER_FILTERS_PACKETS is set to 1. */ #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )
/* Returns true if an UDP socket exists bound to mentioned port number. */
BaseType_t xPortHasUDPSocket( uint16_t usPortNr ); BaseType_t xPortHasUDPSocket( uint16_t usPortNr );
#endif
#if ipconfigUSE_TCP == 1 #if ipconfigUSE_TCP == 1
BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength ); BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength );
BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog ); BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog );
BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags ); BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t uxBufferLength, BaseType_t xFlags );
BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags ); BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags );
Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength ); Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength );
BaseType_t FreeRTOS_shutdown (Socket_t xSocket, BaseType_t xHow); BaseType_t FreeRTOS_shutdown (Socket_t xSocket, BaseType_t xHow);
@ -258,12 +250,16 @@ BaseType_t FreeRTOS_shutdown (Socket_t xSocket, BaseType_t xHow);
/* Return the remote address and IP port. */ /* Return the remote address and IP port. */
BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress ); BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress );
#if( ipconfigUSE_TCP == 1 )
/* returns pdTRUE if TCP socket is connected */ /* returns pdTRUE if TCP socket is connected */
BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket ); BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket );
/* returns the actual size of MSS being used */ /* returns the actual size of MSS being used */
BaseType_t FreeRTOS_mss( Socket_t xSocket ); BaseType_t FreeRTOS_mss( Socket_t xSocket );
#endif
/* for internal use only: return the connection status */ /* for internal use only: return the connection status */
BaseType_t FreeRTOS_connstatus( Socket_t xSocket ); BaseType_t FreeRTOS_connstatus( Socket_t xSocket );
@ -275,9 +271,11 @@ BaseType_t FreeRTOS_maywrite( Socket_t xSocket );
* rx_size returns the number of bytes available in the Rx buffer * rx_size returns the number of bytes available in the Rx buffer
* tx_space returns the free space in the Tx buffer * tx_space returns the free space in the Tx buffer
*/ */
#if( ipconfigUSE_TCP == 1 )
BaseType_t FreeRTOS_rx_size( Socket_t xSocket ); BaseType_t FreeRTOS_rx_size( Socket_t xSocket );
BaseType_t FreeRTOS_tx_space( Socket_t xSocket ); BaseType_t FreeRTOS_tx_space( Socket_t xSocket );
BaseType_t FreeRTOS_tx_size( Socket_t xSocket ); BaseType_t FreeRTOS_tx_size( Socket_t xSocket );
#endif
/* Returns the number of outstanding bytes in txStream. */ /* Returns the number of outstanding bytes in txStream. */
/* The function FreeRTOS_outstanding() was already implemented /* The function FreeRTOS_outstanding() was already implemented
@ -298,6 +296,7 @@ uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength );
#endif /* ipconfigUSE_TCP */ #endif /* ipconfigUSE_TCP */
#if( ipconfigUSE_CALLBACKS != 0 )
/* /*
* Connect / disconnect handler for a TCP socket * Connect / disconnect handler for a TCP socket
* For example: * For example:
@ -308,14 +307,18 @@ uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength );
* FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_CONN_HANDLER, ( void * ) &xHnd, sizeof( xHnd ) ); * FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_CONN_HANDLER, ( void * ) &xHnd, sizeof( xHnd ) );
*/ */
typedef void (* FOnConnected_t )( Socket_t /* xSocket */, BaseType_t /* ulConnected */ ); #ifdef __COVERITY__
typedef void (* FOnConnected_t )( Socket_t xSocket, BaseType_t ulConnected );
#else
typedef void (* FOnConnected_t )( Socket_t, BaseType_t );
#endif
/* /*
* Reception handler for a TCP socket * Reception handler for a TCP socket
* A user-proved function will be called on reception of a message * A user-proved function will be called on reception of a message
* If the handler returns a positive number, the messages will not be stored * If the handler returns a positive number, the messages will not be stored
* For example: * For example:
* static BaseType_t xOnTCPReceive( Socket_t xSocket, void * pData, size_t xLength ) * static BaseType_t xOnTCPReceive( Socket_t xSocket, void * pData, size_t uxLength )
* { * {
* // handle the message * // handle the message
* return 1; * return 1;
@ -323,18 +326,28 @@ typedef void (* FOnConnected_t )( Socket_t /* xSocket */, BaseType_t /* ulConnec
* F_TCP_UDP_Handler_t xHand = { xOnTCPReceive }; * F_TCP_UDP_Handler_t xHand = { xOnTCPReceive };
* FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_RECV_HANDLER, ( void * ) &xHand, sizeof( xHand ) ); * FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_RECV_HANDLER, ( void * ) &xHand, sizeof( xHand ) );
*/ */
typedef BaseType_t (* FOnTCPReceive_t )( Socket_t /* xSocket */, void * /* pData */, size_t /* xLength */ ); #ifdef __COVERITY__
typedef void (* FOnTCPSent_t )( Socket_t /* xSocket */, size_t /* xLength */ ); typedef BaseType_t (* FOnTCPReceive_t )( Socket_t xSocket, void * pData, size_t xLength );
typedef void (* FOnTCPSent_t )( Socket_t xSocket, size_t xLength );
#else
typedef BaseType_t (* FOnTCPReceive_t )( Socket_t, void *, size_t );
typedef void (* FOnTCPSent_t )( Socket_t, size_t );
#endif
/* /*
* Reception handler for a UDP socket * Reception handler for a UDP socket
* A user-proved function will be called on reception of a message * A user-proved function will be called on reception of a message
* If the handler returns a positive number, the messages will not be stored * If the handler returns a positive number, the messages will not be stored
*/ */
typedef BaseType_t (* FOnUDPReceive_t ) (Socket_t /* xSocket */, void * /* pData */, size_t /* xLength */, #ifdef __COVERITY__
const struct freertos_sockaddr * /* pxFrom */, const struct freertos_sockaddr * /* pxDest */ ); typedef BaseType_t (* FOnUDPReceive_t ) (Socket_t xSocket, void * pData, size_t xLength,
typedef void (* FOnUDPSent_t )( Socket_t /* xSocket */, size_t /* xLength */ ); const struct freertos_sockaddr * pxFrom, const struct freertos_sockaddr * pxDest );
typedef void (* FOnUDPSent_t )( Socket_t xSocket, size_t xLength );
#else
typedef BaseType_t (* FOnUDPReceive_t ) (Socket_t, void *, size_t,
const struct freertos_sockaddr *, const struct freertos_sockaddr *);
typedef void (* FOnUDPSent_t )( Socket_t, size_t);
#endif
typedef union xTCP_UDP_HANDLER typedef union xTCP_UDP_HANDLER
{ {
@ -344,12 +357,27 @@ typedef union xTCP_UDP_HANDLER
FOnUDPReceive_t pxOnUDPReceive; /* FREERTOS_SO_UDP_RECV_HANDLER */ FOnUDPReceive_t pxOnUDPReceive; /* FREERTOS_SO_UDP_RECV_HANDLER */
FOnUDPSent_t pxOnUDPSent; /* FREERTOS_SO_UDP_SENT_HANDLER */ FOnUDPSent_t pxOnUDPSent; /* FREERTOS_SO_UDP_SENT_HANDLER */
} F_TCP_UDP_Handler_t; } F_TCP_UDP_Handler_t;
#endif /* ( ipconfigUSE_CALLBACKS != 0 ) */
BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength ); BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t uxOptionLength );
BaseType_t FreeRTOS_closesocket( Socket_t xSocket ); BaseType_t FreeRTOS_closesocket( Socket_t xSocket );
/* The following function header should be placed in FreeRTOS_DNS.h.
It is kept here because some applications expect it in FreeRTOS_Sockets.h.*/
#ifndef __COVERITY__
uint32_t FreeRTOS_gethostbyname( const char *pcHostName ); uint32_t FreeRTOS_gethostbyname( const char *pcHostName );
#endif
BaseType_t FreeRTOS_inet_pton( BaseType_t xAddressFamily, const char *pcSource, void *pvDestination );
const char *FreeRTOS_inet_ntop( BaseType_t xAddressFamily, const void *pvSource, char *pcDestination, socklen_t uxSize );
/* Convert a null-terminated string in dot-decimal-notation (d.d.d.d) to a 32-bit unsigned integer. */
uint32_t FreeRTOS_inet_addr( const char * pcIPAddress ); uint32_t FreeRTOS_inet_addr( const char * pcIPAddress );
BaseType_t FreeRTOS_inet_pton4( const char *pcSource, void *pvDestination );
const char *FreeRTOS_inet_ntop4( const void *pvSource, char *pcDestination, socklen_t uxSize );
/* /*
* For the web server: borrow the circular Rx buffer for inspection * For the web server: borrow the circular Rx buffer for inspection
* HTML driver wants to see if a sequence of 13/10/13/10 is available * HTML driver wants to see if a sequence of 13/10/13/10 is available

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -52,10 +52,10 @@ static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer );
static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer ) static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer )
{ {
/* Make the circular buffer empty */ /* Make the circular buffer empty */
pxBuffer->uxHead = 0u; pxBuffer->uxHead = 0U;
pxBuffer->uxTail = 0u; pxBuffer->uxTail = 0U;
pxBuffer->uxFront = 0u; pxBuffer->uxFront = 0U;
pxBuffer->uxMid = 0u; pxBuffer->uxMid = 0U;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -65,7 +65,7 @@ static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, co
/* Returns the space between uxLower and uxUpper, which equals to the distance minus 1 */ /* Returns the space between uxLower and uxUpper, which equals to the distance minus 1 */
size_t uxCount; size_t uxCount;
uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1u; uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1U;
if( uxCount >= pxBuffer->LENGTH ) if( uxCount >= pxBuffer->LENGTH )
{ {
uxCount -= pxBuffer->LENGTH; uxCount -= pxBuffer->LENGTH;
@ -145,12 +145,13 @@ static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t ux
{ {
/* Increment uxMid, but no further than uxHead */ /* Increment uxMid, but no further than uxHead */
size_t uxSize = uxStreamBufferMidSpace( pxBuffer ); size_t uxSize = uxStreamBufferMidSpace( pxBuffer );
size_t uxMoveCount = uxCount;
if( uxCount > uxSize ) if( uxMoveCount > uxSize )
{ {
uxCount = uxSize; uxMoveCount = uxSize;
} }
pxBuffer->uxMid += uxCount; pxBuffer->uxMid += uxMoveCount;
if( pxBuffer->uxMid >= pxBuffer->LENGTH ) if( pxBuffer->uxMid >= pxBuffer->LENGTH )
{ {
pxBuffer->uxMid -= pxBuffer->LENGTH; pxBuffer->uxMid -= pxBuffer->LENGTH;
@ -165,7 +166,7 @@ BaseType_t xReturn;
size_t uxTail = pxBuffer->uxTail; size_t uxTail = pxBuffer->uxTail;
/* Returns true if ( uxLeft < uxRight ) */ /* Returns true if ( uxLeft < uxRight ) */
if( ( uxLeft < uxTail ) ^ ( uxRight < uxTail ) ) if( ( ( ( uxLeft < uxTail ) ? 1U : 0U ) ^ ( ( uxRight < uxTail ) ? 1U : 0U ) ) != 0U )
{ {
if( uxRight < uxTail ) if( uxRight < uxTail )
{ {
@ -211,7 +212,7 @@ size_t uxSize = uxStreamBufferGetSize( pxBuffer );
* pucData - A pointer to the data to be added. * pucData - A pointer to the data to be added.
* uxCount - The number of bytes to add. * uxCount - The number of bytes to add.
*/ */
size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount ); size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxByteCount );
/* /*
* Read bytes from a stream buffer. * Read bytes from a stream buffer.

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -30,13 +30,13 @@
extern "C" { extern "C" {
#endif #endif
BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer ); BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxDescriptor );
typedef enum eTCP_STATE { typedef enum eTCP_STATE {
/* Comments about the TCP states are borrowed from the very useful /* Comments about the TCP states are borrowed from the very useful
* Wiki page: * Wiki page:
* http://en.wikipedia.org/wiki/Transmission_Control_Protocol */ * http://en.wikipedia.org/wiki/Transmission_Control_Protocol */
eCLOSED = 0u, /* 0 (server + client) no connection state at all. */ eCLOSED = 0U, /* 0 (server + client) no connection state at all. */
eTCP_LISTEN, /* 1 (server) waiting for a connection request eTCP_LISTEN, /* 1 (server) waiting for a connection request
from any remote TCP and port. */ from any remote TCP and port. */
eCONNECT_SYN, /* 2 (client) internal state: socket wants to send eCONNECT_SYN, /* 2 (client) internal state: socket wants to send
@ -50,11 +50,11 @@ typedef enum eTCP_STATE {
or an acknowledgement of the connection termination request previously sent. */ or an acknowledgement of the connection termination request previously sent. */
eFIN_WAIT_2, /* 7 (server + client) waiting for a connection termination request from the remote TCP. */ eFIN_WAIT_2, /* 7 (server + client) waiting for a connection termination request from the remote TCP. */
eCLOSE_WAIT, /* 8 (server + client) waiting for a connection termination request from the local user. */ eCLOSE_WAIT, /* 8 (server + client) waiting for a connection termination request from the local user. */
eCLOSING, /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */ eCLOSING, /* 9 (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */
eLAST_ACK, /* 9 (server + client) waiting for an acknowledgement of the connection termination request eLAST_ACK, /*10 (server + client) waiting for an acknowledgement of the connection termination request
previously sent to the remote TCP previously sent to the remote TCP
(which includes an acknowledgement of its connection termination request). */ (which includes an acknowledgement of its connection termination request). */
eTIME_WAIT, /* 10 (either server or client) waiting for enough time to pass to be sure the remote TCP received the eTIME_WAIT, /*11 (either server or client) waiting for enough time to pass to be sure the remote TCP received the
acknowledgement of its connection termination request. [According to RFC 793 a connection can acknowledgement of its connection termination request. [According to RFC 793 a connection can
stay in TIME-WAIT for a maximum of four minutes known as a MSL (maximum segment lifetime).] */ stay in TIME-WAIT for a maximum of four minutes known as a MSL (maximum segment lifetime).] */
} eIPTCPState_t; } eIPTCPState_t;

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -35,9 +35,8 @@
extern "C" { extern "C" {
#endif #endif
extern BaseType_t xTCPWindowLoggingLevel; /* The name xTCPTimer was already use as the name of an IP-timer. */
typedef struct xTCPTimerStruct
typedef struct xTCPTimer
{ {
uint32_t ulBorn; uint32_t ulBorn;
} TCPTimer_t; } TCPTimer_t;
@ -64,7 +63,7 @@ typedef struct xTCP_SEGMENT
} u; } u;
#if( ipconfigUSE_TCP_WIN != 0 ) #if( ipconfigUSE_TCP_WIN != 0 )
struct xLIST_ITEM xQueueItem; /* TX only: segments can be linked in one of three queues: xPriorityQueue, xTxQueue, and xWaitQueue */ struct xLIST_ITEM xQueueItem; /* TX only: segments can be linked in one of three queues: xPriorityQueue, xTxQueue, and xWaitQueue */
struct xLIST_ITEM xListItem; /* With this item the segment can be connected to a list, depending on who is owning it */ struct xLIST_ITEM xSegmentItem; /* With this item the segment can be connected to a list, depending on who is owning it */
#endif #endif
} TCPSegment_t; } TCPSegment_t;
@ -80,9 +79,9 @@ typedef struct xTCP_WINSIZE
*/ */
/* Keep this as a multiple of 4 */ /* Keep this as a multiple of 4 */
#if( ipconfigUSE_TCP_WIN == 1 ) #if( ipconfigUSE_TCP_WIN == 1 )
#define ipSIZE_TCP_OPTIONS 16u #define ipSIZE_TCP_OPTIONS 16U
#else #else
#define ipSIZE_TCP_OPTIONS 12u #define ipSIZE_TCP_OPTIONS 12U
#endif #endif
/* /*
@ -149,7 +148,7 @@ void vTCPWindowCreate( TCPWindow_t *pxWindow, uint32_t ulRxWindowLength,
/* Destroy a window (always returns NULL) /* Destroy a window (always returns NULL)
* It will free some resources: a collection of segments */ * It will free some resources: a collection of segments */
void vTCPWindowDestroy( TCPWindow_t *pxWindow ); void vTCPWindowDestroy( TCPWindow_t const * pxWindow );
/* Initialize a window */ /* Initialize a window */
void vTCPWindowInit( TCPWindow_t *pxWindow, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS ); void vTCPWindowInit( TCPWindow_t *pxWindow, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS );
@ -167,16 +166,9 @@ void vTCPSegmentCleanup( void );
* But pxWindow->ackno should always be used to set "BUF->ackno" */ * But pxWindow->ackno should always be used to set "BUF->ackno" */
int32_t lTCPWindowRxCheck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength, uint32_t ulSpace ); int32_t lTCPWindowRxCheck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength, uint32_t ulSpace );
/* When lTCPWindowRxCheck returned false, please call store for this unexpected data */
BaseType_t xTCPWindowRxStore( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength );
/* This function will be called as soon as a FIN is received. It will return true /* This function will be called as soon as a FIN is received. It will return true
* if there are no 'open' reception segments */ * if there are no 'open' reception segments */
BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow ); BaseType_t xTCPWindowRxEmpty( const TCPWindow_t *pxWindow );
/* _HT_ Temporary function for testing/debugging
* Not used at this moment */
void vTCPWinShowSegments( TCPWindow_t *pxWindow, BaseType_t bForRx );
/*============================================================================= /*=============================================================================
* *
@ -188,12 +180,12 @@ void vTCPWinShowSegments( TCPWindow_t *pxWindow, BaseType_t bForRx );
int32_t lTCPWindowTxAdd( TCPWindow_t *pxWindow, uint32_t ulLength, int32_t lPosition, int32_t lMax ); int32_t lTCPWindowTxAdd( TCPWindow_t *pxWindow, uint32_t ulLength, int32_t lPosition, int32_t lMax );
/* Check data to be sent and calculate the time period we may sleep */ /* Check data to be sent and calculate the time period we may sleep */
BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay ); BaseType_t xTCPWindowTxHasData( TCPWindow_t const * pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay );
/* See if anything is left to be sent /* See if anything is left to be sent
* Function will be called when a FIN has been received. Only when the TX window is clean, * Function will be called when a FIN has been received. Only when the TX window is clean,
* it will return pdTRUE */ * it will return pdTRUE */
BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow ); BaseType_t xTCPWindowTxDone( const TCPWindow_t *pxWindow );
/* Fetches data to be sent. /* Fetches data to be sent.
* apPos will point to a location with the circular data buffer: txStream */ * apPos will point to a location with the circular data buffer: txStream */

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -64,6 +64,7 @@ already been made. */
#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */ #define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */ #define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ #define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define pdFREERTOS_ERRNO_EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */ #define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */ #define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */ #define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
@ -81,9 +82,15 @@ already been made. */
itself. */ itself. */
#define pdFREERTOS_LITTLE_ENDIAN 0 #define pdFREERTOS_LITTLE_ENDIAN 0
#define pdFREERTOS_BIG_ENDIAN 1 #define pdFREERTOS_BIG_ENDIAN 1
#else
#ifndef pdFREERTOS_ERRNO_EAFNOSUPPORT
#define pdFREERTOS_ERRNO_EAFNOSUPPORT 97 /* Address family not supported by protocol */
#endif /* pdFREERTOS_ERRNO_EAFNOSUPPORT */
#endif /* pdFREERTOS_ERRNO_NONE */ #endif /* pdFREERTOS_ERRNO_NONE */
/* Translate a pdFREERTOS_ERRNO code to a human readable string. */
const char *FreeRTOS_strerror_r( BaseType_t xErrnum, char *pcBuffer, size_t uxLength );
#endif /* FREERTOS_ERRNO_TCP */ #endif /* FREERTOS_ERRNO_TCP */

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -190,4 +190,44 @@ http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Trace.html */
#define iptraceSENDTO_DATA_TOO_LONG() #define iptraceSENDTO_DATA_TOO_LONG()
#endif #endif
#ifndef ipconfigUSE_TCP_MEM_STATS
#define ipconfigUSE_TCP_MEM_STATS 0
#endif
#if( ipconfigUSE_TCP_MEM_STATS == 0 )
/* See tools/tcp_mem_stat.c */
#ifndef iptraceMEM_STATS_CREATE
#define iptraceMEM_STATS_CREATE( xMemType, pxObject, uxSize )
#endif
#ifndef iptraceMEM_STATS_DELETE
#define iptraceMEM_STATS_DELETE( pxObject )
#endif
#ifndef iptraceMEM_STATS_CLOSE
#define iptraceMEM_STATS_CLOSE()
#endif
#endif /* ( ipconfigUSE_TCP_MEM_STATS != 0 ) */
#ifndef ipconfigUSE_DUMP_PACKETS
#define ipconfigUSE_DUMP_PACKETS 0
#endif
#if( ipconfigUSE_DUMP_PACKETS == 0 )
/* See tools/tcp_dump_packets.c */
#ifndef iptraceDUMP_INIT
#define iptraceDUMP_INIT( pcFileName, pxEntries )
#endif
#ifndef iptraceDUMP_PACKET
#define iptraceDUMP_PACKET( pucBuffer, uxLength, xIncoming )
#endif
#endif /* ( ipconfigUSE_DUMP_PACKETS != 0 ) */
#endif /* UDP_TRACE_MACRO_DEFAULTS_H */ #endif /* UDP_TRACE_MACRO_DEFAULTS_H */

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -46,7 +46,7 @@ UBaseType_t uxGetNumberOfFreeNetworkBuffers( void );
UBaseType_t uxGetMinimumFreeNetworkBuffers( void ); UBaseType_t uxGetMinimumFreeNetworkBuffers( void );
/* Copy a network buffer into a bigger buffer. */ /* Copy a network buffer into a bigger buffer. */
NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer, NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( const NetworkBufferDescriptor_t * const pxNetworkBuffer,
size_t uxNewLength); size_t uxNewLength);
/* Increase the size of a Network Buffer. /* Increase the size of a Network Buffer.

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.2.0 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -30,10 +30,16 @@
extern "C" { extern "C" {
#endif #endif
/* NOTE PUBLIC API FUNCTIONS. */ /* INTERNAL API FUNCTIONS. */
BaseType_t xNetworkInterfaceInitialise( void ); BaseType_t xNetworkInterfaceInitialise( void );
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend ); BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend );
/* coverity[misra_c_2012_rule_8_6_violation] */
/* "vNetworkInterfaceAllocateRAMToBuffers" is declared but never defined.
The following function is only used when BufferAllocation_1.c is linked in the project. */
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ); void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] );
/* "xGetPhyLinkStatus" is provided by the network driver. */
/* coverity[misra_c_2012_rule_8_6_violation] */
BaseType_t xGetPhyLinkStatus( void ); BaseType_t xGetPhyLinkStatus( void );
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -0,0 +1,64 @@
/*
* 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
typedef struct xDumpEntry
{
uint32_t ulMask;
size_t uxMax;
size_t uxCount;
} DumpEntry_t;
typedef struct xDumpEntries
{
size_t uxEntryCount;
DumpEntry_t xEntries[ dumpMAX_DUMP_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
#endif

View file

@ -0,0 +1,52 @@
/*
* 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
/* 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

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -54,7 +54,7 @@ be at least this number of buffers available. */
static List_t xFreeBuffersList; static List_t xFreeBuffersList;
/* Some statistics about the use of buffers. */ /* Some statistics about the use of buffers. */
static UBaseType_t uxMinimumFreeNetworkBuffers = 0u; static UBaseType_t uxMinimumFreeNetworkBuffers = 0U;
/* Declares the pool of NetworkBufferDescriptor_t structures that are available /* Declares the pool of NetworkBufferDescriptor_t structures that are available
to the system. All the network buffers referenced from xFreeBuffersList exist to the system. All the network buffers referenced from xFreeBuffersList exist
@ -86,7 +86,7 @@ are not defined then default them to call the normal enter/exit critical
section macros. */ section macros. */
#if !defined( ipconfigBUFFER_ALLOC_LOCK ) #if !defined( ipconfigBUFFER_ALLOC_LOCK )
#define ipconfigBUFFER_ALLOC_INIT( ) do {} while (0) #define ipconfigBUFFER_ALLOC_INIT( ) do {} while ( ipFALSE_BOOL )
#define ipconfigBUFFER_ALLOC_LOCK_FROM_ISR() \ #define ipconfigBUFFER_ALLOC_LOCK_FROM_ISR() \
UBaseType_t uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \ UBaseType_t uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \
{ {
@ -172,7 +172,7 @@ BaseType_t xReturn, x;
ipconfigBUFFER_ALLOC_INIT(); ipconfigBUFFER_ALLOC_INIT();
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ); xNetworkBufferSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
configASSERT( xNetworkBufferSemaphore ); configASSERT( xNetworkBufferSemaphore != NULL );
if( xNetworkBufferSemaphore != NULL ) if( xNetworkBufferSemaphore != NULL )
{ {
@ -225,7 +225,7 @@ UBaseType_t uxCount;
available. */ available. */
if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS ) if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
{ {
/* Protect the structure as they are accessed from tasks and /* Protect the structure as it is accessed from tasks and
interrupts. */ interrupts. */
ipconfigBUFFER_ALLOC_LOCK(); ipconfigBUFFER_ALLOC_LOCK();
{ {
@ -234,7 +234,7 @@ UBaseType_t uxCount;
if( ( bIsValidNetworkDescriptor( pxReturn ) != pdFALSE_UNSIGNED ) && if( ( bIsValidNetworkDescriptor( pxReturn ) != pdFALSE_UNSIGNED ) &&
listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxReturn->xBufferListItem ) ) ) listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxReturn->xBufferListItem ) ) )
{ {
uxListRemove( &( pxReturn->xBufferListItem ) ); ( void ) uxListRemove( &( pxReturn->xBufferListItem ) );
} }
else else
{ {
@ -285,6 +285,7 @@ UBaseType_t uxCount;
} }
else else
{ {
/* lint wants to see at least a comment. */
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER(); iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
} }
} }
@ -343,7 +344,7 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
} }
ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR(); ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR();
xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken ); ( void ) xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
return xHigherPriorityTaskWoken; return xHigherPriorityTaskWoken;
@ -357,8 +358,9 @@ BaseType_t xListItemAlreadyInFreeList;
if( bIsValidNetworkDescriptor( pxNetworkBuffer ) == pdFALSE_UNSIGNED ) if( bIsValidNetworkDescriptor( pxNetworkBuffer ) == pdFALSE_UNSIGNED )
{ {
FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) ); FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) );
return ;
} }
else
{
/* Ensure the buffer is returned to the list of free buffers before the /* Ensure the buffer is returned to the list of free buffers before the
counting semaphore is 'given' to say a buffer is available. */ counting semaphore is 'given' to say a buffer is available. */
ipconfigBUFFER_ALLOC_LOCK(); ipconfigBUFFER_ALLOC_LOCK();
@ -379,13 +381,14 @@ BaseType_t xListItemAlreadyInFreeList;
FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n", FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n",
pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) ); pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) );
} }
if( xListItemAlreadyInFreeList == pdFALSE ) else
{ {
xSemaphoreGive( xNetworkBufferSemaphore ); ( void ) xSemaphoreGive( xNetworkBufferSemaphore );
prvShowWarnings(); prvShowWarnings();
} }
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
} }
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
UBaseType_t uxGetMinimumFreeNetworkBuffers( void ) UBaseType_t uxGetMinimumFreeNetworkBuffers( void )
@ -404,7 +407,7 @@ NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDes
/* In BufferAllocation_1.c all network buffer are allocated with a /* In BufferAllocation_1.c all network buffer are allocated with a
maximum size of 'ipTOTAL_ETHERNET_FRAME_SIZE'.No need to resize the maximum size of 'ipTOTAL_ETHERNET_FRAME_SIZE'.No need to resize the
network buffer. */ network buffer. */
( void ) xNewSizeBytes; pxNetworkBuffer->xDataLength = xNewSizeBytes;
return pxNetworkBuffer; return pxNetworkBuffer;
} }

View file

@ -1,5 +1,5 @@
/* /*
* FreeRTOS+TCP V2.0.11 * FreeRTOS+TCP V2.2.1
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -102,7 +102,7 @@ BaseType_t xReturn, x;
if( xNetworkBufferSemaphore == NULL ) if( xNetworkBufferSemaphore == NULL )
{ {
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ); xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
configASSERT( xNetworkBufferSemaphore ); configASSERT( xNetworkBufferSemaphore != NULL );
if( xNetworkBufferSemaphore != NULL ) if( xNetworkBufferSemaphore != NULL )
{ {
@ -168,9 +168,9 @@ size_t xSize = *pxRequestedSizeBytes;
/* Round up xSize to the nearest multiple of N bytes, /* Round up xSize to the nearest multiple of N bytes,
where N equals 'sizeof( size_t )'. */ where N equals 'sizeof( size_t )'. */
if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u ) if( ( xSize & ( sizeof( size_t ) - 1U ) ) != 0U )
{ {
xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u; xSize = ( xSize | ( sizeof( size_t ) - 1U ) ) + 1U;
} }
*pxRequestedSizeBytes = xSize; *pxRequestedSizeBytes = xSize;
@ -178,7 +178,7 @@ size_t xSize = *pxRequestedSizeBytes;
and a pointer to a network buffer structure (hence the addition of and a pointer to a network buffer structure (hence the addition of
ipBUFFER_PADDING bytes). */ ipBUFFER_PADDING bytes). */
pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING ); pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );
configASSERT( pucEthernetBuffer ); configASSERT( pucEthernetBuffer != NULL );
if( pucEthernetBuffer != NULL ) if( pucEthernetBuffer != NULL )
{ {
@ -212,7 +212,7 @@ size_t uxCount;
if( xNetworkBufferSemaphore != NULL ) if( xNetworkBufferSemaphore != NULL )
{ {
if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) ) if( ( xRequestedSizeBytes != 0U ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
{ {
/* ARP packets can replace application packets, so the storage must be /* ARP packets can replace application packets, so the storage must be
at least large enough to hold an ARP. */ at least large enough to hold an ARP. */
@ -221,10 +221,10 @@ size_t uxCount;
/* Add 2 bytes to xRequestedSizeBytes and round up xRequestedSizeBytes /* Add 2 bytes to xRequestedSizeBytes and round up xRequestedSizeBytes
to the nearest multiple of N bytes, where N equals 'sizeof( size_t )'. */ to the nearest multiple of N bytes, where N equals 'sizeof( size_t )'. */
xRequestedSizeBytes += 2u; xRequestedSizeBytes += 2U;
if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u ) if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1U ) ) != 0U )
{ {
xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u; xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1U ) ) + 1U;
} }
/* If there is a semaphore available, there is a network buffer available. */ /* If there is a semaphore available, there is a network buffer available. */
@ -234,7 +234,7 @@ size_t uxCount;
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList ); pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
uxListRemove( &( pxReturn->xBufferListItem ) ); ( void ) uxListRemove( &( pxReturn->xBufferListItem ) );
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@ -297,6 +297,7 @@ size_t uxCount;
} }
else else
{ {
/* No action. */
iptraceNETWORK_BUFFER_OBTAINED( pxReturn ); iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
} }
@ -340,6 +341,7 @@ BaseType_t xListItemAlreadyInFreeList;
} }
else else
{ {
/* No action. */
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -219,19 +219,19 @@ const TickType_t x5_Seconds = 5000UL;
/* The handler task is created at the highest possible priority to /* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */ ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle ); xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
configASSERT( xEMACTaskHandle ); configASSERT( xEMACTaskHandle != NULL );
} }
if( xTxBufferQueue == NULL ) if( xTxBufferQueue == NULL )
{ {
xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) ); xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) );
configASSERT( xTxBufferQueue ); configASSERT( xTxBufferQueue != NULL );
} }
if( xTXDescriptorSemaphore == NULL ) if( xTXDescriptorSemaphore == NULL )
{ {
xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS ); xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS );
configASSERT( xTXDescriptorSemaphore ); configASSERT( xTXDescriptorSemaphore != NULL );
} }
/* When returning non-zero, the stack will become active and /* When returning non-zero, the stack will become active and
start DHCP (in configured) */ start DHCP (in configured) */
@ -296,7 +296,7 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
#endif /* ipconfigZERO_COPY_TX_DRIVER */ #endif /* ipconfigZERO_COPY_TX_DRIVER */
/* Not interested in a call-back after TX. */ /* Not interested in a call-back after TX. */
iptraceNETWORK_INTERFACE_TRANSMIT(); iptraceNETWORK_INTERFACE_TRANSMIT();
} while( 0 ); } while( ipFALSE_BOOL );
if( bReleaseAfterSend != pdFALSE ) if( bReleaseAfterSend != pdFALSE )
{ {
@ -417,7 +417,7 @@ const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );
/* Calculate the IP header checksum. */ /* Calculate the IP header checksum. */
pxIPHeader->usHeaderChecksum = 0x00; pxIPHeader->usHeaderChecksum = 0x00;
pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER ); pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0U, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );
pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum ); pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );
/* Calculate the TCP checksum for an outgoing packet. */ /* Calculate the TCP checksum for an outgoing packet. */
@ -519,7 +519,7 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
/* Remove compiler warnings about unused parameters. */ /* Remove compiler warnings about unused parameters. */
( void ) pvParameters; ( void ) pvParameters;
configASSERT( xEMACTaskHandle ); configASSERT( xEMACTaskHandle != NULL );
vTaskSetTimeOutState( &xPhyTime ); vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );

View file

@ -141,7 +141,7 @@ typedef struct gmac_dev_mem {
/** Circular buffer is empty ? */ /** Circular buffer is empty ? */
#define CIRC_EMPTY( head, tail ) ( head == tail ) #define CIRC_EMPTY( head, tail ) ( head == tail )
/** Clear circular buffer */ /** Clear circular buffer */
#define CIRC_CLEAR( head, tail ) do { ( head ) = 0; ( tail ) = 0; } while( 0 ) #define CIRC_CLEAR( head, tail ) do { ( head ) = 0; ( tail ) = 0; } while( ipFALSE_BOOL )
/** Increment head or tail */ /** Increment head or tail */
static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize ) static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize )

View file

@ -34,60 +34,60 @@
#ifndef ipconfigPHY_LS_HIGH_CHECK_TIME_MS #ifndef ipconfigPHY_LS_HIGH_CHECK_TIME_MS
/* Check if the LinkStatus in the PHY is still high after 15 seconds of not /* Check if the LinkStatus in the PHY is still high after 15 seconds of not
receiving packets. */ receiving packets. */
#define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000uL #define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000UL
#endif #endif
#ifndef ipconfigPHY_LS_LOW_CHECK_TIME_MS #ifndef ipconfigPHY_LS_LOW_CHECK_TIME_MS
/* Check if the LinkStatus in the PHY is still low every second. */ /* Check if the LinkStatus in the PHY is still low every second. */
#define ipconfigPHY_LS_LOW_CHECK_TIME_MS 1000uL #define ipconfigPHY_LS_LOW_CHECK_TIME_MS 1000UL
#endif #endif
/* As the following 3 macro's are OK in most situations, and so they're not /* As the following 3 macro's are OK in most situations, and so they're not
included in 'FreeRTOSIPConfigDefaults.h'. included in 'FreeRTOSIPConfigDefaults.h'.
Users can change their values in the project's 'FreeRTOSIPConfig.h'. */ Users can change their values in the project's 'FreeRTOSIPConfig.h'. */
#ifndef phyPHY_MAX_RESET_TIME_MS #ifndef phyPHY_MAX_RESET_TIME_MS
#define phyPHY_MAX_RESET_TIME_MS 1000uL #define phyPHY_MAX_RESET_TIME_MS 1000UL
#endif #endif
#ifndef phyPHY_MAX_NEGOTIATE_TIME_MS #ifndef phyPHY_MAX_NEGOTIATE_TIME_MS
#define phyPHY_MAX_NEGOTIATE_TIME_MS 3000uL #define phyPHY_MAX_NEGOTIATE_TIME_MS 3000UL
#endif #endif
#ifndef phySHORT_DELAY_MS #ifndef phySHORT_DELAY_MS
#define phySHORT_DELAY_MS 50uL #define phySHORT_DELAY_MS 50UL
#endif #endif
/* Naming and numbering of basic PHY registers. */ /* Naming and numbering of basic PHY registers. */
#define phyREG_00_BMCR 0x00u /* Basic Mode Control Register. */ #define phyREG_00_BMCR 0x00U /* Basic Mode Control Register. */
#define phyREG_01_BMSR 0x01u /* Basic Mode Status Register. */ #define phyREG_01_BMSR 0x01U /* Basic Mode Status Register. */
#define phyREG_02_PHYSID1 0x02u /* PHYS ID 1 */ #define phyREG_02_PHYSID1 0x02U /* PHYS ID 1 */
#define phyREG_03_PHYSID2 0x03u /* PHYS ID 2 */ #define phyREG_03_PHYSID2 0x03U /* PHYS ID 2 */
#define phyREG_04_ADVERTISE 0x04u /* Advertisement control reg */ #define phyREG_04_ADVERTISE 0x04U /* Advertisement control reg */
/* Naming and numbering of extended PHY registers. */ /* Naming and numbering of extended PHY registers. */
#define PHYREG_10_PHYSTS 0x10u /* 16 PHY status register Offset */ #define PHYREG_10_PHYSTS 0x10U /* 16 PHY status register Offset */
#define phyREG_19_PHYCR 0x19u /* 25 RW PHY Control Register */ #define phyREG_19_PHYCR 0x19U /* 25 RW PHY Control Register */
#define phyREG_1F_PHYSPCS 0x1Fu /* 31 RW PHY Special Control Status */ #define phyREG_1F_PHYSPCS 0x1FU /* 31 RW PHY Special Control Status */
/* Bit fields for 'phyREG_00_BMCR', the 'Basic Mode Control Register'. */ /* Bit fields for 'phyREG_00_BMCR', the 'Basic Mode Control Register'. */
#define phyBMCR_FULL_DUPLEX 0x0100u /* Full duplex. */ #define phyBMCR_FULL_DUPLEX 0x0100U /* Full duplex. */
#define phyBMCR_AN_RESTART 0x0200u /* Auto negotiation restart. */ #define phyBMCR_AN_RESTART 0x0200U /* Auto negotiation restart. */
#define phyBMCR_ISOLATE 0x0400u /* 1 = Isolates 0 = Normal operation. */ #define phyBMCR_ISOLATE 0x0400U /* 1 = Isolates 0 = Normal operation. */
#define phyBMCR_AN_ENABLE 0x1000u /* Enable auto negotiation. */ #define phyBMCR_AN_ENABLE 0x1000U /* Enable auto negotiation. */
#define phyBMCR_SPEED_100 0x2000u /* Select 100Mbps. */ #define phyBMCR_SPEED_100 0x2000U /* Select 100Mbps. */
#define phyBMCR_RESET 0x8000u /* Reset the PHY. */ #define phyBMCR_RESET 0x8000U /* Reset the PHY. */
/* Bit fields for 'phyREG_19_PHYCR', the 'PHY Control Register'. */ /* Bit fields for 'phyREG_19_PHYCR', the 'PHY Control Register'. */
#define PHYCR_MDIX_EN 0x8000u /* Enable Auto MDIX. */ #define PHYCR_MDIX_EN 0x8000U /* Enable Auto MDIX. */
#define PHYCR_MDIX_FORCE 0x4000u /* Force MDIX crossed. */ #define PHYCR_MDIX_FORCE 0x4000U /* Force MDIX crossed. */
#define phyBMSR_AN_COMPLETE 0x0020u /* Auto-Negotiation process completed */ #define phyBMSR_AN_COMPLETE 0x0020U /* Auto-Negotiation process completed */
#define phyBMSR_LINK_STATUS 0x0004u #define phyBMSR_LINK_STATUS 0x0004U
#define phyPHYSTS_LINK_STATUS 0x0001u /* PHY Link mask */ #define phyPHYSTS_LINK_STATUS 0x0001U /* PHY Link mask */
#define phyPHYSTS_SPEED_STATUS 0x0002u /* PHY Speed mask */ #define phyPHYSTS_SPEED_STATUS 0x0002U /* PHY Speed mask */
#define phyPHYSTS_DUPLEX_STATUS 0x0004u /* PHY Duplex mask */ #define phyPHYSTS_DUPLEX_STATUS 0x0004U /* PHY Duplex mask */
/* Bit fields for 'phyREG_1F_PHYSPCS /* Bit fields for 'phyREG_1F_PHYSPCS
001 = 10BASE-T half-duplex 001 = 10BASE-T half-duplex
@ -95,20 +95,20 @@ Users can change their values in the project's 'FreeRTOSIPConfig.h'. */
010 = 100BASE-TX half-duplex 010 = 100BASE-TX half-duplex
110 = 100BASE-TX full-duplex 110 = 100BASE-TX full-duplex
*/ */
#define phyPHYSPCS_SPEED_MASK 0x000Cu #define phyPHYSPCS_SPEED_MASK 0x000CU
#define phyPHYSPCS_SPEED_10 0x0004u #define phyPHYSPCS_SPEED_10 0x0004U
#define phyPHYSPCS_FULL_DUPLEX 0x0010u #define phyPHYSPCS_FULL_DUPLEX 0x0010U
/* /*
* Description of all capabilities that can be advertised to * Description of all capabilities that can be advertised to
* the peer (usually a switch or router). * the peer (usually a switch or router).
*/ */
#define phyADVERTISE_CSMA 0x0001u /* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */ #define phyADVERTISE_CSMA 0x0001U /* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */
#define phyADVERTISE_10HALF 0x0020u /* Try for 10mbps half-duplex. */ #define phyADVERTISE_10HALF 0x0020U /* Try for 10mbps half-duplex. */
#define phyADVERTISE_10FULL 0x0040u /* Try for 10mbps full-duplex. */ #define phyADVERTISE_10FULL 0x0040U /* Try for 10mbps full-duplex. */
#define phyADVERTISE_100HALF 0x0080u /* Try for 100mbps half-duplex. */ #define phyADVERTISE_100HALF 0x0080U /* Try for 100mbps half-duplex. */
#define phyADVERTISE_100FULL 0x0100u /* Try for 100mbps full-duplex. */ #define phyADVERTISE_100FULL 0x0100U /* Try for 100mbps full-duplex. */
#define phyADVERTISE_ALL ( phyADVERTISE_10HALF | phyADVERTISE_10FULL | \ #define phyADVERTISE_ALL ( phyADVERTISE_10HALF | phyADVERTISE_10FULL | \
phyADVERTISE_100HALF | phyADVERTISE_100FULL | \ phyADVERTISE_100HALF | phyADVERTISE_100FULL | \
@ -167,7 +167,7 @@ BaseType_t xResult;
/* Initialise the struct and assign a PHY-read and -write function. */ /* Initialise the struct and assign a PHY-read and -write function. */
void vPhyInitialise( EthernetPhy_t *pxPhyObject, xApplicationPhyReadHook_t fnPhyRead, xApplicationPhyWriteHook_t fnPhyWrite ) void vPhyInitialise( EthernetPhy_t *pxPhyObject, xApplicationPhyReadHook_t fnPhyRead, xApplicationPhyWriteHook_t fnPhyWrite )
{ {
memset( ( void * )pxPhyObject, '\0', sizeof( *pxPhyObject ) ); memset( ( void * )pxPhyObject, 0, sizeof( *pxPhyObject ) );
pxPhyObject->fnPhyRead = fnPhyRead; pxPhyObject->fnPhyRead = fnPhyRead;
pxPhyObject->fnPhyWrite = fnPhyWrite; pxPhyObject->fnPhyWrite = fnPhyWrite;
@ -187,7 +187,7 @@ BaseType_t xPhyAddress;
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_03_PHYSID2, &ulLowerID ); pxPhyObject->fnPhyRead( xPhyAddress, phyREG_03_PHYSID2, &ulLowerID );
/* A valid PHY id can not be all zeros or all ones. */ /* A valid PHY id can not be all zeros or all ones. */
if( ( ulLowerID != ( uint16_t )~0u ) && ( ulLowerID != ( uint16_t )0u ) ) if( ( ulLowerID != ( uint16_t ) ~0U ) && ( ulLowerID != ( uint16_t ) 0U ) )
{ {
uint32_t ulUpperID; uint32_t ulUpperID;
uint32_t ulPhyID; uint32_t ulPhyID;
@ -225,7 +225,7 @@ TimeOut_t xTimer;
BaseType_t xPhyIndex; BaseType_t xPhyIndex;
/* A bit-mask of PHY ports that are ready. */ /* A bit-mask of PHY ports that are ready. */
ulDoneMask = 0ul; ulDoneMask = 0UL;
/* Set the RESET bits high. */ /* Set the RESET bits high. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ ) for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
@ -251,7 +251,7 @@ BaseType_t xPhyIndex;
if( ( ulConfig & phyBMCR_RESET ) == 0 ) if( ( ulConfig & phyBMCR_RESET ) == 0 )
{ {
FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET %d ready\n", (int)xPhyIndex ) ); FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET %d ready\n", (int)xPhyIndex ) );
ulDoneMask |= ( 1ul << xPhyIndex ); ulDoneMask |= ( 1UL << xPhyIndex );
} }
} }
if( ulDoneMask == ulPhyMask ) if( ulDoneMask == ulPhyMask )
@ -270,7 +270,7 @@ BaseType_t xPhyIndex;
/* Clear the reset bits. */ /* Clear the reset bits. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ ) for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{ {
if( ( ulDoneMask & ( 1ul << xPhyIndex ) ) == 0uL ) if( ( ulDoneMask & ( 1UL << xPhyIndex ) ) == 0UL )
{ {
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
@ -454,9 +454,9 @@ with ulPhyMask. */
BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask ) BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )
{ {
BaseType_t xPhyIndex; BaseType_t xPhyIndex;
uint32_t ulValue, ulBitMask = ( uint32_t )1u; uint32_t ulValue, ulBitMask = ( uint32_t )1U;
ulValue = ( uint32_t )0u; ulValue = ( uint32_t ) 0U;
if( pxPhyObject->xPhyPreferences.ucDuplex == PHY_DUPLEX_FULL ) if( pxPhyObject->xPhyPreferences.ucDuplex == PHY_DUPLEX_FULL )
{ {
@ -491,7 +491,7 @@ uint32_t ulPHYLinkStatus, ulRegValue;
TickType_t xRemainingTime; TickType_t xRemainingTime;
TimeOut_t xTimer; TimeOut_t xTimer;
if( ulPhyMask == ( uint32_t )0u ) if( ulPhyMask == ( uint32_t ) 0U )
{ {
return 0; return 0;
} }
@ -512,7 +512,7 @@ TimeOut_t xTimer;
/* Wait until the auto-negotiation will be completed */ /* Wait until the auto-negotiation will be completed */
for( ;; ) for( ;; )
{ {
ulBitMask = ( uint32_t )1u; ulBitMask = ( uint32_t ) 1U;
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{ {
if( ( ulPhyMask & ulBitMask ) != 0lu ) if( ( ulPhyMask & ulBitMask ) != 0lu )
@ -541,16 +541,16 @@ TimeOut_t xTimer;
vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) ); vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
} }
if( ulDoneMask != ( uint32_t)0u ) if( ulDoneMask != ( uint32_t) 0U )
{ {
ulBitMask = ( uint32_t )1u; ulBitMask = ( uint32_t ) 1U;
pxPhyObject->ulLinkStatusMask &= ~( ulDoneMask ); pxPhyObject->ulLinkStatusMask &= ~( ulDoneMask );
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{ {
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ]; uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ];
if( ( ulDoneMask & ulBitMask ) == ( uint32_t )0u ) if( ( ulDoneMask & ulBitMask ) == ( uint32_t ) 0U )
{ {
continue; continue;
} }
@ -632,7 +632,7 @@ TimeOut_t xTimer;
( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half", ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half",
( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100, ( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100,
( ( ulPHYLinkStatus |= phyBMSR_LINK_STATUS ) != 0) ? "high" : "low" ) ); ( ( ulPHYLinkStatus |= phyBMSR_LINK_STATUS ) != 0) ? "high" : "low" ) );
if( ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) != ( uint32_t )0u ) if( ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) != ( uint32_t ) 0U )
{ {
pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_FULL; pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_FULL;
} }
@ -650,7 +650,7 @@ TimeOut_t xTimer;
pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_100; pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_100;
} }
} }
} /* if( ulDoneMask != ( uint32_t)0u ) */ } /* if( ulDoneMask != ( uint32_t) 0U ) */
return 0; return 0;
} }
@ -658,7 +658,7 @@ TimeOut_t xTimer;
BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception ) BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception )
{ {
uint32_t ulStatus, ulBitMask = 1u; uint32_t ulStatus, ulBitMask = 1U;
BaseType_t xPhyIndex; BaseType_t xPhyIndex;
BaseType_t xNeedCheck = pdFALSE; BaseType_t xNeedCheck = pdFALSE;
@ -670,7 +670,7 @@ BaseType_t xNeedCheck = pdFALSE;
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS ); pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{ {
if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) == 0ul ) if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) == 0UL )
{ {
pxPhyObject->ulLinkStatusMask |= ulBitMask; pxPhyObject->ulLinkStatusMask |= ulBitMask;
FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) ); FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
@ -705,7 +705,7 @@ BaseType_t xNeedCheck = pdFALSE;
} }
} }
vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) ); vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 ) if( ( pxPhyObject->ulLinkStatusMask & ( ulBitMask >> 1 ) ) != 0 )
{ {
/* The link status is high, so don't poll the PHY too often. */ /* The link status is high, so don't poll the PHY too often. */
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS ); pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -100,7 +100,7 @@ extern uint8_t ucMACAddress[ 6 ];
if( xStatus != ERROR ) if( xStatus != ERROR )
{ {
vSemaphoreCreateBinary( xEMACRxEventSemaphore ); vSemaphoreCreateBinary( xEMACRxEventSemaphore );
configASSERT( xEMACRxEventSemaphore ); configASSERT( xEMACRxEventSemaphore != NULL );
/* The handler task is created at the highest possible priority to /* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */ ensure the interrupt handler can return directly to it. */
@ -212,7 +212,7 @@ IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
extern uint8_t *EMAC_NextPacketToRead( void ); extern uint8_t *EMAC_NextPacketToRead( void );
( void ) pvParameters; ( void ) pvParameters;
configASSERT( xEMACRxEventSemaphore ); configASSERT( xEMACRxEventSemaphore != NULL );
for( ;; ) for( ;; )
{ {

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -81,7 +81,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif #endif
#ifndef iptraceEMAC_TASK_STARTING #ifndef iptraceEMAC_TASK_STARTING
#define iptraceEMAC_TASK_STARTING() do { } while( 0 ) #define iptraceEMAC_TASK_STARTING() do { } while( ipFALSE_BOOL )
#endif #endif
/* Define the bits of .STATUS that indicate a reception error. */ /* Define the bits of .STATUS that indicate a reception error. */
@ -284,7 +284,7 @@ BaseType_t xReturn = pdPASS;
if( xRxHanderTask == NULL ) if( xRxHanderTask == NULL )
{ {
xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", nwRX_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask ); xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", nwRX_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
configASSERT( xReturn ); configASSERT( xReturn != NULL );
} }
if( xTXDescriptorSemaphore == NULL ) if( xTXDescriptorSemaphore == NULL )
@ -292,7 +292,7 @@ BaseType_t xReturn = pdPASS;
/* Create a counting semaphore, with a value of 'configNUM_TX_DESCRIPTORS' /* Create a counting semaphore, with a value of 'configNUM_TX_DESCRIPTORS'
and a maximum of 'configNUM_TX_DESCRIPTORS'. */ and a maximum of 'configNUM_TX_DESCRIPTORS'. */
xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) configNUM_TX_DESCRIPTORS, ( UBaseType_t ) configNUM_TX_DESCRIPTORS ); xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) configNUM_TX_DESCRIPTORS, ( UBaseType_t ) configNUM_TX_DESCRIPTORS );
configASSERT( xTXDescriptorSemaphore ); configASSERT( xTXDescriptorSemaphore != NULL );
} }
/* Enable MAC interrupts. */ /* Enable MAC interrupts. */
@ -526,7 +526,7 @@ BaseType_t x;
/* Use an assert to check the allocation as +TCP applications will /* Use an assert to check the allocation as +TCP applications will
often not use a malloc() failed hook as the TCP stack will recover often not use a malloc() failed hook as the TCP stack will recover
from allocation failures. */ from allocation failures. */
configASSERT( xDMATxDescriptors[ x ].B1ADD ); configASSERT( xDMATxDescriptors[ x ].B1ADD != 0U );
} }
#endif #endif
@ -592,7 +592,7 @@ BaseType_t x;
/* Use an assert to check the allocation as +TCP applications will often /* Use an assert to check the allocation as +TCP applications will often
not use a malloc failed hook as the TCP stack will recover from not use a malloc failed hook as the TCP stack will recover from
allocation failures. */ allocation failures. */
configASSERT( xDMARxDescriptors[ x ].B1ADD ); configASSERT( xDMARxDescriptors[ x ].B1ADD != 0U );
xDMARxDescriptors[ x ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ x + 1 ] ); xDMARxDescriptors[ x ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ x + 1 ] );
xDMARxDescriptors[ x ].CTRL = ( uint32_t ) RDES_ENH_BS1( ipTOTAL_ETHERNET_FRAME_SIZE ) | RDES_ENH_RCH; xDMARxDescriptors[ x ].CTRL = ( uint32_t ) RDES_ENH_BS1( ipTOTAL_ETHERNET_FRAME_SIZE ) | RDES_ENH_RCH;

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -4,7 +4,7 @@
*/ */
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -828,7 +828,7 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
#endif #endif
) { ) {
/* Drop this packet, not for this device. */ /* Drop this packet, not for this device. */
FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); /* FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); */
return pdFALSE; return pdFALSE;
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -445,6 +445,11 @@ void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_
if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) && if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&
( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) ) ( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )
{ {
/* The received packets will be written to a C source file,
only if 'ipconfigUSE_DUMP_PACKETS' is defined.
Otherwise, there is no action. */
iptraceDUMP_PACKET( ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen, pdTRUE );
uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) ); uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) );
uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen ); uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen );
} }
@ -489,6 +494,10 @@ const DWORD xMaxMSToWait = 1000;
{ {
uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE ); uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );
uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE ); uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE );
/* The packets sent will be written to a C source file,
only if 'ipconfigUSE_DUMP_PACKETS' is defined.
Otherwise, there is no action. */
iptraceDUMP_PACKET( ucBuffer, xLength, pdFALSE );
if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength ) != 0 ) if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength ) != 0 )
{ {
ulWinPCAPSendFailures++; ulWinPCAPSendFailures++;
@ -498,6 +507,31 @@ const DWORD xMaxMSToWait = 1000;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t xPacketBouncedBack( const uint8_t *pucBuffer )
{
EthernetHeader_t *pxEtherHeader;
BaseType_t xResult;
pxEtherHeader = ( EthernetHeader_t * ) pucBuffer;
if( memcmp( ucMACAddress, pxEtherHeader->xSourceAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 )
{
FreeRTOS_printf( ( "Bounced back: %02x:%02x:%02x:%02x:%02x:%02x\n",
pxEtherHeader->xSourceAddress.ucBytes[ 0 ],
pxEtherHeader->xSourceAddress.ucBytes[ 1 ],
pxEtherHeader->xSourceAddress.ucBytes[ 2 ],
pxEtherHeader->xSourceAddress.ucBytes[ 3 ],
pxEtherHeader->xSourceAddress.ucBytes[ 4 ],
pxEtherHeader->xSourceAddress.ucBytes[ 5 ] ) );
xResult = pdTRUE;
}
else
{
xResult = pdFALSE;
}
return xResult;
}
/*-----------------------------------------------------------*/
static void prvInterruptSimulatorTask( void *pvParameters ) static void prvInterruptSimulatorTask( void *pvParameters )
{ {
struct pcap_pkthdr xHeader; struct pcap_pkthdr xHeader;
@ -545,7 +579,14 @@ eFrameProcessingResult_t eResult;
is ok to call the task level function here, but note that is ok to call the task level function here, but note that
some buffer implementations cannot be called from a real some buffer implementations cannot be called from a real
interrupt. */ interrupt. */
if( xPacketBouncedBack( pucPacketData ) == pdFALSE )
{
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 ); pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );
}
else
{
pxNetworkBuffer = NULL;
}
if( pxNetworkBuffer != NULL ) if( pxNetworkBuffer != NULL )
{ {

View file

@ -238,7 +238,7 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer,
} }
} }
#endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */ #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */
if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0uL ) if( ( ulPHYLinkStatus & niBMSR_LINK_STATUS ) != 0UL )
{ {
iptraceNETWORK_INTERFACE_TRANSMIT(); iptraceNETWORK_INTERFACE_TRANSMIT();
emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend ); emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );

View file

@ -10,6 +10,11 @@ Please include the following source files:
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_hw.c $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_hw.c
The file uncached_memory.c can also be found in:
vendors\xilinx\boards\microzed\aws_demos\application_code\xilinx_code
vendors\xilinx\boards\microzed\aws_tests\application_code\xilinx_code
And include the following source files from the Xilinx library: And include the following source files from the Xilinx library:
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps.c $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps.c

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
@ -351,7 +351,7 @@ const TickType_t x5_Seconds = 5000UL;
/* The handler task is created at the highest possible priority to /* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */ ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, "KSZ8851", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle ); xTaskCreate( prvEMACHandlerTask, "KSZ8851", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
configASSERT( xEMACTaskHandle ); configASSERT( xEMACTaskHandle != NULL );
} }
/* When returning non-zero, the stack will become active and /* When returning non-zero, the stack will become active and
@ -1059,7 +1059,7 @@ static void ksz8851snl_low_level_init( void )
if( ksz8851snl_init() < 0 ) if( ksz8851snl_init() < 0 )
{ {
FreeRTOS_printf( ( "ksz8851snl_low_level_init: failed to initialize the Micrel driver!\n" ) ); FreeRTOS_printf( ( "ksz8851snl_low_level_init: failed to initialize the Micrel driver!\n" ) );
configASSERT(0 == 1); configASSERT( ipFALSE_BOOL );
} }
memset( xMicrelDevice.pusHashTable, 255, sizeof( xMicrelDevice.pusHashTable ) ); memset( xMicrelDevice.pusHashTable, 255, sizeof( xMicrelDevice.pusHashTable ) );
ksz8851_reg_write( REG_MAC_HASH_0, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 0 ] ) ); ksz8851_reg_write( REG_MAC_HASH_0, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 0 ] ) );
@ -1166,7 +1166,7 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );
/* Remove compiler warnings about unused parameters. */ /* Remove compiler warnings about unused parameters. */
( void ) pvParameters; ( void ) pvParameters;
configASSERT( xEMACTaskHandle ); configASSERT( xEMACTaskHandle != NULL );
vTaskSetTimeOutState( &xPhyTime ); vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );

View file

@ -1,5 +1,5 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.2.1
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -1,3 +1,22 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
/* /*
* CBMC models a pointer as an object id and an offset into that * CBMC models a pointer as an object id and an offset into that
* object. The top bits of a pointer encode the object id and the * object. The top bits of a pointer encode the object id and the
@ -6,36 +25,53 @@
* size of objects in CBMC. * size of objects in CBMC.
*/ */
#define CBMC_BITS 7 #define CBMC_BITS 7
#define CBMC_MAX_OBJECT_SIZE (0xFFFFFFFF >> CBMC_BITS) #define CBMC_MAX_OBJECT_SIZE ( 0xFFFFFFFF >> ( CBMC_BITS + 1 ) )
enum CBMC_LOOP_CONDITION { CBMC_LOOP_BREAK, CBMC_LOOP_CONTINUE, CBMC_LOOP_RETURN }; #define IMPLIES( a, b ) ( !( a ) || ( b ) )
// CBMC specification: capture old value for precondition / BaseType_t nondet_basetype();
// postcondition checking UBaseType_t nondet_ubasetype();
TickType_t nondet_ticktype();
int32_t nondet_int32();
uint32_t nondet_uint32();
size_t nondet_sizet();
#define nondet_BaseType() nondet_basetype()
void * safeMalloc( size_t size );
enum CBMC_LOOP_CONDITION
{
CBMC_LOOP_BREAK, CBMC_LOOP_CONTINUE, CBMC_LOOP_RETURN
};
/* CBMC specification: capture old value for precondition and */
/* postcondition checking */
#define OLDVAL( var ) _old_ ## var #define OLDVAL( var ) _old_ ## var
#define SAVE_OLDVAL( var, typ ) const typ OLDVAL( var ) = var #define SAVE_OLDVAL( var, typ ) const typ OLDVAL( var ) = var
// CBMC specification: capture old value for values passed by /* CBMC specification: capture old value for values passed by */
// reference in function abstractions /* reference in function abstractions */
#define OBJ( var ) ( * var ) #define OBJ( var ) ( * var )
#define OLDOBJ( var ) _oldobj_ ## var #define OLDOBJ( var ) _oldobj_ ## var
#define SAVE_OLDOBJ( var, typ ) const typ OLDOBJ( var ) = OBJ( var ) #define SAVE_OLDOBJ( var, typ ) const typ OLDOBJ( var ) = OBJ( var )
// CBMC debugging: printfs for expressions /* CBMC debugging: printfs for expressions */
#define __CPROVER_printf( var ) { uint32_t ValueOf_ ## var = ( uint32_t ) var; } #define __CPROVER_printf( var ) { uint32_t ValueOf_ ## var = ( uint32_t ) var; }
#define __CPROVER_printf2( str, exp ) { uint32_t ValueOf_ ## str = ( uint32_t ) ( exp ); } #define __CPROVER_printf2( str, exp ) { uint32_t ValueOf_ ## str = ( uint32_t ) ( exp ); }
// CBMC debugging: printfs for pointer expressions /* CBMC debugging: printfs for pointer expressions */
#define __CPROVER_printf_ptr( var ) { uint8_t * ValueOf_ ## var = ( uint8_t * ) var; } #define __CPROVER_printf_ptr( var ) { uint8_t * ValueOf_ ## var = ( uint8_t * ) var; }
#define __CPROVER_printf2_ptr( str, exp ) { uint8_t * ValueOf_ ## str = ( uint8_t * ) ( exp ); } #define __CPROVER_printf2_ptr( str, exp ) { uint8_t * ValueOf_ ## str = ( uint8_t * ) ( exp ); }
/* /*
* An assertion that pvPortMalloc returns NULL when asked to allocate 0 bytes. * An assertion that pvPortMalloc returns NULL when asked to allocate 0 bytes.
* This assertion is used in some of the Task proofs. * This assertion is used in some of the TaskPool proofs.
*/ */
#define __CPROVER_assert_zero_allocation() \ #define __CPROVER_assert_zero_allocation() \
__CPROVER_assert( pvPortMalloc( 0 ) == NULL, \ __CPROVER_assert( pvPortMalloc( 0 ) == NULL, \
@ -45,7 +81,7 @@ enum CBMC_LOOP_CONDITION { CBMC_LOOP_BREAK, CBMC_LOOP_CONTINUE, CBMC_LOOP_RETURN
* A stub for pvPortMalloc that nondeterministically chooses to return * A stub for pvPortMalloc that nondeterministically chooses to return
* either NULL or an allocation of the requested space. The stub is * either NULL or an allocation of the requested space. The stub is
* guaranteed to return NULL when asked to allocate 0 bytes. * guaranteed to return NULL when asked to allocate 0 bytes.
* This stub is used in some of the Task proofs. * This stub is used in some of the TaskPool proofs.
*/ */
void * pvPortMalloc( size_t xWantedSize ) void * pvPortMalloc( size_t xWantedSize )
{ {
@ -53,6 +89,7 @@ void *pvPortMalloc( size_t xWantedSize )
{ {
return NULL; return NULL;
} }
return nondet_bool() ? malloc( xWantedSize ) : NULL; return nondet_bool() ? malloc( xWantedSize ) : NULL;
} }
@ -61,7 +98,3 @@ void vPortFree( void *pv )
( void ) pv; ( void ) pv;
free( pv ); free( pv );
} }
BaseType_t nondet_basetype();
UBaseType_t nondet_ubasetype();
TickType_t nondet_ticktype();

View file

@ -0,0 +1,141 @@
#include "FreeRTOS.h"
#include "queue.h"
#include "queue_datastructure.h"
#ifndef CBMC_OBJECT_BITS
#define CBMC_OBJECT_BITS 7
#endif
#ifndef CBMC_OBJECT_MAX_SIZE
#define CBMC_OBJECT_MAX_SIZE (UINT32_MAX>>(CBMC_OBJECT_BITS+1))
#endif
/* Using prvCopyDataToQueue together with prvNotifyQueueSetContainer
leads to a problem space explosion. Therefore, we use this stub
and a sepearted proof on prvCopyDataToQueue to deal with it.
As prvNotifyQueueSetContainer is disabled if configUSE_QUEUE_SETS != 1,
in other cases the original implementation should be used. */
#if( configUSE_QUEUE_SETS == 1 )
BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )
{
if(pxQueue->uxItemSize > ( UBaseType_t ) 0)
{
__CPROVER_assert(__CPROVER_r_ok(pvItemToQueue, ( size_t ) pxQueue->uxItemSize), "pvItemToQueue region must be readable");
if(xPosition == queueSEND_TO_BACK){
__CPROVER_assert(__CPROVER_w_ok(( void * ) pxQueue->pcWriteTo, ( size_t ) pxQueue->uxItemSize), "pxQueue->pcWriteTo region must be writable");
}else{
__CPROVER_assert(__CPROVER_w_ok(( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize), "pxQueue->u.xQueue.pcReadFrom region must be writable");
}
return pdFALSE;
}else
{
return nondet_BaseType_t();
}
}
#endif
/* xQueueCreateSet is compiled out if configUSE_QUEUE_SETS != 1.*/
#if( configUSE_QUEUE_SETS == 1 )
QueueSetHandle_t xUnconstrainedQueueSet()
{
UBaseType_t uxEventQueueLength = 2;
QueueSetHandle_t xSet = xQueueCreateSet(uxEventQueueLength);
if( xSet )
{
xSet->cTxLock = nondet_int8_t();
xSet->cRxLock = nondet_int8_t();
xSet->uxMessagesWaiting = nondet_UBaseType_t();
xSet->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
/* This is an invariant checked with a couple of asserts in the code base.
If it is false from the beginning, the CBMC proofs are not able to succeed*/
__CPROVER_assume(xSet->uxMessagesWaiting < xSet->uxLength);
xSet->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
}
return xSet;
}
#endif
/* Create a mostly unconstrained Queue but bound the max item size.
This is required for performance reasons in CBMC at the moment. */
QueueHandle_t xUnconstrainedQueueBoundedItemSize( UBaseType_t uxItemSizeBound ) {
UBaseType_t uxQueueLength;
UBaseType_t uxItemSize;
uint8_t ucQueueType;
__CPROVER_assume(uxQueueLength > 0);
__CPROVER_assume(uxItemSize < uxItemSizeBound);
// QueueGenericCreate method does not check for multiplication overflow
size_t uxQueueStorageSize;
__CPROVER_assume(uxQueueStorageSize < CBMC_OBJECT_MAX_SIZE);
__CPROVER_assume(uxItemSize < uxQueueStorageSize/uxQueueLength);
QueueHandle_t xQueue =
xQueueGenericCreate(uxQueueLength, uxItemSize, ucQueueType);
if(xQueue){
xQueue->cTxLock = nondet_int8_t();
xQueue->cRxLock = nondet_int8_t();
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
/* This is an invariant checked with a couple of asserts in the code base.
If it is false from the beginning, the CBMC proofs are not able to succeed*/
__CPROVER_assume(xQueue->uxMessagesWaiting < xQueue->uxLength);
xQueue->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
xQueue->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
#if( configUSE_QUEUE_SETS == 1)
xQueueAddToSet(xQueue, xUnconstrainedQueueSet());
#endif
}
return xQueue;
}
/* Create a mostly unconstrained Queue */
QueueHandle_t xUnconstrainedQueue( void ) {
UBaseType_t uxQueueLength;
UBaseType_t uxItemSize;
uint8_t ucQueueType;
__CPROVER_assume(uxQueueLength > 0);
// QueueGenericCreate method does not check for multiplication overflow
size_t uxQueueStorageSize;
__CPROVER_assume(uxQueueStorageSize < CBMC_OBJECT_MAX_SIZE);
__CPROVER_assume(uxItemSize < uxQueueStorageSize/uxQueueLength);
QueueHandle_t xQueue =
xQueueGenericCreate(uxQueueLength, uxItemSize, ucQueueType);
if(xQueue){
xQueue->cTxLock = nondet_int8_t();
xQueue->cRxLock = nondet_int8_t();
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
/* This is an invariant checked with a couple of asserts in the code base.
If it is false from the beginning, the CBMC proofs are not able to succeed*/
__CPROVER_assume(xQueue->uxMessagesWaiting < xQueue->uxLength);
xQueue->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
xQueue->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
#if( configUSE_QUEUE_SETS == 1)
xQueueAddToSet(xQueue, xUnconstrainedQueueSet());
#endif
}
return xQueue;
}
/* Create a mostly unconstrained Mutex */
QueueHandle_t xUnconstrainedMutex( void ) {
uint8_t ucQueueType;
QueueHandle_t xQueue =
xQueueCreateMutex(ucQueueType);
if(xQueue){
xQueue->cTxLock = nondet_int8_t();
xQueue->cRxLock = nondet_int8_t();
xQueue->uxMessagesWaiting = nondet_UBaseType_t();
/* This is an invariant checked with a couple of asserts in the code base.
If it is false from the beginning, the CBMC proofs are not able to succeed*/
__CPROVER_assume(xQueue->uxMessagesWaiting < xQueue->uxLength);
xQueue->xTasksWaitingToReceive.uxNumberOfItems = nondet_UBaseType_t();
xQueue->xTasksWaitingToSend.uxNumberOfItems = nondet_UBaseType_t();
#if( configUSE_QUEUE_SETS == 1)
xQueueAddToSet(xQueue, xUnconstrainedQueueSet());
#endif
}
return xQueue;
}

View file

@ -1,121 +0,0 @@
From 884e69144abac08d203bbf8257c6b4a96a2a91ea Mon Sep 17 00:00:00 2001
From: "Mark R. Tuttle" <mrtuttle@amazon.com>
Date: Mon, 21 Oct 2019 14:17:50 -0400
Subject: [PATCH] Remove static storage class from entry points
Many of the entry points we wish to test are marked as being static.
This commit removes the static keyword from all entry points that we
test.
Patch revised on October 21, 2019.
---
.../freertos_plus_tcp/source/FreeRTOS_DHCP.c | 6 +++---
.../standard/freertos_plus_tcp/source/FreeRTOS_DNS.c | 12 ++++++------
.../freertos_plus_tcp/source/FreeRTOS_TCP_WIN.c | 2 +-
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
index c4f79e8e7..d8089a5e7 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
@@ -198,7 +198,7 @@ static void prvSendDHCPDiscover( void );
/*
* Interpret message received on the DHCP socket.
*/
-static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
+BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
/*
* Generate a DHCP request packet, and send it on the DHCP socket.
@@ -234,7 +234,7 @@ static void prvCreateDHCPSocket( void );
/*-----------------------------------------------------------*/
/* The next DHCP transaction Id to be used. */
-static DHCPData_t xDHCPData;
+DHCPData_t xDHCPData;
/*-----------------------------------------------------------*/
@@ -607,7 +607,7 @@ static void prvInitialiseDHCP( void )
}
/*-----------------------------------------------------------*/
-static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
+BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
{
uint8_t *pucUDPPayload, *pucLastByte;
struct freertos_sockaddr xClient;
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
index e511ca324..d6f335304 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
@@ -116,7 +116,7 @@ static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
/*
* Simple routine that jumps over the NAME field of a resource record.
*/
-static uint8_t * prvSkipNameField( uint8_t *pucByte,
+uint8_t * prvSkipNameField( uint8_t *pucByte,
size_t uxSourceLen );
/*
@@ -124,7 +124,7 @@ static uint8_t * prvSkipNameField( uint8_t *pucByte,
* The parameter 'xExpected' indicates whether the identifier in the reply
* was expected, and thus if the DNS cache may be updated with the reply.
*/
-static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
size_t uxBufferLength,
BaseType_t xExpected );
@@ -152,7 +152,7 @@ static uint32_t prvGetHostByName( const char *pcHostName,
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
- static uint8_t * prvReadNameField( uint8_t *pucByte,
+ uint8_t * prvReadNameField( uint8_t *pucByte,
size_t uxSourceLen,
char *pcName,
size_t uxLen );
@@ -765,7 +765,7 @@ static const DNSMessage_t xDefaultPartDNSHeader =
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
- static uint8_t * prvReadNameField( uint8_t *pucByte,
+ uint8_t * prvReadNameField( uint8_t *pucByte,
size_t uxSourceLen,
char *pcName,
size_t uxDestLen )
@@ -843,7 +843,7 @@ static const DNSMessage_t xDefaultPartDNSHeader =
#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
/*-----------------------------------------------------------*/
-static uint8_t * prvSkipNameField( uint8_t *pucByte,
+uint8_t * prvSkipNameField( uint8_t *pucByte,
size_t uxSourceLen )
{
size_t uxChunkLength;
@@ -949,7 +949,7 @@ DNSMessage_t *pxDNSMessageHeader;
#endif /* ipconfigUSE_NBNS */
/*-----------------------------------------------------------*/
-static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
size_t uxBufferLength,
BaseType_t xExpected )
{
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
index 1f5a845fa..1a69807c0 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
@@ -206,7 +206,7 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
/* List of free TCP segments. */
#if( ipconfigUSE_TCP_WIN == 1 )
- static List_t xSegmentList;
+ List_t xSegmentList;
#endif
/* Logging verbosity level. */
--
2.20.1 (Apple Git-117)

View file

@ -1,68 +0,0 @@
From 18ca738652bd0ce0a1345cb3dcd7ffacbc196bfa Mon Sep 17 00:00:00 2001
From: "Mark R. Tuttle" <mrtuttle@amazon.com>
Date: Wed, 30 Oct 2019 09:38:56 -0400
Subject: [PATCH] Remove static attributes from functions implementing
prvCheckOptions for CBMC proofs.
---
.../freertos_plus_tcp/source/FreeRTOS_TCP_IP.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
index 4378e28de..2cd072d24 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
@@ -225,20 +225,20 @@ static BaseType_t prvTCPPrepareConnect( FreeRTOS_Socket_t *pxSocket );
/*
* Parse the TCP option(s) received, if present.
*/
-static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );
+void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );
/*
* Identify and deal with a single TCP header option, advancing the pointer to
* the header. This function returns pdTRUE or pdFALSE depending on whether the
* caller should continue to parse more header options or break the loop.
*/
-static BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow);
+BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow);
/*
* Skip past TCP header options when doing Selective ACK, until there are no
* more options left.
*/
-static void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const ppucLen );
+void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const ppucLen );
/*
* Set the initial properties in the options fields, like the preferred
@@ -1157,7 +1157,7 @@ uint32_t ulInitialSequenceNumber = 0;
* that: ((pxTCPHeader->ucTCPOffset & 0xf0) > 0x50), meaning that the TP header
* is longer than the usual 20 (5 x 4) bytes.
*/
-static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )
+void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )
{
TCPPacket_t * pxTCPPacket;
TCPHeader_t * pxTCPHeader;
@@ -1191,7 +1191,7 @@ BaseType_t xShouldContinueLoop;
/*-----------------------------------------------------------*/
-static BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow)
+BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow)
{
UBaseType_t uxNewMSS;
UBaseType_t xRemainingOptionsBytes = ( *ppucLast ) - ( *ppucPtr );
@@ -1319,7 +1319,7 @@ static BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const pp
/*-----------------------------------------------------------*/
-static void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const pucLen )
+void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const pucLen )
{
uint32_t ulFirst = ulChar2u32( ( *ppucPtr ) );
uint32_t ulLast = ulChar2u32( ( *ppucPtr ) + 4 );
--
2.20.1 (Apple Git-117)

View file

@ -0,0 +1,64 @@
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
index 04b0487..d6e74a9 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
@@ -156,7 +156,11 @@ struct xDHCPMessage_IPv4
typedef struct xDHCPMessage_IPv4 DHCPMessage_IPv4_t;
/* The UDP socket used for all incoming and outgoing DHCP traffic. */
+#ifdef CBMC
+Socket_t xDHCPSocket;
+#else
static Socket_t xDHCPSocket;
+#endif
#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
/* Define the Link Layer IP address: 169.254.x.x */
@@ -179,7 +183,11 @@ static void prvSendDHCPDiscover( void );
/*
* Interpret message received on the DHCP socket.
*/
+#ifdef CBMC
+BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
+#else
static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
+#endif
/*
* Generate a DHCP request packet, and send it on the DHCP socket.
@@ -204,7 +212,11 @@ static uint8_t *prvCreatePartDHCPMessage( struct freertos_sockaddr *pxAddress,
/*
* Create the DHCP socket, if it has not been created already.
*/
+#ifdef CBMC
+void prvCreateDHCPSocket( void );
+#else
static void prvCreateDHCPSocket( void );
+#endif
/*
* Close the DHCP socket.
@@ -223,7 +235,11 @@ static void prvCloseDHCPSocket( void );
/*-----------------------------------------------------------*/
/* Hold information in between steps in the DHCP state machine. */
+#ifdef CBMC
+DHCPData_t xDHCPData;
+#else
static DHCPData_t xDHCPData;
+#endif
/*-----------------------------------------------------------*/
@@ -623,7 +639,11 @@ static void prvInitialiseDHCP( void )
}
/*-----------------------------------------------------------*/
+#ifdef CBMC
+BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
+#else
static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
+#endif
{
uint8_t *pucUDPPayload;
int32_t lBytes;

View file

@ -0,0 +1,100 @@
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
index 480d50b..5557253 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
@@ -114,7 +114,11 @@ static Socket_t prvCreateDNSSocket( void );
/*
* Create the DNS message in the zero copy buffer passed in the first parameter.
*/
+#ifdef CBMC
+size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
+#else
static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
+#endif
const char *pcHostName,
TickType_t uxIdentifier );
@@ -122,7 +126,11 @@ static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
* Simple routine that jumps over the NAME field of a resource record.
* It returns the number of bytes read.
*/
+#ifdef CBMC
+size_t prvSkipNameField( const uint8_t *pucByte,
+#else
static size_t prvSkipNameField( const uint8_t *pucByte,
+#endif
size_t uxLength );
/*
@@ -130,7 +138,11 @@ static size_t prvSkipNameField( const uint8_t *pucByte,
* The parameter 'xExpected' indicates whether the identifier in the reply
* was expected, and thus if the DNS cache may be updated with the reply.
*/
+#ifdef CBMC
+uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+#else
static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+#endif
size_t uxBufferLength,
BaseType_t xExpected );
@@ -184,7 +196,11 @@ static uint32_t prvGetHostByName( const char *pcHostName,
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
+#ifdef CBMC
+ size_t prvReadNameField( const uint8_t *pucByte,
+#else
static size_t prvReadNameField( const uint8_t *pucByte,
+#endif
size_t uxRemainingBytes,
char *pcName,
size_t uxDestLen );
@@ -758,7 +774,11 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
}
/*-----------------------------------------------------------*/
+#ifdef CBMC
+size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
+#else
static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
+#endif
const char *pcHostName,
TickType_t uxIdentifier )
{
@@ -838,7 +858,11 @@ static const DNSMessage_t xDefaultPartDNSHeader =
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
+#ifdef CBMC
+ size_t prvReadNameField( const uint8_t *pucByte,
+#else
static size_t prvReadNameField( const uint8_t *pucByte,
+#endif
size_t uxRemainingBytes,
char *pcName,
size_t uxDestLen )
@@ -932,7 +956,11 @@ static const DNSMessage_t xDefaultPartDNSHeader =
#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
/*-----------------------------------------------------------*/
+#ifdef CBMC
+size_t prvSkipNameField( const uint8_t *pucByte,
+#else
static size_t prvSkipNameField( const uint8_t *pucByte,
+#endif
size_t uxLength )
{
size_t uxChunkLength;
@@ -1050,7 +1078,11 @@ size_t uxPayloadSize;
#endif /* ipconfigUSE_NBNS */
/*-----------------------------------------------------------*/
+#ifdef CBMC
+uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+#else
static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+#endif
size_t uxBufferLength,
BaseType_t xExpected )
{

View file

@ -0,0 +1,87 @@
From afc01793c4531cfbe9f92e7ca2ce9364983d987e Mon Sep 17 00:00:00 2001
From: Mark R Tuttle <mrtuttle@amazon.com>
Date: Tue, 12 May 2020 15:57:56 +0000
Subject: [PATCH] modified lib
---
.../freertos_plus_tcp/source/FreeRTOS_TCP_IP.c | 24 ++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
index dc58621..963b576 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
@@ -198,14 +198,22 @@ static BaseType_t prvTCPPrepareConnect( FreeRTOS_Socket_t *pxSocket );
/*
* Parse the TCP option(s) received, if present.
*/
+#ifdef CBMC
+void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer );
+#else
static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer );
+#endif
/*
* Identify and deal with a single TCP header option, advancing the pointer to
* the header. This function returns pdTRUE or pdFALSE depending on whether the
* caller should continue to parse more header options or break the loop.
*/
+#ifdef CBMC
+size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
+#else
static size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
+#endif
size_t uxTotalLength,
FreeRTOS_Socket_t * const pxSocket,
BaseType_t xHasSYNFlag );
@@ -214,7 +222,11 @@ static size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
* Skip past TCP header options when doing Selective ACK, until there are no
* more options left.
*/
+#ifdef CBMC
+void prvReadSackOption( const uint8_t * const pucPtr,
+#else
static void prvReadSackOption( const uint8_t * const pucPtr,
+#endif
size_t uxIndex,
FreeRTOS_Socket_t * const pxSocket );
@@ -1137,7 +1149,11 @@ uint32_t ulInitialSequenceNumber = 0;
* that: ((pxTCPHeader->ucTCPOffset & 0xf0) > 0x50), meaning that the TP header
* is longer than the usual 20 (5 x 4) bytes.
*/
+#ifdef CBMC
+void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer )
+#else
static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer )
+#endif
{
size_t uxTCPHeaderOffset = ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer );
const ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
@@ -1201,7 +1217,11 @@ uint8_t ucLength;
}
/*-----------------------------------------------------------*/
+#ifdef CBMC
+size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
+#else
static size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
+#endif
size_t uxTotalLength,
FreeRTOS_Socket_t * const pxSocket,
BaseType_t xHasSYNFlag )
@@ -1346,7 +1366,11 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
}
/*-----------------------------------------------------------*/
+#ifdef CBMC
+void prvReadSackOption( const uint8_t * const pucPtr,
+#else
static void prvReadSackOption( const uint8_t * const pucPtr,
+#endif
size_t uxIndex,
FreeRTOS_Socket_t * const pxSocket )
{
--
2.7.4

View file

@ -0,0 +1,17 @@
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
index 0078ab313..b0cccbad8 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
@@ -192,8 +192,12 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
/* List of free TCP segments. */
#if( ipconfigUSE_TCP_WIN == 1 )
+#ifdef CBMC
+ List_t xSegmentList;
+#else
static List_t xSegmentList;
#endif
+#endif
/* Logging verbosity level. */
BaseType_t xTCPWindowLoggingLevel = 0;

View file

@ -13,101 +13,88 @@
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h" #include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_TCP_IP.h"
#include "FreeRTOS_DHCP.h" #include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h" #include "NetworkInterface.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
#include "FreeRTOS_ARP.h" #include "FreeRTOS_ARP.h"
#include "FreeRTOS_TCP_WIN.h"
#include "cbmc.h" #include "cbmc.h"
/****************************************************************
* Signature of function under test
****************************************************************/
void prvCheckOptions( FreeRTOS_Socket_t * pxSocket, void prvCheckOptions( FreeRTOS_Socket_t * pxSocket,
NetworkBufferDescriptor_t *pxNetworkBuffer ); const NetworkBufferDescriptor_t * pxNetworkBuffer );
// Used in specification and abstraction of CheckOptions inner and outer loops /****************************************************************
// Given unconstrained values in harness * Declare the buffer size external to the harness so it can be
* accessed by the preconditions of prvSingleStepTCPHeaderOptions, and
* give the buffer size an unconstrained value in the harness itself.
****************************************************************/
size_t buffer_size; size_t buffer_size;
uint8_t *EthernetBuffer;
// Abstraction of CheckOptions outer loop used in proof of CheckOptions /****************************************************************
// Loop variables passed by reference: VAL(var) is (*var). * Function contract proved correct by CheckOptionsOuter
BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, ****************************************************************/
const unsigned char ** const ppucLast,
FreeRTOS_Socket_t ** const ppxSocket, size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
TCPWindow_t ** const ppxTCPWindow) size_t uxTotalLength,
FreeRTOS_Socket_t * const pxSocket,
BaseType_t xHasSYNFlag )
{ {
// CBMC pointer model (obviously true) /* CBMC model of pointers limits the size of the buffer */
__CPROVER_assume(buffer_size < CBMC_MAX_OBJECT_SIZE);
// Preconditions /* Preconditions */
__CPROVER_assert( buffer_size < CBMC_MAX_OBJECT_SIZE,
"prvSingleStepTCPHeaderOptions: buffer_size < CBMC_MAX_OBJECT_SIZE" );
__CPROVER_assert( 8 <= buffer_size,
"prvSingleStepTCPHeaderOptions: 8 <= buffer_size" );
__CPROVER_assert( pucPtr != NULL,
"prvSingleStepTCPHeaderOptions: pucPtr != NULL" );
__CPROVER_assert( uxTotalLength <= buffer_size,
"prvSingleStepTCPHeaderOptions: uxTotalLength <= buffer_size" );
__CPROVER_assert( pxSocket != NULL,
"prvSingleStepTCPHeaderOptions: pxSocket != NULL" );
// pucPtr is a valid pointer /* Postconditions */
__CPROVER_assert(EthernetBuffer <= OBJ(ppucPtr) && size_t index;
OBJ(ppucPtr) < EthernetBuffer + buffer_size, __CPROVER_assume( index == 1 || index <= uxTotalLength );
"pucPtr is a valid pointer");
// pucLast is a valid pointer (or one past)
__CPROVER_assert(EthernetBuffer <= OBJ(ppucLast) &&
OBJ(ppucLast) <= EthernetBuffer + buffer_size,
"pucLast is a valid pointer");
// pucPtr is before pucLast
__CPROVER_assert(OBJ(ppucPtr) < OBJ(ppucLast),
"pucPtr < pucLast");
// Record initial values return index;
SAVE_OLDOBJ(ppucPtr, unsigned char *);
SAVE_OLDOBJ(ppucLast, unsigned char *);
// Model loop body
size_t offset;
BaseType_t rc;
OBJ(ppucPtr) += offset;
// Postconditions
// rc is boolean
__CPROVER_assume(rc == pdTRUE || rc == pdFALSE);
// pucPtr advanced
__CPROVER_assume(rc == pdFALSE || OLDOBJ(ppucPtr) < OBJ(ppucPtr));
// pucLast unchanged
__CPROVER_assume(OBJ(ppucLast) == OLDOBJ(ppucLast));
// pucPtr <= pucLast
__CPROVER_assume(OBJ(ppucPtr) <= OBJ(ppucLast));
return rc;
} }
// Proof of CheckOptions /****************************************************************
* Proof of CheckOptions
****************************************************************/
void harness() void harness()
{ {
// Buffer can be any buffer of size at most BUFFER_SIZE /* Give buffer_size an unconstrained value */
size_t offset; size_t buf_size;
uint8_t buffer[BUFFER_SIZE];
buffer_size = BUFFER_SIZE - offset;
EthernetBuffer = buffer + offset;
// pxSocket can be any socket buffer_size = buf_size;
/* pxSocket can be any socket */
FreeRTOS_Socket_t pxSocket; FreeRTOS_Socket_t pxSocket;
// pxNetworkBuffer can be any buffer descriptor with any buffer /* pxNetworkBuffer can be any buffer descriptor with any buffer */
NetworkBufferDescriptor_t pxNetworkBuffer; NetworkBufferDescriptor_t pxNetworkBuffer;
pxNetworkBuffer.pucEthernetBuffer = EthernetBuffer; pxNetworkBuffer.pucEthernetBuffer = malloc( buffer_size );
pxNetworkBuffer.xDataLength = buffer_size; pxNetworkBuffer.xDataLength = buffer_size;
//////////////////////////////////////////////////////////////// /****************************************************************
// Specification and proof of CheckOptions * Specification and proof of CheckOptions
****************************************************************/
// CBMC pointer model (obviously true) /* CBMC model of pointers limits the size of the buffer */
__CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE ); __CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE );
// Buffer overflow on pathologically small buffers /* Bound required to bound iteration over the buffer */
// Must be big enough to hold pxTCPPacket and pxTCPHeader __CPROVER_assume( buffer_size <= BUFFER_SIZE );
/* Buffer must be big enough to hold pxTCPPacket and pxTCPHeader */
__CPROVER_assume( buffer_size > 47 ); __CPROVER_assume( buffer_size > 47 );
// EthernetBuffer is a valid pointer (or one past when buffer_size==0)
__CPROVER_assume(buffer <= EthernetBuffer &&
EthernetBuffer <= buffer + BUFFER_SIZE);
// Loop variables passed by reference
prvCheckOptions( &pxSocket, &pxNetworkBuffer ); prvCheckOptions( &pxSocket, &pxNetworkBuffer );
} }

View file

@ -10,9 +10,7 @@
"$(FREERTOS)/Source/tasks.goto", "$(FREERTOS)/Source/tasks.goto",
"$(FREERTOS)/Source/list.goto" "$(FREERTOS)/Source/list.goto"
], ],
"ABSTRACTIONS": "",
"BUFFER_SIZE": 100, "BUFFER_SIZE": 100,
"UNWIND_GOTO": 0,
"DEF": "DEF":
[ [
"BUFFER_SIZE={BUFFER_SIZE}" "BUFFER_SIZE={BUFFER_SIZE}"

View file

@ -13,93 +13,82 @@
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h" #include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_TCP_IP.h"
#include "FreeRTOS_DHCP.h" #include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h" #include "NetworkInterface.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
#include "FreeRTOS_ARP.h" #include "FreeRTOS_ARP.h"
#include "FreeRTOS_TCP_WIN.h"
#include "cbmc.h" #include "cbmc.h"
void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, /****************************************************************
FreeRTOS_Socket_t ** const ppxSocket, * Signature of function under test
unsigned char * const pucLen ); ****************************************************************/
// Given unconstrained values in harness void prvReadSackOption( const uint8_t * const pucPtr,
size_t buffer_size; size_t uxIndex,
uint8_t *EthernetBuffer; FreeRTOS_Socket_t * const pxSocket );
/****************************************************************
* Proof of prvReadSackOption function contract
****************************************************************/
void harness() void harness()
{ {
// Buffer can be any buffer of size at most BUFFER_SIZE /* pucPtr points into a buffer */
size_t offset; size_t buffer_size;
uint8_t buffer[BUFFER_SIZE]; uint8_t * pucPtr = malloc( buffer_size );
buffer_size = BUFFER_SIZE - offset;
EthernetBuffer = buffer + offset;
// pucPtr can be any pointer into buffer /* uxIndex in an index into the buffer */
size_t pucPtr_offset; size_t uxIndex;
unsigned char *pucPtr = EthernetBuffer + pucPtr_offset;
// ucLen can be any byte /* pxSocket can be any socket with some initialized values */
unsigned char ucLen; FreeRTOS_Socket_t * pxSocket = malloc( sizeof( FreeRTOS_Socket_t ) );
// pxSocket can be any socket with some initialized values pxSocket->u.xTCP.txStream = malloc( sizeof( StreamBuffer_t ) );
FreeRTOS_Socket_t xSocket;
FreeRTOS_Socket_t *pxSocket = &xSocket; vListInitialise( &pxSocket->u.xTCP.xTCPWindow.xWaitQueue );
if( nondet_bool() )
{
TCPSegment_t * segment = malloc( sizeof( TCPSegment_t ) );
listSET_LIST_ITEM_OWNER( &segment->xQueueItem, ( void * ) segment );
vListInsertEnd( &pxSocket->u.xTCP.xTCPWindow.xWaitQueue, &segment->xQueueItem );
}
vListInitialise( &pxSocket->u.xTCP.xTCPWindow.xTxSegments );
if( nondet_bool() )
{
TCPSegment_t * segment = malloc( sizeof( TCPSegment_t ) );
vListInitialiseItem( &segment->xSegmentItem );
listSET_LIST_ITEM_OWNER( &segment->xQueueItem, ( void * ) segment );
vListInsertEnd( &pxSocket->u.xTCP.xTCPWindow.xTxSegments, &segment->xQueueItem );
}
vListInitialise( &pxSocket->u.xTCP.xTCPWindow.xPriorityQueue );
extern List_t xSegmentList; extern List_t xSegmentList;
vListInitialise(&xSocket.u.xTCP.xTCPWindow.xWaitQueue);
vListInitialise(&xSocket.u.xTCP.xTCPWindow.xTxSegments);
vListInitialise(&xSocket.u.xTCP.xTCPWindow.xPriorityQueue);
vListInitialise( &xSegmentList ); vListInitialise( &xSegmentList );
StreamBuffer_t txStreamBuffer;
xSocket.u.xTCP.txStream=&txStreamBuffer;
// A singleton list /****************************************************************
TCPSegment_t segment_w; * Specification and proof of CheckOptions inner loop
vListInitialiseItem(&segment_w.xQueueItem); ****************************************************************/
vListInitialiseItem(&segment_w.xListItem);
listSET_LIST_ITEM_OWNER(&segment_w.xQueueItem, (void *) &segment_w);
vListInsertEnd(&xSocket.u.xTCP.xTCPWindow.xWaitQueue, &segment_w.xQueueItem);
// A singleton list /* Preconditions */
TCPSegment_t segment_t;
vListInitialiseItem(&segment_t.xQueueItem);
vListInitialiseItem(&segment_t.xListItem);
listSET_LIST_ITEM_OWNER(&segment_t.xQueueItem, (void *) &segment_t);
vListInsertEnd(&xSocket.u.xTCP.xTCPWindow.xTxSegments, &segment_t.xQueueItem);
//////////////////////////////////////////////////////////////// /* CBMC model of pointers limits the size of the buffer */
// Specification and proof of CheckOptions inner loop
// CBMC pointer model (obviously true)
__CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE ); __CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE );
// Preconditions /* Both preconditions are required to avoid integer overflow in the */
/* pointer offset of the pointer pucPtr + uxIndex + 8 */
__CPROVER_assume( uxIndex <= buffer_size );
__CPROVER_assume( uxIndex + 8 <= buffer_size );
// pucPtr is a valid pointer /* Assuming quite a bit more about the initialization of pxSocket */
__CPROVER_assume(EthernetBuffer <= pucPtr && __CPROVER_assume( pucPtr != NULL );
pucPtr < EthernetBuffer + buffer_size); __CPROVER_assume( pxSocket != NULL );
// pucPtr + 8 is a valid pointer (xBytesRemaining > ucLen)
__CPROVER_assume(EthernetBuffer <= pucPtr + 8 &&
pucPtr + 8 <= EthernetBuffer + buffer_size);
// ucLen >= 8 (while loop condition)
__CPROVER_assume(ucLen >= 8);
// Record initial values prvReadSackOption( pucPtr, uxIndex, pxSocket );
SAVE_OLDVAL(pucPtr, unsigned char *);
SAVE_OLDVAL(ucLen, unsigned char);
// Loop variables passed by reference /* No postconditions required */
prvSkipPastRemainingOptions(&pucPtr, &pxSocket, &ucLen);
// Postconditions
__CPROVER_assert(pucPtr == OLDVAL(pucPtr) + 8, "pucPtr advanced");
__CPROVER_assert(ucLen == OLDVAL(ucLen) - 8, "ucLen decremented");
__CPROVER_assert(EthernetBuffer <= pucPtr &&
pucPtr <= EthernetBuffer + buffer_size,
"pucPtr a valid pointer");
} }

View file

@ -1,6 +1,5 @@
{ {
"ENTRY": "CheckOptionsInner", "ENTRY": "CheckOptionsInner",
"BUFFER_SIZE": 100,
"CBMCFLAGS": [ "CBMCFLAGS": [
"--unwind 1", "--unwind 1",
"--unwindset prvTCPWindowTxCheckAck.1:2,prvTCPWindowFastRetransmit.2:2" "--unwindset prvTCPWindowTxCheckAck.1:2,prvTCPWindowFastRetransmit.2:2"
@ -16,6 +15,5 @@
], ],
"DEF": "DEF":
[ [
"BUFFER_SIZE={BUFFER_SIZE}"
] ]
} }

View file

@ -13,111 +13,88 @@
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h" #include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_TCP_IP.h"
#include "FreeRTOS_DHCP.h" #include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h" #include "NetworkInterface.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
#include "FreeRTOS_ARP.h" #include "FreeRTOS_ARP.h"
#include "FreeRTOS_TCP_WIN.h"
#include "cbmc.h" #include "cbmc.h"
BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, /****************************************************************
const unsigned char ** const ppucLast, * Signature of the function under test
FreeRTOS_Socket_t ** const ppxSocket, ****************************************************************/
TCPWindow_t ** const ppxTCPWindow);
size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
size_t uxTotalLength,
FreeRTOS_Socket_t * const pxSocket,
BaseType_t xHasSYNFlag );
/****************************************************************
* Declare the buffer size external to the harness so it can be
* accessed by the preconditions of prvReadSackOption, and give the
* buffer size an unconstrained value in the harness itself.
****************************************************************/
// Given unconstrained values in harness
size_t buffer_size; size_t buffer_size;
uint8_t *EthernetBuffer;
void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, /****************************************************************
FreeRTOS_Socket_t ** const ppxSocket, * Function contract proved correct by CheckOptionsInner
unsigned char * const pucLen ) ****************************************************************/
void prvReadSackOption( const uint8_t * const pucPtr,
size_t uxIndex,
FreeRTOS_Socket_t * const pxSocket )
{ {
// Preconditions /* Preconditions */
__CPROVER_assert( buffer_size < CBMC_MAX_OBJECT_SIZE,
"prvReadSackOption: buffer_size < CBMC_MAX_OBJECT_SIZE" );
__CPROVER_assert( uxIndex <= buffer_size,
"prvReadSackOption: uxIndex <= buffer_size" );
__CPROVER_assert( uxIndex + 8 <= buffer_size,
"prvReadSackOption: uxIndex + 8 <= buffer_size" );
__CPROVER_assert( pucPtr != NULL,
"prvReadSackOption: pucPtr != NULL" );
__CPROVER_assert( pxSocket != NULL,
"prvReadSackOption: pxSocket != NULL" );
// pucPtr is a valid pointer /* No postconditions required */
__CPROVER_assert(EthernetBuffer <= OBJ(ppucPtr) &&
OBJ(ppucPtr) < EthernetBuffer + buffer_size,
"pucPtr is a valid pointer");
// pucPtr + 8 is a valid pointer
__CPROVER_assert(EthernetBuffer <= OBJ(ppucPtr) + 8 &&
OBJ(ppucPtr) + 8 <= EthernetBuffer + buffer_size,
"pucPtr+8 is a valid pointer");
// len >= 8
__CPROVER_assert(OBJ(pucLen) >= 8, "len >= 8");
// Record initial values
SAVE_OLDOBJ(ppucPtr, unsigned char *);
SAVE_OLDOBJ(pucLen, unsigned char);
// Model loop body
OBJ(ppucPtr) += 8;
OBJ(pucLen) -= 8;
// Postconditions
__CPROVER_assume(OBJ(ppucPtr) == OLDOBJ(ppucPtr) + 8);
__CPROVER_assume(OBJ(pucLen) == OLDOBJ(pucLen) - 8);
__CPROVER_assume(EthernetBuffer <= OBJ(ppucPtr) &&
OBJ(ppucPtr) <= EthernetBuffer + buffer_size);
} }
// Proof of CheckOptions outer loop /****************************************************************
* Proof of prvSingleStepTCPHeaderOptions function contract
****************************************************************/
void harness() void harness()
{ {
// Buffer can be any buffer of size at most BUFFER_SIZE /* Give buffer_size an unconstrained value */
size_t offset; size_t buf_size;
uint8_t buffer[BUFFER_SIZE];
buffer_size = BUFFER_SIZE - offset;
EthernetBuffer = buffer + offset;
// pucPtr and pucLast can be any pointers into buffer buffer_size = buf_size;
size_t pucPtr_offset;
size_t pucLast_offset;
unsigned char *pucPtr = EthernetBuffer + pucPtr_offset;
unsigned char *pucLast = EthernetBuffer + pucLast_offset;
// uxNewMSS can by any byte uint8_t * pucPtr = malloc( buffer_size );
UBaseType_t uxNewMSS; size_t uxTotalLength;
FreeRTOS_Socket_t * pxSocket = malloc( sizeof( FreeRTOS_Socket_t ) );
BaseType_t xHasSYNFlag;
// pxSocket can be any socket /****************************************************************
FreeRTOS_Socket_t xSocket; * Specification and proof of CheckOptions outer loop
FreeRTOS_Socket_t *pxSocket = &xSocket; ****************************************************************/
// pxTCPWindow can be any window (points into socket) /* CBMC model of pointers limits the size of the buffer */
TCPWindow_t *pxTCPWindow = &xSocket.u.xTCP.xTCPWindow;
////////////////////////////////////////////////////////////////
// Specification and proof of CheckOptions outer loop
// CBMC pointer model (obviously true)
__CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE ); __CPROVER_assume( buffer_size < CBMC_MAX_OBJECT_SIZE );
// Preconditions /* Preconditions */
__CPROVER_assume( 8 <= buffer_size ); /* ulFirst and ulLast */
__CPROVER_assume( pucPtr != NULL );
__CPROVER_assume( uxTotalLength <= buffer_size );
__CPROVER_assume( pxSocket != NULL );
// pucPtr is a valid pointer size_t index = prvSingleStepTCPHeaderOptions( pucPtr,
__CPROVER_assume(EthernetBuffer <= pucPtr && uxTotalLength,
pucPtr < EthernetBuffer + buffer_size); pxSocket,
// pucLast is a valid pointer (or one past) xHasSYNFlag );
__CPROVER_assume(EthernetBuffer <= pucLast &&
pucLast <= EthernetBuffer + buffer_size);
// pucPtr is before pucLast
__CPROVER_assume(pucPtr < pucLast);
// Record initial values
SAVE_OLDVAL(pucPtr, uint8_t *);
SAVE_OLDVAL(pucLast, uint8_t *);
// Loop variables passed by reference
// Return value describes loop exit: break or continue
BaseType_t rc =
prvSingleStepTCPHeaderOptions(&pucPtr, &pucLast, &pxSocket, &pxTCPWindow);
// Postconditions
__CPROVER_assert(rc == pdFALSE || OLDVAL(pucPtr) < pucPtr, "pucPtr advanced");
__CPROVER_assert(pucLast == OLDVAL(pucLast), "pucLast unchanged");
__CPROVER_assert(pucPtr <= pucLast, "pucPtr <= pucLast");
/* Postconditions */
__CPROVER_assert( index == 1 || index <= uxTotalLength,
"prvSingleStepTCPHeaderOptions: index <= uxTotalLength" );
} }

View file

@ -1,6 +1,5 @@
{ {
"ENTRY": "CheckOptionsOuter", "ENTRY": "CheckOptionsOuter",
"BUFFER_SIZE": 100,
"CBMCFLAGS": "CBMCFLAGS":
[ [
"--unwind 1", "--unwind 1",
@ -17,6 +16,5 @@
], ],
"DEF": "DEF":
[ [
"BUFFER_SIZE={BUFFER_SIZE}"
] ]
} }

View file

@ -26,76 +26,77 @@
* http://www.FreeRTOS.org * http://www.FreeRTOS.org
*/ */
/* Standard includes. */
#include <stdint.h> #include <stdint.h>
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DHCP.h" #include "FreeRTOS_DHCP.h"
#include "FreeRTOS_ARP.h"
/* /* Static members defined in FreeRTOS_DHCP.c */
* CBMC automatically unwinds strlen on a fixed string extern DHCPData_t xDHCPData;
*/ extern Socket_t xDHCPSocket;
const char * pcApplicationHostnameHook(void) { void prvCreateDHCPSocket();
return "hostname";
}
/* /* Static member defined in freertos_api.c */
* This stub allows us to overcome the unwinding error obtained #ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
* in the do-while loop within function prvCreatePartDHCPMessage. extern uint32_t GetNetworkBuffer_failure_count;
* The behaviour is similar to the original function, but failed allocations #endif
* are not considered here (this is a safe assumption that avoids the error)
*/ /****************************************************************
void *FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks ) * The signature of the function under test.
****************************************************************/
void vDHCPProcess( BaseType_t xReset );
/****************************************************************
* Abstract prvProcessDHCPReplies proved memory safe in ProcessDHCPReplies.
****************************************************************/
BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
{ {
NetworkBufferDescriptor_t xNetworkBuffer; return nondet_BaseType();
void *pvReturn;
xNetworkBuffer.xDataLength = ipUDP_PAYLOAD_OFFSET_IPv4 + xRequestedSizeBytes;
xNetworkBuffer.pucEthernetBuffer = malloc( xNetworkBuffer.xDataLength );
pvReturn = (void *) &( xNetworkBuffer.pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
return pvReturn;
} }
/* /****************************************************************
* We stub out FreeRTOS_recvfrom to do nothing but return a buffer of * The proof of vDHCPProcess
* arbitrary size (but size at most BUFFER_SIZE) containing arbitrary ****************************************************************/
* data. We need to bound the size of the buffer in order to bound
* the number of iterations of the loop prvProcessDHCPReplies.0 that
* iterates over the buffer contents. The bound BUFFER_SIZE is chosen
* to be large enough to ensure complete code coverage, and small
* enough to ensure CBMC terminates within a reasonable amount of
* time.
*/
int32_t FreeRTOS_recvfrom(
Socket_t xSocket, void *pvBuffer, size_t xBufferLength,
BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress,
socklen_t *pxSourceAddressLength )
{
__CPROVER_assert(xFlags & FREERTOS_ZERO_COPY, "I can only do ZERO_COPY");
size_t xBufferSize;
/* A DHCP message (min. size 241B) is preceded by the IP buffer padding (10B) and the UDP payload (42B) */
__CPROVER_assume(xBufferSize >= ipBUFFER_PADDING + ipUDP_PAYLOAD_OFFSET_IPv4);
/* The last field of a DHCP message (Options) is variable in length, but 6 additional bytes are enough */
/* to obtain maximum coverage with this proof. Hence, we have BUFFER_SIZE=299 */
__CPROVER_assume(xBufferSize <= BUFFER_SIZE);
/* The buffer gets allocated and we set the pointer past the UDP payload (i.e., start of DHCP message) */
*((char **)pvBuffer) = malloc(xBufferSize) + ipBUFFER_PADDING + ipUDP_PAYLOAD_OFFSET_IPv4;
return xBufferSize - ipUDP_PAYLOAD_OFFSET_IPv4 - ipBUFFER_PADDING;
}
/*
* The harness test proceeds to call DHCPProcess with an unconstrained value
*/
void harness() void harness()
{ {
BaseType_t xReset; BaseType_t xReset;
/****************************************************************
* Initialize the counter used to bound the number of times
* GetNetworkBufferWithDescriptor can fail.
****************************************************************/
#ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
GetNetworkBuffer_failure_count = 0;
#endif
/****************************************************************
* Assume a valid socket in most states of the DHCP state machine.
*
* The socket is created in the eWaitingSendFirstDiscover state.
* xReset==True resets the state to eWaitingSendFirstDiscover.
****************************************************************/
if( !( ( xDHCPData.eDHCPState == eWaitingSendFirstDiscover ) ||
( xReset != pdFALSE ) ) )
{
prvCreateDHCPSocket();
__CPROVER_assume( xDHCPSocket != NULL );
}
vDHCPProcess( xReset ); vDHCPProcess( xReset );
} }

View file

@ -28,18 +28,29 @@
{ {
"ENTRY": "DHCPProcess", "ENTRY": "DHCPProcess",
"CBMCFLAGS": "--unwind 4 --unwindset strlen.0:11,memcmp.0:7,prvProcessDHCPReplies.0:8 --nondet-static",
# Minimal buffer size for maximum coverage, see harness for details.
"BUFFER_SIZE": 299,
# The number of times GetNetworkBufferWithDescriptor can be allowed to fail
# (plus 1).
"FAILURE_BOUND": 2,
"CBMCFLAGS": "--unwind 4 --unwindset strlen.0:11,memcmp.0:7,prvProcessDHCPReplies.0:8,prvCreatePartDHCPMessage.0:{FAILURE_BOUND} --nondet-static --flush",
"OBJS": "OBJS":
[ [
"$(ENTRY)_harness.goto", "$(ENTRY)_harness.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/stubs/cbmc.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/stubs/freertos_api.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.goto", "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.goto", "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.goto",
"$(FREERTOS)/Source/tasks.goto" "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.goto"
], ],
# Minimal buffer size for maximum coverage, see harness for details.
"BUFFER_SIZE": 299,
"DEF": "DEF":
[ [
"BUFFER_SIZE={BUFFER_SIZE}" "BUFFER_SIZE={BUFFER_SIZE}",
"CBMC_REQUIRE_NETWORKBUFFER_ETHERNETBUFFER_NONNULL=1",
"CBMC_GETNETWORKBUFFER_FAILURE_BOUND={FAILURE_BOUND}"
] ]
} }

View file

@ -0,0 +1,16 @@
{ "expected-missing-functions":
[
"vPortEnterCritical",
"vPortExitCritical",
"vSocketBind",
"vSocketClose",
"vTaskSetTimeOutState",
"xTaskGetTickCount",
"xTaskGetCurrentTaskHandle",
"xQueueGenericSend",
"xApplicationGetRandomNumber",
"vLoggingPrintf"
],
"proof-name": "DHCPProcess",
"proof-root": "tools/cbmc/proofs"
}

View file

@ -1,49 +1,94 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "queue.h" #include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
/* This assumes the length of pcHostName is bounded by MAX_HOSTNAME_LEN and the size of UDPPayloadBuffer is bounded by #include "cbmc.h"
MAX_REQ_SIZE. */
void *safeMalloc(size_t xWantedSize) { /****************************************************************
if(xWantedSize == 0) { * We abstract:
return NULL; *
} * All kernel task scheduling functions since we are doing
uint8_t byte; * sequential verification and the sequential verification of these
return byte ? malloc(xWantedSize) : NULL; * sequential primitives is done elsewhere.
} *
* Many methods in the FreeRTOS TCP API in stubs/freertos_api.c
*
* prvParseDNSReply proved memory safe elsewhere
*
* prvCreateDNSMessage
*
* This proof assumes the length of pcHostName is bounded by
* MAX_HOSTNAME_LEN. We have to bound this length because we have to
* bound the iterations of strcmp.
****************************************************************/
/* Abstraction of FreeRTOS_GetUDPPayloadBuffer. This should be checked later. For now we are allocating a fixed sized memory of size MAX_REQ_SIZE. */ /****************************************************************
void * FreeRTOS_GetUDPPayloadBuffer(size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks ) { * Abstract prvParseDNSReply proved memory save in ParseDNSReply.
void *pvReturn = safeMalloc(MAX_REQ_SIZE); *
return pvReturn; * We stub out his function to fill the payload buffer with
} * unconstrained data and return an unconstrained size.
*
* The function under test uses only the return value of this
* function.
****************************************************************/
/* Abstraction of FreeRTOS_socket. This abstraction allocates a memory of size Socket_t. */
Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol ) {
Socket_t xSocket = safeMalloc(sizeof(Socket_t)); /* Replaced malloc by safeMalloc */
return xSocket;
}
/* This function only uses the return value of prvParseDNSReply. Hence it returns an unconstrained uint32 value */
uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer, uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer,
size_t xBufferLength, size_t xBufferLength,
BaseType_t xExpected ) {} BaseType_t xExpected )
{
uint32_t size;
void harness() { __CPROVER_havoc_object( pucUDPPayloadBuffer );
size_t len; return size;
__CPROVER_assume(len >= 0 && len <= MAX_HOSTNAME_LEN);
char *pcHostName = safeMalloc(len); /* Replaced malloc by safeMalloc */
if (len && pcHostName) {
pcHostName[len-1] = NULL;
} }
if (pcHostName) { /* Guarding against NULL pointer */
/****************************************************************
* Abstract prvCreateDNSMessage
*
* This function writes a header, a hostname, and a constant amount of
* data into the payload buffer, and returns the amount of data
* written. This abstraction just fills the entire buffer with
* unconstrained data and returns and unconstrained length.
****************************************************************/
size_t prvCreateDNSMessage( uint8_t * pucUDPPayloadBuffer,
const char * pcHostName,
TickType_t uxIdentifier )
{
__CPROVER_havoc_object( pucUDPPayloadBuffer );
size_t size;
return size;
}
/****************************************************************
* The proof for FreeRTOS_gethostbyname.
****************************************************************/
void harness()
{
size_t len;
__CPROVER_assume( len <= MAX_HOSTNAME_LEN );
char * pcHostName = safeMalloc( len );
__CPROVER_assume( len > 0 ); /* prvProcessDNSCache strcmp */
__CPROVER_assume( pcHostName != NULL );
pcHostName[ len - 1 ] = NULL;
FreeRTOS_gethostbyname( pcHostName ); FreeRTOS_gethostbyname( pcHostName );
} }
}

View file

@ -1,29 +1,33 @@
{ {
"ENTRY": "DNSgetHostByName", "ENTRY": "DNSgetHostByName",
################################################################ ################################################################
# This configuration sets callback to 0. It also sets MAX_HOSTNAME_LEN to 10 and MAX_REQ_SIZE to 50 for performance issues. # This configuration sets callback to 0.
# It also sets MAX_HOSTNAME_LEN to 10 to bound strcmp.
# According to the specification MAX_HOST_NAME is upto 255. # According to the specification MAX_HOST_NAME is upto 255.
"callback": 0, "callback": 0,
"MAX_HOSTNAME_LEN": 10, "MAX_HOSTNAME_LEN": 10,
"MAX_REQ_SIZE": 50,
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1", "HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
"CBMCFLAGS": "CBMCFLAGS":
[ [
"--unwind 1", "--unwind 1",
"--unwindset prvProcessDNSCache.0:5,prvGetHostByName.0:{HOSTNAME_UNWIND},prvCreateDNSMessage.0:{HOSTNAME_UNWIND},prvCreateDNSMessage.1:{HOSTNAME_UNWIND},strlen.0:{HOSTNAME_UNWIND},__builtin___strcpy_chk.0:{HOSTNAME_UNWIND},strcmp.0:{HOSTNAME_UNWIND},strcpy.0:{HOSTNAME_UNWIND}", "--unwindset prvProcessDNSCache.0:5,prvGetHostByName.0:{HOSTNAME_UNWIND},prvCreateDNSMessage.0:{HOSTNAME_UNWIND},prvCreateDNSMessage.1:{HOSTNAME_UNWIND},strlen.0:{HOSTNAME_UNWIND},__builtin___strcpy_chk.0:{HOSTNAME_UNWIND},strcmp.0:{HOSTNAME_UNWIND},strcpy.0:{HOSTNAME_UNWIND}",
"--nondet-static" "--nondet-static"
], ],
"OBJS": "OBJS":
[ [
"$(ENTRY)_harness.goto", "$(ENTRY)_harness.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.goto", "$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/stubs/cbmc.goto",
"$(FREERTOS)/Source/tasks.goto" "$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/stubs/freertos_api.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.goto"
], ],
"DEF": "DEF":
[ [
"ipconfigDNS_USE_CALLBACKS={callback}", "ipconfigDNS_USE_CALLBACKS={callback}",
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}", "MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}"
"MAX_REQ_SIZE={MAX_REQ_SIZE}" ]
],
"OPT" : "-m32"
} }

View file

@ -0,0 +1,9 @@
{ "expected-missing-functions":
[
"vLoggingPrintf",
"xApplicationGetRandomNumber",
"xTaskGetTickCount"
],
"proof-name": "DNSgetHostByName",
"proof-root": "tools/cbmc/proofs"
}

View file

@ -1,81 +1,110 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "queue.h" #include "task.h"
#include "list.h" #include "semphr.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "FreeRTOS_DNS.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
/* This proof assumes the length of pcHostName is bounded by MAX_HOSTNAME_LEN and the size of UDPPayloadBuffer is bounded by #include "cbmc.h"
MAX_REQ_SIZE. This also abstracts the concurrency. */
void *safeMalloc(size_t xWantedSize) { /* This returns a NULL pointer if the requested size is 0. /****************************************************************
The implementation of malloc does not return a NULL pointer instead returns a pointer for which there is no memory allocation. */ * We abstract:
if(xWantedSize == 0) { *
return NULL; * All kernel task scheduling functions since we are doing
} * sequential verification and the sequential verification of these
uint8_t byte; * sequential primitives is done elsewhere.
return byte ? malloc(xWantedSize) : NULL; *
} * Many methods in the FreeRTOS TCP API in stubs/freertos_api.c
*
* prvParseDNSReply proved memory safe elsewhere
*
* prvCreateDNSMessage
*
* This proof assumes the length of pcHostName is bounded by
* MAX_HOSTNAME_LEN. We have to bound this length because we have to
* bound the iterations of strcmp.
****************************************************************/
/* Abstraction of pvPortMalloc which calls safemalloc internally. */ /****************************************************************
void *pvPortMalloc(size_t xWantedSize) { * Abstract prvParseDNSReply proved memory safe in ParseDNSReply.
return safeMalloc(xWantedSize); *
} * We stub out his function to fill the payload buffer with
* unconstrained data and return an unconstrained size.
*
* The function under test uses only the return value of this
* function.
****************************************************************/
/* Abstraction of FreeRTOS_GetUDPPayloadBuffer.
We always return MAX_REQ_SIZE bytes to keep the proof performant.
This is safe because:
- If the caller requested more bytes, then there is a risk that they
will write past the end of the returned buffer. This proof
therefore shows that the code is memory safe even if
xRequestedSizeBytes > MAX_REQ_SIZE.
- If the caller requested fewer bytes, then they will not be
iterating past the end of the buffer anyway.*/
void * FreeRTOS_GetUDPPayloadBuffer(size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks ) {
void *pvReturn = safeMalloc(MAX_REQ_SIZE);
return pvReturn;
}
/* Abstraction of FreeRTOS_socket. This abstraction allocates a memory of size Socket_t. */
Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol ){
Socket_t xCreatedSocket = safeMalloc(sizeof(Socket_t)); // replacing malloc with safeMalloc
return xCreatedSocket;
}
/* This function FreeRTOS_gethostbyname_a only uses the return value of prvParseDNSReply. Hence it returns an unconstrained uint32 value */
uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer, uint32_t prvParseDNSReply( uint8_t * pucUDPPayloadBuffer,
size_t xBufferLength, size_t xBufferLength,
BaseType_t xExpected ) {} BaseType_t xExpected )
{
__CPROVER_assert(pucUDPPayloadBuffer != NULL,
"Precondition: pucUDPPayloadBuffer != NULL");
/* Abstraction of xTaskResumeAll from task pool. This also abstracts the concurrency. */ __CPROVER_havoc_object( pucUDPPayloadBuffer );
BaseType_t xTaskResumeAll(void) { } return nondet_uint32();
}
/* The function func mimics the callback function.*/ /****************************************************************
void func(const char * pcHostName, void * pvSearchID, uint32_t ulIPAddress) { } * Abstract prvCreateDNSMessage
*
* This function writes a header, a hostname, and a constant amount of
* data into the payload buffer, and returns the amount of data
* written. This abstraction just fills the entire buffer with
* unconstrained data and returns and unconstrained length.
****************************************************************/
typedef struct xDNS_Callback { size_t prvCreateDNSMessage( uint8_t * pucUDPPayloadBuffer,
TickType_t xRemaningTime; /* Timeout in ms */ const char * pcHostName,
FOnDNSEvent pCallbackFunction; /* Function to be called when the address has been found or when a timeout has beeen reached */ TickType_t uxIdentifier )
TimeOut_t xTimeoutState; {
void *pvSearchID; __CPROVER_assert(pucUDPPayloadBuffer != NULL,
struct xLIST_ITEM xListItem; "Precondition: pucUDPPayloadBuffer != NULL");
char pcName[ 1 ]; __CPROVER_assert(pcHostName != NULL,
} DNSCallback_t; "Precondition: pcHostName != NULL");
__CPROVER_havoc_object( pucUDPPayloadBuffer );
return nondet_sizet();
}
/****************************************************************
* A stub for a function callback.
****************************************************************/
void func(const char * pcHostName, void * pvSearchID, uint32_t ulIPAddress)
{
}
/****************************************************************
* The proof for FreeRTOS_gethostbyname_a.
****************************************************************/
void harness() { void harness() {
size_t len;
__CPROVER_assume( len <= MAX_HOSTNAME_LEN );
char * pcHostName = safeMalloc( len );
__CPROVER_assume( len > 0 ); /* prvProcessDNSCache strcmp */
__CPROVER_assume( pcHostName != NULL );
pcHostName[ len - 1 ] = NULL;
FOnDNSEvent pCallback = func; FOnDNSEvent pCallback = func;
TickType_t xTimeout; TickType_t xTimeout;
void *pvSearchID; void *pvSearchID;
size_t len;
__CPROVER_assume(len >= 0 && len <= MAX_HOSTNAME_LEN);
char *pcHostName = safeMalloc(len); // replacing malloc with safeMalloc
if (len && pcHostName) {
pcHostName[len-1] = NULL;
}
if (pcHostName) { // Guarding against NULL pointer
FreeRTOS_gethostbyname_a(pcHostName, pCallback, pvSearchID, xTimeout); FreeRTOS_gethostbyname_a(pcHostName, pCallback, pvSearchID, xTimeout);
} }
}

View file

@ -5,7 +5,6 @@
# According to the specification MAX_HOST_NAME is upto 255. # According to the specification MAX_HOST_NAME is upto 255.
"callback": 1, "callback": 1,
"MAX_HOSTNAME_LEN": 10, "MAX_HOSTNAME_LEN": 10,
"MAX_REQ_SIZE": 50,
"HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1", "HOSTNAME_UNWIND": "__eval {MAX_HOSTNAME_LEN} + 1",
"CBMCFLAGS": "CBMCFLAGS":
[ [
@ -16,14 +15,16 @@
"OBJS": "OBJS":
[ [
"$(ENTRY)_harness.goto", "$(ENTRY)_harness.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/stubs/cbmc.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/stubs/freertos_api.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.goto", "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.goto",
"$(FREERTOS)/Source/tasks.goto" "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.goto"
], ],
"DEF": "DEF":
[ [
"ipconfigDNS_USE_CALLBACKS={callback}", "ipconfigDNS_USE_CALLBACKS={callback}",
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}", "MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}",
"MAX_REQ_SIZE={MAX_REQ_SIZE}" # This value is defined only when ipconfigUSE_DNS_CACHE==1
], "ipconfigDNS_CACHE_NAME_LENGTH=254"
"OPT" : "-m32" ]
} }

View file

@ -0,0 +1,13 @@
{ "expected-missing-functions":
[
"vLoggingPrintf",
"xApplicationGetRandomNumber",
"vListInsertEnd",
"vTaskSetTimeOutState",
"vTaskSuspendAll",
"xTaskGetTickCount",
"xTaskResumeAll"
],
"proof-name": "DNSgetHostByName_a",
"proof-root": "tools/cbmc/proofs"
}

View file

@ -22,7 +22,8 @@
"DEF": "DEF":
[ [
"ipconfigDNS_USE_CALLBACKS={callback}", "ipconfigDNS_USE_CALLBACKS={callback}",
"MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}" "MAX_HOSTNAME_LEN={MAX_HOSTNAME_LEN}",
], # This value is defined only when ipconfigUSE_DNS_CACHE==1
"OPT" : "-m32" "ipconfigDNS_CACHE_NAME_LENGTH=254"
]
} }

View file

@ -1,4 +1,4 @@
default: cbmc default: report
# ____________________________________________________________________ # ____________________________________________________________________
# CBMC binaries # CBMC binaries
@ -114,14 +114,13 @@ goto:
$(MAKE) $(ENTRY).goto $(MAKE) $(ENTRY).goto
cbmc.txt: $(ENTRY).goto cbmc.txt: $(ENTRY).goto
cbmc $(CBMCFLAGS) --unwinding-assertions --trace @RULE_INPUT@ > $@ 2>&1 - cbmc $(CBMCFLAGS) --unwinding-assertions --trace @RULE_INPUT@ > $@ 2>&1
property.xml: $(ENTRY).goto property.xml: $(ENTRY).goto
cbmc $(CBMCFLAGS) --unwinding-assertions --show-properties --xml-ui @RULE_INPUT@ \ cbmc $(CBMCFLAGS) --unwinding-assertions --show-properties --xml-ui @RULE_INPUT@ > $@ 2>&1
2>&1 > $@
coverage.xml: $(ENTRY).goto coverage.xml: $(ENTRY).goto
cbmc $(CBMCFLAGS) --cover location --xml-ui @RULE_INPUT@ 2>&1 > $@ cbmc $(CBMCFLAGS) --cover location --xml-ui @RULE_INPUT@ > $@ 2>&1
cbmc: cbmc.txt cbmc: cbmc.txt
@ -148,7 +147,7 @@ report: cbmc.txt property.xml coverage.xml
clean: clean:
@RM@ $(OBJS) $(ENTRY).goto @RM@ $(OBJS) $(ENTRY).goto
@RM@ $(ENTRY)[0-9].goto $(ENTRY)[0-9].txt @RM@ $(ENTRY)[0-9].goto $(ENTRY)[0-9].txt
@RM@ cbmc.txt property.xml coverage.xml TAGS @RM@ cbmc.txt property.xml coverage.xml TAGS TAGS-*
@RM@ *~ \#* @RM@ *~ \#*
@RM@ queue_datastructure.h @RM@ queue_datastructure.h

View file

@ -3,13 +3,17 @@
"PROOFS": [ "." ], "PROOFS": [ "." ],
"DEF ": [ "DEF ": [
"_DEBUG",
"__free_rtos__", "WIN32",
"_CONSOLE",
"_WIN32_WINNT=0x0500",
"WINVER=0x400", "WINVER=0x400",
"_CONSOLE",
"_CRT_SECURE_NO_WARNINGS", "_CRT_SECURE_NO_WARNINGS",
"_DEBUG",
"_WIN32_WINNT=0x0500",
"__PRETTY_FUNCTION__=__FUNCTION__", "__PRETTY_FUNCTION__=__FUNCTION__",
"__free_rtos__",
"CBMC",
"'configASSERT(X)=__CPROVER_assert(X,\"Assertion Error\")'", "'configASSERT(X)=__CPROVER_assert(X,\"Assertion Error\")'",
"'configPRECONDITION(X)=__CPROVER_assume(X)'" "'configPRECONDITION(X)=__CPROVER_assume(X)'"
], ],
@ -18,12 +22,13 @@
"$(FREERTOS)/Source/include", "$(FREERTOS)/Source/include",
"$(FREERTOS)/Source/portable/MSVC-MingW", "$(FREERTOS)/Source/portable/MSVC-MingW",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include", "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC", "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC",
"$(FREERTOS)/../FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap", "$(FREERTOS)/../FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap",
"$(FREERTOS)/Demo/Common/include", "$(FREERTOS)/Demo/Common/include",
"$(FREERTOS)/Test/CBMC/include", "$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/include",
"$(FREERTOS)/Test/CBMC/patches" "$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/patches",
"$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/windows",
"$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/windows2"
], ],
"CBMCFLAGS ": [ "CBMCFLAGS ": [

View file

@ -11,6 +11,13 @@
# Reasonable values are size > 12 = sizeof(xDNSMessage) # Reasonable values are size > 12 = sizeof(xDNSMessage)
"NETWORK_BUFFER_SIZE": 40, "NETWORK_BUFFER_SIZE": 40,
################################################################
# This is the size of the buffer into which the name is copied.
# Set to any positive value.
# In the source, NAME_SIZE=254 and NETWORK_BUFFER_SIZE >> NAME_SIZE
# In the proof, NAME_SIZE >= 4 required for good coverage.
"NAME_SIZE": "10",
################################################################ ################################################################
# Loop prvParseDNSReply.0: # Loop prvParseDNSReply.0:
# file lib/FreeRTOS-Plus-TCP/source/FreeRTOS_DNS.c line 915 # file lib/FreeRTOS-Plus-TCP/source/FreeRTOS_DNS.c line 915
@ -55,6 +62,7 @@
"DEF": "DEF":
[ [
"NETWORK_BUFFER_SIZE={NETWORK_BUFFER_SIZE}" "NETWORK_BUFFER_SIZE={NETWORK_BUFFER_SIZE}",
"NAME_SIZE={NAME_SIZE}"
] ]
} }

View file

@ -20,146 +20,111 @@
#include "cbmc.h" #include "cbmc.h"
/****************************************************************
* Signature of function under test
****************************************************************/
uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer, uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
size_t xBufferLength, size_t uxBufferLength,
TickType_t xIdentifier); BaseType_t xExpected );
// Used in specification and abstraction of prvReadNameField, prvSkipNameField /****************************************************************
// Given unconstrained values in harness * Abstraction of prvReadNameField proved in ReadNameField
uint8_t *buffer; ****************************************************************/
size_t buffer_size;
// Abstraction of prvReadNameField size_t prvReadNameField( const uint8_t *pucByte,
uint8_t *prvReadNameField(uint8_t *pucByte, size_t uxRemainingBytes,
size_t xSourceLen,
char *pcName, char *pcName,
size_t xDestLen){ size_t uxDestLen )
{
__CPROVER_assert(NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE");
__CPROVER_assert(NAME_SIZE < CBMC_MAX_OBJECT_SIZE,
"NAME_SIZE < CBMC_MAX_OBJECT_SIZE");
__CPROVER_assert(NAME_SIZE >= 4,
"NAME_SIZE >= 4 required for good coverage.");
// Preconditions
// pointers are valid pointers into buffers /* Preconditions */
__CPROVER_assert(xSourceLen == 0 || __CPROVER_assert(uxRemainingBytes < CBMC_MAX_OBJECT_SIZE,
(buffer <= pucByte && pucByte < buffer + buffer_size), "ReadNameField: uxRemainingBytes < CBMC_MAX_OBJECT_SIZE)");
"pucByte valid pointer"); __CPROVER_assert(uxDestLen < CBMC_MAX_OBJECT_SIZE,
// __CPROVER_assume(name <= pcName && pcName < name + name_size); "ReadNameField: uxDestLen < CBMC_MAX_OBJECT_SIZE)");
(void) *(pcName); // can only test for valid pointer
// lengths are valid values for space remaining in the buffers __CPROVER_assert(uxRemainingBytes <= NETWORK_BUFFER_SIZE,
__CPROVER_assert(pucByte + xSourceLen <= buffer + buffer_size, "ReadNameField: uxRemainingBytes <= NETWORK_BUFFER_SIZE)");
"xSourceLen valid length");
// __CPROVER_assume(pcName + xDestLen <= name + name_size);
(void) *(pcName + (xDestLen-1)); // can only test for valid pointer
// CBMC loop unwinding: bounds depend on xSourceLen and xDestLen /* This precondition in the function contract for prvReadNameField
__CPROVER_assert(xSourceLen <= NETWORK_BUFFER_SIZE, * fails because prvCheckOptions called prvReadNameField with the
"xSourceLen loop unwinding"); * constant value 254.
// __CPROVER_assume(xDestLen <= NAME_SIZE); __CPROVER_assert(uxDestLen <= NAME_SIZE,
"ReadNameField: uxDestLen <= NAME_SIZE)");
*/
// Buffer overflow from integer overflow in expression len < xDestLen-1 __CPROVER_assert( pucByte != NULL ,
// xDestLen == 254 in code "ReadNameField: pucByte != NULL )");
__CPROVER_assert(xDestLen > 0, "xDestLen nonzero"); __CPROVER_assert( pcName != NULL ,
"ReadNameField: pcName != NULL )");
SAVE_OLDVAL(pucByte, uint8_t *); __CPROVER_assert(uxDestLen > 0,
SAVE_OLDVAL(pcName, char *); "ReadNameField: uxDestLen > 0)");
SAVE_OLDVAL(xSourceLen, size_t);
SAVE_OLDVAL(xDestLen, size_t);
// Function body /* Return value */
char bit; size_t index;
size_t offset;
uint8_t *rc = bit ? pucByte + offset : 0;
__CPROVER_assume(offset <= NETWORK_BUFFER_SIZE);
// Postconditions /* Postconditions */
__CPROVER_assume((rc == 0) || __CPROVER_assume( index <= uxDestLen+1 && index <= uxRemainingBytes );
(rc - OLDVAL(pucByte) >= 1 &&
rc - OLDVAL(pucByte) <= OLDVAL(xSourceLen) &&
rc - OLDVAL(pucByte) <= OLDVAL(xDestLen)+2 &&
pucByte == OLDVAL(pucByte) &&
pcName == OLDVAL(pcName) &&
buffer <= rc && rc <= buffer + buffer_size));
return rc; return index;
} }
// Abstraction of prvSkipNameField /****************************************************************
uint8_t *prvSkipNameField( uint8_t *pucByte, size_t xSourceLen ){ * Abstraction of prvSkipNameField proved in SkipNameField
****************************************************************/
// Preconditions size_t prvSkipNameField( const uint8_t *pucByte, size_t uxLength )
{
// pointer is valid pointer into buffer __CPROVER_assert(NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
__CPROVER_assert(xSourceLen == 0 || "NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE");
(buffer <= pucByte && pucByte < buffer + buffer_size),
"pucByte valid pointer");
// length is valid value for space remaining in the buffer
__CPROVER_assert(pucByte + xSourceLen <= buffer + buffer_size,
"xSourceLen valid length");
// CBMC loop unwinding: bound depend on xSourceLen /* Preconditions */
__CPROVER_assert(xSourceLen <= NETWORK_BUFFER_SIZE, __CPROVER_assert(uxLength < CBMC_MAX_OBJECT_SIZE,
"xSourceLen loop unwinding"); "SkipNameField: uxLength < CBMC_MAX_OBJECT_SIZE)");
__CPROVER_assert(uxLength <= NETWORK_BUFFER_SIZE,
"SkipNameField: uxLength <= NETWORK_BUFFER_SIZE)");
__CPROVER_assert(pucByte != NULL,
"SkipNameField: pucByte != NULL)");
SAVE_OLDVAL(pucByte, uint8_t *); /* Return value */
SAVE_OLDVAL(xSourceLen, size_t); size_t index;
// Function body /* Postconditions */
char bit; __CPROVER_assume(index <= uxLength);
size_t offset;
uint8_t *rc = bit ? pucByte + offset : 0;
__CPROVER_assume(offset <= NETWORK_BUFFER_SIZE);
// Postconditions
__CPROVER_assume((rc == 0) ||
(rc - OLDVAL(pucByte) >= 1 &&
rc - OLDVAL(pucByte) <= OLDVAL(xSourceLen) &&
pucByte == OLDVAL(pucByte) &&
buffer <= rc && rc <= buffer + buffer_size));
return rc;
return index;
} }
/****************************************************************
* Proof of prvParseDNSReply
****************************************************************/
void harness() { void harness() {
// Choose arbitrary buffer of size at most NETWORK_BUFFER_SIZE size_t uxBufferLength;
uint8_t my_buffer[NETWORK_BUFFER_SIZE]; BaseType_t xExpected;
size_t my_buffer_offset; uint8_t *pucUDPPayloadBuffer = malloc(uxBufferLength);
buffer = my_buffer + my_buffer_offset;
buffer_size = NETWORK_BUFFER_SIZE - my_buffer_offset;
__CPROVER_assume(my_buffer_offset <= NETWORK_BUFFER_SIZE);
__CPROVER_havoc_object(my_buffer); __CPROVER_assert(NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
"NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE");
// Choose arbitrary pointer into the buffer __CPROVER_assume(uxBufferLength < CBMC_MAX_OBJECT_SIZE);
size_t buffer_offset; __CPROVER_assume(uxBufferLength <= NETWORK_BUFFER_SIZE);
uint8_t *pucUDPPayloadBuffer = buffer + buffer_offset; __CPROVER_assume(pucUDPPayloadBuffer != NULL);
// Choose arbitrary value for space remaining in the buffer uint32_t index = prvParseDNSReply( pucUDPPayloadBuffer,
size_t xBufferLength; uxBufferLength,
xExpected );
// Choose arbitrary identifier
TickType_t xIdentifier;
////////////////////////////////////////////////////////////////
// Specification and proof of prvReadNameField
// CBMC pointer model (this is obviously true)
__CPROVER_assume(NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE);
// Preconditions
// pointer is valid pointer into buffer
__CPROVER_assume(buffer <= pucUDPPayloadBuffer &&
pucUDPPayloadBuffer < buffer + buffer_size);
// length is valid value for space remaining in the buffer
__CPROVER_assume(pucUDPPayloadBuffer + xBufferLength
<= buffer + buffer_size);
// CBMC loop unwinding: bounds depend on xBufferLength
__CPROVER_assume(xBufferLength <= NETWORK_BUFFER_SIZE);
prvParseDNSReply(pucUDPPayloadBuffer, xBufferLength, xIdentifier);
} }

View file

@ -7,22 +7,24 @@
"ENTRY": "ProcessDHCPReplies", "ENTRY": "ProcessDHCPReplies",
################################################################ ################################################################
# Buffer size # Buffer header: sizeof(DHCPMessage_t) = 241
# Reasonable sizes are BUFFER_SIZE > 241 = sizeof(DHCHMessage_t)) # Buffer header: sizeof(DHCPMessage_IPv4_t) = 240
# Sizes smaller than this causes CBMC to fail in simplify_byte_extract "BUFFER_HEADER": 240,
"BUFFER_SIZE": 300,
################################################################ ################################################################
# Buffer header: sizeof(DHCHMessage_t) = 241 # Buffer size
"BUFFER_HEADER": 241, # Reasonable sizes are BUFFER_SIZE > BUFFER_HEADER
# Sizes smaller than this causes CBMC to fail in simplify_byte_extract
"BUFFER_SIZE": 252,
################################################################ ################################################################
# Buffer payload # Buffer payload
"BUFFER_PAYLOAD": "__eval 1 if {BUFFER_SIZE} <= {BUFFER_HEADER} else {BUFFER_SIZE} - {BUFFER_HEADER} + 2", "BUFFER_PAYLOAD": "__eval 1 if {BUFFER_SIZE} <= {BUFFER_HEADER} else {BUFFER_SIZE} - {BUFFER_HEADER} + 1",
################################################################ ################################################################
"CBMCFLAGS": [ "CBMCFLAGS": [
# "--nondet-static",
"--unwind 1", "--unwind 1",
"--unwindset memcmp.0:7,prvProcessDHCPReplies.0:{BUFFER_PAYLOAD}" "--unwindset memcmp.0:7,prvProcessDHCPReplies.0:{BUFFER_PAYLOAD}"
], ],
@ -30,6 +32,8 @@
"OBJS": "OBJS":
[ [
"$(ENTRY)_harness.goto", "$(ENTRY)_harness.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/stubs/cbmc.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/stubs/freertos_api.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.goto", "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.goto",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.goto", "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.goto",
"$(FREERTOS)/Source/event_groups.goto", "$(FREERTOS)/Source/event_groups.goto",
@ -38,6 +42,7 @@
"DEF": "DEF":
[ [
"BUFFER_SIZE={BUFFER_SIZE}" "CBMC_DHCPMESSAGE_HEADER_SIZE={BUFFER_HEADER}",
"CBMC_FREERTOS_RECVFROM_BUFFER_BOUND={BUFFER_SIZE}"
] ]
} }

View file

@ -1,11 +1,9 @@
/* Standard includes. */ /* Standard includes. */
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "queue.h"
#include "semphr.h" #include "semphr.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
@ -13,52 +11,27 @@
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h" #include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_TCP_IP.h"
#include "FreeRTOS_DHCP.h" #include "FreeRTOS_DHCP.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#include "FreeRTOS_ARP.h" #include "FreeRTOS_ARP.h"
#include "FreeRTOS_TCP_WIN.h"
// Used to model FreeRTOS_recvfrom returning an arbitrary buffer
char read_buffer[BUFFER_SIZE]; /****************************************************************
* Signature of function under test
****************************************************************/
BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType ); BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
// Stub /****************************************************************
int32_t FreeRTOS_recvfrom( * The proof for FreeRTOS_gethostbyname.
Socket_t xSocket, void *pvBuffer, size_t xBufferLength, ****************************************************************/
BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress,
socklen_t *pxSourceAddressLength ) void harness()
{ {
__CPROVER_assert(xFlags & FREERTOS_ZERO_COPY, "I can only do ZERO_COPY"); /* Omitting model of an unconstrained xDHCPData because xDHCPData is */
/* the source of uninitialized data only on line 647 to set a */
// Choose buffer size /* transaction id is an outgoing message */
size_t offset;
size_t buffer_size = BUFFER_SIZE - offset;
char *buffer = read_buffer + offset;
__CPROVER_assume(offset <= BUFFER_SIZE);
// Choose buffer contents
// __CPROVER_havoc_object may not interact well with simplifier
char temporary[BUFFER_SIZE];
memcpy(read_buffer, temporary, BUFFER_SIZE);
*((char **)pvBuffer) = buffer;
return buffer_size;
}
// Stub
void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer )
{
// no-op
}
void harness() {
// Omitting model of an unconstrained xDHCPData because xDHCPData is
// the source of uninitialized data only on line 647 to set a
// transaction id is an outgoing message
BaseType_t xExpectedMessageType; BaseType_t xExpectedMessageType;
prvProcessDHCPReplies( xExpectedMessageType ); prvProcessDHCPReplies( xExpectedMessageType );
} }

View file

@ -1,6 +1,10 @@
{ {
"ENTRY": "ReadNameField", "ENTRY": "ReadNameField",
################################################################
#Enable DNS callbacks or else ReadNameField is not defined
"callbacks": "1",
################################################################ ################################################################
# This is the network buffer size. Set to any positive value. # This is the network buffer size. Set to any positive value.
"NETWORK_BUFFER_SIZE" : "10", "NETWORK_BUFFER_SIZE" : "10",
@ -9,19 +13,18 @@
# This is the size of the buffer into which the name is copied. # This is the size of the buffer into which the name is copied.
# Set to any positive value. # Set to any positive value.
# In the source, NAME_SIZE=254 and NETWORK_BUFFER_SIZE >> NAME_SIZE # In the source, NAME_SIZE=254 and NETWORK_BUFFER_SIZE >> NAME_SIZE
"NAME_SIZE": "10", # In the proof, NAME_SIZE >= 4 required for good coverage.
"NAME_SIZE": "6",
################################################################ ################################################################
# Loop prvReadNameField.0: # Loop prvReadNameField.0:
# "file lib/FreeRTOS-Plus-TCP/source/FreeRTOS_DNS.c line 725
# should be min of buffer size and name size # should be min of buffer size and name size
# but loop must be unwound at least once, so max of this and 1+1 # but loop must be unwound at least once, so max of this and 1+1
"READLOOP0": "prvReadNameField.0", "READLOOP0": "prvReadNameField.0",
"READLOOP0_UNWIND": "__eval max(2, min({NETWORK_BUFFER_SIZE}, {NAME_SIZE}))", "READLOOP0_UNWIND": "__eval max(2, min({NETWORK_BUFFER_SIZE}, {NAME_SIZE}+1))",
################################################################ ################################################################
# Loop prvReadNameField.1: # Loop prvReadNameField.1:
# "file lib/FreeRTOS-Plus-TCP/source/FreeRTOS_DNS.c line 715
# should be min of buffer size and name size # should be min of buffer size and name size
# but loop must be unwound at least twice, so max of this and 2+1 # but loop must be unwound at least twice, so max of this and 2+1
"READLOOP1": "prvReadNameField.1", "READLOOP1": "prvReadNameField.1",
@ -44,6 +47,8 @@
"DEF": "DEF":
[ [
"NETWORK_BUFFER_SIZE={NETWORK_BUFFER_SIZE}", "NETWORK_BUFFER_SIZE={NETWORK_BUFFER_SIZE}",
"NAME_SIZE={NAME_SIZE}" "NAME_SIZE={NAME_SIZE}",
"ipconfigDNS_USE_CALLBACKS={callbacks}",
"ipconfigDNS_CACHE_NAME_LENGTH=254"
] ]
} }

View file

@ -20,80 +20,83 @@
#include "cbmc.h" #include "cbmc.h"
uint8_t *prvReadNameField( uint8_t *pucByte, size_t xSourceLen, char *pcName, size_t xDestLen ); /****************************************************************
* Signature of function under test
****************************************************************/
size_t prvReadNameField( const uint8_t *pucByte,
size_t uxRemainingBytes,
char *pcName,
size_t uxDestLen );
/****************************************************************
* The function under test is not defined in all configurations
****************************************************************/
#if ( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
/* prvReadNameField is defined in this configuration */
#else
/* prvReadNameField is not defined in this configuration, stub it. */
size_t prvReadNameField( const uint8_t *pucByte,
size_t uxRemainingBytes,
char *pcName,
size_t uxDestLen )
{
return 0;
}
#endif
/****************************************************************
* Proof of prvReadNameField function contract
****************************************************************/
void harness() { void harness() {
// Choose arbitrary buffer of size at most NETWORK_BUFFER_SIZE __CPROVER_assert(NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
uint8_t my_buffer[NETWORK_BUFFER_SIZE]; "NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE");
size_t my_buffer_offset; __CPROVER_assert(NAME_SIZE < CBMC_MAX_OBJECT_SIZE,
uint8_t *buffer = my_buffer + my_buffer_offset; "NAME_SIZE < CBMC_MAX_OBJECT_SIZE");
size_t buffer_size = NETWORK_BUFFER_SIZE - my_buffer_offset;
__CPROVER_assume(my_buffer_offset <= NETWORK_BUFFER_SIZE);
// Choose arbitrary name of size at most NAME_SIZE __CPROVER_assert(NAME_SIZE >= 4,
char my_name[NAME_SIZE]; "NAME_SIZE >= 4 required for good coverage.");
size_t my_name_offset;
char *name = my_name + my_name_offset;
size_t name_size = NAME_SIZE - my_name_offset;
__CPROVER_assume(my_name_offset <= NAME_SIZE);
// Choose arbitrary pointers into buffer and name
size_t buffer_offset;
size_t name_offset;
uint8_t *pucByte = buffer + buffer_offset;
char *pcName = name + name_offset;
__CPROVER_assume(buffer_offset <= NETWORK_BUFFER_SIZE);
__CPROVER_assume(name_offset <= NAME_SIZE);
// Choose arbitrary values for space remaining in the buffers size_t uxRemainingBytes;
size_t xSourceLen; size_t uxDestLen;
size_t xDestLen;
//////////////////////////////////////////////////////////////// uint8_t *pucByte = malloc(uxRemainingBytes);
// Specification and proof of prvReadNameField char *pcName = malloc(uxDestLen);
// CBMC pointer model (this is obviously true) /* Preconditions */
__CPROVER_assume(NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE);
__CPROVER_assume(NAME_SIZE < CBMC_MAX_OBJECT_SIZE);
// Preconditions __CPROVER_assume(uxRemainingBytes < CBMC_MAX_OBJECT_SIZE);
__CPROVER_assume(uxDestLen < CBMC_MAX_OBJECT_SIZE);
// pointers are valid pointers into buffers __CPROVER_assume(uxRemainingBytes <= NETWORK_BUFFER_SIZE);
__CPROVER_assume(xSourceLen == 0 || __CPROVER_assume(uxDestLen <= NAME_SIZE);
(buffer <= pucByte && pucByte < buffer + buffer_size));
__CPROVER_assume(name <= pcName && pcName < name + name_size);
// lengths are valid values for space remaining in the buffers __CPROVER_assume( pucByte != NULL );
__CPROVER_assume(pucByte + xSourceLen <= buffer + buffer_size); __CPROVER_assume( pcName != NULL );
__CPROVER_assume(pcName + xDestLen <= name + name_size);
// CBMC loop unwinding: bounds depend on xSourceLen and xDestLen /* Avoid overflow on uxSourceLen - 1U with uxSourceLen == uxRemainingBytes */
__CPROVER_assume(xSourceLen <= NETWORK_BUFFER_SIZE); //__CPROVER_assume(uxRemainingBytes > 0);
__CPROVER_assume(xDestLen <= NAME_SIZE);
// Buffer overflow via integer overflow in comparison xNameLen < xDestLen - 1 /* Avoid overflow on uxDestLen - 1U */
// In actual code, xDestLen == 254 __CPROVER_assume(uxDestLen > 0);
__CPROVER_assume(xDestLen > 0);
// Save values before function call size_t index = prvReadNameField( pucByte,
SAVE_OLDVAL(pucByte, uint8_t *); uxRemainingBytes,
SAVE_OLDVAL(pcName, char *); pcName,
SAVE_OLDVAL(xSourceLen, size_t); uxDestLen );
SAVE_OLDVAL(xDestLen, size_t);
// function return value is either NULL or the updated value of pucByte /* Postconditions */
uint8_t *rc = prvReadNameField(pucByte, xSourceLen, pcName, xDestLen);
// Postconditions __CPROVER_assert( index <= uxDestLen+1 && index <= uxRemainingBytes,
"prvReadNamefield: index <= uxDestLen+1");
// pucByte can be advanced one position past the end of the buffer
__CPROVER_assert((rc == 0) ||
(rc - OLDVAL(pucByte) >= 1 &&
rc - OLDVAL(pucByte) <= OLDVAL(xSourceLen) &&
rc - OLDVAL(pucByte) <= OLDVAL(xDestLen)+2 &&
pucByte == OLDVAL(pucByte) &&
pcName == OLDVAL(pcName) &&
buffer <= rc && rc <= buffer + buffer_size),
"updated pucByte");
} }

View file

@ -20,56 +20,35 @@
#include "cbmc.h" #include "cbmc.h"
uint8_t *prvSkipNameField( uint8_t *pucByte, size_t xSourceLen ); /****************************************************************
* Signature of function under test
****************************************************************/
size_t prvSkipNameField( const uint8_t *pucByte, size_t uxLength );
/****************************************************************
* Proof of prvSkipNameField function contract
****************************************************************/
void harness() { void harness() {
// Choose arbitrary buffer of size at most NETWORK_BUFFER_SIZE __CPROVER_assert(NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE,
uint8_t my_buffer[NETWORK_BUFFER_SIZE]; "NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE");
size_t my_buffer_offset;
uint8_t *buffer = my_buffer + my_buffer_offset;
size_t buffer_size = NETWORK_BUFFER_SIZE - my_buffer_offset;
__CPROVER_assume(my_buffer_offset <= NETWORK_BUFFER_SIZE);
// Choose arbitrary pointer into buffer size_t uxLength;
size_t buffer_offset; uint8_t *pucByte = malloc( uxLength );
uint8_t *pucByte = buffer + buffer_offset;
__CPROVER_assume(buffer_offset <= NETWORK_BUFFER_SIZE);
// Choose arbitrary value for space remaining in the buffer /* Preconditions */
size_t xSourceLen;
//////////////////////////////////////////////////////////////// __CPROVER_assume(uxLength < CBMC_MAX_OBJECT_SIZE);
// Specification and proof of prvSkipNameField __CPROVER_assume(uxLength <= NETWORK_BUFFER_SIZE);
__CPROVER_assume(pucByte != NULL);
// CBMC pointer model (this is obviously true) size_t index = prvSkipNameField( pucByte, uxLength );
__CPROVER_assume(NETWORK_BUFFER_SIZE < CBMC_MAX_OBJECT_SIZE);
// Preconditions /* Postconditions */
// pointer is valid pointer into buffer __CPROVER_assert(index <= uxLength,
__CPROVER_assume(xSourceLen == 0 || "prvSkipNameField: index <= uxLength");
(buffer <= pucByte && pucByte < buffer + buffer_size));
// length is valid value for space remaining in the buffer
__CPROVER_assume(pucByte + xSourceLen <= buffer + buffer_size);
// CBMC loop unwinding: bound depend on xSourceLen
__CPROVER_assume(xSourceLen <= NETWORK_BUFFER_SIZE);
SAVE_OLDVAL(pucByte, uint8_t *);
SAVE_OLDVAL(xSourceLen, size_t);
// function return value is either NULL or the updated value of pucByte
uint8_t *rc = prvSkipNameField(pucByte, xSourceLen);
// Postconditions
// pucByte can be advanced one position past the end of the buffer
__CPROVER_assert((rc == 0) ||
(rc - OLDVAL(pucByte) >= 1 &&
rc - OLDVAL(pucByte) <= OLDVAL(xSourceLen) &&
pucByte == OLDVAL(pucByte) &&
buffer <= rc && rc <= buffer + buffer_size),
"updated pucByte");
} }

View file

@ -0,0 +1,12 @@
#include "cbmc.h"
/****************************************************************
* Model a malloc that can fail (CBMC malloc does not fail) and
* check that CBMC can model an object of the requested size.
****************************************************************/
void * safeMalloc( size_t size )
{
__CPROVER_assert( size < CBMC_MAX_OBJECT_SIZE, "safeMalloc size too big" );
return nondet_bool() ? NULL : malloc( size );
}

View file

@ -0,0 +1,379 @@
/* 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_UDP_IP.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h"
#include "cbmc.h"
/****************************************************************
* This is a collection of abstractions of methods in the FreeRTOS TCP
* API. The abstractions simply perform minimal validation of
* function arguments, and return unconstrained values of the
* appropriate type.
****************************************************************/
/****************************************************************
* Abstract FreeRTOS_socket.
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/socket.html
*
* We stub out this function to do nothing but allocate space for a
* socket containing unconstrained data or return an error.
****************************************************************/
Socket_t FreeRTOS_socket( BaseType_t xDomain,
BaseType_t xType,
BaseType_t xProtocol )
{
return nondet_bool() ?
FREERTOS_INVALID_SOCKET : malloc( sizeof( Socket_t ) );
}
/****************************************************************
* Abstract FreeRTOS_setsockopt.
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/setsockopt.html
****************************************************************/
BaseType_t FreeRTOS_setsockopt( Socket_t xSocket,
int32_t lLevel,
int32_t lOptionName,
const void * pvOptionValue,
size_t uxOptionLength )
{
__CPROVER_assert( xSocket != NULL,
"FreeRTOS precondition: xSocket != NULL" );
__CPROVER_assert( pvOptionValue != NULL,
"FreeRTOS precondition: pvOptionValue != NULL" );
return nondet_BaseType();
}
/****************************************************************
* Abstract FreeRTOS_closesocket.
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/close.html
****************************************************************/
BaseType_t FreeRTOS_closesocket( Socket_t xSocket )
{
__CPROVER_assert( xSocket != NULL,
"FreeRTOS precondition: xSocket != NULL" );
return nondet_BaseType();
}
/****************************************************************
* Abstract FreeRTOS_bind.
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/bind.html
****************************************************************/
BaseType_t FreeRTOS_bind( Socket_t xSocket,
struct freertos_sockaddr * pxAddress,
socklen_t xAddressLength )
{
__CPROVER_assert( xSocket != NULL,
"FreeRTOS precondition: xSocket != NULL" );
__CPROVER_assert( pxAddress != NULL,
"FreeRTOS precondition: pxAddress != NULL" );
return nondet_BaseType();
}
/****************************************************************
* Abstract FreeRTOS_inet_addr.
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/inet_addr.html
****************************************************************/
uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )
{
__CPROVER_assert( pcIPAddress != NULL,
"FreeRTOS precondition: pcIPAddress != NULL" );
return nondet_uint32();
}
/****************************************************************
* Abstract FreeRTOS_recvfrom.
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/recvfrom.html
*
* We stub out this function to do nothing but allocate a buffer of
* unconstrained size containing unconstrained data and return the
* size (or return the size 0 if the allocation fails).
****************************************************************/
int32_t FreeRTOS_recvfrom( Socket_t xSocket,
void * pvBuffer,
size_t uxBufferLength,
BaseType_t xFlags,
struct freertos_sockaddr * pxSourceAddress,
socklen_t * pxSourceAddressLength )
{
/****************************************************************
* "If the zero copy calling semantics are used (the ulFlasg
* parameter does not have the FREERTOS_ZERO_COPY bit set) then
* pvBuffer does not point to a buffer and xBufferLength is not
* used." This is from the documentation.
****************************************************************/
__CPROVER_assert( xFlags & FREERTOS_ZERO_COPY, "I can only do ZERO_COPY" );
__CPROVER_assert( pvBuffer != NULL,
"FreeRTOS precondition: pvBuffer != NULL" );
/****************************************************************
* TODO: We need to check this out.
*
* The code calls recvfrom with these parameters NULL, it is not
* clear from the documentation that this is allowed.
****************************************************************/
#if 0
__CPROVER_assert( pxSourceAddress != NULL,
"FreeRTOS precondition: pxSourceAddress != NULL" );
__CPROVER_assert( pxSourceAddressLength != NULL,
"FreeRTOS precondition: pxSourceAddress != NULL" );
#endif
size_t payload_size;
__CPROVER_assume( payload_size + sizeof( UDPPacket_t )
< CBMC_MAX_OBJECT_SIZE );
/****************************************************************
* TODO: We need to make this lower bound explicit in the Makefile.json
*
* DNSMessage_t is a typedef in FreeRTOS_DNS.c
* sizeof(DNSMessage_t) = 6 * sizeof(uint16_t)
****************************************************************/
__CPROVER_assume( payload_size >= 6 * sizeof( uint16_t ) );
#ifdef CBMC_FREERTOS_RECVFROM_BUFFER_BOUND
__CPROVER_assume( payload_size <= CBMC_FREERTOS_RECVFROM_BUFFER_BOUND );
#endif
uint32_t buffer_size = payload_size + sizeof( UDPPacket_t );
uint8_t *buffer = safeMalloc( buffer_size );
if ( buffer == NULL ) {
buffer_size = 0;
}
else
{
buffer = buffer + sizeof( UDPPacket_t );
buffer_size = buffer_size - sizeof( UDPPacket_t );
}
*( ( uint8_t ** ) pvBuffer ) = buffer;
return buffer_size;
}
/****************************************************************
* Abstract FreeRTOS_recvfrom.
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/sendto.html
****************************************************************/
int32_t FreeRTOS_sendto( Socket_t xSocket,
const void * pvBuffer,
size_t uxTotalDataLength,
BaseType_t xFlags,
const struct freertos_sockaddr * pxDestinationAddress,
socklen_t xDestinationAddressLength )
{
__CPROVER_assert( xSocket != NULL,
"FreeRTOS precondition: xSocket != NULL" );
__CPROVER_assert( pvBuffer != NULL,
"FreeRTOS precondition: pvBuffer != NULL" );
__CPROVER_assert( pxDestinationAddress != NULL,
"FreeRTOS precondition: pxDestinationAddress != NULL" );
return nondet_int32();
}
/****************************************************************
* Abstract FreeRTOS_GetUDPPayloadBuffer
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/FreeRTOS_GetUDPPayloadBuffer.html
*
* We stub out this function to do nothing but allocate a buffer of
* unconstrained size containing unconstrained data and return a
* pointer to the buffer (or NULL).
****************************************************************/
void * FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes,
TickType_t xBlockTimeTicks )
{
size_t size;
__CPROVER_assume( size < CBMC_MAX_OBJECT_SIZE );
__CPROVER_assume( size >= sizeof( UDPPacket_t ) );
uint8_t *buffer = safeMalloc( size );
return buffer == NULL ? buffer : buffer + sizeof( UDPPacket_t );
}
/****************************************************************
* Abstract FreeRTOS_GetUDPPayloadBuffer
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/FreeRTOS_ReleaseUDPPayloadBuffer.html
****************************************************************/
void FreeRTOS_ReleaseUDPPayloadBuffer( void * pvBuffer )
{
__CPROVER_assert( pvBuffer != NULL,
"FreeRTOS precondition: pvBuffer != NULL" );
__CPROVER_assert( __CPROVER_POINTER_OFFSET( pvBuffer )
== sizeof( UDPPacket_t ),
"FreeRTOS precondition: pvBuffer offset" );
free( pvBuffer - sizeof( UDPPacket_t ) );
}
/****************************************************************
* Abstract pxGetNetworkBufferWithDescriptor.
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/pxGetNetworkBufferWithDescriptor.html
*
* The real allocator take buffers off a list.
****************************************************************/
uint32_t GetNetworkBuffer_failure_count;
NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
TickType_t xBlockTimeTicks )
{
__CPROVER_assert(
xRequestedSizeBytes + ipBUFFER_PADDING < CBMC_MAX_OBJECT_SIZE,
"pxGetNetworkBufferWithDescriptor: request too big" );
/*
* The semantics of this function is to wait until a buffer with
* at least the requested number of bytes becomes available. If a
* timeout occurs before the buffer is available, then return a
* NULL pointer.
*/
NetworkBufferDescriptor_t * desc = safeMalloc( sizeof( *desc ) );
#ifdef CBMC_GETNETWORKBUFFER_FAILURE_BOUND
/*
* This interprets the failure bound as being one greater than the
* actual number of times GetNetworkBuffer should be allowed to
* fail.
*
* This makes it possible to use the same bound for loop unrolling
* which must be one greater than the actual number of times the
* loop should be unwound.
*
* NOTE: Using this bound with --nondet-static requires setting
* (or assuming) GetNetworkBuffer_failure_count to a value (like 0)
* in the proof harness that won't induce an integer overflow.
*/
GetNetworkBuffer_failure_count++;
__CPROVER_assume(
IMPLIES(
GetNetworkBuffer_failure_count >= CBMC_GETNETWORKBUFFER_FAILURE_BOUND,
desc != NULL ) );
#endif
if( desc != NULL )
{
/*
* We may want to experiment with allocating space other than
* (more than) the exact amount of space requested.
*/
size_t size = xRequestedSizeBytes;
__CPROVER_assume( size < CBMC_MAX_OBJECT_SIZE );
desc->pucEthernetBuffer = safeMalloc( size );
desc->xDataLength = desc->pucEthernetBuffer == NULL ? 0 : size;
#ifdef CBMC_REQUIRE_NETWORKBUFFER_ETHERNETBUFFER_NONNULL
/* This may be implied by the semantics of the function. */
__CPROVER_assume( desc->pucEthernetBuffer != NULL );
#endif
/* Allow method to fail again next time */
GetNetworkBuffer_failure_count = 0;
}
return desc;
}
/****************************************************************
* Abstract pxGetNetworkBufferWithDescriptor.
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/vReleaseNetworkBufferAndDescriptor.html
****************************************************************/
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
__CPROVER_assert( pxNetworkBuffer != NULL,
"Precondition: pxNetworkBuffer != NULL" );
if( pxNetworkBuffer->pucEthernetBuffer != NULL )
{
free( pxNetworkBuffer->pucEthernetBuffer );
}
free( pxNetworkBuffer );
}
/****************************************************************
* Abstract FreeRTOS_GetAddressConfiguration
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/FreeRTOS_GetAddressConfiguration.html
****************************************************************/
void FreeRTOS_GetAddressConfiguration( uint32_t * pulIPAddress,
uint32_t * pulNetMask,
uint32_t * pulGatewayAddress,
uint32_t * pulDNSServerAddress )
{
if( pulIPAddress != NULL )
{
*pulIPAddress = nondet_unint32();
}
if( pulNetMask != NULL )
{
*pulNetMask = nondet_unint32();
}
if( pulGatewayAddress != NULL )
{
*pulGatewayAddress = nondet_unint32();
}
if( pulDNSServerAddress != NULL )
{
*pulDNSServerAddress = nondet_unint32();
}
}
/****************************************************************/
/****************************************************************
* This is a collection of methods that are defined by the user
* application but are invoked by the FreeRTOS API.
****************************************************************/
/****************************************************************
* Abstract FreeRTOS_GetAddressConfiguration
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/vApplicationIPNetworkEventHook.html
****************************************************************/
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
{
}
/****************************************************************
* Abstract pcApplicationHostnameHook
* https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html
****************************************************************/
const char * pcApplicationHostnameHook( void )
{
return "hostname";
}
/****************************************************************/

View file

@ -1,3 +1,22 @@
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_DHCP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
/* /*
* CBMC models a pointer as an object id and an offset into that * CBMC models a pointer as an object id and an offset into that
* object. The top bits of a pointer encode the object id and the * object. The top bits of a pointer encode the object id and the
@ -6,36 +25,53 @@
* size of objects in CBMC. * size of objects in CBMC.
*/ */
#define CBMC_BITS 7 #define CBMC_BITS 7
#define CBMC_MAX_OBJECT_SIZE (0xFFFFFFFF >> CBMC_BITS) #define CBMC_MAX_OBJECT_SIZE ( 0xFFFFFFFF >> ( CBMC_BITS + 1 ) )
enum CBMC_LOOP_CONDITION { CBMC_LOOP_BREAK, CBMC_LOOP_CONTINUE, CBMC_LOOP_RETURN }; #define IMPLIES( a, b ) ( !( a ) || ( b ) )
// CBMC specification: capture old value for precondition / BaseType_t nondet_basetype();
// postcondition checking UBaseType_t nondet_ubasetype();
TickType_t nondet_ticktype();
int32_t nondet_int32();
uint32_t nondet_uint32();
size_t nondet_sizet();
#define nondet_BaseType() nondet_basetype()
void * safeMalloc( size_t size );
enum CBMC_LOOP_CONDITION
{
CBMC_LOOP_BREAK, CBMC_LOOP_CONTINUE, CBMC_LOOP_RETURN
};
/* CBMC specification: capture old value for precondition and */
/* postcondition checking */
#define OLDVAL( var ) _old_ ## var #define OLDVAL( var ) _old_ ## var
#define SAVE_OLDVAL( var, typ ) const typ OLDVAL( var ) = var #define SAVE_OLDVAL( var, typ ) const typ OLDVAL( var ) = var
// CBMC specification: capture old value for values passed by /* CBMC specification: capture old value for values passed by */
// reference in function abstractions /* reference in function abstractions */
#define OBJ( var ) ( * var ) #define OBJ( var ) ( * var )
#define OLDOBJ( var ) _oldobj_ ## var #define OLDOBJ( var ) _oldobj_ ## var
#define SAVE_OLDOBJ( var, typ ) const typ OLDOBJ( var ) = OBJ( var ) #define SAVE_OLDOBJ( var, typ ) const typ OLDOBJ( var ) = OBJ( var )
// CBMC debugging: printfs for expressions /* CBMC debugging: printfs for expressions */
#define __CPROVER_printf( var ) { uint32_t ValueOf_ ## var = ( uint32_t ) var; } #define __CPROVER_printf( var ) { uint32_t ValueOf_ ## var = ( uint32_t ) var; }
#define __CPROVER_printf2( str, exp ) { uint32_t ValueOf_ ## str = ( uint32_t ) ( exp ); } #define __CPROVER_printf2( str, exp ) { uint32_t ValueOf_ ## str = ( uint32_t ) ( exp ); }
// CBMC debugging: printfs for pointer expressions /* CBMC debugging: printfs for pointer expressions */
#define __CPROVER_printf_ptr( var ) { uint8_t * ValueOf_ ## var = ( uint8_t * ) var; } #define __CPROVER_printf_ptr( var ) { uint8_t * ValueOf_ ## var = ( uint8_t * ) var; }
#define __CPROVER_printf2_ptr( str, exp ) { uint8_t * ValueOf_ ## str = ( uint8_t * ) ( exp ); } #define __CPROVER_printf2_ptr( str, exp ) { uint8_t * ValueOf_ ## str = ( uint8_t * ) ( exp ); }
/* /*
* An assertion that pvPortMalloc returns NULL when asked to allocate 0 bytes. * An assertion that pvPortMalloc returns NULL when asked to allocate 0 bytes.
* This assertion is used in some of the Task proofs. * This assertion is used in some of the TaskPool proofs.
*/ */
#define __CPROVER_assert_zero_allocation() \ #define __CPROVER_assert_zero_allocation() \
__CPROVER_assert( pvPortMalloc( 0 ) == NULL, \ __CPROVER_assert( pvPortMalloc( 0 ) == NULL, \
@ -45,7 +81,7 @@ enum CBMC_LOOP_CONDITION { CBMC_LOOP_BREAK, CBMC_LOOP_CONTINUE, CBMC_LOOP_RETURN
* A stub for pvPortMalloc that nondeterministically chooses to return * A stub for pvPortMalloc that nondeterministically chooses to return
* either NULL or an allocation of the requested space. The stub is * either NULL or an allocation of the requested space. The stub is
* guaranteed to return NULL when asked to allocate 0 bytes. * guaranteed to return NULL when asked to allocate 0 bytes.
* This stub is used in some of the Task proofs. * This stub is used in some of the TaskPool proofs.
*/ */
void * pvPortMalloc( size_t xWantedSize ) void * pvPortMalloc( size_t xWantedSize )
{ {
@ -53,6 +89,7 @@ void *pvPortMalloc( size_t xWantedSize )
{ {
return NULL; return NULL;
} }
return nondet_bool() ? malloc( xWantedSize ) : NULL; return nondet_bool() ? malloc( xWantedSize ) : NULL;
} }
@ -61,7 +98,3 @@ void vPortFree( void *pv )
( void ) pv; ( void ) pv;
free( pv ); free( pv );
} }
BaseType_t nondet_basetype();
UBaseType_t nondet_ubasetype();
TickType_t nondet_ticktype();

View file

@ -1,121 +0,0 @@
From 884e69144abac08d203bbf8257c6b4a96a2a91ea Mon Sep 17 00:00:00 2001
From: "Mark R. Tuttle" <mrtuttle@amazon.com>
Date: Mon, 21 Oct 2019 14:17:50 -0400
Subject: [PATCH] Remove static storage class from entry points
Many of the entry points we wish to test are marked as being static.
This commit removes the static keyword from all entry points that we
test.
Patch revised on October 21, 2019.
---
.../freertos_plus_tcp/source/FreeRTOS_DHCP.c | 6 +++---
.../standard/freertos_plus_tcp/source/FreeRTOS_DNS.c | 12 ++++++------
.../freertos_plus_tcp/source/FreeRTOS_TCP_WIN.c | 2 +-
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
index c4f79e8e7..d8089a5e7 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
@@ -198,7 +198,7 @@ static void prvSendDHCPDiscover( void );
/*
* Interpret message received on the DHCP socket.
*/
-static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
+BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
/*
* Generate a DHCP request packet, and send it on the DHCP socket.
@@ -234,7 +234,7 @@ static void prvCreateDHCPSocket( void );
/*-----------------------------------------------------------*/
/* The next DHCP transaction Id to be used. */
-static DHCPData_t xDHCPData;
+DHCPData_t xDHCPData;
/*-----------------------------------------------------------*/
@@ -607,7 +607,7 @@ static void prvInitialiseDHCP( void )
}
/*-----------------------------------------------------------*/
-static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
+BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
{
uint8_t *pucUDPPayload, *pucLastByte;
struct freertos_sockaddr xClient;
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
index e511ca324..d6f335304 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
@@ -116,7 +116,7 @@ static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
/*
* Simple routine that jumps over the NAME field of a resource record.
*/
-static uint8_t * prvSkipNameField( uint8_t *pucByte,
+uint8_t * prvSkipNameField( uint8_t *pucByte,
size_t uxSourceLen );
/*
@@ -124,7 +124,7 @@ static uint8_t * prvSkipNameField( uint8_t *pucByte,
* The parameter 'xExpected' indicates whether the identifier in the reply
* was expected, and thus if the DNS cache may be updated with the reply.
*/
-static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
size_t uxBufferLength,
BaseType_t xExpected );
@@ -152,7 +152,7 @@ static uint32_t prvGetHostByName( const char *pcHostName,
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
- static uint8_t * prvReadNameField( uint8_t *pucByte,
+ uint8_t * prvReadNameField( uint8_t *pucByte,
size_t uxSourceLen,
char *pcName,
size_t uxLen );
@@ -765,7 +765,7 @@ static const DNSMessage_t xDefaultPartDNSHeader =
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
- static uint8_t * prvReadNameField( uint8_t *pucByte,
+ uint8_t * prvReadNameField( uint8_t *pucByte,
size_t uxSourceLen,
char *pcName,
size_t uxDestLen )
@@ -843,7 +843,7 @@ static const DNSMessage_t xDefaultPartDNSHeader =
#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
/*-----------------------------------------------------------*/
-static uint8_t * prvSkipNameField( uint8_t *pucByte,
+uint8_t * prvSkipNameField( uint8_t *pucByte,
size_t uxSourceLen )
{
size_t uxChunkLength;
@@ -949,7 +949,7 @@ DNSMessage_t *pxDNSMessageHeader;
#endif /* ipconfigUSE_NBNS */
/*-----------------------------------------------------------*/
-static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
size_t uxBufferLength,
BaseType_t xExpected )
{
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
index 1f5a845fa..1a69807c0 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
@@ -206,7 +206,7 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
/* List of free TCP segments. */
#if( ipconfigUSE_TCP_WIN == 1 )
- static List_t xSegmentList;
+ List_t xSegmentList;
#endif
/* Logging verbosity level. */
--
2.20.1 (Apple Git-117)

View file

@ -1,68 +0,0 @@
From 18ca738652bd0ce0a1345cb3dcd7ffacbc196bfa Mon Sep 17 00:00:00 2001
From: "Mark R. Tuttle" <mrtuttle@amazon.com>
Date: Wed, 30 Oct 2019 09:38:56 -0400
Subject: [PATCH] Remove static attributes from functions implementing
prvCheckOptions for CBMC proofs.
---
.../freertos_plus_tcp/source/FreeRTOS_TCP_IP.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
index 4378e28de..2cd072d24 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
@@ -225,20 +225,20 @@ static BaseType_t prvTCPPrepareConnect( FreeRTOS_Socket_t *pxSocket );
/*
* Parse the TCP option(s) received, if present.
*/
-static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );
+void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );
/*
* Identify and deal with a single TCP header option, advancing the pointer to
* the header. This function returns pdTRUE or pdFALSE depending on whether the
* caller should continue to parse more header options or break the loop.
*/
-static BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow);
+BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow);
/*
* Skip past TCP header options when doing Selective ACK, until there are no
* more options left.
*/
-static void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const ppucLen );
+void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const ppucLen );
/*
* Set the initial properties in the options fields, like the preferred
@@ -1157,7 +1157,7 @@ uint32_t ulInitialSequenceNumber = 0;
* that: ((pxTCPHeader->ucTCPOffset & 0xf0) > 0x50), meaning that the TP header
* is longer than the usual 20 (5 x 4) bytes.
*/
-static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )
+void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )
{
TCPPacket_t * pxTCPPacket;
TCPHeader_t * pxTCPHeader;
@@ -1191,7 +1191,7 @@ BaseType_t xShouldContinueLoop;
/*-----------------------------------------------------------*/
-static BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow)
+BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const ppucPtr, const unsigned char ** const ppucLast, FreeRTOS_Socket_t ** const ppxSocket, TCPWindow_t ** const ppxTCPWindow)
{
UBaseType_t uxNewMSS;
UBaseType_t xRemainingOptionsBytes = ( *ppucLast ) - ( *ppucPtr );
@@ -1319,7 +1319,7 @@ static BaseType_t prvSingleStepTCPHeaderOptions( const unsigned char ** const pp
/*-----------------------------------------------------------*/
-static void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const pucLen )
+void prvSkipPastRemainingOptions( const unsigned char ** const ppucPtr, FreeRTOS_Socket_t ** const ppxSocket, unsigned char * const pucLen )
{
uint32_t ulFirst = ulChar2u32( ( *ppucPtr ) );
uint32_t ulLast = ulChar2u32( ( *ppucPtr ) + 4 );
--
2.20.1 (Apple Git-117)

View file

@ -0,0 +1,64 @@
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
index 04b0487..d6e74a9 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
@@ -156,7 +156,11 @@ struct xDHCPMessage_IPv4
typedef struct xDHCPMessage_IPv4 DHCPMessage_IPv4_t;
/* The UDP socket used for all incoming and outgoing DHCP traffic. */
+#ifdef CBMC
+Socket_t xDHCPSocket;
+#else
static Socket_t xDHCPSocket;
+#endif
#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )
/* Define the Link Layer IP address: 169.254.x.x */
@@ -179,7 +183,11 @@ static void prvSendDHCPDiscover( void );
/*
* Interpret message received on the DHCP socket.
*/
+#ifdef CBMC
+BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
+#else
static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );
+#endif
/*
* Generate a DHCP request packet, and send it on the DHCP socket.
@@ -204,7 +212,11 @@ static uint8_t *prvCreatePartDHCPMessage( struct freertos_sockaddr *pxAddress,
/*
* Create the DHCP socket, if it has not been created already.
*/
+#ifdef CBMC
+void prvCreateDHCPSocket( void );
+#else
static void prvCreateDHCPSocket( void );
+#endif
/*
* Close the DHCP socket.
@@ -223,7 +235,11 @@ static void prvCloseDHCPSocket( void );
/*-----------------------------------------------------------*/
/* Hold information in between steps in the DHCP state machine. */
+#ifdef CBMC
+DHCPData_t xDHCPData;
+#else
static DHCPData_t xDHCPData;
+#endif
/*-----------------------------------------------------------*/
@@ -623,7 +639,11 @@ static void prvInitialiseDHCP( void )
}
/*-----------------------------------------------------------*/
+#ifdef CBMC
+BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
+#else
static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )
+#endif
{
uint8_t *pucUDPPayload;
int32_t lBytes;

View file

@ -0,0 +1,100 @@
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
index 480d50b..5557253 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
@@ -114,7 +114,11 @@ static Socket_t prvCreateDNSSocket( void );
/*
* Create the DNS message in the zero copy buffer passed in the first parameter.
*/
+#ifdef CBMC
+size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
+#else
static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
+#endif
const char *pcHostName,
TickType_t uxIdentifier );
@@ -122,7 +126,11 @@ static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
* Simple routine that jumps over the NAME field of a resource record.
* It returns the number of bytes read.
*/
+#ifdef CBMC
+size_t prvSkipNameField( const uint8_t *pucByte,
+#else
static size_t prvSkipNameField( const uint8_t *pucByte,
+#endif
size_t uxLength );
/*
@@ -130,7 +138,11 @@ static size_t prvSkipNameField( const uint8_t *pucByte,
* The parameter 'xExpected' indicates whether the identifier in the reply
* was expected, and thus if the DNS cache may be updated with the reply.
*/
+#ifdef CBMC
+uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+#else
static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+#endif
size_t uxBufferLength,
BaseType_t xExpected );
@@ -184,7 +196,11 @@ static uint32_t prvGetHostByName( const char *pcHostName,
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
+#ifdef CBMC
+ size_t prvReadNameField( const uint8_t *pucByte,
+#else
static size_t prvReadNameField( const uint8_t *pucByte,
+#endif
size_t uxRemainingBytes,
char *pcName,
size_t uxDestLen );
@@ -758,7 +774,11 @@ TickType_t uxWriteTimeOut_ticks = ipconfigDNS_SEND_BLOCK_TIME_TICKS;
}
/*-----------------------------------------------------------*/
+#ifdef CBMC
+size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
+#else
static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer,
+#endif
const char *pcHostName,
TickType_t uxIdentifier )
{
@@ -838,7 +858,11 @@ static const DNSMessage_t xDefaultPartDNSHeader =
#if( ipconfigUSE_DNS_CACHE == 1 ) || ( ipconfigDNS_USE_CALLBACKS == 1 )
+#ifdef CBMC
+ size_t prvReadNameField( const uint8_t *pucByte,
+#else
static size_t prvReadNameField( const uint8_t *pucByte,
+#endif
size_t uxRemainingBytes,
char *pcName,
size_t uxDestLen )
@@ -932,7 +956,11 @@ static const DNSMessage_t xDefaultPartDNSHeader =
#endif /* ipconfigUSE_DNS_CACHE || ipconfigDNS_USE_CALLBACKS */
/*-----------------------------------------------------------*/
+#ifdef CBMC
+size_t prvSkipNameField( const uint8_t *pucByte,
+#else
static size_t prvSkipNameField( const uint8_t *pucByte,
+#endif
size_t uxLength )
{
size_t uxChunkLength;
@@ -1050,7 +1078,11 @@ size_t uxPayloadSize;
#endif /* ipconfigUSE_NBNS */
/*-----------------------------------------------------------*/
+#ifdef CBMC
+uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+#else
static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer,
+#endif
size_t uxBufferLength,
BaseType_t xExpected )
{

View file

@ -0,0 +1,87 @@
From afc01793c4531cfbe9f92e7ca2ce9364983d987e Mon Sep 17 00:00:00 2001
From: Mark R Tuttle <mrtuttle@amazon.com>
Date: Tue, 12 May 2020 15:57:56 +0000
Subject: [PATCH] modified lib
---
.../freertos_plus_tcp/source/FreeRTOS_TCP_IP.c | 24 ++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
index dc58621..963b576 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
@@ -198,14 +198,22 @@ static BaseType_t prvTCPPrepareConnect( FreeRTOS_Socket_t *pxSocket );
/*
* Parse the TCP option(s) received, if present.
*/
+#ifdef CBMC
+void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer );
+#else
static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer );
+#endif
/*
* Identify and deal with a single TCP header option, advancing the pointer to
* the header. This function returns pdTRUE or pdFALSE depending on whether the
* caller should continue to parse more header options or break the loop.
*/
+#ifdef CBMC
+size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
+#else
static size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
+#endif
size_t uxTotalLength,
FreeRTOS_Socket_t * const pxSocket,
BaseType_t xHasSYNFlag );
@@ -214,7 +222,11 @@ static size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
* Skip past TCP header options when doing Selective ACK, until there are no
* more options left.
*/
+#ifdef CBMC
+void prvReadSackOption( const uint8_t * const pucPtr,
+#else
static void prvReadSackOption( const uint8_t * const pucPtr,
+#endif
size_t uxIndex,
FreeRTOS_Socket_t * const pxSocket );
@@ -1137,7 +1149,11 @@ uint32_t ulInitialSequenceNumber = 0;
* that: ((pxTCPHeader->ucTCPOffset & 0xf0) > 0x50), meaning that the TP header
* is longer than the usual 20 (5 x 4) bytes.
*/
+#ifdef CBMC
+void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer )
+#else
static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, const NetworkBufferDescriptor_t *pxNetworkBuffer )
+#endif
{
size_t uxTCPHeaderOffset = ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer );
const ProtocolHeaders_t *pxProtocolHeaders = ipPOINTER_CAST( ProtocolHeaders_t *,
@@ -1201,7 +1217,11 @@ uint8_t ucLength;
}
/*-----------------------------------------------------------*/
+#ifdef CBMC
+size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
+#else
static size_t prvSingleStepTCPHeaderOptions( const uint8_t * const pucPtr,
+#endif
size_t uxTotalLength,
FreeRTOS_Socket_t * const pxSocket,
BaseType_t xHasSYNFlag )
@@ -1346,7 +1366,11 @@ TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
}
/*-----------------------------------------------------------*/
+#ifdef CBMC
+void prvReadSackOption( const uint8_t * const pucPtr,
+#else
static void prvReadSackOption( const uint8_t * const pucPtr,
+#endif
size_t uxIndex,
FreeRTOS_Socket_t * const pxSocket )
{
--
2.7.4

View file

@ -0,0 +1,17 @@
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
index 0078ab313..b0cccbad8 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
@@ -192,8 +192,12 @@ extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewL
/* List of free TCP segments. */
#if( ipconfigUSE_TCP_WIN == 1 )
+#ifdef CBMC
+ List_t xSegmentList;
+#else
static List_t xSegmentList;
#endif
+#endif
/* Logging verbosity level. */
BaseType_t xTCPWindowLoggingLevel = 0;

View file

@ -117,11 +117,10 @@ cbmc.txt: $(ENTRY).goto
- cbmc $(CBMCFLAGS) --unwinding-assertions --trace @RULE_INPUT@ > $@ 2>&1 - cbmc $(CBMCFLAGS) --unwinding-assertions --trace @RULE_INPUT@ > $@ 2>&1
property.xml: $(ENTRY).goto property.xml: $(ENTRY).goto
cbmc $(CBMCFLAGS) --unwinding-assertions --show-properties --xml-ui @RULE_INPUT@ \ cbmc $(CBMCFLAGS) --unwinding-assertions --show-properties --xml-ui @RULE_INPUT@ > $@ 2>&1
2>&1 > $@
coverage.xml: $(ENTRY).goto coverage.xml: $(ENTRY).goto
cbmc $(CBMCFLAGS) --cover location --xml-ui @RULE_INPUT@ 2>&1 > $@ cbmc $(CBMCFLAGS) --cover location --xml-ui @RULE_INPUT@ > $@ 2>&1
cbmc: cbmc.txt cbmc: cbmc.txt
@ -148,7 +147,7 @@ report: cbmc.txt property.xml coverage.xml
clean: clean:
@RM@ $(OBJS) $(ENTRY).goto @RM@ $(OBJS) $(ENTRY).goto
@RM@ $(ENTRY)[0-9].goto $(ENTRY)[0-9].txt @RM@ $(ENTRY)[0-9].goto $(ENTRY)[0-9].txt
@RM@ cbmc.txt property.xml coverage.xml TAGS @RM@ cbmc.txt property.xml coverage.xml TAGS TAGS-*
@RM@ *~ \#* @RM@ *~ \#*
@RM@ queue_datastructure.h @RM@ queue_datastructure.h

View file

@ -10,6 +10,7 @@
"WINVER=0x400", "WINVER=0x400",
"_CRT_SECURE_NO_WARNINGS", "_CRT_SECURE_NO_WARNINGS",
"__PRETTY_FUNCTION__=__FUNCTION__", "__PRETTY_FUNCTION__=__FUNCTION__",
"CBMC",
"'configASSERT(X)=__CPROVER_assert(X,\"Assertion Error\")'", "'configASSERT(X)=__CPROVER_assert(X,\"Assertion Error\")'",
"'configPRECONDITION(X)=__CPROVER_assume(X)'" "'configPRECONDITION(X)=__CPROVER_assume(X)'"
], ],
@ -18,12 +19,13 @@
"$(FREERTOS)/Source/include", "$(FREERTOS)/Source/include",
"$(FREERTOS)/Source/portable/MSVC-MingW", "$(FREERTOS)/Source/portable/MSVC-MingW",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include", "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement",
"$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC", "$(FREERTOS)/../FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC",
"$(FREERTOS)/../FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap", "$(FREERTOS)/../FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap",
"$(FREERTOS)/Demo/Common/include", "$(FREERTOS)/Demo/Common/include",
"$(FREERTOS)/Test/CBMC/include", "$(FREERTOS)/Test/CBMC/include",
"$(FREERTOS)/Test/CBMC/patches" "$(FREERTOS)/Test/CBMC/patches",
"$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/windows",
"$(FREERTOS)/../FreeRTOS-Plus/Test/CBMC/windows2"
], ],
"CBMCFLAGS ": [ "CBMCFLAGS ": [