IB/uverbs: Add modify ESP flow_action
authorMatan Barak <matanb@mellanox.com>
Wed, 28 Mar 2018 06:27:48 +0000 (09:27 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Wed, 4 Apr 2018 18:06:26 +0000 (12:06 -0600)
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>
drivers/infiniband/core/uverbs_std_types_flow_action.c
include/rdma/ib_verbs.h
include/uapi/rdma/ib_user_ioctl_cmds.h

index 3d4c7b8dff489496c424d64e3b06941213777fd8..cbcec3da12f685054c93d102e3e67556f5a71045 100644 (file)
@@ -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,
-                                    u32 flags)
+                                    u32 flags, bool is_modify)
 {
        u64 verbs_flags = flags;
 
        if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_FLOW_ACTION_ESP_ESN))
                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;
 };
 
@@ -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,
 };
 
+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,
                        const void __user *val_ptr,
                        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,
                                 struct ib_uverbs_file *file,
                                 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 = {};
        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.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)) {
                esp_attr->keymat.protocol =
@@ -252,6 +284,11 @@ static int parse_flow_action_esp(struct ib_device *ib_dev,
                if (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;
        }
 
@@ -278,7 +315,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)(struct ib_device
        if (!ib_dev->create_flow_action_esp)
                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)
                return ret;
 
@@ -297,6 +334,33 @@ static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)(struct ib_device
        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[] = {
        [IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM] = {
                .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[] = {
+       [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] = {
                .ptr = {
                        .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_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,
        uverbs_destroy_def_handler,
        &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,
                            &UVERBS_TYPE_ALLOC_IDR(0, uverbs_free_flow_action),
                            &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));
 
index c674fc1e596bfa177dd379911d07f90b5690481e..8c3ca073016d788a48e253103725aa372f9374c0 100644 (file)
@@ -2038,6 +2038,7 @@ enum ib_flow_action_attrs_esp_flags {
 
        /* Kernel flags */
        IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED  = 1ULL << 32,
+       IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS  = 1ULL << 33,
 };
 
 struct ib_flow_spec_list {
@@ -2404,6 +2405,9 @@ struct ib_device {
                                                             const struct ib_flow_action_attrs_esp *attr,
                                                             struct uverbs_attr_bundle *attrs);
        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
index d3a2c03ea4a87a008d02026dfb01d1e866ce3310..500b64a444adb9dbf1a99589f53c017bcf353c0c 100644 (file)
@@ -97,6 +97,7 @@ enum uverbs_methods_cq {
 enum uverbs_methods_actions_flow_action_ops {
        UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
        UVERBS_METHOD_FLOW_ACTION_DESTROY,
+       UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY,
 };
 
 #endif