Linux-libre 5.4.49-gnu
[librecmc/linux-libre.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         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), /* 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
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         /* Allow only DEVX object as dest when inserting to FDB */
104         if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_FDB && !dest_devx)
105                 return -EINVAL;
106
107         /* Allow only DEVX object or QP as dest when inserting to RDMA_RX */
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                 /* Verify that the given DEVX object is a flow
119                  * steering destination.
120                  */
121                 if (!mlx5_ib_devx_is_flow_dest(devx_obj, &dest_id, &dest_type))
122                         return -EINVAL;
123                 /* Allow only flow table as dest when inserting to FDB or RDMA_RX */
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         /* New users should use MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE and older
238          * users should switch to it. We leave this to not break userspace
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 };