lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251218091050.55047-7-15927021679@163.com>
Date: Thu, 18 Dec 2025 17:09:46 +0800
From: Xiong Weimin <15927021679@....com>
To: "Michael S . Tsirkin" <mst@...hat.com>,
	David Hildenbrand <david@...hat.com>,
	Jason Wang <jasowang@...hat.com>,
	Stefano Garzarella <sgarzare@...hat.com>,
	Thomas Monjalon <thomas@...jalon.net>,
	David Marchand <david.marchand@...hat.com>,
	Luca Boccassi <bluca@...ian.org>,
	Kevin Traynor <ktraynor@...hat.com>,
	Christian Ehrhardt <christian.ehrhardt@...onical.com>,
	Xuan Zhuo <xuanzhuo@...ux.alibaba.com>,
	Eugenio Pérez <eperezma@...hat.com>,
	Xueming Li <xuemingl@...dia.com>,
	Maxime Coquelin <maxime.coquelin@...hat.com>,
	Chenbo Xia <chenbox@...dia.com>,
	Bruce Richardson <bruce.richardson@...el.com>
Cc: kvm@...r.kernel.org,
	virtualization@...ts.linux.dev,
	netdev@...r.kernel.org,
	xiongweimin <xiongweimin@...inos.cn>
Subject: [PATCH 06/10] drivers/infiniband/hw/virtio: Implement port management and QP modification verbs

From: xiongweimin <xiongweimin@...inos.cn>

This commit adds essential RDMA verbs implementation for the virtio RDMA driver:

1. Port modification support (vrdma_modify_port):
   - Adds IB_PORT_SHUTDOWN flag handling for port deactivation
   - Maintains port capability mask state
   - Enforces strict attribute mask validation
   - Provides proper locking with port_mutex

2. Queue Pair modification support (vrdma_modify_qp):
   - Implements full QP attribute translation to virtio commands
   - Handles all standard IB_QP_* attribute masks (21 bits)
   - Uses efficient two-buffer scheme for device communication
   - Includes comprehensive error handling

Key features:
- Minimal port modification support focused on shutdown capability
- Complete QP state transition handling
- Attribute-by-attribute translation with 32+ fields covered
- Safe memory management with guaranteed cleanup
- Verbose error logging for debugging

Signed-off-by: Xiong Weimin <xiongweimin@...inos.cn>
---
 .../infiniband/hw/virtio/vrdma_dev_api.h      |  12 +
 .../drivers/infiniband/hw/virtio/vrdma_ib.c   | 223 +++++++++++++++++-
 .../drivers/infiniband/hw/virtio/vrdma_ib.h   |  54 +++++
 3 files changed, 288 insertions(+), 1 deletion(-)

diff --git a/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_dev_api.h b/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_dev_api.h
index 84dc05a96..d0ce02601 100644
--- a/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_dev_api.h
+++ b/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_dev_api.h
@@ -14,6 +14,8 @@
 
 #include <rdma/vrdma_abi.h>
 
+#include "vrdma_ib.h"
+
 /**
  * struct vrdma_config - Virtio RDMA device configuration
  *
@@ -213,6 +215,16 @@ struct vrdma_rsp_map_mr_sg {
 	__u32 npages;
 };
 
+struct vrdma_cmd_modify_qp {
+    __u32 qpn;
+    __u32 attr_mask;
+    struct vrdma_qp_attr attrs;
+};
+
+struct vrdma_rsp_modify_qp {
+    __u32 qpn;
+};
+
 #define VRDMA_CTRL_OK	0
 #define VRDMA_CTRL_ERR	1
 
diff --git a/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.c b/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.c
index 738935e3d..2d9a612f3 100644
--- a/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.c
+++ b/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.c
@@ -55,6 +55,37 @@ static const char * const cmd_str[] = {
 	[VIRTIO_RDMA_CMD_REQ_NOTIFY_CQ]	= "REQ_NOTIFY_CQ",
 };
 
+static void ib_qp_cap_to_vrdma(struct vrdma_qp_cap *dst, const struct ib_qp_cap *src)
+{
+	//dst->max_send_wr = src->max_send_wr;
+	dst->max_send_wr = src->max_send_wr;
+	dst->max_recv_wr = src->max_recv_wr;
+	dst->max_send_sge = src->max_send_sge;
+	dst->max_recv_sge = src->max_recv_sge;
+	dst->max_inline_data = src->max_inline_data;
+}
+
+static void ib_global_route_to_vrdma(struct vrdma_global_route *dst,
+			       const struct ib_global_route *src)
+{
+	dst->dgid = src->dgid;
+	dst->flow_label = src->flow_label;
+	dst->sgid_index = src->sgid_index;
+	dst->hop_limit = src->hop_limit;
+	dst->traffic_class = src->traffic_class;
+}
+
+static void rdma_ah_attr_to_vrdma(struct vrdma_ah_attr *dst,
+			    const struct rdma_ah_attr *src)
+{
+	ib_global_route_to_vrdma(&dst->grh, rdma_ah_read_grh(src));
+	dst->sl = rdma_ah_get_sl(src);
+	dst->static_rate = rdma_ah_get_static_rate(src);
+	dst->port_num = rdma_ah_get_port_num(src);
+	dst->ah_flags = rdma_ah_get_ah_flags(src);
+	memcpy(&dst->roce, &src->roce, sizeof(struct roce_ah_attr));
+}
+
 /**
  * vrdma_exec_verbs_cmd - Execute a verbs command via control virtqueue
  * @vrdev: VRDMA device
@@ -1922,6 +1953,194 @@ void vrdma_mmap_free(struct rdma_user_mmap_entry *rdma_entry)
 	kfree(entry);
 }
 
+/**
+ * vrdma_modify_port - Modify port attributes (limited support)
+ * @ibdev:	Verbs device
+ * @port:	Port number (1-indexed)
+ * @mask:	Bitmask of attributes to modify
+ * @props:	New port properties
+ *
+ * Currently only supports IB_PORT_SHUTDOWN flag.
+ * Other flags are rejected with -EOPNOTSUPP.
+ *
+ * Context: Can sleep (holds mutex).
+ * Return:
+ * * 0 on success
+ * * -EOPNOTSUPP if unsupported mask bits set
+ * * error code from ib_query_port() on failure
+ */
+static int vrdma_modify_port(struct ib_device *ibdev, u32 port, int mask,
+			     struct ib_port_modify *props)
+{
+	struct vrdma_dev *vdev = to_vdev(ibdev);
+	struct ib_port_attr attr;
+	int ret;
+
+	/* Only allow IB_PORT_SHUTDOWN; reject all others */
+	if (mask & ~IB_PORT_SHUTDOWN) {
+		pr_warn("vRDMA: unsupported port modify mask %#x\n", mask);
+		return -EOPNOTSUPP;
+	}
+
+	mutex_lock(&vdev->port_mutex);
+
+	/* Query current port state (required by spec before modify in some cases) */
+	ret = ib_query_port(ibdev, port, &attr);
+	if (ret) {
+		pr_err("vRDMA: failed to query port %u: %d\n", port, ret);
+		goto out_unlock;
+	}
+
+	/* Apply capability mask changes */
+	vdev->port_cap_mask |= props->set_port_cap_mask;
+	vdev->port_cap_mask &= ~props->clr_port_cap_mask;
+
+	/* Handle shutdown request */
+	if (mask & IB_PORT_SHUTDOWN) {
+		vdev->ib_active = false;
+		pr_info("vRDMA: port %u marked as inactive\n", port);
+	}
+
+	ret = 0;  /* Success */
+
+out_unlock:
+	mutex_unlock(&vdev->port_mutex);
+	return ret;
+}
+
+/**
+ * vrdma_modify_qp - Modify QP attributes via backend
+ * @ibqp:	Queue pair to modify
+ * @attr:	New QP attributes
+ * @attr_mask:	Which fields in @attr are valid
+ * @udata:	User data (unused here)
+ *
+ * Sends a VIRTIO_RDMA_CMD_MODIFY_QP command to the host backend
+ * to update the QP's state and parameters.
+ *
+ * Context: Process context (may sleep due to memory allocation).
+ * Return:
+ * * 0 on success
+ * * -ENOMEM if command buffer allocation fails
+ * * -EIO or other negative errno on communication failure
+ */
+static int vrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		    int attr_mask, struct ib_udata *udata)
+{
+	struct vrdma_dev *vdev = to_vdev(ibqp->device);
+	struct vrdma_cmd_modify_qp *cmd;
+	struct vrdma_rsp_modify_qp *rsp;
+	struct scatterlist in, out;
+	int rc;
+
+	/* Allocate command and response buffers */
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
+	if (!rsp) {
+		kfree(cmd);
+		return -ENOMEM;
+	}
+
+	/* Fill command header */
+	cmd->qpn = to_vqp(ibqp)->qp_handle;
+	cmd->attr_mask = attr_mask & ((1U << 21) - 1);  /* Limit to 21 bits */
+
+	/* Conditionally copy fields based on attr_mask */
+	if (attr_mask & IB_QP_STATE)
+		cmd->attrs.qp_state = attr->qp_state;
+
+	if (attr_mask & IB_QP_CUR_STATE)
+		cmd->attrs.cur_qp_state = attr->cur_qp_state;
+
+	if (attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY)
+		cmd->attrs.en_sqd_async_notify = attr->en_sqd_async_notify;
+
+	if (attr_mask & IB_QP_ACCESS_FLAGS)
+		cmd->attrs.qp_access_flags = attr->qp_access_flags;
+
+	if (attr_mask & IB_QP_PKEY_INDEX)
+		cmd->attrs.pkey_index = attr->pkey_index;
+
+	if (attr_mask & IB_QP_PORT)
+		cmd->attrs.port_num = attr->port_num;
+
+	if (attr_mask & IB_QP_QKEY)
+		cmd->attrs.qkey = attr->qkey;
+
+	if (attr_mask & IB_QP_AV)
+		rdma_ah_attr_to_vrdma(&cmd->attrs.ah_attr, &attr->ah_attr);
+
+	if (attr_mask & IB_QP_ALT_PATH)
+		rdma_ah_attr_to_vrdma(&cmd->attrs.alt_ah_attr, &attr->alt_ah_attr);
+
+	if (attr_mask & IB_QP_PATH_MTU)
+		cmd->attrs.path_mtu = attr->path_mtu;
+
+	if (attr_mask & IB_QP_TIMEOUT)
+		cmd->attrs.timeout = attr->timeout;
+
+	if (attr_mask & IB_QP_RETRY_CNT)
+		cmd->attrs.retry_cnt = attr->retry_cnt;
+
+	if (attr_mask & IB_QP_RNR_RETRY)
+		cmd->attrs.rnr_retry = attr->rnr_retry;
+
+	if (attr_mask & IB_QP_MIN_RNR_TIMER)
+		cmd->attrs.min_rnr_timer = attr->min_rnr_timer;
+
+	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC)
+		cmd->attrs.max_rd_atomic = attr->max_rd_atomic;
+
+	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
+		cmd->attrs.max_dest_rd_atomic = attr->max_dest_rd_atomic;
+
+	if (attr_mask & IB_QP_PATH_MIG_STATE)
+		cmd->attrs.path_mig_state = attr->path_mig_state;
+
+	if (attr_mask & IB_QP_CAP)
+		ib_qp_cap_to_vrdma(&cmd->attrs.cap, &attr->cap);
+
+	if (attr_mask & IB_QP_DEST_QPN)
+		cmd->attrs.dest_qp_num = attr->dest_qp_num;
+
+	if (attr_mask & IB_QP_RQ_PSN)
+		cmd->attrs.rq_psn = attr->rq_psn;
+
+	if (attr_mask & IB_QP_SQ_PSN)
+		cmd->attrs.sq_psn = attr->sq_psn;
+
+	cmd->attrs.alt_pkey_index = attr->alt_pkey_index;
+	cmd->attrs.alt_port_num = attr->alt_port_num;
+	cmd->attrs.alt_timeout = attr->alt_timeout;
+
+	if (attr_mask & IB_QP_RATE_LIMIT)
+		cmd->attrs.rate_limit = attr->rate_limit;
+
+	/* Prepare scatterlists for virtqueue I/O */
+	sg_init_one(&in, cmd, sizeof(*cmd));
+	sg_init_one(&out, rsp, sizeof(*rsp));
+
+	/* Send command to backend */
+	rc = vrdma_exec_verbs_cmd(vdev, VIRTIO_RDMA_CMD_MODIFY_QP, &in, &out);
+	if (rc) {
+		dev_err(&vdev->vdev->dev,
+			"VIRTIO_RDMA_CMD_MODIFY_QP failed: qpn=0x%x, err=%d\n",
+			cmd->qpn, rc);
+		goto out_free;
+	}
+
+	/* Optional: Update local QP state based on response if needed */
+	// e.g., to_vqp(ibqp)->state = rsp->new_state;
+
+out_free:
+	kfree(rsp);
+	kfree(cmd);
+	return rc;
+}
+
 static const struct ib_device_ops vrdma_dev_ops = {
 	.owner = THIS_MODULE,
 	.uverbs_abi_ver = VIRTIO_RDMA_ABI_VERSION,
@@ -1950,7 +2169,9 @@ static const struct ib_device_ops vrdma_dev_ops = {
 	.get_link_layer = vrdma_port_link_layer,
 	.map_mr_sg = vrdma_map_mr_sg,
 	.mmap = vrdma_mmap,
-	.mmap_free = vrdma_mmap_free,		
+	.mmap_free = vrdma_mmap_free,
+	.modify_port = vrdma_modify_port,
+	.modify_qp = vrdma_modify_qp,			
 };
 
 /**
diff --git a/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.h b/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.h
index 6759c4349..eaff37c3c 100644
--- a/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.h
+++ b/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.h
@@ -173,6 +173,60 @@ struct vrdma_qp {
 	struct vrdma_user_mmap_entry *rq_entry; /* Mmap entry for RQ buffer */
 };
 
