blob: 1fc302d41a53acff4548c05df1be4552c2c3fb4d [file] [log] [blame]
Yishai Hadasfd44e382018-07-23 15:25:07 +03001// 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>
Mark Bloch841eefc2018-08-28 14:18:52 +030010#include <rdma/uverbs_std_types.h>
Yishai Hadasfd44e382018-07-23 15:25:07 +030011#include <rdma/mlx5_user_ioctl_cmds.h>
Mark Blochb4749bf2018-08-28 14:18:51 +030012#include <rdma/mlx5_user_ioctl_verbs.h>
Yishai Hadasfd44e382018-07-23 15:25:07 +030013#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
Mark Blochb4749bf2018-08-28 14:18:51 +030021static int
22mlx5_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;
Mark Bloch52438be2019-03-28 15:46:23 +020032 case MLX5_IB_UAPI_FLOW_TABLE_TYPE_FDB:
33 *namespace = MLX5_FLOW_NAMESPACE_FDB;
34 break;
Mark Blochb4749bf2018-08-28 14:18:51 +030035 default:
36 return -EINVAL;
37 }
38
39 return 0;
40}
41
Yishai Hadasfd44e382018-07-23 15:25:07 +030042static 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
Mark Blochfa76d242018-09-06 17:27:06 +030064#define MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS 2
Yishai Hadas32269442018-07-23 15:25:09 +030065static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
Jason Gunthorpe15a1b4b2018-11-25 20:51:15 +020066 struct uverbs_attr_bundle *attrs)
Yishai Hadas32269442018-07-23 15:25:09 +030067{
Mark Blochb823dd62018-09-06 17:27:05 +030068 struct mlx5_flow_act flow_act = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG};
Yishai Hadas32269442018-07-23 15:25:09 +030069 struct mlx5_ib_flow_handler *flow_handler;
70 struct mlx5_ib_flow_matcher *fs_matcher;
Mark Blochfa76d242018-09-06 17:27:06 +030071 struct ib_uobject **arr_flow_actions;
72 struct ib_uflow_resources *uflow_res;
Yishai Hadas32269442018-07-23 15:25:09 +030073 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);
Jason Gunthorpee79c9c62019-04-01 17:08:23 -030081 struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
Mark Blochfa76d242018-09-06 17:27:06 +030082 int len, ret, i;
Mark Blochbfc5d832018-11-20 20:31:08 +020083 u32 counter_id = 0;
Yishai Hadas32269442018-07-23 15:25:09 +030084
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
Mark Blocha7ee18b2018-09-06 17:27:08 +030093 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
Mark Bloch52438be2019-03-28 15:46:23 +020099 /* 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
Yishai Hadas32269442018-07-23 15:25:09 +0300103 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;
Mark Bloch52438be2019-03-28 15:46:23 +0200114 /* 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;
Mark Blocha7ee18b2018-09-06 17:27:08 +0300118 } else if (dest_qp) {
Yishai Hadas32269442018-07-23 15:25:09 +0300119 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;
Mark Blocha7ee18b2018-09-06 17:27:08 +0300135 } else {
136 dest_type = MLX5_FLOW_DESTINATION_TYPE_PORT;
Yishai Hadas32269442018-07-23 15:25:09 +0300137 }
138
Mark Blochbfc5d832018-11-20 20:31:08 +0200139 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 }
Yishai Hadas32269442018-07-23 15:25:09 +0300148
Alex Vesker419822c2018-12-04 15:34:05 +0200149 if (dest_type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
150 fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS)
151 return -EINVAL;
152
Yishai Hadas32269442018-07-23 15:25:09 +0300153 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);
Yishai Hadas32269442018-07-23 15:25:09 +0300157
Mark Blochfa76d242018-09-06 17:27:06 +0300158 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
Mark Blochba4a4112018-10-10 09:55:10 +0300175 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 }
Linus Torvaldsda19a102018-10-26 07:38:19 -0700182 flow_act.flags |= FLOW_ACT_HAS_TAG;
Mark Blochba4a4112018-10-10 09:55:10 +0300183 }
184
Mark Blochb823dd62018-09-06 17:27:05 +0300185 flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher, &flow_act,
Mark Blochbfc5d832018-11-20 20:31:08 +0200186 counter_id,
Mark Blochb823dd62018-09-06 17:27:05 +0300187 cmd_in, inlen,
Yishai Hadas32269442018-07-23 15:25:09 +0300188 dest_id, dest_type);
Mark Blochfa76d242018-09-06 17:27:06 +0300189 if (IS_ERR(flow_handler)) {
190 ret = PTR_ERR(flow_handler);
191 goto err_out;
192 }
Yishai Hadas32269442018-07-23 15:25:09 +0300193
Mark Blochfa76d242018-09-06 17:27:06 +0300194 ib_set_flow(uobj, &flow_handler->ibflow, qp, &dev->ib_dev, uflow_res);
Yishai Hadas32269442018-07-23 15:25:09 +0300195
196 return 0;
Mark Blochfa76d242018-09-06 17:27:06 +0300197err_out:
198 ib_uverbs_flow_resources_free(uflow_res);
199 return ret;
Yishai Hadas32269442018-07-23 15:25:09 +0300200}
201
Yishai Hadasfd44e382018-07-23 15:25:07 +0300202static int flow_matcher_cleanup(struct ib_uobject *uobject,
Shamir Rabinovitcha6a37972019-03-31 19:10:04 +0300203 enum rdma_remove_reason why,
204 struct uverbs_attr_bundle *attrs)
Yishai Hadasfd44e382018-07-23 15:25:07 +0300205{
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
Mark Bloch52438be2019-03-28 15:46:23 +0200217static 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
Yishai Hadasfd44e382018-07-23 15:25:07 +0300265static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
Jason Gunthorpe15a1b4b2018-11-25 20:51:15 +0200266 struct uverbs_attr_bundle *attrs)
Yishai Hadasfd44e382018-07-23 15:25:07 +0300267{
268 struct ib_uobject *uobj = uverbs_attr_get_uobject(
269 attrs, MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE);
Jason Gunthorpee79c9c62019-04-01 17:08:23 -0300270 struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
Yishai Hadasfd44e382018-07-23 15:25:07 +0300271 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
Mark Bloch52438be2019-03-28 15:46:23 +0200303 err = mlx5_ib_matcher_ns(attrs, obj);
Mark Blocha7ee18b2018-09-06 17:27:08 +0300304 if (err)
305 goto end;
306
Yishai Hadasfd44e382018-07-23 15:25:07 +0300307 uobj->object = obj;
308 obj->mdev = dev->mdev;
309 atomic_set(&obj->usecnt, 0);
310 return 0;
311
312end:
313 kfree(obj);
314 return err;
315}
316
Mark Blochb4749bf2018-08-28 14:18:51 +0300317void 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;
Mark Blocha090d0d2018-08-28 14:18:54 +0300324 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;
Mark Bloch08aeb972018-08-28 14:18:53 +0300328 case MLX5_IB_FLOW_ACTION_DECAP:
329 break;
Mark Blochb4749bf2018-08-28 14:18:51 +0300330 default:
331 break;
332 }
333}
334
335static struct ib_flow_action *
336mlx5_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
366static 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
373static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)(
Mark Blochb4749bf2018-08-28 14:18:51 +0300374 struct uverbs_attr_bundle *attrs)
375{
376 struct ib_uobject *uobj = uverbs_attr_get_uobject(
377 attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE);
Jason Gunthorpee79c9c62019-04-01 17:08:23 -0300378 struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
Mark Blochb4749bf2018-08-28 14:18:51 +0300379 enum mlx5_ib_uapi_flow_table_type ft_type;
380 struct ib_flow_action *action;
Dan Carpenter58f7c0b2018-12-22 10:43:32 +0300381 int num_actions;
Mark Blochb4749bf2018-08-28 14:18:51 +0300382 void *in;
Mark Blochb4749bf2018-08-28 14:18:51 +0300383 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);
Mark Blochb4749bf2018-08-28 14:18:51 +0300390
Moni Shouacbfdd442018-12-11 13:37:51 +0200391 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;
Mark Blochb4749bf2018-08-28 14:18:51 +0300396
397 ret = uverbs_get_const(&ft_type, attrs,
398 MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE);
399 if (ret)
400 return ret;
Mark Blochb4749bf2018-08-28 14:18:51 +0300401 action = mlx5_ib_create_modify_header(mdev, ft_type, num_actions, in);
402 if (IS_ERR(action))
403 return PTR_ERR(action);
404
Jason Gunthorpee79c9c62019-04-01 17:08:23 -0300405 uverbs_flow_action_fill_action(action, uobj, &mdev->ib_dev,
Mark Bloch841eefc2018-08-28 14:18:52 +0300406 IB_FLOW_ACTION_UNSPECIFIED);
Mark Blochb4749bf2018-08-28 14:18:51 +0300407
408 return 0;
409}
410
Mark Bloch08aeb972018-08-28 14:18:53 +0300411static 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) {
Mark Blocha090d0d2018-08-28 14:18:54 +0300416 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;
Mark Bloch08aeb972018-08-28 14:18:53 +0300431 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
Mark Blocha090d0d2018-08-28 14:18:54 +0300442static 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
461static 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
Mark Bloch08aeb972018-08-28 14:18:53 +0300492static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)(
Mark Bloch08aeb972018-08-28 14:18:53 +0300493 struct uverbs_attr_bundle *attrs)
494{
495 struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
496 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE);
Jason Gunthorpee79c9c62019-04-01 17:08:23 -0300497 struct mlx5_ib_dev *mdev = mlx5_udata_to_mdev(&attrs->driver_udata);
Mark Bloch08aeb972018-08-28 14:18:53 +0300498 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;
Mark Blocha090d0d2018-08-28 14:18:54 +0300525 } 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;
Mark Bloch08aeb972018-08-28 14:18:53 +0300543 }
544
Jason Gunthorpee79c9c62019-04-01 17:08:23 -0300545 uverbs_flow_action_fill_action(&maction->ib_action, uobj, &mdev->ib_dev,
Mark Bloch08aeb972018-08-28 14:18:53 +0300546 IB_FLOW_ACTION_UNSPECIFIED);
547 return 0;
Mark Blocha090d0d2018-08-28 14:18:54 +0300548
549free_maction:
550 kfree(maction);
551 return ret;
Mark Bloch08aeb972018-08-28 14:18:53 +0300552}
553
Yishai Hadasfd44e382018-07-23 15:25:07 +0300554DECLARE_UVERBS_NAMED_METHOD(
Yishai Hadas32269442018-07-23 15:25:09 +0300555 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,
Mark Blochfa76d242018-09-06 17:27:06 +0300574 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,
Mark Blochba4a4112018-10-10 09:55:10 +0300579 UA_OPTIONAL),
580 UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_TAG,
581 UVERBS_ATTR_TYPE(u32),
Mark Blochbfc5d832018-11-20 20:31:08 +0200582 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));
Yishai Hadas32269442018-07-23 15:25:09 +0300587
588DECLARE_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
595ADD_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
600DECLARE_UVERBS_NAMED_METHOD(
Mark Blochb4749bf2018-08-28 14:18:51 +0300601 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
Mark Bloch08aeb972018-08-28 14:18:53 +0300615DECLARE_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),
Mark Blocha090d0d2018-08-28 14:18:54 +0300621 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),
Mark Bloch08aeb972018-08-28 14:18:53 +0300625 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
Mark Blochb4749bf2018-08-28 14:18:51 +0300632ADD_UVERBS_METHODS(
633 mlx5_ib_flow_actions,
634 UVERBS_OBJECT_FLOW_ACTION,
Mark Bloch08aeb972018-08-28 14:18:53 +0300635 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER),
636 &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT));
Mark Blochb4749bf2018-08-28 14:18:51 +0300637
638DECLARE_UVERBS_NAMED_METHOD(
Yishai Hadasfd44e382018-07-23 15:25:07 +0300639 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),
Mark Blocha7ee18b2018-09-06 17:27:08 +0300653 UA_MANDATORY),
654 UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
655 enum ib_flow_flags,
Mark Bloch52438be2019-03-28 15:46:23 +0200656 UA_OPTIONAL),
657 UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE,
658 enum mlx5_ib_uapi_flow_table_type,
Mark Blocha7ee18b2018-09-06 17:27:08 +0300659 UA_OPTIONAL));
Yishai Hadasfd44e382018-07-23 15:25:07 +0300660
661DECLARE_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
668DECLARE_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
Jason Gunthorpe0cbf4322018-11-12 22:59:50 +0200673const struct uapi_definition mlx5_ib_flow_defs[] = {
Leon Romanovskya1462352018-12-10 11:19:49 +0200674 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
Mark Bloch7f575102019-03-28 15:46:25 +0200675 MLX5_IB_OBJECT_FLOW_MATCHER),
Leon Romanovskya1462352018-12-10 11:19:49 +0200676 UAPI_DEF_CHAIN_OBJ_TREE(
677 UVERBS_OBJECT_FLOW,
Mark Blochc1b03c22019-01-24 14:33:32 +0200678 &mlx5_ib_fs),
Jason Gunthorpe0cbf4322018-11-12 22:59:50 +0200679 UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
680 &mlx5_ib_flow_actions),
681 {},
682};