Index: sys/cam/ctl/ctl_frontend_iscsi.c =================================================================== --- sys/cam/ctl/ctl_frontend_iscsi.c +++ sys/cam/ctl/ctl_frontend_iscsi.c @@ -909,7 +909,12 @@ return; } +#if 0 + if (cdw->cdw_datasn + (request->ip_npdus == 0 ? 0 : + request->ip_npdus - 1) != ntohl(bhsdo->bhsdo_datasn)) { +#else if (cdw->cdw_datasn != ntohl(bhsdo->bhsdo_datasn)) { +#endif CFISCSI_SESSION_WARN(cs, "received Data-Out PDU with " "DataSN %u, while expected %u; dropping connection", ntohl(bhsdo->bhsdo_datasn), cdw->cdw_datasn); @@ -917,7 +922,10 @@ cfiscsi_session_terminate(cs); return; } - cdw->cdw_datasn++; + if (request->ip_npdus != 0) + cdw->cdw_datasn += request->ip_npdus; + else + cdw->cdw_datasn++; io = cdw->cdw_ctl_io; KASSERT((io->io_hdr.flags & CTL_FLAG_DATA_MASK) != CTL_FLAG_DATA_IN, Index: sys/dev/cxgbe/cxgbei/cxgbei.h =================================================================== --- sys/dev/cxgbe/cxgbei/cxgbei.h +++ sys/dev/cxgbe/cxgbei/cxgbei.h @@ -58,7 +58,6 @@ uint32_t tt; /* Transfer tag. */ - uint32_t next_datasn; uint32_t next_buffer_offset; uint32_t last_datasn; }; Index: sys/dev/cxgbe/cxgbei/cxgbei.c =================================================================== --- sys/dev/cxgbe/cxgbei/cxgbei.c +++ sys/dev/cxgbe/cxgbei/cxgbei.c @@ -591,10 +591,12 @@ cmp->next_buffer_offset; if (prev_seg_len != 0) { + uint32_t orig_datasn; + /* - * Since cfiscsi doesn't know about previous - * headers, pretend that the entire r2t data - * length was received in this single segment. + * Return a "large" PDU representing the burst + * of PDUs. Adjust the offset and length of + * this PDU to represent the entire burst. */ ip->ip_data_len += prev_seg_len; bhsdo->bhsdo_data_segment_len[2] = ip->ip_data_len; @@ -603,11 +605,16 @@ bhsdo->bhsdo_buffer_offset = htobe32(cmp->next_buffer_offset); - npdus = htobe32(bhsdo->bhsdo_datasn) - cmp->last_datasn; + orig_datasn = htobe32(bhsdo->bhsdo_datasn); + npdus = orig_datasn - cmp->last_datasn; + bhsdo->bhsdo_datasn = htobe32(cmp->last_datasn + 1); + cmp->last_datasn = orig_datasn; + ip->ip_npdus = npdus; } else { MPASS(htobe32(bhsdo->bhsdo_datasn) == cmp->last_datasn + 1); npdus = 1; + cmp->last_datasn = htobe32(bhsdo->bhsdo_datasn); } #if 1 @@ -617,9 +624,6 @@ htobe32(bhsdo->bhsdo_datasn)); #endif cmp->next_buffer_offset += ip->ip_data_len; - cmp->last_datasn = htobe32(bhsdo->bhsdo_datasn); - bhsdo->bhsdo_datasn = htobe32(cmp->next_datasn); - cmp->next_datasn++; toep->ofld_rxq->rx_iscsi_ddp_pdus += npdus; toep->ofld_rxq->rx_iscsi_ddp_octets += ip->ip_data_len; } else { Index: sys/dev/cxgbe/cxgbei/icl_cxgbei.c =================================================================== --- sys/dev/cxgbe/cxgbei/icl_cxgbei.c +++ sys/dev/cxgbe/cxgbei/icl_cxgbei.c @@ -1359,7 +1359,6 @@ prsv->prsv_tag &= ~pr->pr_alias_mask; prsv->prsv_tag |= alias << pr->pr_alias_shift & pr->pr_alias_mask; - ddp->cmp.next_datasn = 0; ddp->cmp.last_datasn = -1; cxgbei_insert_cmp(icc, &ddp->cmp, prsv->prsv_tag); *tttp = htobe32(prsv->prsv_tag); Index: sys/dev/iscsi/icl.h =================================================================== --- sys/dev/iscsi/icl.h +++ sys/dev/iscsi/icl.h @@ -75,6 +75,13 @@ size_t ip_data_len; struct mbuf *ip_data_mbuf; + /* + * When a "large" received PDU represents multiple on-the-wire + * PDUs, this is the count of on-the-wire PDUs. For PDUs that + * match on-the-wire PDUs, this should be set to zero. + */ + u_int ip_npdus; + /* * User (initiator or provider) private fields. */