Commit 7d12f8d5 authored by Matan Barak's avatar Matan Barak Committed by Jason Gunthorpe

IB/uverbs: Add modify ESP flow_action

flow_actions of ESP type could be modified during runtime. This could be
common for example when ESN should be changed. Adding a new
UVERBS_FLOW_ACTION_ESP_MODIFY method for changing ESP parameters of an
existing ESP flow_action.
The new method uses the UVERBS_FLOW_ACTION_ESP_CREATE attributes, but
adds a new IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS which means ESP_ATTRS
should be changed.
In addition, we add a new FLOW_ACTION_ESP_REPLAY_NONE replay type that
could be used when one wants to disable a replay protection over a
specific flow_action.
Reviewed-by: default avatarYishai Hadas <yishaih@mellanox.com>
Signed-off-by: default avatarMatan Barak <matanb@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 21e82d3e
...@@ -46,13 +46,17 @@ static int uverbs_free_flow_action(struct ib_uobject *uobject, ...@@ -46,13 +46,17 @@ static int uverbs_free_flow_action(struct ib_uobject *uobject,
} }
static u64 esp_flags_uverbs_to_verbs(struct uverbs_attr_bundle *attrs, static u64 esp_flags_uverbs_to_verbs(struct uverbs_attr_bundle *attrs,
u32 flags) u32 flags, bool is_modify)
{ {
u64 verbs_flags = flags; u64 verbs_flags = flags;
if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ESN)) if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ESN))
verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED; verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED;
if (is_modify && uverbs_attr_is_valid(attrs,
UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS))
verbs_flags |= IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS;
return verbs_flags; return verbs_flags;
}; };
...@@ -81,6 +85,32 @@ static int (* const flow_action_esp_keymat_validate[])(struct ib_flow_action_att ...@@ -81,6 +85,32 @@ static int (* const flow_action_esp_keymat_validate[])(struct ib_flow_action_att
[IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = validate_flow_action_esp_keymat_aes_gcm, [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = validate_flow_action_esp_keymat_aes_gcm,
}; };
static int flow_action_esp_replay_none(struct ib_flow_action_attrs_esp_replays *replay,
bool is_modify)
{
/* This is used in order to modify an esp flow action with an enabled
* replay protection to a disabled one. This is only supported via
* modify, as in create verb we can simply drop the REPLAY attribute and
* achieve the same thing.
*/
return is_modify ? 0 : -EINVAL;
}
static int flow_action_esp_replay_def_ok(struct ib_flow_action_attrs_esp_replays *replay,
bool is_modify)
{
/* Some replay protections could always be enabled without validating
* anything.
*/
return 0;
}
static int (* const flow_action_esp_replay_validate[])(struct ib_flow_action_attrs_esp_replays *replay,
bool is_modify) = {
[IB_UVERBS_FLOW_ACTION_ESP_REPLAY_NONE] = flow_action_esp_replay_none,
[IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = flow_action_esp_replay_def_ok,
};
static int parse_esp_ip(enum ib_flow_spec_type proto, static int parse_esp_ip(enum ib_flow_spec_type proto,
const void __user *val_ptr, const void __user *val_ptr,
size_t len, union ib_flow_spec *out) size_t len, union ib_flow_spec *out)
...@@ -194,7 +224,8 @@ struct ib_flow_action_esp_attr { ...@@ -194,7 +224,8 @@ struct ib_flow_action_esp_attr {
static int parse_flow_action_esp(struct ib_device *ib_dev, static int parse_flow_action_esp(struct ib_device *ib_dev,
struct ib_uverbs_file *file, struct ib_uverbs_file *file,
struct uverbs_attr_bundle *attrs, struct uverbs_attr_bundle *attrs,
struct ib_flow_action_esp_attr *esp_attr) struct ib_flow_action_esp_attr *esp_attr,
bool is_modify)
{ {
struct ib_uverbs_flow_action_esp uverbs_esp = {}; struct ib_uverbs_flow_action_esp uverbs_esp = {};
int ret; int ret;
...@@ -222,7 +253,8 @@ static int parse_flow_action_esp(struct ib_device *ib_dev, ...@@ -222,7 +253,8 @@ static int parse_flow_action_esp(struct ib_device *ib_dev,
esp_attr->hdr.tfc_pad = uverbs_esp.tfc_pad; esp_attr->hdr.tfc_pad = uverbs_esp.tfc_pad;
esp_attr->hdr.hard_limit_pkts = uverbs_esp.hard_limit_pkts; esp_attr->hdr.hard_limit_pkts = uverbs_esp.hard_limit_pkts;
} }
esp_attr->hdr.flags = esp_flags_uverbs_to_verbs(attrs, uverbs_esp.flags); esp_attr->hdr.flags = esp_flags_uverbs_to_verbs(attrs, uverbs_esp.flags,
is_modify);
if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT)) { if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT)) {
esp_attr->keymat.protocol = esp_attr->keymat.protocol =
...@@ -252,6 +284,11 @@ static int parse_flow_action_esp(struct ib_device *ib_dev, ...@@ -252,6 +284,11 @@ static int parse_flow_action_esp(struct ib_device *ib_dev,
if (ret) if (ret)
return ret; return ret;
ret = flow_action_esp_replay_validate[esp_attr->replay.protocol](&esp_attr->replay,
is_modify);
if (ret)
return ret;
esp_attr->hdr.replay = &esp_attr->replay; esp_attr->hdr.replay = &esp_attr->replay;
} }
...@@ -278,7 +315,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)(struct ib_device ...@@ -278,7 +315,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)(struct ib_device
if (!ib_dev->create_flow_action_esp) if (!ib_dev->create_flow_action_esp)
return -EOPNOTSUPP; return -EOPNOTSUPP;
ret = parse_flow_action_esp(ib_dev, file, attrs, &esp_attr); ret = parse_flow_action_esp(ib_dev, file, attrs, &esp_attr, false);
if (ret) if (ret)
return ret; return ret;
...@@ -297,6 +334,33 @@ static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)(struct ib_device ...@@ -297,6 +334,33 @@ static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)(struct ib_device
return 0; return 0;
} }
static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY)(struct ib_device *ib_dev,
struct ib_uverbs_file *file,
struct uverbs_attr_bundle *attrs)
{
int ret;
struct ib_uobject *uobj;
struct ib_flow_action *action;
struct ib_flow_action_esp_attr esp_attr = {};
if (!ib_dev->modify_flow_action_esp)
return -EOPNOTSUPP;
ret = parse_flow_action_esp(ib_dev, file, attrs, &esp_attr, true);
if (ret)
return ret;
uobj = uverbs_attr_get(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE)->obj_attr.uobject;
action = uobj->object;
if (action->type != IB_FLOW_ACTION_ESP)
return -EINVAL;
return ib_dev->modify_flow_action_esp(action,
&esp_attr.hdr,
attrs);
}
static const struct uverbs_attr_spec uverbs_flow_action_esp_keymat[] = { static const struct uverbs_attr_spec uverbs_flow_action_esp_keymat[] = {
[IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = { [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = {
.ptr = { .ptr = {
...@@ -308,6 +372,13 @@ static const struct uverbs_attr_spec uverbs_flow_action_esp_keymat[] = { ...@@ -308,6 +372,13 @@ static const struct uverbs_attr_spec uverbs_flow_action_esp_keymat[] = {
}; };
static const struct uverbs_attr_spec uverbs_flow_action_esp_replay[] = { static const struct uverbs_attr_spec uverbs_flow_action_esp_replay[] = {
[IB_UVERBS_FLOW_ACTION_ESP_REPLAY_NONE] = {
.ptr = {
.type = UVERBS_ATTR_TYPE_PTR_IN,
/* No need to specify any data */
.len = 0,
}
},
[IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = { [IB_UVERBS_FLOW_ACTION_ESP_REPLAY_BMP] = {
.ptr = { .ptr = {
.type = UVERBS_ATTR_TYPE_PTR_IN, .type = UVERBS_ATTR_TYPE_PTR_IN,
...@@ -334,6 +405,21 @@ static DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE, ...@@ -334,6 +405,21 @@ static DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
&UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP, &UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_encap, type))); UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_encap, type)));
static DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY,
&UVERBS_ATTR_IDR(UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE, UVERBS_OBJECT_FLOW_ACTION,
UVERBS_ACCESS_WRITE,
UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
&UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ATTRS,
UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp, hard_limit_pkts),
UA_FLAGS(UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)),
&UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ESN, UVERBS_ATTR_TYPE(__u32)),
&UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_KEYMAT,
uverbs_flow_action_esp_keymat),
&UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_FLOW_ACTION_ESP_REPLAY,
uverbs_flow_action_esp_replay),
&UVERBS_ATTR_PTR_IN(UVERBS_ATTR_FLOW_ACTION_ESP_ENCAP,
UVERBS_ATTR_STRUCT(struct ib_uverbs_flow_action_esp_encap, type)));
static DECLARE_UVERBS_NAMED_METHOD_WITH_HANDLER(UVERBS_METHOD_FLOW_ACTION_DESTROY, static DECLARE_UVERBS_NAMED_METHOD_WITH_HANDLER(UVERBS_METHOD_FLOW_ACTION_DESTROY,
uverbs_destroy_def_handler, uverbs_destroy_def_handler,
&UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_FLOW_ACTION_HANDLE, &UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_FLOW_ACTION_HANDLE,
...@@ -344,5 +430,6 @@ static DECLARE_UVERBS_NAMED_METHOD_WITH_HANDLER(UVERBS_METHOD_FLOW_ACTION_DESTRO ...@@ -344,5 +430,6 @@ static DECLARE_UVERBS_NAMED_METHOD_WITH_HANDLER(UVERBS_METHOD_FLOW_ACTION_DESTRO
DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_FLOW_ACTION, DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_FLOW_ACTION,
&UVERBS_TYPE_ALLOC_IDR(0, uverbs_free_flow_action), &UVERBS_TYPE_ALLOC_IDR(0, uverbs_free_flow_action),
&UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE), &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE),
&UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_DESTROY)); &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_DESTROY),
&UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY));
...@@ -2038,6 +2038,7 @@ enum ib_flow_action_attrs_esp_flags { ...@@ -2038,6 +2038,7 @@ enum ib_flow_action_attrs_esp_flags {
/* Kernel flags */ /* Kernel flags */
IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED = 1ULL << 32, IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED = 1ULL << 32,
IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS = 1ULL << 33,
}; };
struct ib_flow_spec_list { struct ib_flow_spec_list {
...@@ -2404,6 +2405,9 @@ struct ib_device { ...@@ -2404,6 +2405,9 @@ struct ib_device {
const struct ib_flow_action_attrs_esp *attr, const struct ib_flow_action_attrs_esp *attr,
struct uverbs_attr_bundle *attrs); struct uverbs_attr_bundle *attrs);
int (*destroy_flow_action)(struct ib_flow_action *action); int (*destroy_flow_action)(struct ib_flow_action *action);
int (*modify_flow_action_esp)(struct ib_flow_action *action,
const struct ib_flow_action_attrs_esp *attr,
struct uverbs_attr_bundle *attrs);
/** /**
* rdma netdev operation * rdma netdev operation
......
...@@ -97,6 +97,7 @@ enum uverbs_methods_cq { ...@@ -97,6 +97,7 @@ enum uverbs_methods_cq {
enum uverbs_methods_actions_flow_action_ops { enum uverbs_methods_actions_flow_action_ops {
UVERBS_METHOD_FLOW_ACTION_ESP_CREATE, UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
UVERBS_METHOD_FLOW_ACTION_DESTROY, UVERBS_METHOD_FLOW_ACTION_DESTROY,
UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY,
}; };
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment