mirror of
https://github.com/torvalds/linux.git
synced 2024-12-11 05:33:09 +00:00
RDMA/mlx5: Add a new flow action verb - modify header
Expose the ability to create a flow action which changes packet headers. The data passed from userspace should be modify header actions as defined by HW specification. Signed-off-by: Mark Bloch <markb@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
parent
0953fffec9
commit
b4749bf256
@ -8,6 +8,7 @@
|
||||
#include <rdma/uverbs_types.h>
|
||||
#include <rdma/uverbs_ioctl.h>
|
||||
#include <rdma/mlx5_user_ioctl_cmds.h>
|
||||
#include <rdma/mlx5_user_ioctl_verbs.h>
|
||||
#include <rdma/ib_umem.h>
|
||||
#include <linux/mlx5/driver.h>
|
||||
#include <linux/mlx5/fs.h>
|
||||
@ -16,6 +17,24 @@
|
||||
#define UVERBS_MODULE_NAME mlx5_ib
|
||||
#include <rdma/uverbs_named_ioctl.h>
|
||||
|
||||
static int
|
||||
mlx5_ib_ft_type_to_namespace(enum mlx5_ib_uapi_flow_table_type table_type,
|
||||
enum mlx5_flow_namespace_type *namespace)
|
||||
{
|
||||
switch (table_type) {
|
||||
case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX:
|
||||
*namespace = MLX5_FLOW_NAMESPACE_BYPASS;
|
||||
break;
|
||||
case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX:
|
||||
*namespace = MLX5_FLOW_NAMESPACE_EGRESS;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct uverbs_attr_spec mlx5_ib_flow_type[] = {
|
||||
[MLX5_IB_FLOW_TYPE_NORMAL] = {
|
||||
.type = UVERBS_ATTR_TYPE_PTR_IN,
|
||||
@ -175,6 +194,100 @@ end:
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
|
||||
{
|
||||
switch (maction->flow_action_raw.sub_type) {
|
||||
case MLX5_IB_FLOW_ACTION_MODIFY_HEADER:
|
||||
mlx5_modify_header_dealloc(maction->flow_action_raw.dev->mdev,
|
||||
maction->flow_action_raw.action_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct ib_flow_action *
|
||||
mlx5_ib_create_modify_header(struct mlx5_ib_dev *dev,
|
||||
enum mlx5_ib_uapi_flow_table_type ft_type,
|
||||
u8 num_actions, void *in)
|
||||
{
|
||||
enum mlx5_flow_namespace_type namespace;
|
||||
struct mlx5_ib_flow_action *maction;
|
||||
int ret;
|
||||
|
||||
ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace);
|
||||
if (ret)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
maction = kzalloc(sizeof(*maction), GFP_KERNEL);
|
||||
if (!maction)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = mlx5_modify_header_alloc(dev->mdev, namespace, num_actions, in,
|
||||
&maction->flow_action_raw.action_id);
|
||||
|
||||
if (ret) {
|
||||
kfree(maction);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
maction->flow_action_raw.sub_type =
|
||||
MLX5_IB_FLOW_ACTION_MODIFY_HEADER;
|
||||
maction->flow_action_raw.dev = dev;
|
||||
|
||||
return &maction->ib_action;
|
||||
}
|
||||
|
||||
static bool mlx5_ib_modify_header_supported(struct mlx5_ib_dev *dev)
|
||||
{
|
||||
return MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
|
||||
max_modify_header_actions) ||
|
||||
MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, max_modify_header_actions);
|
||||
}
|
||||
|
||||
static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)(
|
||||
struct ib_uverbs_file *file,
|
||||
struct uverbs_attr_bundle *attrs)
|
||||
{
|
||||
struct ib_uobject *uobj = uverbs_attr_get_uobject(
|
||||
attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE);
|
||||
struct mlx5_ib_dev *mdev = to_mdev(uobj->context->device);
|
||||
enum mlx5_ib_uapi_flow_table_type ft_type;
|
||||
struct ib_flow_action *action;
|
||||
size_t num_actions;
|
||||
void *in;
|
||||
int len;
|
||||
int ret;
|
||||
|
||||
if (!mlx5_ib_modify_header_supported(mdev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
in = uverbs_attr_get_alloced_ptr(attrs,
|
||||
MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM);
|
||||
len = uverbs_attr_get_len(attrs,
|
||||
MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM);
|
||||
|
||||
if (len % MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto))
|
||||
return -EINVAL;
|
||||
|
||||
ret = uverbs_get_const(&ft_type, attrs,
|
||||
MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
num_actions = len / MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto),
|
||||
action = mlx5_ib_create_modify_header(mdev, ft_type, num_actions, in);
|
||||
if (IS_ERR(action))
|
||||
return PTR_ERR(action);
|
||||
|
||||
atomic_set(&action->usecnt, 0);
|
||||
action->device = uobj->context->device;
|
||||
action->type = IB_FLOW_ACTION_UNSPECIFIED;
|
||||
action->uobject = uobj;
|
||||
uobj->object = action;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DECLARE_UVERBS_NAMED_METHOD(
|
||||
MLX5_IB_METHOD_CREATE_FLOW,
|
||||
UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
|
||||
@ -209,6 +322,26 @@ ADD_UVERBS_METHODS(mlx5_ib_fs,
|
||||
&UVERBS_METHOD(MLX5_IB_METHOD_CREATE_FLOW),
|
||||
&UVERBS_METHOD(MLX5_IB_METHOD_DESTROY_FLOW));
|
||||
|
||||
DECLARE_UVERBS_NAMED_METHOD(
|
||||
MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER,
|
||||
UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE,
|
||||
UVERBS_OBJECT_FLOW_ACTION,
|
||||
UVERBS_ACCESS_NEW,
|
||||
UA_MANDATORY),
|
||||
UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM,
|
||||
UVERBS_ATTR_MIN_SIZE(MLX5_UN_SZ_BYTES(
|
||||
set_action_in_add_action_in_auto)),
|
||||
UA_MANDATORY,
|
||||
UA_ALLOC_AND_COPY),
|
||||
UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE,
|
||||
enum mlx5_ib_uapi_flow_table_type,
|
||||
UA_MANDATORY));
|
||||
|
||||
ADD_UVERBS_METHODS(
|
||||
mlx5_ib_flow_actions,
|
||||
UVERBS_OBJECT_FLOW_ACTION,
|
||||
&UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER));
|
||||
|
||||
DECLARE_UVERBS_NAMED_METHOD(
|
||||
MLX5_IB_METHOD_FLOW_MATCHER_CREATE,
|
||||
UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE,
|
||||
@ -247,6 +380,7 @@ int mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root)
|
||||
|
||||
root[i++] = &flow_objects;
|
||||
root[i++] = &mlx5_ib_fs;
|
||||
root[i++] = &mlx5_ib_flow_actions;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
@ -3995,6 +3995,9 @@ static int mlx5_ib_destroy_flow_action(struct ib_flow_action *action)
|
||||
*/
|
||||
mlx5_accel_esp_destroy_xfrm(maction->esp_aes_gcm.ctx);
|
||||
break;
|
||||
case IB_FLOW_ACTION_UNSPECIFIED:
|
||||
mlx5_ib_destroy_flow_action_raw(maction);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(true);
|
||||
break;
|
||||
|
@ -151,6 +151,10 @@ struct mlx5_ib_pd {
|
||||
u32 pdn;
|
||||
};
|
||||
|
||||
enum {
|
||||
MLX5_IB_FLOW_ACTION_MODIFY_HEADER,
|
||||
};
|
||||
|
||||
#define MLX5_IB_FLOW_MCAST_PRIO (MLX5_BY_PASS_NUM_PRIOS - 1)
|
||||
#define MLX5_IB_FLOW_LAST_PRIO (MLX5_BY_PASS_NUM_REGULAR_PRIOS - 1)
|
||||
#if (MLX5_IB_FLOW_LAST_PRIO <= 0)
|
||||
@ -814,6 +818,11 @@ struct mlx5_ib_flow_action {
|
||||
u64 ib_flags;
|
||||
struct mlx5_accel_esp_xfrm *ctx;
|
||||
} esp_aes_gcm;
|
||||
struct {
|
||||
struct mlx5_ib_dev *dev;
|
||||
u32 sub_type;
|
||||
u32 action_id;
|
||||
} flow_action_raw;
|
||||
};
|
||||
};
|
||||
|
||||
@ -860,7 +869,7 @@ to_mcounters(struct ib_counters *ibcntrs)
|
||||
|
||||
struct mlx5_ib_dev {
|
||||
struct ib_device ib_dev;
|
||||
const struct uverbs_object_tree_def *driver_trees[6];
|
||||
const struct uverbs_object_tree_def *driver_trees[7];
|
||||
struct mlx5_core_dev *mdev;
|
||||
struct mlx5_roce roce[MLX5_MAX_PORTS];
|
||||
int num_ports;
|
||||
@ -1238,6 +1247,7 @@ struct mlx5_ib_flow_handler *mlx5_ib_raw_fs_rule_add(
|
||||
void *cmd_in, int inlen, int dest_id, int dest_type);
|
||||
bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type);
|
||||
int mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root);
|
||||
void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction);
|
||||
#else
|
||||
static inline int
|
||||
mlx5_ib_devx_create(struct mlx5_ib_dev *dev,
|
||||
@ -1256,6 +1266,11 @@ mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void
|
||||
mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
|
||||
{
|
||||
return;
|
||||
};
|
||||
#endif
|
||||
static inline void init_query_mad(struct ib_smp *mad)
|
||||
{
|
||||
|
@ -166,4 +166,14 @@ enum mlx5_ib_flow_methods {
|
||||
MLX5_IB_METHOD_DESTROY_FLOW,
|
||||
};
|
||||
|
||||
enum mlx5_ib_flow_action_methods {
|
||||
MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER = (1U << UVERBS_ID_NS_SHIFT),
|
||||
};
|
||||
|
||||
enum mlx5_ib_create_flow_action_create_modify_header_attrs {
|
||||
MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
|
||||
MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM,
|
||||
MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -39,5 +39,10 @@ enum mlx5_ib_uapi_flow_action_flags {
|
||||
MLX5_IB_UAPI_FLOW_ACTION_FLAGS_REQUIRE_METADATA = 1 << 0,
|
||||
};
|
||||
|
||||
enum mlx5_ib_uapi_flow_table_type {
|
||||
MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX = 0x0,
|
||||
MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX = 0x1,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user