root/drivers/infiniband/hw/mlx5/flow.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mlx5_ib_ft_type_to_namespace
  2. UVERBS_HANDLER
  3. flow_matcher_cleanup
  4. mlx5_ib_matcher_ns
  5. UVERBS_HANDLER
  6. mlx5_ib_destroy_flow_action_raw
  7. mlx5_ib_create_modify_header
  8. mlx5_ib_modify_header_supported
  9. UVERBS_HANDLER
  10. mlx5_ib_flow_action_packet_reformat_valid
  11. mlx5_ib_dv_to_prm_packet_reforamt_type
  12. mlx5_ib_flow_action_create_packet_reformat_ctx
  13. UVERBS_HANDLER

   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 };

/* [<][>][^][v][top][bottom][index][help] */