git: 075c8d9db328 - stable/13 - cxgbei: Handle errors in PDUs.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Fri, 29 Oct 2021 23:58:40 UTC
The branch stable/13 has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=075c8d9db3281fa6de48eae2e097d00b4c7349d7

commit 075c8d9db3281fa6de48eae2e097d00b4c7349d7
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2021-09-10 22:10:00 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2021-10-29 23:34:01 +0000

    cxgbei: Handle errors in PDUs.
    
    When a PDU with an error (bad padding, header digest, or data digest)
    is received, log the error via ICL_WARN() and then reset the
    connection via the ic_error callback.
    
    While here, add per-rxq counters for errors.
    
    Sponsored by:   Chelsio Communications
    
    (cherry picked from commit 4d4cf62e29b06a763dfa8b218de38c8d2cf051bb)
---
 sys/dev/cxgbe/adapter.h       |  3 ++
 sys/dev/cxgbe/cxgbei/cxgbei.c | 67 ++++++++++++++++++++++++++++++++++---------
 sys/dev/cxgbe/cxgbei/cxgbei.h |  3 --
 sys/dev/cxgbe/t4_sge.c        |  9 ++++++
 4 files changed, 65 insertions(+), 17 deletions(-)

diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index c5a10c563e87..5c87a1ac5e31 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -674,6 +674,9 @@ struct sge_ofld_rxq {
 	uint64_t rx_iscsi_ddp_octets;
 	uint64_t rx_iscsi_fl_pdus;
 	uint64_t rx_iscsi_fl_octets;
+	uint64_t rx_iscsi_padding_errors;
+	uint64_t rx_iscsi_header_digest_errors;
+	uint64_t rx_iscsi_data_digest_errors;
 	u_long	rx_toe_tls_records;
 	u_long	rx_toe_tls_octets;
 } __aligned(CACHE_LINE_SIZE);
diff --git a/sys/dev/cxgbe/cxgbei/cxgbei.c b/sys/dev/cxgbe/cxgbei/cxgbei.c
index 2fa38f941b91..bd34e6a2a149 100644
--- a/sys/dev/cxgbe/cxgbei/cxgbei.c
+++ b/sys/dev/cxgbe/cxgbei/cxgbei.c
@@ -335,12 +335,21 @@ do_rx_iscsi_ddp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
 
 	icp->icp_flags |= ICPF_RX_STATUS;
 	ip = &icp->ip;
-	if (val & F_DDP_PADDING_ERR)
-		icp->icp_flags |= ICPF_PAD_ERR;
-	if (val & F_DDP_HDRCRC_ERR)
-		icp->icp_flags |= ICPF_HCRC_ERR;
-	if (val & F_DDP_DATACRC_ERR)
-		icp->icp_flags |= ICPF_DCRC_ERR;
+	if (val & F_DDP_PADDING_ERR) {
+		ICL_WARN("received PDU 0x%02x with invalid padding",
+		    ip->ip_bhs->bhs_opcode);
+		toep->ofld_rxq->rx_iscsi_padding_errors++;
+	}
+	if (val & F_DDP_HDRCRC_ERR) {
+		ICL_WARN("received PDU 0x%02x with invalid header digest",
+		    ip->ip_bhs->bhs_opcode);
+		toep->ofld_rxq->rx_iscsi_header_digest_errors++;
+	}
+	if (val & F_DDP_DATACRC_ERR) {
+		ICL_WARN("received PDU 0x%02x with invalid data digest",
+		    ip->ip_bhs->bhs_opcode);
+		toep->ofld_rxq->rx_iscsi_data_digest_errors++;
+	}
 	if (val & F_DDP_PDU && ip->ip_data_mbuf == NULL) {
 		MPASS((icp->icp_flags & ICPF_RX_FLBUF) == 0);
 		MPASS(ip->ip_data_len > 0);
@@ -400,6 +409,16 @@ do_rx_iscsi_ddp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
 	}
 	MPASS(icc->icc_signature == CXGBEI_CONN_SIGNATURE);
 	ic = &icc->ic;
+	if ((val & (F_DDP_PADDING_ERR | F_DDP_HDRCRC_ERR |
+	    F_DDP_DATACRC_ERR)) != 0) {
+		SOCKBUF_UNLOCK(sb);
+		INP_WUNLOCK(inp);
+
+		icl_cxgbei_conn_pdu_free(NULL, ip);
+		toep->ulpcb2 = NULL;
+		ic->ic_error(ic);
+		return (0);
+	}
 	icl_cxgbei_new_pdu_set_conn(ip, ic);
 
 	MPASS(m == NULL); /* was unused, we'll use it now. */
@@ -514,12 +533,21 @@ do_rx_iscsi_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
 	icp->icp_flags |= ICPF_RX_HDR;
 	icp->icp_flags |= ICPF_RX_STATUS;
 
