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