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. MFC after: 2 days Differential Revision: https://reviews.freebsd.org/D4975
This commit is contained in:
parent
9ad7e03f72
commit
c0b9f85bd6
@ -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_ARP:
|
||||
case ESE_DZ_L3_CLASS_FCOE:
|
||||
break;
|
||||
|
||||
case ESE_DZ_L3_CLASS_IP6_FRAG:
|
||||
case ESE_DZ_L3_CLASS_IP6:
|
||||
flags |= EFX_PKT_IPV6;
|
||||
break;
|
||||
|
||||
case ESE_DZ_L3_CLASS_IP4_FRAG:
|
||||
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) == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
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:
|
||||
case ESE_DZ_L3_CLASS_IP6_FRAG:
|
||||
flags |= EFX_PKT_IPV6;
|
||||
|
||||
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)
|
||||
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_TCP:
|
||||
flags |= EFX_PKT_TCP;
|
||||
if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR) == 0)
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user