aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2025-11-10 15:50:47 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2025-11-10 15:50:47 +0000
commitc1b3c5f5f3fab895df3d2e75ac3edee4e9aa6432 (patch)
treed8a30ccc73f477901f85ba7eb215fa9eecf4cc5e
parent62caae230859423ae045b5d754f30d193ca628c0 (diff)
nvmf: Add a transport hook to limit the maximum command capsule size
NVMe controllers advertise the largest supported size of a command capsule in the controller data (IOCCSZ). Smart NIC offload transports may have a cap on the size of the largest data PDU that can be received. These transports can implement this hook to limit the advertised IOCCSZ to limit the in-capsule-data payload sent by remote hosts. Sponsored by: Chelsio Communications
-rw-r--r--sys/dev/nvmf/nvmf_tcp.c7
-rw-r--r--sys/dev/nvmf/nvmf_transport.c6
-rw-r--r--sys/dev/nvmf/nvmf_transport.h6
-rw-r--r--sys/dev/nvmf/nvmf_transport_internal.h3
4 files changed, 22 insertions, 0 deletions
diff --git a/sys/dev/nvmf/nvmf_tcp.c b/sys/dev/nvmf/nvmf_tcp.c
index 0e31c0495775..481c769cedcb 100644
--- a/sys/dev/nvmf/nvmf_tcp.c
+++ b/sys/dev/nvmf/nvmf_tcp.c
@@ -1602,6 +1602,12 @@ tcp_free_qpair(struct nvmf_qpair *nq)
tcp_release_qpair(qp);
}
+static uint32_t
+tcp_max_ioccsz(struct nvmf_qpair *nq)
+{
+ return (0);
+}
+
static uint64_t
tcp_max_xfer_size(struct nvmf_qpair *nq)
{
@@ -1878,6 +1884,7 @@ tcp_send_controller_data(struct nvmf_capsule *nc, uint32_t data_offset,
struct nvmf_transport_ops tcp_ops = {
.allocate_qpair = tcp_allocate_qpair,
.free_qpair = tcp_free_qpair,
+ .max_ioccsz = tcp_max_ioccsz,
.max_xfer_size = tcp_max_xfer_size,
.allocate_capsule = tcp_allocate_capsule,
.free_capsule = tcp_free_capsule,
diff --git a/sys/dev/nvmf/nvmf_transport.c b/sys/dev/nvmf/nvmf_transport.c
index d552393f7adf..92d71d1b13fd 100644
--- a/sys/dev/nvmf/nvmf_transport.c
+++ b/sys/dev/nvmf/nvmf_transport.c
@@ -194,6 +194,12 @@ nvmf_max_xfer_size(struct nvmf_qpair *qp)
return (qp->nq_ops->max_xfer_size(qp));
}
+uint32_t
+nvmf_max_ioccsz(struct nvmf_qpair *qp)
+{
+ return (qp->nq_ops->max_ioccsz(qp));
+}
+
uint8_t
nvmf_validate_command_capsule(struct nvmf_capsule *nc)
{
diff --git a/sys/dev/nvmf/nvmf_transport.h b/sys/dev/nvmf/nvmf_transport.h
index 38b661ab3c91..495e0dbc8c37 100644
--- a/sys/dev/nvmf/nvmf_transport.h
+++ b/sys/dev/nvmf/nvmf_transport.h
@@ -92,6 +92,12 @@ uint64_t nvmf_max_xfer_size(struct nvmf_qpair *qp);
/* Controller-specific APIs. */
/*
+ * Largest I/O command capsule size (IOCCSZ) supported by the
+ * transport. If the transport does not have a limit, returns 0.
+ */
+uint32_t nvmf_max_ioccsz(struct nvmf_qpair *qp);
+
+/*
* A controller calls this function to check for any
* transport-specific errors (invalid fields) in a received command
* capsule. The callback returns a generic command status value:
diff --git a/sys/dev/nvmf/nvmf_transport_internal.h b/sys/dev/nvmf/nvmf_transport_internal.h
index 511aac120fdc..9b459716168a 100644
--- a/sys/dev/nvmf/nvmf_transport_internal.h
+++ b/sys/dev/nvmf/nvmf_transport_internal.h
@@ -25,6 +25,9 @@ struct nvmf_transport_ops {
const nvlist_t *nvl);
void (*free_qpair)(struct nvmf_qpair *qp);
+ /* Limit on I/O command capsule size. */
+ uint32_t (*max_ioccsz)(struct nvmf_qpair *qp);
+
/* Limit on transfer size. */
uint64_t (*max_xfer_size)(struct nvmf_qpair *qp);