Commit 7c7511f1 authored by Saravanan Vajravel's avatar Saravanan Vajravel Committed by Leon Romanovsky
Browse files

RDMA/bnxt_re: Add support for flow create/destroy



- Added support for create_flow and destroy_flow verbs. These
  verbs are used on RawEth QP to add a specific flow action.
- To support TCP dump on RoCE, added IB_FLOW_ATTR_SNIFFER
  attribute.
- In create_flow verb, driver allocates mirror_vnic and configure it
  with RawEth QP. Once this is done, driver will enable mirroring.
- In destroy_flow, driver will disable mirroring and free the mirror
  vnic.

Signed-off-by: default avatarSaravanan Vajravel <saravanan.vajravel@broadcom.com>
Reviewed-by: default avatarKashyap Desai <kashyap.desai@broadcom.com>
Reviewed-by: default avatarSelvin Xavier <selvin.xavier@broadcom.com>
Signed-off-by: default avatarKalesh AP <kalesh-anakkur.purayil@broadcom.com>
Link: https://patch.msgid.link/20250822040801.776196-8-kalesh-anakkur.purayil@broadcom.com


Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
parent fd6c9ae7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -232,6 +232,7 @@ struct bnxt_re_dev {
	u16 mirror_vnic_id;
	union ib_gid ugid;
	u32 ugid_index;
	u8 sniffer_flow_created : 1;
};

#define to_bnxt_re_dev(ptr, member)	\
+87 −0
Original line number Diff line number Diff line
@@ -4449,6 +4449,93 @@ void bnxt_re_dealloc_ucontext(struct ib_ucontext *ib_uctx)
	}
}

static int bnxt_re_setup_vnic(struct bnxt_re_dev *rdev, struct bnxt_re_qp *qp)
{
	int rc;

	rc = bnxt_re_hwrm_alloc_vnic(rdev);
	if (rc)
		return rc;

	rc = bnxt_re_hwrm_cfg_vnic(rdev, qp->qplib_qp.id);
	if (rc)
		goto out_free_vnic;

	return 0;
out_free_vnic:
	bnxt_re_hwrm_free_vnic(rdev);
	return rc;
}

struct ib_flow *bnxt_re_create_flow(struct ib_qp *ib_qp,
				    struct ib_flow_attr *attr,
				    struct ib_udata *udata)
{
	struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
	struct bnxt_re_dev *rdev = qp->rdev;
	struct bnxt_re_flow *flow;
	int rc;

	if (attr->type != IB_FLOW_ATTR_SNIFFER ||
	    !rdev->rcfw.roce_mirror)
		return ERR_PTR(-EOPNOTSUPP);

	mutex_lock(&rdev->qp_lock);
	if (rdev->sniffer_flow_created) {
		ibdev_err(&rdev->ibdev, "RoCE Mirroring is already Configured\n");
		mutex_unlock(&rdev->qp_lock);
		return ERR_PTR(-EBUSY);
	}

	flow = kzalloc(sizeof(*flow), GFP_KERNEL);
	if (!flow) {
		mutex_unlock(&rdev->qp_lock);
		return ERR_PTR(-ENOMEM);
	}

	flow->rdev = rdev;

	rc = bnxt_re_setup_vnic(rdev, qp);
	if (rc)
		goto out_free_flow;

	rc = bnxt_qplib_create_flow(&rdev->qplib_res);
	if (rc)
		goto out_free_vnic;

	rdev->sniffer_flow_created = 1;
	mutex_unlock(&rdev->qp_lock);

	return &flow->ib_flow;

out_free_vnic:
	bnxt_re_hwrm_free_vnic(rdev);
out_free_flow:
	mutex_unlock(&rdev->qp_lock);
	kfree(flow);
	return ERR_PTR(rc);
}

