Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Jan 2016 06:07:40 +0000 (UTC)
From:      Andrew Rybchenko <arybchik@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r294310 - head/sys/dev/sfxge/common
Message-ID:  <201601190607.u0J67eUv064146@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: arybchik
Date: Tue Jan 19 06:07:39 2016
New Revision: 294310
URL: https://svnweb.freebsd.org/changeset/base/294310

Log:
  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

Modified:
  head/sys/dev/sfxge/common/hunt_ev.c

Modified: head/sys/dev/sfxge/common/hunt_ev.c
==============================================================================
--- head/sys/dev/sfxge/common/hunt_ev.c	Tue Jan 19 06:03:44 2016	(r294309)
+++ head/sys/dev/sfxge/common/hunt_ev.c	Tue Jan 19 06:07:39 2016	(r294310)
@@ -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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201601190607.u0J67eUv064146>