From: Hadar Hen Zion had...@mellanox.com
Implement ib_uverbs_create_flow and ib_uverbs_destroy_flow to
support flow steering for user space applications.
Signed-off-by: Hadar Hen Zion had...@mellanox.com
Signed-off-by: Or Gerlitz ogerl...@mellanox.com
---
drivers/infiniband/core/uverbs.h |3 +
drivers/infiniband/core/uverbs_cmd.c | 206 +
drivers/infiniband/core/uverbs_main.c | 13 ++-
include/rdma/ib_verbs.h |1 +
include/uapi/rdma/ib_user_verbs.h | 108 +-
5 files changed, 329 insertions(+), 2 deletions(-)
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 0fcd7aa..ad9d102 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -155,6 +155,7 @@ extern struct idr ib_uverbs_cq_idr;
extern struct idr ib_uverbs_qp_idr;
extern struct idr ib_uverbs_srq_idr;
extern struct idr ib_uverbs_xrcd_idr;
+extern struct idr ib_uverbs_rule_idr;
void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
@@ -215,5 +216,7 @@ IB_UVERBS_DECLARE_CMD(destroy_srq);
IB_UVERBS_DECLARE_CMD(create_xsrq);
IB_UVERBS_DECLARE_CMD(open_xrcd);
IB_UVERBS_DECLARE_CMD(close_xrcd);
+IB_UVERBS_DECLARE_CMD(create_flow);
+IB_UVERBS_DECLARE_CMD(destroy_flow);
#endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c
b/drivers/infiniband/core/uverbs_cmd.c
index a7d00f6..956782b 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -54,6 +54,7 @@ static struct uverbs_lock_class qp_lock_class = { .name =
QP-uobj };
static struct uverbs_lock_class ah_lock_class = { .name = AH-uobj };
static struct uverbs_lock_class srq_lock_class = { .name = SRQ-uobj };
static struct uverbs_lock_class xrcd_lock_class = { .name = XRCD-uobj };
+static struct uverbs_lock_class rule_lock_class = { .name = RULE-uobj };
#define INIT_UDATA(udata, ibuf, obuf, ilen, olen) \
do {\
@@ -330,6 +331,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
INIT_LIST_HEAD(ucontext-srq_list);
INIT_LIST_HEAD(ucontext-ah_list);
INIT_LIST_HEAD(ucontext-xrcd_list);
+ INIT_LIST_HEAD(ucontext-rule_list);
ucontext-closing = 0;
resp.num_comp_vectors = file-device-num_comp_vectors;
@@ -2587,6 +2589,210 @@ out_put:
return ret ? ret : in_len;
}
+static int kern_spec_to_ib_spec(struct ib_kern_spec *kern_spec,
+ struct _ib_flow_spec *ib_spec)
+{
+ ib_spec-type = kern_spec-type;
+
+ switch (ib_spec-type) {
+ case IB_FLOW_SPEC_ETH:
+ ib_spec-eth.size = sizeof(struct ib_flow_spec_eth);
+ memcpy(ib_spec-eth.val, kern_spec-eth.val,
+ sizeof(struct ib_flow_eth_filter));
+ memcpy(ib_spec-eth.mask, kern_spec-eth.mask,
+ sizeof(struct ib_flow_eth_filter));
+ break;
+ case IB_FLOW_SPEC_IB:
+ ib_spec-ib.size = sizeof(struct ib_flow_spec_ib);
+ memcpy(ib_spec-ib.val, kern_spec-ib.val,
+ sizeof(struct ib_flow_ib_filter));
+ memcpy(ib_spec-ib.mask, kern_spec-ib.mask,
+ sizeof(struct ib_flow_ib_filter));
+ break;
+ case IB_FLOW_SPEC_IPV4:
+ ib_spec-ipv4.size = sizeof(struct ib_flow_spec_ipv4);
+ memcpy(ib_spec-ipv4.val, kern_spec-ipv4.val,
+ sizeof(struct ib_flow_ipv4_filter));
+ memcpy(ib_spec-ipv4.mask, kern_spec-ipv4.mask,
+ sizeof(struct ib_flow_ipv4_filter));
+ break;
+ case IB_FLOW_SPEC_TCP:
+ case IB_FLOW_SPEC_UDP:
+ ib_spec-tcp_udp.size = sizeof(struct ib_flow_spec_tcp_udp);
+ memcpy(ib_spec-tcp_udp.val, kern_spec-tcp_udp.val,
+ sizeof(struct ib_flow_tcp_udp_filter));
+ memcpy(ib_spec-tcp_udp.mask, kern_spec-tcp_udp.mask,
+ sizeof(struct ib_flow_tcp_udp_filter));
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+ssize_t ib_uverbs_create_flow(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_create_flow cmd;
+ struct ib_uverbs_create_flow_resp resp;
+ struct ib_uobject *uobj;
+ struct ib_flow*flow_id;
+ struct ib_kern_flow_attr *kern_flow_attr;
+ struct ib_flow_attr *flow_attr;
+ struct ib_qp *qp;
+ int err = 0;
+ void *kern_spec;
+ void *ib_spec;
+ int i;
+
+ if (out_len sizeof(resp))
+ return -ENOSPC;
+
+ if (copy_from_user(cmd, buf,