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: Yishai Hadas <yishaih@mellanox.com> Signed-off-by: Matan Barak <matanb@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
parent
21e82d3e1d
commit
7d12f8d5a1
@ -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
|
|||||||
[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 {
|
|||||||
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,
|
|||||||
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,
|
|||||||
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
|
|||||||
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
|
|||||||
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[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
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,
|
|||||||
&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
|
|||||||
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 {
|
|||||||
|
|
||||||
/* 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 {
|
|||||||
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 {
|
|||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user