Author: arybchik
Date: Wed Jan 20 08:28:32 2016
New Revision: 294404
URL: https://svnweb.freebsd.org/changeset/base/294404

Log:
  MFC r294310
  
  sfxge: improve error handling in ef10_ev_rx()
  
  Ensure that checksum flags and L3/L4 fields are ignored
  if lower level errors are reported in the event.
  
  Remove checks for CRC0_ERR (bad iSCSI header CRC) and
  CRC1_ERR (bad iSCSI payload or FCoE/FCoIP CRC) as they
  are not used by any existing code.
  
  Submitted by:   Andy Moreton <amoreton at solarflare.com>
  Sponsored by:   Solarflare Communications, Inc.

Modified:
  stable/10/sys/dev/sfxge/common/hunt_ev.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/sfxge/common/hunt_ev.c
==============================================================================
--- stable/10/sys/dev/sfxge/common/hunt_ev.c    Wed Jan 20 08:26:58 2016        
(r294403)
+++ stable/10/sys/dev/sfxge/common/hunt_ev.c    Wed Jan 20 08:28:32 2016        
(r294404)
@@ -486,17 +486,14 @@ ef10_ev_rx(
 {
        efx_nic_t *enp = eep->ee_enp;
        uint32_t size;
-#if 0
-       boolean_t parse_err;
-#endif
        uint32_t label;
-       uint32_t mcast;
-       uint32_t eth_base_class;
+       uint32_t mac_class;
        uint32_t eth_tag_class;
        uint32_t l3_class;
        uint32_t l4_class;
        uint32_t next_read_lbits;
        uint16_t flags;
+       boolean_t cont;
        boolean_t should_abort;
        efx_evq_rxq_state_t *eersp;
        unsigned int desc_count;
@@ -508,10 +505,15 @@ ef10_ev_rx(
        if (enp->en_reset_flags & (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR))
                return (B_FALSE);
 
-       /*
-        * FIXME: likely to be incomplete, incorrect and inefficient.
-        * Improvements in all three areas are required.
-        */
+       /* Basic packet information */
+       size = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_BYTES);
+       next_read_lbits = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DSC_PTR_LBITS);
+       label = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_QLABEL);
+       eth_tag_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_TAG_CLASS);
+       mac_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_MAC_CLASS);
+       l3_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L3_CLASS);
+       l4_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L4_CLASS);
+       cont = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CONT);
 
        if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DROP_EVENT) != 0) {
                /* Drop this event */
@@ -519,9 +521,7 @@ ef10_ev_rx(
        }
        flags = 0;
 
-       size = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_BYTES);
-
-       if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CONT) != 0) {
+       if (cont != 0) {
                /*
                 * This may be part of a scattered frame, or it may be a
                 * truncated frame if scatter is disabled on this RXQ.
@@ -534,41 +534,9 @@ ef10_ev_rx(
                flags |= EFX_PKT_CONT;
        }
 
-#if 0
-       /* TODO What to do if the packet is flagged with parsing error */
-       parse_err = (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_PARSE_INCOMPLETE) != 0);
-#endif
-       label = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_QLABEL);
-
-       if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECRC_ERR) != 0) {
-               /* Ethernet frame CRC bad */
-               flags |= EFX_DISCARD;
-       }
-       if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CRC0_ERR) != 0) {
-               /* IP+TCP, bad CRC in iSCSI header */
-               flags |= EFX_DISCARD;
-       }
-       if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CRC1_ERR) != 0) {
-               /* IP+TCP, bad CRC in iSCSI payload or FCoE or FCoIP */
-               flags |= EFX_DISCARD;
-       }
-       if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECC_ERR) != 0) {
-               /* ECC memory error */
-               flags |= EFX_DISCARD;
-       }
-
-       mcast = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_MAC_CLASS);
-       if (mcast == ESE_DZ_MAC_CLASS_UCAST)
+       if (mac_class == ESE_DZ_MAC_CLASS_UCAST)
                flags |= EFX_PKT_UNICAST;
 
-       eth_base_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_BASE_CLASS);
-       eth_tag_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_TAG_CLASS);
-       l3_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L3_CLASS);
-       l4_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L4_CLASS);
-
-       /* bottom 4 bits of incremented index (not last desc consumed) */
-       next_read_lbits = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DSC_PTR_LBITS);
-
        /* Increment the count of descriptors read */
        eersp = &eep->ee_rxq_state[label];
        desc_count = (next_read_lbits - eersp->eers_rx_read_ptr) &
@@ -587,88 +555,84 @@ ef10_ev_rx(
        /* Calculate the index of the the last descriptor consumed */
        last_used_id = (eersp->eers_rx_read_ptr - 1) & eersp->eers_rx_mask;
 
-       /* EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_OVERRIDE_HOLDOFF); */
-
-       switch (eth_base_class) {
-       case ESE_DZ_ETH_BASE_CLASS_LLC_SNAP:
-       case ESE_DZ_ETH_BASE_CLASS_LLC:
-       case ESE_DZ_ETH_BASE_CLASS_ETH2:
-       default:
-               break;
+       /* Check for errors that invalidate checksum and L3/L4 fields */
+       if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECC_ERR) != 0) {
+               /* RX frame truncated (error flag is misnamed) */
+               EFX_EV_QSTAT_INCR(eep, EV_RX_FRM_TRUNC);
+               flags |= EFX_DISCARD;
+               goto deliver;
+       }
+       if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECRC_ERR) != 0) {
+               /* Bad Ethernet frame CRC */
+               EFX_EV_QSTAT_INCR(eep, EV_RX_ETH_CRC_ERR);
+               flags |= EFX_DISCARD;
+               goto deliver;
+       }
+       if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_PARSE_INCOMPLETE)) {
+               /*
+                * Hardware parse failed, due to malformed headers
+                * or headers that are too long for the parser.
+                * Headers and checksums must be validated by the host.
+                */
+               // TODO: EFX_EV_QSTAT_INCR(eep, EV_RX_PARSE_INCOMPLETE);
+               goto deliver;
        }
 
