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