1
2
3
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>
10#include <rdma/uverbs_std_types.h>
11#include <rdma/mlx5_user_ioctl_cmds.h>
12#include <rdma/mlx5_user_ioctl_verbs.h>
13#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
21static 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;
32 case MLX5_IB_UAPI_FLOW_TABLE_TYPE_FDB:
33 *namespace = MLX5_FLOW_NAMESPACE_FDB;
34 break;
35 default:
36 return -EINVAL;
37 }
38
39 return 0;
40}
41
42static const struct uverbs_attr_spec mlx5_ib_flow_type[] = {
43 [MLX5_IB_FLOW_TYPE_NORMAL] = {
44 .type = UVERBS_ATTR_TYPE_PTR_IN,
45 .u.ptr = {
46 .len = sizeof(u16),
47 .min_len = sizeof(u16),
48 }
49 },
50 [MLX5_IB_FLOW_TYPE_SNIFFER] = {
51 .type = UVERBS_ATTR_TYPE_PTR_IN,
52 UVERBS_ATTR_NO_DATA(),
53 },
54 [MLX5_IB_FLOW_TYPE_ALL_DEFAULT] = {
55 .type = UVERBS_ATTR_TYPE_PTR_IN,
56 UVERBS_ATTR_NO_DATA(),
57 },
58 [MLX5_IB_FLOW_TYPE_MC_DEFAULT] = {
59 .type = UVERBS_ATTR_TYPE_PTR_IN,
60 UVERBS_ATTR_NO_DATA(),
61 },
62};
63
64#define MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS 2
65static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
66 struct uverbs_attr_bundle *attrs)
67{
68 struct mlx5_flow_context flow_context = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG};
69 struct mlx5_ib_flow_handler *flow_handler;
70 struct mlx5_ib_flow_matcher *fs_matcher;
71 struct ib_uobject **arr_flow_actions;
72 struct ib_uflow_resources *uflow_res;
73 struct mlx5_flow_act flow_act = {};
74 void *devx_obj;
75 int dest_id, dest_type;
76 void *cmd_in;
77 int inlen;
78 bool dest_devx, dest_qp;
79 struct ib_qp *qp = NULL;
80 struct ib_uobject *uobj =
81 uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE);
82 struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
83 int len, ret, i;
84 u32 counter_id = 0;
85
86 if (!capable(CAP_NET_RAW))
87 return -EPERM;
88
89 dest_devx =
90 uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
91 dest_qp = uverbs_attr_is_valid(attrs,
92 MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
93
94 fs_matcher = uverbs_attr_get_obj(attrs,
95 MLX5_IB_ATTR_CREATE_FLOW_MATCHER);
96 if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS &&
97 ((dest_devx && dest_qp) || (!dest_devx && !dest_qp)))
98 return -EINVAL;
99
100
101 if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB && !dest_devx)
102 return -EINVAL;
103
104 if (dest_devx) {
105 devx_obj = uverbs_attr_get_obj(
106 attrs, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX);
107 if (IS_ERR(devx_obj))
108 return PTR_ERR(devx_obj);
109
110
111
112
113 if (!mlx5_ib_devx_is_flow_dest(devx_obj, &dest_id, &dest_type))
114 return -EINVAL;
115
116 if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB &&
117 dest_type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE)
118 return -EINVAL;
119 } else if (dest_qp) {
120 struct mlx5_ib_qp *mqp;
121
122 qp = uverbs_attr_get_obj(attrs,
123 MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
124 if (IS_ERR(qp))
125 return PTR_ERR(qp);
126
127 if (qp->qp_type != IB_QPT_RAW_PACKET)
128 return -EINVAL;
129
130 mqp = to_mqp(qp);
131 if (mqp->flags & MLX5_IB_QP_RSS)
132 dest_id = mqp->rss_qp.tirn;
133 else
134 dest_id = mqp->raw_packet_qp.rq.tirn;
135 dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
136 } else {
137 dest_type = MLX5_FLOW_DESTINATION_TYPE_PORT;
138 }
139
140 len = uverbs_attr_get_uobjs_arr(attrs,
141 MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, &arr_flow_actions);
142 if (len) {
143 devx_obj = arr_flow_actions[0]->object;
144
145 if (!mlx5_ib_devx_is_flow_counter(devx_obj, &counter_id))
146 return -EINVAL;
147 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
148 }
149
150 if (dest_type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
151 fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS)
152 return -EINVAL;
153
154 cmd_in = uverbs_attr_get_alloced_ptr(
155 attrs, MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
156 inlen = uverbs_attr_get_len(attrs,
157 MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
158
159 uflow_res = flow_resources_alloc(MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS);
160 if (!uflow_res)
161 return -ENOMEM;
162
163 len = uverbs_attr_get_uobjs_arr(attrs,
164 MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, &arr_flow_actions);
165 for (i = 0; i < len; i++) {
166 struct mlx5_ib_flow_action *maction =
167 to_mflow_act(arr_flow_actions[i]->object);
168
169 ret = parse_flow_flow_action(maction, false, &flow_act);
170 if (ret)
171 goto err_out;
172 flow_resources_add(uflow_res, IB_FLOW_SPEC_ACTION_HANDLE,
173 arr_flow_actions[i]->object);
174 }
175
176 ret = uverbs_copy_from(&flow_context.flow_tag, attrs,
177 MLX5_IB_ATTR_CREATE_FLOW_TAG);
178 if (!ret) {
179 if (flow_context.flow_tag >= BIT(24)) {
180 ret = -EINVAL;
181 goto err_out;
182 }
183 flow_context.flags |= FLOW_CONTEXT_HAS_TAG;
184 }
185
186 flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher,
187 &flow_context,
188 &flow_act,
189 counter_id,
190 cmd_in, inlen,
191 dest_id, dest_type);
192 if (IS_ERR(flow_handler)) {
193 ret = PTR_ERR(flow_handler);
194 goto err_out;
195 }
196
197 ib_set_flow(uobj, &flow_handler->ibflow, qp, &dev->ib_dev, uflow_res);
198
199 return 0;
200err_out:
201 ib_uverbs_flow_resources_free(uflow_res);
202 return ret;
203}
204
205static int flow_matcher_cleanup(struct ib_uobject *uobject,
206 enum rdma_remove_reason why,
207 struct uverbs_attr_bundle *attrs)
208{
209 struct mlx5_ib_flow_matcher *obj = uobject->object;
210 int ret;
211
212 ret = ib_destroy_usecnt(&obj->usecnt, why, uobject);
213 if (ret)
214 return ret;
215
216 kfree(obj);
217 return 0;
218}
219
220static int mlx5_ib_matcher_ns(struct uverbs_attr_bundle *attrs,
221 struct mlx5_ib_flow_matcher *obj)
222{
223 enum mlx5_ib_uapi_flow_table_type ft_type =
224 MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX;
225 u32 flags;
226 int err;
227
228
229
230
231 if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE) &&
232 uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS))
233 return -EINVAL;
234
235 if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE)) {
236 err = uverbs_get_const(&ft_type, attrs,
237 MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE);
238 if (err)
239 return err;
240
241 err = mlx5_ib_ft_type_to_namespace(ft_type, &obj->ns_type);
242 if (err)
243 return err;
244
245 return 0;
246 }
247
248 if (uverbs_attr_is_valid(attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS)) {
249 err = uverbs_get_flags32(&flags, attrs,
250 MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
251 IB_FLOW_ATTR_FLAGS_EGRESS);
252 if (err)
253 return err;
254
255 if (flags) {
256 mlx5_ib_ft_type_to_namespace(
257 MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX,
258 &obj->ns_type);
259 return 0;
260 }
261 }
262
263 obj->ns_type = MLX5_FLOW_NAMESPACE_BYPASS;
264
265 return 0;
266}
267
268static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
269 struct uverbs_attr_bundle *attrs)
270{
271 struct ib_uobject *uobj = uverbs_attr_get_uobject(
272 attrs, MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE);
273 struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
274 struct mlx5_ib_flow_matcher *obj;
275 int err;
276
277 obj = kzalloc(sizeof(struct mlx5_ib_flow_matcher), GFP_KERNEL);
278 if (!obj)
279 return -ENOMEM;
280
281 obj->mask_len = uverbs_attr_get_len(
282 attrs, MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
283 err = uverbs_copy_from(&obj->matcher_mask,
284 attrs,
285 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
286 if (err)
287 goto end;
288
289 obj->flow_type = uverbs_attr_get_enum_id(
290 attrs, MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
291
292 if (obj->flow_type == MLX5_IB_FLOW_TYPE_NORMAL) {
293 err = uverbs_copy_from(&obj->priority,
294 attrs,
295 MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE);
296 if (err)
297 goto end;
298 }
299
300 err = uverbs_copy_from(&obj->match_criteria_enable,
301 attrs,
302 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA);
303 if (err)
304 goto end;
305
306 err = mlx5_ib_matcher_ns(attrs, obj);
307 if (err)
308 goto end;
309
310 uobj->object = obj;
311 obj->mdev = dev->mdev;
312 atomic_set(&obj->usecnt, 0);
313 return 0;
314
315end:
316 kfree(obj);
317 return err;
318}
319
320void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
321{
322 switch (maction->flow_action_raw.sub_type) {
323 case MLX5_IB_FLOW_ACTION_MODIFY_HEADER:
324 mlx5_modify_header_dealloc(maction->flow_action_raw.dev->mdev,
325 maction->flow_action_raw.action_id);
326 break;
327 case MLX5_IB_FLOW_ACTION_PACKET_REFORMAT:
328 mlx5_packet_reformat_dealloc(maction->flow_action_raw.dev->mdev,
329 maction->flow_action_raw.action_id);
330 break;
331 case MLX5_IB_FLOW_ACTION_DECAP:
332 break;
333 default:
334 break;
335 }
336}
337
338static struct ib_flow_action *
339mlx5_ib_create_modify_header(struct mlx5_ib_dev *dev,
340 enum mlx5_ib_uapi_flow_table_type ft_type,
341 u8 num_actions, void *in)
342{
343 enum mlx5_flow_namespace_type namespace;
344 struct mlx5_ib_flow_action *maction;
345 int ret;
346
347 ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace);
348 if (ret)
349 return ERR_PTR(-EINVAL);
350
351 maction = kzalloc(sizeof(*maction), GFP_KERNEL);
352 if (!maction)
353 return ERR_PTR(-ENOMEM);
354
355 ret = mlx5_modify_header_alloc(dev->mdev, namespace, num_actions, in,
356 &maction->flow_action_raw.action_id);
357
358 if (ret) {
359 kfree(maction);
360 return ERR_PTR(ret);
361 }
362 maction->flow_action_raw.sub_type =
363 MLX5_IB_FLOW_ACTION_MODIFY_HEADER;
364 maction->flow_action_raw.dev = dev;
365
366 return &maction->ib_action;
367}
368
369static bool mlx5_ib_modify_header_supported(struct mlx5_ib_dev *dev)
370{
371 return MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
372 max_modify_header_actions) ||
373 MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, max_modify_header_actions);
374}
375
376static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)(
377 struct uverbs_attr_bundle *attrs)
378{
379 struct ib_uobject *uobj = uverbs_attr_get_uobject(
380 attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE);
381 struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
382 enum mlx5_ib_uapi_flow_table_type ft_type;
383 struct ib_flow_action *action;
384 int num_actions;
385 void *in;
386 int ret;
387
388 if (!mlx5_ib_modify_header_supported(mdev))
389 return -EOPNOTSUPP;
390
391 in = uverbs_attr_get_alloced_ptr(attrs,
392 MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM);
393
394 num_actions = uverbs_attr_ptr_get_array_size(
395 attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM,
396 MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto));
397 if (num_actions < 0)
398 return num_actions;
399
400 ret = uverbs_get_const(&ft_type, attrs,
401 MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE);
402 if (ret)
403 return ret;
404 action = mlx5_ib_create_modify_header(mdev, ft_type, num_actions, in);
405 if (IS_ERR(action))
406 return PTR_ERR(action);
407
408 uverbs_flow_action_fill_action(action, uobj, &mdev->ib_dev,
409 IB_FLOW_ACTION_UNSPECIFIED);
410
411 return 0;
412}
413
414static bool mlx5_ib_flow_action_packet_reformat_valid(struct mlx5_ib_dev *ibdev,
415 u8 packet_reformat_type,
416 u8 ft_type)
417{
418 switch (packet_reformat_type) {
419 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
420 if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX)
421 return MLX5_CAP_FLOWTABLE(ibdev->mdev,
422 encap_general_header);
423 break;
424 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
425 if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX)
426 return MLX5_CAP_FLOWTABLE_NIC_TX(ibdev->mdev,
427 reformat_l2_to_l3_tunnel);
428 break;
429 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2:
430 if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX)
431 return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev,
432 reformat_l3_tunnel_to_l2);
433 break;
434 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2:
435 if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX)
436 return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev, decap);
437 break;
438 default:
439 break;
440 }
441
442 return false;
443}
444
445static int mlx5_ib_dv_to_prm_packet_reforamt_type(u8 dv_prt, u8 *prm_prt)
446{
447 switch (dv_prt) {
448 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
449 *prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL;
450 break;
451 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2:
452 *prm_prt = MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
453 break;
454 case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
455 *prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
456 break;
457 default:
458 return -EINVAL;
459 }
460
461 return 0;
462}
463
464static int mlx5_ib_flow_action_create_packet_reformat_ctx(
465 struct mlx5_ib_dev *dev,
466 struct mlx5_ib_flow_action *maction,
467 u8 ft_type, u8 dv_prt,
468 void *in, size_t len)
469{
470 enum mlx5_flow_namespace_type namespace;
471 u8 prm_prt;
472 int ret;
473
474 ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace);
475 if (ret)
476 return ret;
477
478 ret = mlx5_ib_dv_to_prm_packet_reforamt_type(dv_prt, &prm_prt);
479 if (ret)
480 return ret;
481
482 ret = mlx5_packet_reformat_alloc(dev->mdev, prm_prt, len,
483 in, namespace,
484 &maction->flow_action_raw.action_id);
485 if (ret)
486 return ret;
487
488 maction->flow_action_raw.sub_type =
489 MLX5_IB_FLOW_ACTION_PACKET_REFORMAT;
490 maction->flow_action_raw.dev = dev;
491
492 return 0;
493}
494
495static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)(
496 struct uverbs_attr_bundle *attrs)
497{
498 struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
499 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE);
500 struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
501 enum mlx5_ib_uapi_flow_action_packet_reformat_type dv_prt;
502 enum mlx5_ib_uapi_flow_table_type ft_type;
503 struct mlx5_ib_flow_action *maction;
504 int ret;
505
506 ret = uverbs_get_const(&ft_type, attrs,
507 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE);
508 if (ret)
509 return ret;
510
511 ret = uverbs_get_const(&dv_prt, attrs,
512 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE);
513 if (ret)
514 return ret;
515
516 if (!mlx5_ib_flow_action_packet_reformat_valid(mdev, dv_prt, ft_type))
517 return -EOPNOTSUPP;
518
519 maction = kzalloc(sizeof(*maction), GFP_KERNEL);
520 if (!maction)
521 return -ENOMEM;
522
523 if (dv_prt ==
524 MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2) {
525 maction->flow_action_raw.sub_type =
526 MLX5_IB_FLOW_ACTION_DECAP;
527 maction->flow_action_raw.dev = mdev;
528 } else {
529 void *in;
530 int len;
531
532 in = uverbs_attr_get_alloced_ptr(attrs,
533 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF);
534 if (IS_ERR(in)) {
535 ret = PTR_ERR(in);
536 goto free_maction;
537 }
538
539 len = uverbs_attr_get_len(attrs,
540 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF);
541
542 ret = mlx5_ib_flow_action_create_packet_reformat_ctx(mdev,
543 maction, ft_type, dv_prt, in, len);
544 if (ret)
545 goto free_maction;
546 }
547
548 uverbs_flow_action_fill_action(&maction->ib_action, uobj, &mdev->ib_dev,
549 IB_FLOW_ACTION_UNSPECIFIED);
550 return 0;
551
552free_maction:
553 kfree(maction);
554 return ret;
555}
556
557DECLARE_UVERBS_NAMED_METHOD(
558 MLX5_IB_METHOD_CREATE_FLOW,
559 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
560 UVERBS_OBJECT_FLOW,
561 UVERBS_ACCESS_NEW,
562 UA_MANDATORY),
563 UVERBS_ATTR_PTR_IN(
564 MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE,
565 UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
566 UA_MANDATORY,
567 UA_ALLOC_AND_COPY),
568 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_MATCHER,
569 MLX5_IB_OBJECT_FLOW_MATCHER,
570 UVERBS_ACCESS_READ,
571 UA_MANDATORY),
572 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_QP,
573 UVERBS_OBJECT_QP,
574 UVERBS_ACCESS_READ),
575 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX,
576 MLX5_IB_OBJECT_DEVX_OBJ,
577 UVERBS_ACCESS_READ),
578 UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS,
579 UVERBS_OBJECT_FLOW_ACTION,
580 UVERBS_ACCESS_READ, 1,
581 MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS,
582 UA_OPTIONAL),
583 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_TAG,
584 UVERBS_ATTR_TYPE(u32),
585 UA_OPTIONAL),
586 UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX,
587 MLX5_IB_OBJECT_DEVX_OBJ,
588 UVERBS_ACCESS_READ, 1, 1,
589 UA_OPTIONAL));
590
591DECLARE_UVERBS_NAMED_METHOD_DESTROY(
592 MLX5_IB_METHOD_DESTROY_FLOW,
593 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
594 UVERBS_OBJECT_FLOW,
595 UVERBS_ACCESS_DESTROY,
596 UA_MANDATORY));
597
598ADD_UVERBS_METHODS(mlx5_ib_fs,
599 UVERBS_OBJECT_FLOW,
600 &UVERBS_METHOD(MLX5_IB_METHOD_CREATE_FLOW),
601 &UVERBS_METHOD(MLX5_IB_METHOD_DESTROY_FLOW));
602
603DECLARE_UVERBS_NAMED_METHOD(
604 MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER,
605 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE,
606 UVERBS_OBJECT_FLOW_ACTION,
607 UVERBS_ACCESS_NEW,
608 UA_MANDATORY),
609 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM,
610 UVERBS_ATTR_MIN_SIZE(MLX5_UN_SZ_BYTES(
611 set_action_in_add_action_in_auto)),
612 UA_MANDATORY,
613 UA_ALLOC_AND_COPY),
614 UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE,
615 enum mlx5_ib_uapi_flow_table_type,
616 UA_MANDATORY));
617
618DECLARE_UVERBS_NAMED_METHOD(
619 MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT,
620 UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE,
621 UVERBS_OBJECT_FLOW_ACTION,
622 UVERBS_ACCESS_NEW,
623 UA_MANDATORY),
624 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF,
625 UVERBS_ATTR_MIN_SIZE(1),
626 UA_ALLOC_AND_COPY,
627 UA_OPTIONAL),
628 UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE,
629 enum mlx5_ib_uapi_flow_action_packet_reformat_type,
630 UA_MANDATORY),
631 UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE,
632 enum mlx5_ib_uapi_flow_table_type,
633 UA_MANDATORY));
634
635ADD_UVERBS_METHODS(
636 mlx5_ib_flow_actions,
637 UVERBS_OBJECT_FLOW_ACTION,
638 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER),
639 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT));
640
641DECLARE_UVERBS_NAMED_METHOD(
642 MLX5_IB_METHOD_FLOW_MATCHER_CREATE,
643 UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE,
644 MLX5_IB_OBJECT_FLOW_MATCHER,
645 UVERBS_ACCESS_NEW,
646 UA_MANDATORY),
647 UVERBS_ATTR_PTR_IN(
648 MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK,
649 UVERBS_ATTR_SIZE(1, sizeof(struct mlx5_ib_match_params)),
650 UA_MANDATORY),
651 UVERBS_ATTR_ENUM_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE,
652 mlx5_ib_flow_type,
653 UA_MANDATORY),
654 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA,
655 UVERBS_ATTR_TYPE(u8),
656 UA_MANDATORY),
657 UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
658 enum ib_flow_flags,
659 UA_OPTIONAL),
660 UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE,
661 enum mlx5_ib_uapi_flow_table_type,
662 UA_OPTIONAL));
663
664DECLARE_UVERBS_NAMED_METHOD_DESTROY(
665 MLX5_IB_METHOD_FLOW_MATCHER_DESTROY,
666 UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_DESTROY_HANDLE,
667 MLX5_IB_OBJECT_FLOW_MATCHER,
668 UVERBS_ACCESS_DESTROY,
669 UA_MANDATORY));
670
671DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_FLOW_MATCHER,
672 UVERBS_TYPE_ALLOC_IDR(flow_matcher_cleanup),
673 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_CREATE),
674 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_MATCHER_DESTROY));
675
676const struct uapi_definition mlx5_ib_flow_defs[] = {
677 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
678 MLX5_IB_OBJECT_FLOW_MATCHER),
679 UAPI_DEF_CHAIN_OBJ_TREE(
680 UVERBS_OBJECT_FLOW,
681 &mlx5_ib_fs),
682 UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
683 &mlx5_ib_flow_actions),
684 {},
685};
686