-	if (val & F_DDP_PADDING_ERR)
-		icp->icp_flags |= ICPF_PAD_ERR;
-	if (val & F_DDP_HDRCRC_ERR)
-		icp->icp_flags |= ICPF_HCRC_ERR;
-	if (val & F_DDP_DATACRC_ERR)
-		icp->icp_flags |= ICPF_DCRC_ERR;
+	if (val & F_DDP_PADDING_ERR) {
+		ICL_WARN("received PDU 0x%02x with invalid padding",
+		    ip->ip_bhs->bhs_opcode);
+		toep->ofld_rxq->rx_iscsi_padding_errors++;
+	}
+	if (val & F_DDP_HDRCRC_ERR) {
+		ICL_WARN("received PDU 0x%02x with invalid header digest",
+		    ip->ip_bhs->bhs_opcode);
+		toep->ofld_rxq->rx_iscsi_header_digest_errors++;
+	}
+	if (val & F_DDP_DATACRC_ERR) {
+		ICL_WARN("received PDU 0x%02x with invalid data digest",
+		    ip->ip_bhs->bhs_opcode);
+		toep->ofld_rxq->rx_iscsi_data_digest_errors++;
+	}
 
 	INP_WLOCK(inp);
 	if (__predict_false(inp->inp_flags & (INP_DROPPED | INP_TIMEWAIT))) {
@@ -557,6 +585,19 @@ do_rx_iscsi_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
 		return (0);
 	}
 
+	MPASS(icc->icc_signature == CXGBEI_CONN_SIGNATURE);
+	ic = &icc->ic;
+	if ((val & (F_DDP_PADDING_ERR | F_DDP_HDRCRC_ERR |
+	    F_DDP_DATACRC_ERR)) != 0) {
+		INP_WUNLOCK(inp);
+
+		icl_cxgbei_conn_pdu_free(NULL, ip);
+		toep->ulpcb2 = NULL;
+		m_freem(m);
+		ic->ic_error(ic);
+		return (0);
+	}
+
 	data_digest_len = (icc->ulp_submode & ULP_CRC_DATA) ?
 	    ISCSI_DATA_DIGEST_SIZE : 0;
 	hdr_digest_len = (icc->ulp_submode & ULP_CRC_HEADER) ?
@@ -658,8 +699,6 @@ do_rx_iscsi_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
 		m_freem(m);
 		return (0);
 	}
-	MPASS(icc->icc_signature == CXGBEI_CONN_SIGNATURE);
-	ic = &icc->ic;
 	icl_cxgbei_new_pdu_set_conn(ip, ic);
 
 	/* Enqueue the PDU to the received pdus queue. */
diff --git a/sys/dev/cxgbe/cxgbei/cxgbei.h b/sys/dev/cxgbe/cxgbei/cxgbei.h
index 09d556988091..58a5dac6d63b 100644
--- a/sys/dev/cxgbe/cxgbei/cxgbei.h
+++ b/sys/dev/cxgbe/cxgbei/cxgbei.h
@@ -96,9 +96,6 @@ enum {
 	ICPF_RX_FLBUF	= 1 << 1, /* PDU payload received in a freelist. */
 	ICPF_RX_DDP	= 1 << 2, /* PDU payload DDP'd. */
 	ICPF_RX_STATUS	= 1 << 3, /* Rx status received. */
-	ICPF_HCRC_ERR	= 1 << 4, /* Header digest error. */
-	ICPF_DCRC_ERR	= 1 << 5, /* Data digest error. */
-	ICPF_PAD_ERR	= 1 << 6, /* Padding error. */
 
 	CXGBEI_PDU_SIGNATURE = 0x12344321
 };
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index 6b40a23516d7..bddacb448ff5 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -4162,6 +4162,15 @@ add_ofld_rxq_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *oid,
 	SYSCTL_ADD_U64(ctx, children, OID_AUTO, "fl_pdus",
 	    CTLFLAG_RD, &ofld_rxq->rx_iscsi_fl_pdus, 0,
 	    "# of PDUs with data delivered in freelist");
+	SYSCTL_ADD_U64(ctx, children, OID_AUTO, "padding_errors",
+	    CTLFLAG_RD, &ofld_rxq->rx_iscsi_padding_errors, 0,
+	    "# of PDUs with invalid padding");
+	SYSCTL_ADD_U64(ctx, children, OID_AUTO, "header_digest_errors",
+	    CTLFLAG_RD, &ofld_rxq->rx_iscsi_header_digest_errors, 0,
+	    "# of PDUs with invalid header digests");
+	SYSCTL_ADD_U64(ctx, children, OID_AUTO, "data_digest_errors",
+	    CTLFLAG_RD, &ofld_rxq->rx_iscsi_data_digest_errors, 0,
+	    "# of PDUs with invalid data digests");
 }
 #endif