int bnxt_re_destroy_flow(struct ib_flow *flow_id)
{
	struct bnxt_re_flow *flow =
		container_of(flow_id, struct bnxt_re_flow, ib_flow);
	struct bnxt_re_dev *rdev = flow->rdev;
	int rc;

	mutex_lock(&rdev->qp_lock);
	rc = bnxt_qplib_destroy_flow(&rdev->qplib_res);
	if (rc)
		ibdev_dbg(&rdev->ibdev, "failed to destroy_flow rc = %d\n", rc);
	rdev->sniffer_flow_created = 0;

	bnxt_re_hwrm_free_vnic(rdev);
	mutex_unlock(&rdev->qp_lock);
	kfree(flow);

	return rc;
}

static struct bnxt_re_cq *bnxt_re_search_for_cq(struct bnxt_re_dev *rdev, u32 cq_id)
{
	struct bnxt_re_cq *cq = NULL, *tmp_cq;
+5 −0
Original line number Diff line number Diff line
@@ -272,6 +272,11 @@ struct ib_mr *bnxt_re_reg_user_mr_dmabuf(struct ib_pd *ib_pd, u64 start,
					 struct uverbs_attr_bundle *attrs);
int bnxt_re_alloc_ucontext(struct ib_ucontext *ctx, struct ib_udata *udata);
void bnxt_re_dealloc_ucontext(struct ib_ucontext *context);
struct ib_flow *bnxt_re_create_flow(struct ib_qp *ib_qp,
				    struct ib_flow_attr *attr,
				    struct ib_udata *udata);
int bnxt_re_destroy_flow(struct ib_flow *flow_id);

int bnxt_re_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry);

+2 −0
Original line number Diff line number Diff line
@@ -1365,6 +1365,8 @@ static const struct ib_device_ops bnxt_re_dev_ops = {
	.reg_user_mr_dmabuf = bnxt_re_reg_user_mr_dmabuf,
	.req_notify_cq = bnxt_re_req_notify_cq,
	.resize_cq = bnxt_re_resize_cq,
	.create_flow = bnxt_re_create_flow,
	.destroy_flow = bnxt_re_destroy_flow,
	INIT_RDMA_OBJ_SIZE(ib_ah, bnxt_re_ah, ib_ah),
	INIT_RDMA_OBJ_SIZE(ib_cq, bnxt_re_cq, ib_cq),
	INIT_RDMA_OBJ_SIZE(ib_pd, bnxt_re_pd, ib_pd),
+37 −0
Original line number Diff line number Diff line
@@ -1146,3 +1146,40 @@ int bnxt_qplib_query_cc_param(struct bnxt_qplib_res *res,
	dma_free_coherent(&rcfw->pdev->dev, sbuf.size, sbuf.sb, sbuf.dma_addr);
	return rc;
}

int bnxt_qplib_create_flow(struct bnxt_qplib_res *res)
{
	struct creq_roce_mirror_cfg_resp resp = {};
	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
	struct cmdq_roce_mirror_cfg req = {};
	struct bnxt_qplib_cmdqmsg msg = {};

	bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
				 CMDQ_BASE_OPCODE_ROCE_MIRROR_CFG,
				 sizeof(req));

	req.mirror_flags = (u8)CMDQ_ROCE_MIRROR_CFG_MIRROR_ENABLE;

	bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req),
				sizeof(resp), 0);
	return bnxt_qplib_rcfw_send_message(rcfw, &msg);
}

int bnxt_qplib_destroy_flow(struct bnxt_qplib_res *res)
{
	struct creq_roce_mirror_cfg_resp resp = {};
	struct bnxt_qplib_rcfw *rcfw = res->rcfw;
	struct cmdq_roce_mirror_cfg req = {};
	struct bnxt_qplib_cmdqmsg msg = {};

	bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
				 CMDQ_BASE_OPCODE_ROCE_MIRROR_CFG,
				 sizeof(req));

	req.mirror_flags &= ~((u8)CMDQ_ROCE_MIRROR_CFG_MIRROR_ENABLE);

	bnxt_qplib_fill_cmdqmsg(&msg, &req, &resp, NULL, sizeof(req),
				sizeof(resp), 0);

	return bnxt_qplib_rcfw_send_message(rcfw, &msg);
}
Loading