-       switch (eth_tag_class) {
-       case ESE_DZ_ETH_TAG_CLASS_RSVD7:
-       case ESE_DZ_ETH_TAG_CLASS_RSVD6:
-       case ESE_DZ_ETH_TAG_CLASS_RSVD5:
-       case ESE_DZ_ETH_TAG_CLASS_RSVD4:
-               break;
-
-       case ESE_DZ_ETH_TAG_CLASS_RSVD3: /* Triple tagged */
-       case ESE_DZ_ETH_TAG_CLASS_VLAN2: /* Double tagged */
-       case ESE_DZ_ETH_TAG_CLASS_VLAN1: /* VLAN tagged */
+       if ((eth_tag_class == ESE_DZ_ETH_TAG_CLASS_VLAN1) ||
+           (eth_tag_class == ESE_DZ_ETH_TAG_CLASS_VLAN2)) {
                flags |= EFX_PKT_VLAN_TAGGED;
-               break;
-
-       case ESE_DZ_ETH_TAG_CLASS_NONE:
-       default:
-               break;
        }
 
        switch (l3_class) {
-       case ESE_DZ_L3_CLASS_RSVD7: /* Used by firmware for packet overrun */
-#if 0
-               parse_err = B_TRUE;
-#endif
-               flags |= EFX_DISCARD;
-               break;
+       case ESE_DZ_L3_CLASS_IP4:
+       case ESE_DZ_L3_CLASS_IP4_FRAG:
+               flags |= EFX_PKT_IPV4;
+               if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_IPCKSUM_ERR)) {
+                       EFX_EV_QSTAT_INCR(eep, EV_RX_IPV4_HDR_CHKSUM_ERR);
+               } else {
+                       flags |= EFX_CKSUM_IPV4;
+               }
 
-       case ESE_DZ_L3_CLASS_ARP:
-       case ESE_DZ_L3_CLASS_FCOE:
+               if (l4_class == ESE_DZ_L4_CLASS_TCP) {
+                       EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV4);
+                       flags |= EFX_PKT_TCP;
+               } else if (l4_class == ESE_DZ_L4_CLASS_UDP) {
+                       EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV4);
+                       flags |= EFX_PKT_UDP;
+               } else {
+                       EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV4);
+               }
                break;
 
-       case ESE_DZ_L3_CLASS_IP6_FRAG:
        case ESE_DZ_L3_CLASS_IP6:
+       case ESE_DZ_L3_CLASS_IP6_FRAG:
                flags |= EFX_PKT_IPV6;
-               break;
 
-       case ESE_DZ_L3_CLASS_IP4_FRAG:
-       case ESE_DZ_L3_CLASS_IP4:
-               flags |= EFX_PKT_IPV4;
-               if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_IPCKSUM_ERR) == 0)
-                       flags |= EFX_CKSUM_IPV4;
+               if (l4_class == ESE_DZ_L4_CLASS_TCP) {
+                       EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV6);
+                       flags |= EFX_PKT_TCP;
+               } else if (l4_class == ESE_DZ_L4_CLASS_UDP) {
+                       EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV6);
+                       flags |= EFX_PKT_UDP;
+               } else {
+                       EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV6);
+               }
                break;
 
-       case ESE_DZ_L3_CLASS_UNKNOWN:
        default:
+               EFX_EV_QSTAT_INCR(eep, EV_RX_NON_IP);
                break;
        }
 
-       switch (l4_class) {
-       case ESE_DZ_L4_CLASS_RSVD7:
-       case ESE_DZ_L4_CLASS_RSVD6:
-       case ESE_DZ_L4_CLASS_RSVD5:
-       case ESE_DZ_L4_CLASS_RSVD4:
-       case ESE_DZ_L4_CLASS_RSVD3:
-               break;
-
-       case ESE_DZ_L4_CLASS_UDP:
-               flags |= EFX_PKT_UDP;
-               if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR) == 0)
-                       flags |= EFX_CKSUM_TCPUDP;
-               break;
-
-       case ESE_DZ_L4_CLASS_TCP:
-               flags |= EFX_PKT_TCP;
-               if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR) == 0)
+       if (flags & (EFX_PKT_TCP | EFX_PKT_UDP)) {
+               if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR)) {
+                       EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_UDP_CHKSUM_ERR);
+               } else {
                        flags |= EFX_CKSUM_TCPUDP;
-               break;
-
-       case ESE_DZ_L4_CLASS_UNKNOWN:
-       default:
-               break;
+               }
        }
 
+deliver:
        /* If we're not discarding the packet then it is ok */
        if (~flags & EFX_DISCARD)
                EFX_EV_QSTAT_INCR(eep, EV_RX_OK);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to