+struct vrdma_global_route {
+	union ib_gid		dgid;
+	uint32_t		flow_label;
+	uint8_t			sgid_index;
+	uint8_t			hop_limit;
+	uint8_t			traffic_class;
+};
+
+struct vrdma_ah_attr {
+	struct vrdma_global_route	grh;
+	uint8_t		sl;
+	uint8_t		static_rate;
+	uint8_t		port_num;
+	uint8_t		ah_flags;
+	struct roce_ah_attr roce;
+};
+
+struct vrdma_qp_cap {
+	uint32_t		max_send_wr;
+	uint32_t		max_recv_wr;
+	uint32_t		max_send_sge;
+	uint32_t		max_recv_sge;
+	uint32_t		max_inline_data;
+};
+
+struct vrdma_qp_attr {
+	enum ib_qp_state	qp_state;
+	enum ib_qp_state	cur_qp_state;
+	enum ib_mtu		path_mtu;
+	enum ib_mig_state	path_mig_state;
+	uint32_t			qkey;
+	uint32_t			rq_psn;
+	uint32_t			sq_psn;
+	uint32_t			dest_qp_num;
+	uint32_t			qp_access_flags;
+	uint16_t			pkey_index;
+	uint16_t			alt_pkey_index;
+	uint8_t			en_sqd_async_notify;
+	uint8_t			sq_draining;
+	uint8_t			max_rd_atomic;
+	uint8_t			max_dest_rd_atomic;
+	uint8_t			min_rnr_timer;
+	uint8_t			port_num;
+	uint8_t			timeout;
+	uint8_t			retry_cnt;
+	uint8_t			rnr_retry;
+	uint8_t			alt_port_num;
+	uint8_t			alt_timeout;
+	uint32_t			rate_limit;
+	struct vrdma_qp_cap	cap;
+	struct vrdma_ah_attr	ah_attr;
+	struct vrdma_ah_attr	alt_ah_attr;
+};
+
 /**
  * struct vrdma_mr - Software state of a Virtio-RDMA Memory Region (MR)
  * @ibmr:		InfiniBand core MR object (contains rkey, lkey, etc.)
-- 
2.43.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