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