1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
3 * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.
6 #include <rdma/ib_user_verbs.h>
7 #include <rdma/ib_verbs.h>
8 #include <rdma/uverbs_types.h>
9 #include <rdma/uverbs_ioctl.h>
10 #include <rdma/mlx5_user_ioctl_cmds.h>
11 #include <rdma/ib_umem.h>
12 #include <linux/mlx5/driver.h>
13 #include <linux/mlx5/fs.h>
16 #define UVERBS_MODULE_NAME mlx5_ib
17 #include <rdma/uverbs_named_ioctl.h>
19 static const struct uverbs_attr_spec mlx5_ib_flow_type[] = {
20 [MLX5_IB_FLOW_TYPE_NORMAL] = {
21 .type = UVERBS_ATTR_TYPE_PTR_IN,
23 .len = sizeof(u16), /* data is priority */
24 .min_len = sizeof(u16),
27 [MLX5_IB_FLOW_TYPE_SNIFFER] = {
28 .type = UVERBS_ATTR_TYPE_PTR_IN,
29 UVERBS_ATTR_NO_DATA(),
31 [MLX5_IB_FLOW_TYPE_ALL_DEFAULT] = {
32 .type = UVERBS_ATTR_TYPE_PTR_IN,
33 UVERBS_ATTR_NO_DATA(),
35 [MLX5_IB_FLOW_TYPE_MC_DEFAULT] = {
36 .type = UVERBS_ATTR_TYPE_PTR_IN,
37 UVERBS_ATTR_NO_DATA(),
41 static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
42 struct ib_device *ib_dev, struct ib_uverbs_file *file,
43 struct uverbs_attr_bundle *attrs)
45 struct mlx5_ib_flow_handler *flow_handler;
46 struct mlx5_ib_flow_matcher *fs_matcher;
48 int dest_id, dest_type;
51 bool dest_devx, dest_qp;
52 struct ib_qp *qp = NULL;
53 struct ib_uobject *uobj =
54 uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE);
55 struct mlx5_ib_dev *dev = to_mdev(uobj->context->device);
57 if (!capable(CAP_NET_RAW))
61 uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
62 dest_qp = uverbs_attr_is_valid(attrs,
63 MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
65 if ((dest_devx && dest_qp) || (!dest_devx && !dest_qp))
69 devx_obj = uverbs_attr_get_obj(
70 attrs, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
72 return PTR_ERR(devx_obj);
74 /* Verify that the given DEVX object is a flow
75 * steering destination.
77 if (!mlx5_ib_devx_is_flow_dest(devx_obj, &dest_id, &dest_type))
80 struct mlx5_ib_qp *mqp;
82 qp = uverbs_attr_get_obj(attrs,
83 MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
87 if (qp->qp_type != IB_QPT_RAW_PACKET)
91 if (mqp->flags & MLX5_IB_QP_RSS)
92 dest_id = mqp->rss_qp.tirn;
94 dest_id = mqp->raw_packet_qp.rq.tirn;
95 dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
101 cmd_in = uverbs_attr_get_alloced_ptr(
102 attrs, MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
103 inlen = uverbs_attr_get_len(attrs,
104 MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
105 fs_matcher = uverbs_attr_get_obj(attrs,
106 MLX5_IB_ATTR_CREATE_FLOW_MATCHER);
107 flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher, cmd_in, inlen,
109 if (IS_ERR(flow_handler))
110 return PTR_ERR(flow_handler);
112 ib_set_flow(uobj, &flow_handler->ibflow, qp, ib_dev);
117 static int flow_matcher_cleanup(struct ib_uobject *uobject,
118 enum rdma_remove_reason why)
120 struct mlx5_ib_flow_matcher *obj = uobject->object;
123 ret = ib_destroy_usecnt(&obj->usecnt, why, uobject);
131 static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
132 struct ib_device *ib_dev, struct ib_uverbs_file *file,
133 struct uverbs_attr_bundle *attrs)
135 struct ib_uobject *uobj = uverbs_attr_get_uobject(
136 attrs, MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE);
137 struct mlx5_ib_dev *dev = to_mdev(uobj->context->device);
138 struct mlx5_ib_flow_matcher *obj;
141 obj = kzalloc(sizeof(struct mlx5_ib_flow_matcher), GFP_KERNEL);
145 obj->mask_len = uverbs_attr_get_len(
146 attrs, MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
147 err = uverbs_copy_from(&obj->matcher_mask,
149 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
153 obj->flow_type = uverbs_attr_get_enum_id(
154 attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
156 if (obj->flow_type == MLX5_IB_FLOW_TYPE_NORMAL) {
157 err = uverbs_copy_from(&obj->priority,
159 MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
164 err = uverbs_copy_from(&obj->match_criteria_enable,
166 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA);
171 obj->mdev = dev->mdev;
172 atomic_set(&obj->usecnt, 0);
180 DECLARE_UVERBS_NAMED_METHOD(
181 MLX5_IB_METHOD_CREATE_FLOW,
182 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
187 MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE,
188 UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
191 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_MATCHER,
192 MLX5_IB_OBJECT_FLOW_MATCHER,
195 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_QP,
198 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX,
199 MLX5_IB_OBJECT_DEVX_OBJ,
200 UVERBS_ACCESS_READ));
202 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
203 MLX5_IB_METHOD_DESTROY_FLOW,
204 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
206 UVERBS_ACCESS_DESTROY,
209 ADD_UVERBS_METHODS(mlx5_ib_fs,
211 &UVERBS_METHOD(MLX5_IB_METHOD_CREATE_FLOW),
212 &UVERBS_METHOD(MLX5_IB_METHOD_DESTROY_FLOW));
214 DECLARE_UVERBS_NAMED_METHOD(
215 MLX5_IB_METHOD_FLOW_MATCHER_CREATE,
216 UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE,
217 MLX5_IB_OBJECT_FLOW_MATCHER,
221 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK,
222 UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
224 UVERBS_ATTR_ENUM_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE,
227 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA,
228 UVERBS_ATTR_TYPE(u8),
231 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
232 MLX5_IB_METHOD_FLOW_MATCHER_DESTROY,
233 UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_DESTROY_HANDLE,
234 MLX5_IB_OBJECT_FLOW_MATCHER,
235 UVERBS_ACCESS_DESTROY,
238 DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER,
239 UVERBS_TYPE_ALLOC_IDR(flow_matcher_cleanup),
240 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_CREATE),
241 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_DESTROY));
243 DECLARE_UVERBS_OBJECT_TREE(flow_objects,
244 &UVERBS_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER));