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