Skip to content

Commit 1c7623d

Browse files
evpopovEmil Popovactions-userActoryOutony-josi-aws
authored
Improves the calculation of the offset at which we store the IP version value (FreeRTOS#979)
* Defines ipUDP_PAYLOAD_IP_TYPE_OFFSET as an offset dependent on the IPv6 and UDP headers. Calculates ipIP_TYPE_OFFSET automatically based on the sizes it depends on instead of using a hardcoded number. Removes the definitions of ipIP_TYPE_OFFSET and ipUDP_PAYLOAD_IP_TYPE_OFFSET from FreeRTOS_IPv6_Private.h because they are already defined in FreeRTOS_IPv4_Private.h Makes ipIP_TYPE_OFFSET define signed so asserts can properly check for negative values. Adds an assert to ensure that storing of the IP-Type for IPv4 frames does not result in overwriting the ethernet header which would be the case if ipIP_TYPE_OFFSET somehow became negative or zero. Adds a comment to the code storing of the IP-Type byte for IPv6 frames emphasizing that it is not required and only used for debugging. * Uncrustify: triggered by comment. * Correct the comment of ipUDP_PAYLOAD_IP_TYPE_OFFSET. --------- Co-authored-by: Emil Popov <[email protected]> Co-authored-by: GitHub Action <[email protected]> Co-authored-by: ActoryOu <[email protected]> Co-authored-by: Tony Josi <[email protected]>
1 parent 574b646 commit 1c7623d

File tree

4 files changed

+34
-22
lines changed

4 files changed

+34
-22
lines changed

source/FreeRTOS_IP.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1824,9 +1824,9 @@ static eFrameProcessingResult_t prvProcessIPPacket( const IPPacket_t * pxIPPacke
18241824
/* coverity[misra_c_2012_rule_11_3_violation] */
18251825
eReturn = prvAllowIPPacketIPv6( ( ( const IPHeader_IPv6_t * ) &( pxIPPacket->xIPHeader ) ), pxNetworkBuffer, uxHeaderLength );
18261826

1827-
/* The IP-header type is copied to a location 6 bytes before the messages
1828-
* starts. It might be needed later on when a UDP-payload buffer is being
1829-
* used. */
1827+
/* The IP-header type is copied to a special reserved location a few bytes before the message
1828+
* starts. In the case of IPv6, this value is never actually used and the line below can safely be removed
1829+
* with no ill effects. We only store it to help with debugging. */
18301830
pxNetworkBuffer->pucEthernetBuffer[ 0 - ( BaseType_t ) ipIP_TYPE_OFFSET ] = pxIPHeader_IPv6->ucVersionTrafficClass;
18311831
}
18321832
break;
@@ -1854,7 +1854,7 @@ static eFrameProcessingResult_t prvProcessIPPacket( const IPPacket_t * pxIPPacke
18541854
eReturn = prvAllowIPPacketIPv4( pxIPPacket, pxNetworkBuffer, uxHeaderLength );
18551855

18561856
{
1857-
/* The IP-header type is copied to a location 6 bytes before the
1857+
/* The IP-header type is copied to a special reserved location a few bytes before the
18581858
* messages starts. It might be needed later on when a UDP-payload
18591859
* buffer is being used. */
18601860
pxNetworkBuffer->pucEthernetBuffer[ 0 - ( BaseType_t ) ipIP_TYPE_OFFSET ] = pxIPHeader->ucVersionHeaderLength;

source/FreeRTOS_IP_Utils.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,12 @@ void vPreCheckConfigs( void )
996996
}
997997
#endif
998998
/* LCOV_EXCL_BR_STOP */
999+
1000+
/* ipIP_TYPE_OFFSET is used like so:
1001+
* pxNetworkBuffer->pucEthernetBuffer[ 0 - ( BaseType_t ) ipIP_TYPE_OFFSET ] = IP-Version-Byte
1002+
* It's value MUST be > 0. Otherwise, storing the IPv4 version byte
1003+
* will overwrite the Ethernet header. */
1004+
configASSERT( ipIP_TYPE_OFFSET > 0 );
9991005
}
10001006
#endif /* if ( configASSERT_DEFINED == 1 ) */
10011007
}

source/include/FreeRTOS_IPv4_Private.h

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,32 @@
3737
/* *INDENT-ON* */
3838

3939
/* The maximum UDP payload length. */
40-
#define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER ) - ipSIZE_OF_UDP_HEADER )
40+
#define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER ) - ipSIZE_OF_UDP_HEADER )
4141

42-
#define TCP_PACKET_SIZE ( sizeof( TCPPacket_t ) )
42+
#define TCP_PACKET_SIZE ( sizeof( TCPPacket_t ) )
4343

4444
/* The offset into an IP packet into which the IP data (payload) starts. */
45-
#define ipIP_PAYLOAD_OFFSET ( sizeof( IPPacket_t ) )
45+
#define ipIP_PAYLOAD_OFFSET ( sizeof( IPPacket_t ) )
4646
/* The offset into a UDP packet at which the UDP data (payload) starts. */
47-
#define ipUDP_PAYLOAD_OFFSET_IPv4 ( sizeof( UDPPacket_t ) )
48-
/* The value of 'ipUDP_PAYLOAD_IP_TYPE_OFFSET' is 42 + 6 = 48 bytes. */
49-
/* __HT_ just to get it compiled. */
50-
#if !defined( ipIP_TYPE_OFFSET )
51-
#define ipIP_TYPE_OFFSET ( 6U )
52-
#endif
53-
#define ipUDP_PAYLOAD_IP_TYPE_OFFSET ( sizeof( UDPPacket_t ) + ipIP_TYPE_OFFSET )
47+
#define ipUDP_PAYLOAD_OFFSET_IPv4 ( sizeof( UDPPacket_t ) )
48+
/* The value of 'ipUDP_PAYLOAD_IP_TYPE_OFFSET' is 8 + 40 = 48 bytes. */
49+
#define ipUDP_PAYLOAD_IP_TYPE_OFFSET ( sizeof( UDPHeader_t ) + sizeof( IPHeader_IPv6_t ) )
50+
51+
/* ipIP_TYPE_OFFSET is involved in some sorcery. pxUDPPayloadBuffer_to_NetworkBuffer() must be able to convert
52+
* a payload pointer ( like for example a pointer to the DNS payload of a packet ) back to a NetworkBufferDescriptor_t.
53+
* This must work for both IPv4 and IPv6 packets. The pointer conversion is done by subtracting a constant from the payload pointer.
54+
* For IPv6, this magic number is ( sizeof( UDPHeader_t ) + sizeof( IPHeader_IPv6_t ) ) which equals 48 bytes.
55+
* If however we use that same constant for an IPv4 packet, we end up somewhere in front of the Ethernet header.
56+
* In order to accommodate that, the Ethernet frame buffer gets allocated a bit larger than needed.
57+
* For IPv4 frames, prvProcessIPPacket() stores the version header field at a negative offset, a few bytes before the start
58+
* of the Ethernet header. That IPv4 version field MUST be stored the same distance from the payload as in IPv6.
59+
* ipIP_TYPE_OFFSET must be equal to: sizeof( UDPHeader_t ) + sizeof( IPHeader_IPv6_t ) - ( sizeof( UDPPacket_t )
60+
* In most situations, ipIP_TYPE_OFFSET will end up being equal to 6. If the Ethernet header is enlarged to include VLAN
61+
* tag support, ipIP_TYPE_OFFSET will shrink to 2. With the current design, the Ethernet header cannot be expanded to contain
62+
* more than one VLAN tag or ipIP_TYPE_OFFSET will become less than zero. ipIP_TYPE_OFFSET should never be allowed to be <= 0
63+
* or storing of the IPv4 version byte will overwrite the Ethernet header of the frame.
64+
*/
65+
#define ipIP_TYPE_OFFSET ( ( int32_t ) sizeof( UDPHeader_t ) + ( int32_t ) sizeof( IPHeader_IPv6_t ) - ( int32_t ) sizeof( UDPPacket_t ) )
5466

5567
#include "pack_struct_start.h"
5668
struct xIP_HEADER

source/include/FreeRTOS_IPv6_Private.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,16 @@
5656
#undef TCP_PACKET_SIZE
5757
#define TCP_PACKET_SIZE ( sizeof( TCPPacket_IPv6_t ) )
5858

59-
/* The offset from the UDP payload where the IP type will be stored.
60-
* For IPv4 packets, this it located 6 bytes before pucEthernetBuffer.
61-
* For IPv6 packets, this it located in the usual 'ucVersionTrafficClass'. */
62-
#define ipIP_TYPE_OFFSET ( 6U )
6359
/* The offset into an IP packet into which the IP data (payload) starts. */
6460
#define ipIPv6_PAYLOAD_OFFSET ( sizeof( IPPacket_IPv6_t ) )
6561
/* MISRA Ref 20.5.1 [Use of undef] */
6662
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-2051 */
6763
/* coverity[misra_c_2012_rule_20_5_violation] */
6864
/* The maximum UDP payload length. */
6965
#undef ipMAX_UDP_PAYLOAD_LENGTH
70-
#define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv6_HEADER ) - ipSIZE_OF_UDP_HEADER )
66+
#define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv6_HEADER ) - ipSIZE_OF_UDP_HEADER )
7167
/* The offset into a UDP packet at which the UDP data (payload) starts. */
72-
#define ipUDP_PAYLOAD_OFFSET_IPv6 ( sizeof( UDPPacket_IPv6_t ) )
73-
/* The value of 'ipUDP_PAYLOAD_IP_TYPE_OFFSET' is 42 + 6 = 48 bytes. */
74-
#define ipUDP_PAYLOAD_IPv6_TYPE_OFFSET ( sizeof( UDPPacket_IPv6_t ) + ipIP_TYPE_OFFSET )
68+
#define ipUDP_PAYLOAD_OFFSET_IPv6 ( sizeof( UDPPacket_IPv6_t ) )
7569

7670
#if ( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
7771

0 commit comments

Comments
 (0)