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