aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2021-08-02 16:41:27 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2021-10-29 23:17:31 +0000
commit202f2c169bec8a0fc5d1981980b1388e9912201b (patch)
tree6b78ab5d43d5d4fc6051f642087f5f83c722b96e
parent7f82047ec961383a0f8c11f9943522831f590f97 (diff)
downloadsrc-202f2c169bec8a0fc5d1981980b1388e9912201b.tar.gz
src-202f2c169bec8a0fc5d1981980b1388e9912201b.zip
cxgbe tom: Permit rcv_nxt mismatches on FIN for iSCSI connections on T6.
The remote peer might send a FIN in the middle of a burst of data PDUs. In the case of T6 with data PDU completion moderation, the driver would not have seen these PDUs since the final PDU in the burst was never received resulting in a stale rcv_nxt when the FIN is received. While here, invert the logic in the condition to be more readable and always set tp->rcv_nxt from the sequence number in the CPL. This sets the proper value of rcv_nxt for FINs on connections with data received but not reported via a CPL (e.g. a partial iSCSI PDU burst interrupted by a FIN). Reported by: Jithesh Arakkan @ Chelsio Reviewed by: np Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D30871 (cherry picked from commit d59f1c49e26ba29e7583019bb5d6aa029466fdb6) cxgbe tom: Update rcv_nxt for a FIN after handle_ddp_close(). For TCP DDP, handle_ddp_close() needs to see the pre-FIN rcv_nxt to determine how much data was placed in the local buffer before the FIN was received. The changes in d59f1c49e26b broke this by updating rcv_nxt before calling handle_ddp_close(). Fixes: d59f1c49e26b cxgbe tom: Permit rcv_nxt mismatches on FIN for iSCSI connections on T6. Sponsored by: Chelsio Communications (cherry picked from commit 5dbf8c1588da167c17c45bdf78de51fcb4929504)
-rw-r--r--sys/dev/cxgbe/tom/t4_cpl_io.c20
-rw-r--r--sys/dev/cxgbe/tom/t4_ddp.c3
2 files changed, 16 insertions, 7 deletions
diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c
index acb2d3408244..66e3955445f9 100644
--- a/sys/dev/cxgbe/tom/t4_cpl_io.c
+++ b/sys/dev/cxgbe/tom/t4_cpl_io.c
@@ -1292,8 +1292,6 @@ do_peer_close(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
if (toep->flags & TPF_ABORT_SHUTDOWN)
goto done;
- tp->rcv_nxt++; /* FIN */
-
so = inp->inp_socket;
socantrcvmore(so);
if (ulp_mode(toep) == ULP_MODE_TCPDDP) {
@@ -1304,12 +1302,22 @@ do_peer_close(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
DDP_UNLOCK(toep);
}
- if (ulp_mode(toep) != ULP_MODE_RDMA) {
- KASSERT(tp->rcv_nxt == be32toh(cpl->rcv_nxt),
- ("%s: rcv_nxt mismatch: %u %u", __func__, tp->rcv_nxt,
- be32toh(cpl->rcv_nxt)));
+ if (ulp_mode(toep) == ULP_MODE_RDMA ||
+ (ulp_mode(toep) == ULP_MODE_ISCSI && chip_id(sc) >= CHELSIO_T6)) {
+ /*
+ * There might be data received via DDP before the FIN
+ * not reported to the driver. Just assume the
+ * sequence number in the CPL is correct as the
+ * sequence number of the FIN.
+ */
+ } else {
+ KASSERT(tp->rcv_nxt + 1 == be32toh(cpl->rcv_nxt),
+ ("%s: rcv_nxt mismatch: %u %u", __func__, tp->rcv_nxt,
+ be32toh(cpl->rcv_nxt)));
}
+ tp->rcv_nxt = be32toh(cpl->rcv_nxt);
+
switch (tp->t_state) {
case TCPS_SYN_RECEIVED:
tp->t_starttime = ticks;
diff --git a/sys/dev/cxgbe/tom/t4_ddp.c b/sys/dev/cxgbe/tom/t4_ddp.c
index 2b58cb60d4fd..be142ffb9e4f 100644
--- a/sys/dev/cxgbe/tom/t4_ddp.c
+++ b/sys/dev/cxgbe/tom/t4_ddp.c
@@ -700,7 +700,8 @@ handle_ddp_close(struct toepcb *toep, struct tcpcb *tp, __be32 rcv_nxt)
INP_WLOCK_ASSERT(toep->inp);
DDP_ASSERT_LOCKED(toep);
- len = be32toh(rcv_nxt) - tp->rcv_nxt;
+ /* - 1 is to ignore the byte for FIN */
+ len = be32toh(rcv_nxt) - tp->rcv_nxt - 1;
tp->rcv_nxt += len;
while (toep->ddp.active_count > 0) {