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
This commit is contained in:
parent
c96b4d87ba
commit
4d4cf62e29
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -4163,6 +4163,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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user