The branch main has been updated by jhb:

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

commit bedfac1f026fa8e2e6572ca380d89d74a01d5def
Author:     John Baldwin <[email protected]>
AuthorDate: 2024-09-05 21:14:36 +0000
Commit:     John Baldwin <[email protected]>
CommitDate: 2024-09-05 21:14:36 +0000

    nvmf_tcp: Fully honor kern.nvmf.tcp.max_transmit_data for C2H_DATA PDUs
    
    The previous version of tcp_send_controller_data avoided sending a
    chain of multiple mbufs that exceeded the limit, but if an individual
    mbuf was larger than the limit it was sent as a single, over-sized
    PDU.  Fix by using m_split() to split individual mbufs larger than the
    limit.
    
    Note that this is not a protocol error, per se, as there is no limit
    on C2H_DATA PDU lengths (unlike the MAXH2CDATA parameter).  This fix
    just honors the administrative limit more faithfully.  This case is
    also very unlikely with the default limit of 256k.
    
    Sponsored by:   Chelsio Communications
---
 sys/dev/nvmf/nvmf_tcp.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/sys/dev/nvmf/nvmf_tcp.c b/sys/dev/nvmf/nvmf_tcp.c
index 67d239b63faf..22275aaa835b 100644
--- a/sys/dev/nvmf/nvmf_tcp.c
+++ b/sys/dev/nvmf/nvmf_tcp.c
@@ -1784,7 +1784,6 @@ tcp_send_controller_data(struct nvmf_capsule *nc, 
uint32_t data_offset,
 {
        struct nvmf_tcp_qpair *qp = TQP(nc->nc_qpair);
        struct nvme_sgl_descriptor *sgl;
-       struct mbuf *n, *p;
        uint32_t data_len;
        bool last_pdu, last_xfer;
 
@@ -1813,21 +1812,29 @@ tcp_send_controller_data(struct nvmf_capsule *nc, 
uint32_t data_offset,
 
        /* Queue one more C2H_DATA PDUs containing the data from 'm'. */
        while (m != NULL) {
+               struct mbuf *n;
                uint32_t todo;
 
-               todo = m->m_len;
-               p = m;
-               n = p->m_next;
-               while (n != NULL) {
-                       if (todo + n->m_len > qp->max_tx_data) {
-                               p->m_next = NULL;
-                               break;
-                       }
-                       todo += n->m_len;
-                       p = n;
+               if (m->m_len > qp->max_tx_data) {
+                       n = m_split(m, qp->max_tx_data, M_WAITOK);
+                       todo = m->m_len;
+               } else {
+                       struct mbuf *p;
+
+                       todo = m->m_len;
+                       p = m;
                        n = p->m_next;
+                       while (n != NULL) {
+                               if (todo + n->m_len > qp->max_tx_data) {
+                                       p->m_next = NULL;
+                                       break;
+                               }
+                               todo += n->m_len;
+                               p = n;
+                               n = p->m_next;
+                       }
+                       MPASS(m_length(m, NULL) == todo);
                }
-               MPASS(m_length(m, NULL) == todo);
 
                last_pdu = (n == NULL && last_xfer);
                tcp_send_c2h_pdu(qp, nc->nc_sqe.cid, data_offset, m, todo,

Reply via email to