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_uverbs_file *file, struct uverbs_attr_bundle *attrs)
44 struct mlx5_ib_flow_handler *flow_handler;
45 struct mlx5_ib_flow_matcher *fs_matcher;
47 int dest_id, dest_type;
50 bool dest_devx, dest_qp;
51 struct ib_qp *qp = NULL;
52 struct ib_uobject *uobj =
53 uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE);
54 struct mlx5_ib_dev *dev = to_mdev(uobj->context->device);
56 if (!capable(CAP_NET_RAW))
60 uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
61 dest_qp = uverbs_attr_is_valid(attrs,
62 MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
64 if ((dest_devx && dest_qp) || (!dest_devx && !dest_qp))
68 devx_obj = uverbs_attr_get_obj(
69 attrs, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
71 return PTR_ERR(devx_obj);
73 /* Verify that the given DEVX object is a flow
74 * steering destination.
76 if (!mlx5_ib_devx_is_flow_dest(devx_obj, &dest_id, &dest_type))
79 struct mlx5_ib_qp *mqp;
81 qp = uverbs_attr_get_obj(attrs,
82 MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
86 if (qp->qp_type != IB_QPT_RAW_PACKET)
90 if (mqp->flags & MLX5_IB_QP_RSS)
91 dest_id = mqp->rss_qp.tirn;
93 dest_id = mqp->raw_packet_qp.rq.tirn;
94 dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
100 cmd_in = uverbs_attr_get_alloced_ptr(
101 attrs, MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
102 inlen = uverbs_attr_get_len(attrs,
103 MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
104 fs_matcher = uverbs_attr_get_obj(attrs,
105 MLX5_IB_ATTR_CREATE_FLOW_MATCHER);
106 flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher, cmd_in, inlen,
108 if (IS_ERR(flow_handler))
109 return PTR_ERR(flow_handler);
111 ib_set_flow(uobj, &flow_handler->ibflow, qp, &dev->ib_dev);
116 static int flow_matcher_cleanup(struct ib_uobject *uobject,
117 enum rdma_remove_reason why)
119 struct mlx5_ib_flow_matcher *obj = uobject->object;
122 ret = ib_destroy_usecnt(&obj->usecnt, why, uobject);
130 static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
131 struct ib_uverbs_file *file, struct uverbs_attr_bundle *attrs)
133 struct ib_uobject *uobj = uverbs_attr_get_uobject(
134 attrs, MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE);
135 struct mlx5_ib_dev *dev = to_mdev(uobj->context->device);
136 struct mlx5_ib_flow_matcher *obj;
139 obj = kzalloc(sizeof(struct mlx5_ib_flow_matcher), GFP_KERNEL);
143 obj->mask_len = uverbs_attr_get_len(
144 attrs, MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
145 err = uverbs_copy_from(&obj->matcher_mask,
147 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
151 obj->flow_type = uverbs_attr_get_enum_id(
152 attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
154 if (obj->flow_type == MLX5_IB_FLOW_TYPE_NORMAL) {
155 err = uverbs_copy_from(&obj->priority,
157 MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
162 err = uverbs_copy_from(&obj->match_criteria_enable,
164 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA);
169 obj->mdev = dev->mdev;
170 atomic_set(&obj->usecnt, 0);
178 DECLARE_UVERBS_NAMED_METHOD(
179 MLX5_IB_METHOD_CREATE_FLOW,
180 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
185 MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE,
186 UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
189 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_MATCHER,
190 MLX5_IB_OBJECT_FLOW_MATCHER,
193 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_QP,
196 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX,
197 MLX5_IB_OBJECT_DEVX_OBJ,
198 UVERBS_ACCESS_READ));
200 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
201 MLX5_IB_METHOD_DESTROY_FLOW,
202 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
204 UVERBS_ACCESS_DESTROY,
207 ADD_UVERBS_METHODS(mlx5_ib_fs,
209 &UVERBS_METHOD(MLX5_IB_METHOD_CREATE_FLOW),
210 &UVERBS_METHOD(MLX5_IB_METHOD_DESTROY_FLOW));
212 DECLARE_UVERBS_NAMED_METHOD(
213 MLX5_IB_METHOD_FLOW_MATCHER_CREATE,
214 UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE,
215 MLX5_IB_OBJECT_FLOW_MATCHER,
219 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK,
220 UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
222 UVERBS_ATTR_ENUM_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE,
225 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA,
226 UVERBS_ATTR_TYPE(u8),
229 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
230 MLX5_IB_METHOD_FLOW_MATCHER_DESTROY,
231 UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_DESTROY_HANDLE,
232 MLX5_IB_OBJECT_FLOW_MATCHER,
233 UVERBS_ACCESS_DESTROY,
236 DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER,
237 UVERBS_TYPE_ALLOC_IDR(flow_matcher_cleanup),
238 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_CREATE),
239 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_DESTROY));
241 DECLARE_UVERBS_OBJECT_TREE(flow_objects,
242 &UVERBS_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER));
244 int mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root)
248 root[i++] = &flow_objects;
249 root[i++] = &mlx5_ib_fs;