TCP stack priority of ARP and IPv4

hello, im exploring and learning from FreeRTOS TCP.

in function: prvProcessEthernetPacket ---- file: FreeRTOS_IP.c

noticed in the switch case the following code:

/* Interpret the received Ethernet packet. */

        switch( pxEthernetHeader->usFrameType )

        {

        case ipARP_FRAME_TYPE:

            /* The Ethernet frame contains an ARP packet. */

            if( pxNetworkBuffer->xDataLength >= sizeof( ARPPacket_t ) )

            {

                eReturned = eARPProcessPacket( ipCAST_PTR_TO_TYPE_PTR( ARPPacket_t, pxNetworkBuffer->pucEthernetBuffer ) );

            }

            else

            {

                eReturned = eReleaseBuffer;

            }

            break;

        case ipIPv4_FRAME_TYPE:

            /* The Ethernet frame contains an IP packet. */

            if( pxNetworkBuffer->xDataLength >= sizeof( IPPacket_t ) )

            {

                eReturned = prvProcessIPPacket( ipCAST_PTR_TO_TYPE_PTR( IPPacket_t, pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer );

            }

            else

            {

                eReturned = eReleaseBuffer;

            }

            break;

        default:

            /* No other packet types are handled.  Nothing to do. */

            eReturned = eReleaseBuffer;

            break;

        }

the question is why ARP frame is being checked first, most frames going to be ipv4 correct? isn’t it better to check them on priority for performance reason?

Hello,

Many compilers translate switch–case constructs to branch tables where the evaluation orders makes no difference.

As a side note, in many Wireshark traces I saw there were frighteningly many frequent ARP requests, often by network management software.

1 Like

thank you,

as far as i know that this only works on sequence or packed numbers. other wise compiler have to use the if statements. which is in this case.

thanks, still isnt ipv4 messages are much more than ARP ?

I agree with @RAc and I wouldn’t guess how (optimizing) compilers generate code. They’re doing amazing things nowadays.
The order of switch cases is almost never an issue wrt. performance.

1 Like

i wouldn’t call my self guessing how compiler optimizes the code, i stated that as far as i know that it optimizing switch case or long if else condition to a branch table works with closely sequenced numbers. i might be wrong but that is what i know.

c++20 standard attributes has switch specifiers [[likely]] and [[unlikely]] for that reason no ?

in any case, thank you both i learned things today :slightly_smiling_face: :+1:

un/likely are programming hints for the compiler regarding the hot code path the compiler can’t know about and if supported finally for the processor regarding branch prediction.
Some cores like ARM support branch prediction hint flags at processor instruction level.
These compiler hints might also help the compiler optimizing high level instruction flow regarding speculative execution/prefetching/caching (if supported by the processor).

These are the two main switch statements for receiving a packet:

switch( pxEthernetHeader->usFrameType )
{
    case ipARP_FRAME_TYPE:
        break;

    case ipIPv4_FRAME_TYPE:
        prvProcessIPPacket();
        break;

    default:
}

prvProcessIPPacket()
{
    switch( ucProtocol )
    {
        case ipPROTOCOL_ICMP:
            break;

        case ipPROTOCOL_UDP:
           break;

        case ipPROTOCOL_TCP:
            Break;
    }
}

I agree with @hs2 and @RAc that the effect of these orders are so small that reordering them will not improve performance. The biggest delays can be found in large memcpy’s and in the actual sending or receiving of packets.

Although: some implementations of memcpy are extremely optimised, and when data caching is used, the time taken by a memcpy() can be close to nothing.

Answering your question: why this order and not another order? The answer is semantic: ARP comes before IP (IPv4). And ICMP is more basic than UDP, which is more basic than TCP.