blob: dbee17d22d50b844ce28dfad3546012959f5a49e [file] [log] [blame]
Yishai Hadasfd44e382018-07-23 15:25:07 +03001// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2/*
3 * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.
4 */
5
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>
Mark Bloch841eefc2018-08-28 14:18:52 +030010#include <rdma/uverbs_std_types.h>
Yishai Hadasfd44e382018-07-23 15:25:07 +030011#include <rdma/mlx5_user_ioctl_cmds.h>
Mark Blochb4749bf2018-08-28 14:18:51 +030012#include <rdma/mlx5_user_ioctl_verbs.h>
Yishai Hadasfd44e382018-07-23 15:25:07 +030013#include <rdma/ib_umem.h>
14#include <linux/mlx5/driver.h>
15#include <linux/mlx5/fs.h>
16#include "mlx5_ib.h"
17
18#define UVERBS_MODULE_NAME mlx5_ib
19#include <rdma/uverbs_named_ioctl.h>
20
Mark Blochb4749bf2018-08-28 14:18:51 +030021static int
22mlx5_ib_ft_type_to_namespace(enum mlx5_ib_uapi_flow_table_type table_type,
23 enum mlx5_flow_namespace_type *namespace)
24{
25 switch (table_type) {
26 case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX:
27 *namespace = MLX5_FLOW_NAMESPACE_BYPASS;
28 break;
29 case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX:
30 *namespace = MLX5_FLOW_NAMESPACE_EGRESS;
31 break;
Mark Bloch52438be2019-03-28 15:46:23 +020032 case MLX5_IB_UAPI_FLOW_TABLE_TYPE_FDB:
33 *namespace = MLX5_FLOW_NAMESPACE_FDB;
34 break;
Mark Zhangd8abe882019-08-19 14:36:26 +030035 case MLX5_IB_UAPI_FLOW_TABLE_TYPE_RDMA_RX:
36 *namespace = MLX5_FLOW_NAMESPACE_RDMA_RX;
37 break;
Mark Blochb4749bf2018-08-28 14:18:51 +030038 default:
39 return -EINVAL;
40 }
41
42 return 0;
43}
44
Yishai Hadasfd44e382018-07-23 15:25:07 +030045static const struct uverbs_attr_spec mlx5_ib_flow_type[] = {
46 [MLX5_IB_FLOW_TYPE_NORMAL] = {
47 .type = UVERBS_ATTR_TYPE_PTR_IN,
48 .u.ptr = {
49 .len = sizeof(u16), /* data is priority */
50 .min_len = sizeof(u16),
51 }
52 },
53 [MLX5_IB_FLOW_TYPE_SNIFFER] = {
54 .type = UVERBS_ATTR_TYPE_PTR_IN,
55 UVERBS_ATTR_NO_DATA(),
56 },
57 [MLX5_IB_FLOW_TYPE_ALL_DEFAULT] = {
58 .type = UVERBS_ATTR_TYPE_PTR_IN,
59 UVERBS_ATTR_NO_DATA(),
60 },
61 [MLX5_IB_FLOW_TYPE_MC_DEFAULT] = {
62 .type = UVERBS_ATTR_TYPE_PTR_IN,
63 UVERBS_ATTR_NO_DATA(),
64 },
65};
66
Mark Blochfa76d242018-09-06 17:27:06 +030067#define MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS 2
Yishai Hadas32269442018-07-23 15:25:09 +030068static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
Jason Gunthorpe15a1b4b2018-11-25 20:51:15 +020069 struct uverbs_attr_bundle *attrs)
Yishai Hadas32269442018-07-23 15:25:09 +030070{
Jianbo Liubb0ee7d2019-06-25 17:47:58 +000071 struct mlx5_flow_context flow_context = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG};
Yishai Hadas32269442018-07-23 15:25:09 +030072 struct mlx5_ib_flow_handler *flow_handler;
73 struct mlx5_ib_flow_matcher *fs_matcher;
Mark Blochfa76d242018-09-06 17:27:06 +030074 struct ib_uobject **arr_flow_actions;
75 struct ib_uflow_resources *uflow_res;
Jianbo Liubb0ee7d2019-06-25 17:47:58 +000076 struct mlx5_flow_act flow_act = {};
Yishai Hadas32269442018-07-23 15:25:09 +030077 void *devx_obj;
78 int dest_id, dest_type;
79 void *cmd_in;
80 int inlen;
81 bool dest_devx, dest_qp;
82 struct ib_qp *qp = NULL;
83 struct ib_uobject *uobj =
84 uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE);
Jason Gunthorpee79c9c62019-04-01 17:08:23 -030085 struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
Mark Blochfa76d242018-09-06 17:27:06 +030086 int len, ret, i;
Mark Blochbfc5d832018-11-20 20:31:08 +020087 u32 counter_id = 0;
Yevgeny Kliteynik208d70f2019-11-03 16:07:23 +020088 u32 *offset_attr;
89 u32 offset = 0;
Yishai Hadas32269442018-07-23 15:25:09 +030090
91 if (!capable(CAP_NET_RAW))
92 return -EPERM;
93
94 dest_devx =
95 uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
96 dest_qp = uverbs_attr_is_valid(attrs,
97 MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
98
Mark Blocha7ee18b2018-09-06 17:27:08 +030099 fs_matcher = uverbs_attr_get_obj(attrs,
100 MLX5_IB_ATTR_CREATE_FLOW_MATCHER);
101 if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS &&
102 ((dest_devx && dest_qp) || (!dest_devx && !dest_qp)))
103 return -EINVAL;
104
Mark Bloch52438be2019-03-28 15:46:23 +0200105 /* Allow only DEVX object as dest when inserting to FDB */
106 if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB && !dest_devx)
107 return -EINVAL;
108
Mark Zhangd8abe882019-08-19 14:36:26 +0300109 /* Allow only DEVX object or QP as dest when inserting to RDMA_RX */
110 if ((fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) &&
111 ((!dest_devx && !dest_qp) || (dest_devx && dest_qp)))
112 return -EINVAL;
113
Yishai Hadas32269442018-07-23 15:25:09 +0300114 if (dest_devx) {
115 devx_obj = uverbs_attr_get_obj(
116 attrs, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
117 if (IS_ERR(devx_obj))
118 return PTR_ERR(devx_obj);
119
120 /* Verify that the given DEVX object is a flow
121 * steering destination.
122 */
123 if (!mlx5_ib_devx_is_flow_dest(devx_obj, &dest_id, &dest_type))
124 return -EINVAL;
Mark Zhangd8abe882019-08-19 14:36:26 +0300125 /* Allow only flow table as dest when inserting to FDB or RDMA_RX */
126 if ((fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB ||
127 fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_RDMA_RX) &&
Mark Bloch52438be2019-03-28 15:46:23 +0200128 dest_type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE)
129 return -EINVAL;
Mark Blocha7ee18b2018-09-06 17:27:08 +0300130 } else if (dest_qp) {
Yishai Hadas32269442018-07-23 15:25:09 +0300131 struct mlx5_ib_qp *mqp;
132
133 qp = uverbs_attr_get_obj(attrs,
134 MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
135 if (IS_ERR(qp))
136 return PTR_ERR(qp);
137
138 if (qp->qp_type != IB_QPT_RAW_PACKET)
139 return -EINVAL;
140
141 mqp = to_mqp(qp);
142 if (mqp->flags & MLX5_IB_QP_RSS)
143 dest_id = mqp->rss_qp.tirn;
144 else
145 dest_id = mqp->raw_packet_qp.rq.tirn;
146 dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
Mark Blocha7ee18b2018-09-06 17:27:08 +0300147 } else {
148 dest_type = MLX5_FLOW_DESTINATION_TYPE_PORT;
Yishai Hadas32269442018-07-23 15:25:09 +0300149 }
150
Mark Blochbfc5d832018-11-20 20:31:08 +0200151 len = uverbs_attr_get_uobjs_arr(attrs,
152 MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, &arr_flow_actions);
153 if (len) {
154 devx_obj = arr_flow_actions[0]->object;
155
Yevgeny Kliteynik208d70f2019-11-03 16:07:23 +0200156 if (uverbs_attr_is_valid(attrs,
157 MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET)) {
158
159 int num_offsets = uverbs_attr_ptr_get_array_size(
160 attrs,
161 MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET,
162 sizeof(u32));
163
164 if (num_offsets != 1)
165 return -EINVAL;
166
167 offset_attr = uverbs_attr_get_alloced_ptr(
168 attrs,
169 MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET);
170 offset = *offset_attr;
171 }
172
173 if (!mlx5_ib_devx_is_flow_counter(devx_obj, offset,
174 &counter_id))
Mark Blochbfc5d832018-11-20 20:31:08 +0200175 return -EINVAL;
Yevgeny Kliteynik208d70f2019-11-03 16:07:23 +0200176
Mark Blochbfc5d832018-11-20 20:31:08 +0200177 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
178 }
Yishai Hadas32269442018-07-23 15:25:09 +0300179
Alex Vesker419822c2018-12-04 15:34:05 +0200180 if (dest_type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
181 fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS)
182 return -EINVAL;
183
Yishai Hadas32269442018-07-23 15:25:09 +0300184 cmd_in = uverbs_attr_get_alloced_ptr(
185 attrs, MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
186 inlen = uverbs_attr_get_len(attrs,
187 MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
Yishai Hadas32269442018-07-23 15:25:09 +0300188
Mark Blochfa76d242018-09-06 17:27:06 +0300189 uflow_res = flow_resources_alloc(MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS);
190 if (!uflow_res)
191 return -ENOMEM;
192
193 len = uverbs_attr_get_uobjs_arr(attrs,
194 MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, &arr_flow_actions);
195 for (i = 0; i < len; i++) {
196 struct mlx5_ib_flow_action *maction =
197 to_mflow_act(arr_flow_actions[i]->object);
198
199 ret = parse_flow_flow_action(maction, false, &flow_act);
200 if (ret)
201 goto err_out;
202 flow_resources_add(uflow_res, IB_FLOW_SPEC_ACTION_HANDLE,
203 arr_flow_actions[i]->object);
204 }
205
Jianbo Liubb0ee7d2019-06-25 17:47:58 +0000206 ret = uverbs_copy_from(&flow_context.flow_tag, attrs,
Mark Blochba4a4112018-10-10 09:55:10 +0300207 MLX5_IB_ATTR_CREATE_FLOW_TAG);
208 if (!ret) {
Jianbo Liubb0ee7d2019-06-25 17:47:58 +0000209 if (flow_context.flow_tag >= BIT(24)) {
Mark Blochba4a4112018-10-10 09:55:10 +0300210 ret = -EINVAL;
211 goto err_out;
212 }
Jianbo Liubb0ee7d2019-06-25 17:47:58 +0000213 flow_context.flags |= FLOW_CONTEXT_HAS_TAG;
Mark Blochba4a4112018-10-10 09:55:10 +0300214 }
215
Jianbo Liubb0ee7d2019-06-25 17:47:58 +0000216 flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher,
217 &flow_context,
218 &flow_act,
Mark Blochbfc5d832018-11-20 20:31:08 +0200219 counter_id,
Mark Blochb823dd62018-09-06 17:27:05 +0300220 cmd_in, inlen,
Yishai Hadas32269442018-07-23 15:25:09 +0300221 dest_id, dest_type);
Mark Blochfa76d242018-09-06 17:27:06 +0300222 if (IS_ERR(flow_handler)) {
223 ret = PTR_ERR(flow_handler);
224 goto err_out;
225 }
Yishai Hadas32269442018-07-23 15:25:09 +0300226
Mark Blochfa76d242018-09-06 17:27:06 +0300227 ib_set_flow(uobj, &flow_handler->ibflow, qp, &dev->ib_dev, uflow_res);
Yishai Hadas32269442018-07-23 15:25:09 +0300228
229 return 0;
Mark Blochfa76d242018-09-06 17:27:06 +0300230err_out:
231 ib_uverbs_flow_resources_free(uflow_res);
232 return ret;
Yishai Hadas32269442018-07-23 15:25:09 +0300233}
234
Yishai Hadasfd44e382018-07-23 15:25:07 +0300235static int flow_matcher_cleanup(struct ib_uobject *uobject,
Shamir Rabinovitcha6a37972019-03-31 19:10:04 +0300236 enum rdma_remove_reason why,
237 struct uverbs_attr_bundle *attrs)
Yishai Hadasfd44e382018-07-23 15:25:07 +0300238{
239 struct mlx5_ib_flow_matcher *obj = uobject->object;
240 int ret;
241
242 ret = ib_destroy_usecnt(&obj->usecnt, why, uobject);
243 if (ret)
244 return ret;
245
246 kfree(obj);
247 return 0;
248}
249
Mark Bloch52438be2019-03-28 15:46:23 +0200250static int mlx5_ib_matcher_ns(struct uverbs_attr_bundle *attrs,
251 struct mlx5_ib_flow_matcher *obj)
252{
253 enum mlx5_ib_uapi_flow_table_type ft_type =
254 MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX;
255 u32 flags;
256 int err;
257
258 /* New users should use MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE and older
259 * users should switch to it. We leave this to not break userspace
260 */
261 if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE) &&
262 uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS))
263 return -EINVAL;
264
265 if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE)) {
266 err = uverbs_get_const(&ft_type, attrs,
267 MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE);
268 if (err)
269 return err;
270
271 err = mlx5_ib_ft_type_to_namespace(ft_type, &obj->ns_type);
272 if (err)
273 return err;
274
275 return 0;
276 }
277
278 if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS)) {
279 err = uverbs_get_flags32(&flags, attrs,
280 MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
281 IB_FLOW_ATTR_FLAGS_EGRESS);
282 if (err)
283 return err;
284
285 if (flags) {
286 mlx5_ib_ft_type_to_namespace(
287 MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX,
288 &obj->ns_type);
289 return 0;
290 }
291 }
292
293 obj->ns_type = MLX5_FLOW_NAMESPACE_BYPASS;
294
295 return 0;
296}
297
Yishai Hadasfd44e382018-07-23 15:25:07 +0300298static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
Jason Gunthorpe15a1b4b2018-11-25 20:51:15 +0200299 struct uverbs_attr_bundle *attrs)
Yishai Hadasfd44e382018-07-23 15:25:07 +0300300{
301 struct ib_uobject *uobj = uverbs_attr_get_uobject(
302 attrs, MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE);
Jason Gunthorpee79c9c62019-04-01 17:08:23 -0300303 struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
Yishai Hadasfd44e382018-07-23 15:25:07 +0300304 struct mlx5_ib_flow_matcher *obj;
305 int err;
306
307 obj = kzalloc(sizeof(struct mlx5_ib_flow_matcher), GFP_KERNEL);
308 if (!obj)
309 return -ENOMEM;
310
311 obj->mask_len = uverbs_attr_get_len(
312 attrs, MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
313 err = uverbs_copy_from(&obj->matcher_mask,
314 attrs,
315 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
316 if (err)
317 goto end;
318
319 obj->flow_type = uverbs_attr_get_enum_id(
320 attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
321
322 if (obj->flow_type == MLX5_IB_FLOW_TYPE_NORMAL) {
323 err = uverbs_copy_from(&obj->priority,
324 attrs,
325 MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
326 if (err)
327 goto end;
328 }
329
330 err = uverbs_copy_from(&obj->match_criteria_enable,
331 attrs,
332 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA);
333 if (err)
334 goto end;
335
Mark Bloch52438be2019-03-28 15:46:23 +0200336 err = mlx5_ib_matcher_ns(attrs, obj);
Mark Blocha7ee18b2018-09-06 17:27:08 +0300337 if (err)
338 goto end;
339
Yishai Hadasfd44e382018-07-23 15:25:07 +0300340 uobj->object = obj;
341 obj->mdev = dev->mdev;
342 atomic_set(&obj->usecnt, 0);
343 return 0;
344
345end:
346 kfree(obj);
347 return err;
348}
349
Mark Blochb4749bf2018-08-28 14:18:51 +0300350void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
351{
352 switch (maction->flow_action_raw.sub_type) {
353 case MLX5_IB_FLOW_ACTION_MODIFY_HEADER:
354 mlx5_modify_header_dealloc(maction->flow_action_raw.dev->mdev,
Maor Gottlieb2b688ea2019-08-15 13:54:17 +0300355 maction->flow_action_raw.modify_hdr);
Mark Blochb4749bf2018-08-28 14:18:51 +0300356 break;
Mark Blocha090d0d2018-08-28 14:18:54 +0300357 case MLX5_IB_FLOW_ACTION_PACKET_REFORMAT:
358 mlx5_packet_reformat_dealloc(maction->flow_action_raw.dev->mdev,
Maor Gottlieb2b688ea2019-08-15 13:54:17 +0300359 maction->flow_action_raw.pkt_reformat);
Mark Blocha090d0d2018-08-28 14:18:54 +0300360 break;
Mark Bloch08aeb972018-08-28 14:18:53 +0300361 case MLX5_IB_FLOW_ACTION_DECAP:
362 break;
Mark Blochb4749bf2018-08-28 14:18:51 +0300363 default:
364 break;
365 }
366}
367
368static struct ib_flow_action *
369mlx5_ib_create_modify_header(struct mlx5_ib_dev *dev,
370 enum mlx5_ib_uapi_flow_table_type ft_type,
371 u8 num_actions, void *in)
372{
373 enum mlx5_flow_namespace_type namespace;
374 struct mlx5_ib_flow_action *maction;
375 int ret;
376
377 ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace);
378 if (ret)
379 return ERR_PTR(-EINVAL);
380
381 maction = kzalloc(sizeof(*maction), GFP_KERNEL);
382 if (!maction)
383 return ERR_PTR(-ENOMEM);
384
Maor Gottlieb2b688ea2019-08-15 13:54:17 +0300385 maction->flow_action_raw.modify_hdr =
386 mlx5_modify_header_alloc(dev->mdev, namespace, num_actions, in);
Mark Blochb4749bf2018-08-28 14:18:51 +0300387
Maor Gottlieb2b688ea2019-08-15 13:54:17 +0300388 if (IS_ERR(maction->flow_action_raw.modify_hdr)) {
389 ret = PTR_ERR(maction->flow_action_raw.modify_hdr);
Mark Blochb4749bf2018-08-28 14:18:51 +0300390 kfree(maction);
391 return ERR_PTR(ret);
392 }
393 maction->flow_action_raw.sub_type =
394 MLX5_IB_FLOW_ACTION_MODIFY_HEADER;
395 maction->flow_action_raw.dev = dev;
396
397 return &maction->ib_action;
398}
399
400static bool mlx5_ib_modify_header_supported(struct mlx5_ib_dev *dev)
401{
402 return MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
403 max_modify_header_actions) ||
404 MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, max_modify_header_actions);
405}
406
407static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)(
Mark Blochb4749bf2018-08-28 14:18:51 +0300408 struct uverbs_attr_bundle *attrs)
409{
410 struct ib_uobject *uobj = uverbs_attr_get_uobject(
411 attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE);
Jason Gunthorpee79c9c62019-04-01 17:08:23 -0300412 struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
Mark Blochb4749bf2018-08-28 14:18:51 +0300413 enum mlx5_ib_uapi_flow_table_type ft_type;
414 struct ib_flow_action *action;
Dan Carpenter58f7c0b2018-12-22 10:43:32 +0300415 int num_actions;
Mark Blochb4749bf2018-08-28 14:18:51 +0300416 void *in;
Mark Blochb4749bf2018-08-28 14:18:51 +0300417 int ret;
418
419 if (!mlx5_ib_modify_header_supported(mdev))
420 return -EOPNOTSUPP;
421
422 in = uverbs_attr_get_alloced_ptr(attrs,
423 MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM);
Mark Blochb4749bf2018-08-28 14:18:51 +0300424
Moni Shouacbfdd442018-12-11 13:37:51 +0200425 num_actions = uverbs_attr_ptr_get_array_size(
426 attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM,
427 MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto));
428 if (num_actions < 0)
429 return num_actions;
Mark Blochb4749bf2018-08-28 14:18:51 +0300430
431 ret = uverbs_get_const(&ft_type, attrs,
432 MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE);
433 if (ret)
434 return ret;
Mark Blochb4749bf2018-08-28 14:18:51 +0300435 action = mlx5_ib_create_modify_header(mdev, ft_type, num_actions, in);
436 if (IS_ERR(action))
437 return PTR_ERR(action);
438
Jason Gunthorpee79c9c62019-04-01 17:08:23 -0300439 uverbs_flow_action_fill_action(action, uobj, &mdev->ib_dev,
Mark Bloch841eefc2018-08-28 14:18:52 +0300440 IB_FLOW_ACTION_UNSPECIFIED);
Mark Blochb4749bf2018-08-28 14:18:51 +0300441
442 return 0;
443}
444
Mark Bloch08aeb972018-08-28 14:18:53 +0300445static bool mlx5_ib_flow_action_packet_reformat_valid(struct mlx5_ib_dev *ibdev,
446 u8 packet_reformat_type,
447 u8 ft_type)
448{
449 switch (packet_reformat_type) {
Mark Blocha090d0d2018-08-28 14:18:54 +0300450 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
451 if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX)
452 return MLX5_CAP_FLOWTABLE(ibdev->mdev,
453 encap_general_header);
454 break;
455 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
456 if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX)
457 return MLX5_CAP_FLOWTABLE_NIC_TX(ibdev->mdev,
458 reformat_l2_to_l3_tunnel);
459 break;
460 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2:
461 if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX)
462 return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev,
463 reformat_l3_tunnel_to_l2);
464 break;
Mark Bloch08aeb972018-08-28 14:18:53 +0300465 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2:
466 if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX)
467 return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev, decap);
468 break;
469 default:
470 break;
471 }
472
473 return false;
474}
475
Mark Blocha090d0d2018-08-28 14:18:54 +0300476static int mlx5_ib_dv_to_prm_packet_reforamt_type(u8 dv_prt, u8 *prm_prt)
477{
478 switch (dv_prt) {
479 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
480 *prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL;
481 break;
482 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2:
483 *prm_prt = MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
484 break;
485 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
486 *prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
487 break;
488 default:
489 return -EINVAL;
490 }
491
492 return 0;
493}
494
495static int mlx5_ib_flow_action_create_packet_reformat_ctx(
496 struct mlx5_ib_dev *dev,
497 struct mlx5_ib_flow_action *maction,
498 u8 ft_type, u8 dv_prt,
499 void *in, size_t len)
500{
501 enum mlx5_flow_namespace_type namespace;
502 u8 prm_prt;
503 int ret;
504
505 ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace);
506 if (ret)
507 return ret;
508
509 ret = mlx5_ib_dv_to_prm_packet_reforamt_type(dv_prt, &prm_prt);
510 if (ret)
511 return ret;
512
Maor Gottlieb2b688ea2019-08-15 13:54:17 +0300513 maction->flow_action_raw.pkt_reformat =
514 mlx5_packet_reformat_alloc(dev->mdev, prm_prt, len,
515 in, namespace);
516 if (IS_ERR(maction->flow_action_raw.pkt_reformat)) {
517 ret = PTR_ERR(maction->flow_action_raw.pkt_reformat);
Mark Blocha090d0d2018-08-28 14:18:54 +0300518 return ret;
Maor Gottlieb2b688ea2019-08-15 13:54:17 +0300519 }
Mark Blocha090d0d2018-08-28 14:18:54 +0300520
521 maction->flow_action_raw.sub_type =
522 MLX5_IB_FLOW_ACTION_PACKET_REFORMAT;
523 maction->flow_action_raw.dev = dev;
524
525 return 0;
526}
527
Mark Bloch08aeb972018-08-28 14:18:53 +0300528static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)(
Mark Bloch08aeb972018-08-28 14:18:53 +0300529 struct uverbs_attr_bundle *attrs)
530{
531 struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
532 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE);
Jason Gunthorpee79c9c62019-04-01 17:08:23 -0300533 struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
Mark Bloch08aeb972018-08-28 14:18:53 +0300534 enum mlx5_ib_uapi_flow_action_packet_reformat_type dv_prt;
535 enum mlx5_ib_uapi_flow_table_type ft_type;
536 struct mlx5_ib_flow_action *maction;
537 int ret;
538
539 ret = uverbs_get_const(&ft_type, attrs,
540 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE);
541 if (ret)
542 return ret;
543
544 ret = uverbs_get_const(&dv_prt, attrs,
545 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE);
546 if (ret)
547 return ret;
548
549 if (!mlx5_ib_flow_action_packet_reformat_valid(mdev, dv_prt, ft_type))
550 return -EOPNOTSUPP;
551
552 maction = kzalloc(sizeof(*maction), GFP_KERNEL);
553 if (!maction)
554 return -ENOMEM;
555
556 if (dv_prt ==
557 MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2) {
558 maction->flow_action_raw.sub_type =
559 MLX5_IB_FLOW_ACTION_DECAP;
560 maction->flow_action_raw.dev = mdev;
Mark Blocha090d0d2018-08-28 14:18:54 +0300561 } else {
562 void *in;
563 int len;
564
565 in = uverbs_attr_get_alloced_ptr(attrs,
566 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF);
567 if (IS_ERR(in)) {
568 ret = PTR_ERR(in);
569 goto free_maction;
570 }
571
572 len = uverbs_attr_get_len(attrs,
573 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF);
574
575 ret = mlx5_ib_flow_action_create_packet_reformat_ctx(mdev,
576 maction, ft_type, dv_prt, in, len);
577 if (ret)
578 goto free_maction;
Mark Bloch08aeb972018-08-28 14:18:53 +0300579 }
580
Jason Gunthorpee79c9c62019-04-01 17:08:23 -0300581 uverbs_flow_action_fill_action(&maction->ib_action, uobj, &mdev->ib_dev,
Mark Bloch08aeb972018-08-28 14:18:53 +0300582 IB_FLOW_ACTION_UNSPECIFIED);
583 return 0;
Mark Blocha090d0d2018-08-28 14:18:54 +0300584
585free_maction:
586 kfree(maction);
587 return ret;
Mark Bloch08aeb972018-08-28 14:18:53 +0300588}
589
Yishai Hadasfd44e382018-07-23 15:25:07 +0300590DECLARE_UVERBS_NAMED_METHOD(
Yishai Hadas32269442018-07-23 15:25:09 +0300591 MLX5_IB_METHOD_CREATE_FLOW,
592 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
593 UVERBS_OBJECT_FLOW,
594 UVERBS_ACCESS_NEW,
595 UA_MANDATORY),
596 UVERBS_ATTR_PTR_IN(
597 MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE,
598 UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
599 UA_MANDATORY,
600 UA_ALLOC_AND_COPY),
601 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_MATCHER,
602 MLX5_IB_OBJECT_FLOW_MATCHER,
603 UVERBS_ACCESS_READ,
604 UA_MANDATORY),
605 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_QP,
606 UVERBS_OBJECT_QP,
607 UVERBS_ACCESS_READ),
608 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX,
609 MLX5_IB_OBJECT_DEVX_OBJ,
Mark Blochfa76d242018-09-06 17:27:06 +0300610 UVERBS_ACCESS_READ),
611 UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS,
612 UVERBS_OBJECT_FLOW_ACTION,
613 UVERBS_ACCESS_READ, 1,
614 MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS,
Mark Blochba4a4112018-10-10 09:55:10 +0300615 UA_OPTIONAL),
616 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_TAG,
617 UVERBS_ATTR_TYPE(u32),
Mark Blochbfc5d832018-11-20 20:31:08 +0200618 UA_OPTIONAL),
619 UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX,
620 MLX5_IB_OBJECT_DEVX_OBJ,
621 UVERBS_ACCESS_READ, 1, 1,
Yevgeny Kliteynik208d70f2019-11-03 16:07:23 +0200622 UA_OPTIONAL),
623 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET,
624 UVERBS_ATTR_MIN_SIZE(sizeof(u32)),
625 UA_OPTIONAL,
626 UA_ALLOC_AND_COPY));
Yishai Hadas32269442018-07-23 15:25:09 +0300627
628DECLARE_UVERBS_NAMED_METHOD_DESTROY(
629 MLX5_IB_METHOD_DESTROY_FLOW,
630 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
631 UVERBS_OBJECT_FLOW,
632 UVERBS_ACCESS_DESTROY,
633 UA_MANDATORY));
634
635ADD_UVERBS_METHODS(mlx5_ib_fs,
636 UVERBS_OBJECT_FLOW,
637 &UVERBS_METHOD(MLX5_IB_METHOD_CREATE_FLOW),
638 &UVERBS_METHOD(MLX5_IB_METHOD_DESTROY_FLOW));
639
640DECLARE_UVERBS_NAMED_METHOD(
Mark Blochb4749bf2018-08-28 14:18:51 +0300641 MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER,
642 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE,
643 UVERBS_OBJECT_FLOW_ACTION,
644 UVERBS_ACCESS_NEW,
645 UA_MANDATORY),
646 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM,
647 UVERBS_ATTR_MIN_SIZE(MLX5_UN_SZ_BYTES(
648 set_action_in_add_action_in_auto)),
649 UA_MANDATORY,
650 UA_ALLOC_AND_COPY),
651 UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE,
652 enum mlx5_ib_uapi_flow_table_type,
653 UA_MANDATORY));
654
Mark Bloch08aeb972018-08-28 14:18:53 +0300655DECLARE_UVERBS_NAMED_METHOD(
656 MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT,
657 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE,
658 UVERBS_OBJECT_FLOW_ACTION,
659 UVERBS_ACCESS_NEW,
660 UA_MANDATORY),
Mark Blocha090d0d2018-08-28 14:18:54 +0300661 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF,
662 UVERBS_ATTR_MIN_SIZE(1),
663 UA_ALLOC_AND_COPY,
664 UA_OPTIONAL),
Mark Bloch08aeb972018-08-28 14:18:53 +0300665 UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE,
666 enum mlx5_ib_uapi_flow_action_packet_reformat_type,
667 UA_MANDATORY),
668 UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE,
669 enum mlx5_ib_uapi_flow_table_type,
670 UA_MANDATORY));
671
Mark Blochb4749bf2018-08-28 14:18:51 +0300672ADD_UVERBS_METHODS(
673 mlx5_ib_flow_actions,
674 UVERBS_OBJECT_FLOW_ACTION,
Mark Bloch08aeb972018-08-28 14:18:53 +0300675 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER),
676 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT));
Mark Blochb4749bf2018-08-28 14:18:51 +0300677
678DECLARE_UVERBS_NAMED_METHOD(
Yishai Hadasfd44e382018-07-23 15:25:07 +0300679 MLX5_IB_METHOD_FLOW_MATCHER_CREATE,
680 UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE,
681 MLX5_IB_OBJECT_FLOW_MATCHER,
682 UVERBS_ACCESS_NEW,
683 UA_MANDATORY),
684 UVERBS_ATTR_PTR_IN(
685 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK,
686 UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
687 UA_MANDATORY),
688 UVERBS_ATTR_ENUM_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE,
689 mlx5_ib_flow_type,
690 UA_MANDATORY),
691 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA,
692 UVERBS_ATTR_TYPE(u8),
Mark Blocha7ee18b2018-09-06 17:27:08 +0300693 UA_MANDATORY),
694 UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
695 enum ib_flow_flags,
Mark Bloch52438be2019-03-28 15:46:23 +0200696 UA_OPTIONAL),
697 UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE,
698 enum mlx5_ib_uapi_flow_table_type,
Mark Blocha7ee18b2018-09-06 17:27:08 +0300699 UA_OPTIONAL));
Yishai Hadasfd44e382018-07-23 15:25:07 +0300700
701DECLARE_UVERBS_NAMED_METHOD_DESTROY(
702 MLX5_IB_METHOD_FLOW_MATCHER_DESTROY,
703 UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_DESTROY_HANDLE,
704 MLX5_IB_OBJECT_FLOW_MATCHER,
705 UVERBS_ACCESS_DESTROY,
706 UA_MANDATORY));
707
708DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER,
709 UVERBS_TYPE_ALLOC_IDR(flow_matcher_cleanup),
710 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_CREATE),
711 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_DESTROY));
712
Jason Gunthorpe0cbf4322018-11-12 22:59:50 +0200713const struct uapi_definition mlx5_ib_flow_defs[] = {
Leon Romanovskya1462352018-12-10 11:19:49 +0200714 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
Mark Bloch7f575102019-03-28 15:46:25 +0200715 MLX5_IB_OBJECT_FLOW_MATCHER),
Leon Romanovskya1462352018-12-10 11:19:49 +0200716 UAPI_DEF_CHAIN_OBJ_TREE(
717 UVERBS_OBJECT_FLOW,
Mark Blochc1b03c22019-01-24 14:33:32 +0200718 &mlx5_ib_fs),
Jason Gunthorpe0cbf4322018-11-12 22:59:50 +0200719 UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
720 &mlx5_ib_flow_actions),
721 {},
722};