Branches hurt performance more than arithmetic and/or conditional moves.

From: [email protected] <[email protected]> On Behalf Of "??
Sent: Monday, July 20, 2020 10:17 PM
To: vpp-dev <[email protected]>
Subject: [vpp-dev] Why not break the check flow when the first error occurs of 
ip4_inout()?

Hi all,

When I'm reading the ip4_input.c code, I'm confused about the following code.

vnet/vnet/ip/ip4_input.c:ip4_input_inline()
{
             ...
            error0 = error1 = IP4_ERROR_NONE;

            /* Punt packets with options. */
            error0 = (ip0->ip_version_and_header_length & 0xf) != 5 ? 
IP4_ERROR_OPTIONS : error0;
            error1 = (ip1->ip_version_and_header_length & 0xf) != 5 ? 
IP4_ERROR_OPTIONS : error1;

            /* Version != 4?  Drop it. */
            error0 = (ip0->ip_version_and_header_length >> 4) != 4 ? 
IP4_ERROR_VERSION : error0;
            error1 = (ip1->ip_version_and_header_length >> 4) != 4 ? 
IP4_ERROR_VERSION : error1;

            /* Verify header checksum. */
            ....
            error0 = 0xffff != ip_csum_fold (sum0) ? IP4_ERROR_BAD_CHECKSUM : 
error0;
            error1 = 0xffff != ip_csum_fold (sum1) ? IP4_ERROR_BAD_CHECKSUM : 
error1;

            /* Drop fragmentation offset 1 packets. */
            ....
            error0 = ip4_get_fragment_offset (ip0) == 1 ? 
IP4_ERROR_FRAGMENT_OFFSET_ONE : error0;
            error1 = ip4_get_fragment_offset (ip1) == 1 ? 
IP4_ERROR_FRAGMENT_OFFSET_ONE : error1;

            /* TTL < 1? Drop it. */
            error0 = (ip0->ttl < 1 && cast0 == VNET_UNICAST) ? 
IP4_ERROR_TIME_EXPIRED : error0;
            error1 = (ip1->ttl < 1 && cast1 == VNET_UNICAST) ? 
IP4_ERROR_TIME_EXPIRED : error1;

            /* Verify lengths. */
            error0 = ip_len0 < sizeof (ip0[0]) ? IP4_ERROR_TOO_SHORT : error0;
            error1 = ip_len1 < sizeof (ip1[0]) ? IP4_ERROR_TOO_SHORT : error1;

            p0->error = error_node->errors[error0];
            p1->error = error_node->errors[error1];

            if (PREDICT_FALSE(error0 != IP4_ERROR_NONE))
            {
                if (error0 == IP4_ERROR_TIME_EXPIRED) {
                    icmp4_error_set_vnet_buffer(p0, ICMP4_time_exceeded,
                            ICMP4_time_exceeded_ttl_exceeded_in_transit, 0);
                    next0 = IP4_INPUT_NEXT_ICMP_ERROR;
                } else
                    next0 = error0 != IP4_ERROR_OPTIONS ? IP4_INPUT_NEXT_DROP : 
IP4_INPUT_NEXT_PUNT;
            }
            if (PREDICT_FALSE(error1 != IP4_ERROR_NONE))
            {
                if (error1 == IP4_ERROR_TIME_EXPIRED) {
                    icmp4_error_set_vnet_buffer(p1, ICMP4_time_exceeded,
                            ICMP4_time_exceeded_ttl_exceeded_in_transit, 0);
                    next1 = IP4_INPUT_NEXT_ICMP_ERROR;
                } else
                    next1 = error1 != IP4_ERROR_OPTIONS ? IP4_INPUT_NEXT_DROP : 
IP4_INPUT_NEXT_PUNT;
            }
}

-----------------------------------------------------------------------------------------------

1. why not break the check flow when the first error occurs? for example:
     error0 = (ip0->ip_version_and_header_length & 0xf) != 5 ? 
IP4_ERROR_OPTIONS : error0;
     if (error0 != IP4_ERROR_NONE) {goto error_handle;}

2. suppose all the results of checking are wrong, I think at the end, we could 
only get the last error rather than the first error.
     options error, version error, ...and length error, so the last error is 
IP4_ERROR_TOO_SHORT

Is there any optimization concept behind this? Can I improe(hope it will 
improve :-)) the code like the following, before we check the next error, let's 
check wether the error has occured:

  /* init error to none */
  error0 = error1 = IP4_ERROR_NONE;

  /* check the first error */
  error0 = (ip0->ip_version_and_header_length & 0xf) != 5 ? IP4_ERROR_OPTIONS : 
error0;

  error0 = error0 != IP4_ERROR_NONE? error0 : 
((ip0->ip_version_and_header_length >> 4) != 4 ? IP4_ERROR_VERSION : error0);
  error0 = error0 != IP4_ERROR_NONE? error0 : (0xffff != ip_csum_fold (sum0) ? 
IP4_ERROR_BAD_CHECKSUM : error0);
  ...


-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#17013): https://lists.fd.io/g/vpp-dev/message/17013
Mute This Topic: https://lists.fd.io/mt/75696670/21656
Group Owner: [email protected]
Unsubscribe: https://lists.fd.io/g/vpp-dev/unsub  [[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to