]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net/mlx5: IPsec, Refactor SA handle creation and destruction
authorRaed Salem <raeds@mellanox.com>
Wed, 23 Oct 2019 14:04:13 +0000 (17:04 +0300)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 20 Apr 2020 21:20:20 +0000 (14:20 -0700)
Currently the SA handle is created and managed as part of the common
code for different IPsec supporting HW, this handle is passed to HW
to be used on Rx to identify the SA handle that was used to
return the xfrm state to stack.

The above implementation pose a limitation on managing this handle.

Refactor by moving management of this field to the specific HW code.

Downstream patches will introduce the Connect-X support for IPsec that
will use this handle differently than current implementation.

Signed-off-by: Raed Salem <raeds@mellanox.com>
Reviewed-by: Boris Pismenny <borisp@mellanox.com>
Reviewed-by: Huy Nguyen <huyn@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/accel/ipsec.c
drivers/net/ethernet/mellanox/mlx5/core/accel/ipsec.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.h

index a92cd88d369cedcfc2142a8b394715a2010fcf16..8a4985d8cbfe5125e11424354d4110f9ec216a40 100644 (file)
@@ -57,7 +57,8 @@ int mlx5_accel_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters,
 }
 
 void *mlx5_accel_esp_create_hw_context(struct mlx5_core_dev *mdev,
-                                      struct mlx5_accel_esp_xfrm *xfrm)
+                                      struct mlx5_accel_esp_xfrm *xfrm,
+                                      u32 *sa_handle)
 {
        __be32 saddr[4] = {}, daddr[4] = {};
 
@@ -71,7 +72,7 @@ void *mlx5_accel_esp_create_hw_context(struct mlx5_core_dev *mdev,
 
        return mlx5_fpga_ipsec_create_sa_ctx(mdev, xfrm, saddr,
                                             daddr, xfrm->attrs.spi,
-                                            xfrm->attrs.is_ipv6);
+                                            xfrm->attrs.is_ipv6, sa_handle);
 }
 
 void mlx5_accel_esp_free_hw_context(void *context)
index f9b8e2a041c1eb0779b61f525459ec0b6fe33087..e89747674712c99f76abbb56bcdcef843e2a6cb9 100644 (file)
@@ -47,7 +47,8 @@ int mlx5_accel_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters,
                                   unsigned int count);
 
 void *mlx5_accel_esp_create_hw_context(struct mlx5_core_dev *mdev,
-                                      struct mlx5_accel_esp_xfrm *xfrm);
+                                      struct mlx5_accel_esp_xfrm *xfrm,
+                                      u32 *sa_handle);
 void mlx5_accel_esp_free_hw_context(void *context);
 
 int mlx5_accel_ipsec_init(struct mlx5_core_dev *mdev);
@@ -60,7 +61,8 @@ void mlx5_accel_ipsec_cleanup(struct mlx5_core_dev *mdev);
 
 static inline void *
 mlx5_accel_esp_create_hw_context(struct mlx5_core_dev *mdev,
-                                struct mlx5_accel_esp_xfrm *xfrm)
+                                struct mlx5_accel_esp_xfrm *xfrm,
+                                u32 *sa_handle)
 {
        return NULL;
 }
index 9e6c2216c93ecbe1272955e2b89dff1c068fc254..92eb3bad4acd12f9aa371803508c85158b09bc57 100644 (file)
@@ -75,18 +75,23 @@ struct xfrm_state *mlx5e_ipsec_sadb_rx_lookup(struct mlx5e_ipsec *ipsec,
        return ret;
 }
 
-static int mlx5e_ipsec_sadb_rx_add(struct mlx5e_ipsec_sa_entry *sa_entry)
+static int  mlx5e_ipsec_sadb_rx_add(struct mlx5e_ipsec_sa_entry *sa_entry,
+                                   unsigned int handle)
 {
        struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
+       struct mlx5e_ipsec_sa_entry *_sa_entry;
        unsigned long flags;
-       int ret;
 
-       ret = ida_simple_get(&ipsec->halloc, 1, 0, GFP_KERNEL);
-       if (ret < 0)
-               return ret;
+       rcu_read_lock();
+       hash_for_each_possible_rcu(ipsec->sadb_rx, _sa_entry, hlist, handle)
+               if (_sa_entry->handle == handle) {
+                       rcu_read_unlock();
+                       return  -EEXIST;
+               }
+       rcu_read_unlock();
 
        spin_lock_irqsave(&ipsec->sadb_rx_lock, flags);
-       sa_entry->handle = ret;
+       sa_entry->handle = handle;
        hash_add_rcu(ipsec->sadb_rx, &sa_entry->hlist, sa_entry->handle);
        spin_unlock_irqrestore(&ipsec->sadb_rx_lock, flags);
 
@@ -103,15 +108,6 @@ static void mlx5e_ipsec_sadb_rx_del(struct mlx5e_ipsec_sa_entry *sa_entry)
        spin_unlock_irqrestore(&ipsec->sadb_rx_lock, flags);
 }
 
-static void mlx5e_ipsec_sadb_rx_free(struct mlx5e_ipsec_sa_entry *sa_entry)
-{
-       struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
-
-       /* xfrm already doing sync rcu between del and free callbacks */
-
-       ida_simple_remove(&ipsec->halloc, sa_entry->handle);
-}
-
 static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry)
 {
        struct xfrm_replay_state_esn *replay_esn;
@@ -292,6 +288,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x)
        struct net_device *netdev = x->xso.dev;
        struct mlx5_accel_esp_xfrm_attrs attrs;
        struct mlx5e_priv *priv;
+       unsigned int sa_handle;
        int err;
 
        priv = netdev_priv(netdev);
@@ -309,20 +306,6 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x)
        sa_entry->x = x;
        sa_entry->ipsec = priv->ipsec;
 
-       /* Add the SA to handle processed incoming packets before the add SA
-        * completion was received
-        */
-       if (x->xso.flags & XFRM_OFFLOAD_INBOUND) {
-               err = mlx5e_ipsec_sadb_rx_add(sa_entry);
-               if (err) {
-                       netdev_info(netdev, "Failed adding to SADB_RX: %d\n", err);
-                       goto err_entry;
-               }
-       } else {
-               sa_entry->set_iv_op = (x->props.flags & XFRM_STATE_ESN) ?
-                               mlx5e_ipsec_set_iv_esn : mlx5e_ipsec_set_iv;
-       }
-
        /* check esn */
        mlx5e_ipsec_update_esn_state(sa_entry);
 
@@ -333,30 +316,38 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x)
                                           MLX5_ACCEL_XFRM_FLAG_REQUIRE_METADATA);
        if (IS_ERR(sa_entry->xfrm)) {
                err = PTR_ERR(sa_entry->xfrm);
-               goto err_sadb_rx;
+               goto err_sa_entry;
        }
 
        /* create hw context */
        sa_entry->hw_context =
                        mlx5_accel_esp_create_hw_context(priv->mdev,
-                                                        sa_entry->xfrm);
+                                                        sa_entry->xfrm,
+                                                        &sa_handle);
        if (IS_ERR(sa_entry->hw_context)) {
                err = PTR_ERR(sa_entry->hw_context);
                goto err_xfrm;
        }
 
+       if (x->xso.flags & XFRM_OFFLOAD_INBOUND) {
+               err = mlx5e_ipsec_sadb_rx_add(sa_entry, sa_handle);
+               if (err)
+                       goto err_hw_ctx;
+       } else {
+               sa_entry->set_iv_op = (x->props.flags & XFRM_STATE_ESN) ?
+                               mlx5e_ipsec_set_iv_esn : mlx5e_ipsec_set_iv;
+       }
+
        x->xso.offload_handle = (unsigned long)sa_entry;
        goto out;
 
+err_hw_ctx:
+       mlx5_accel_esp_free_hw_context(sa_entry->hw_context);
 err_xfrm:
        mlx5_accel_esp_destroy_xfrm(sa_entry->xfrm);
-err_sadb_rx:
-       if (x->xso.flags & XFRM_OFFLOAD_INBOUND) {
-               mlx5e_ipsec_sadb_rx_del(sa_entry);
-               mlx5e_ipsec_sadb_rx_free(sa_entry);
-       }
-err_entry:
+err_sa_entry:
        kfree(sa_entry);
+
 out:
        return err;
 }
@@ -385,9 +376,6 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x)
                mlx5_accel_esp_destroy_xfrm(sa_entry->xfrm);
        }
 
-       if (x->xso.flags & XFRM_OFFLOAD_INBOUND)
-               mlx5e_ipsec_sadb_rx_free(sa_entry);
-
        kfree(sa_entry);
 }
 
index c8736b6b41728e0ed7986e5332a7a04c024ce99c..0604216eb94f1c786bd96e16c08d08e6190e2af8 100644 (file)
@@ -65,6 +65,7 @@ struct mlx5_fpga_esp_xfrm;
 struct mlx5_fpga_ipsec_sa_ctx {
        struct rhash_head               hash;
        struct mlx5_ifc_fpga_ipsec_sa   hw_sa;
+       u32                             sa_handle;
        struct mlx5_core_dev            *dev;
        struct mlx5_fpga_esp_xfrm       *fpga_xfrm;
 };
@@ -119,6 +120,8 @@ struct mlx5_fpga_ipsec {
         */
        struct rb_root rules_rb;
        struct mutex rules_rb_lock; /* rules lock */
+
+       struct ida halloc;
 };
 
 static bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev)
@@ -666,7 +669,8 @@ void *mlx5_fpga_ipsec_create_sa_ctx(struct mlx5_core_dev *mdev,
                                    struct mlx5_accel_esp_xfrm *accel_xfrm,
                                    const __be32 saddr[4],
                                    const __be32 daddr[4],
-                                   const __be32 spi, bool is_ipv6)
+                                   const __be32 spi, bool is_ipv6,
+                                   u32 *sa_handle)
 {
        struct mlx5_fpga_ipsec_sa_ctx *sa_ctx;
        struct mlx5_fpga_esp_xfrm *fpga_xfrm =
@@ -704,6 +708,17 @@ void *mlx5_fpga_ipsec_create_sa_ctx(struct mlx5_core_dev *mdev,
                goto exists;
        }
 
+       if (accel_xfrm->attrs.action & MLX5_ACCEL_ESP_ACTION_DECRYPT) {
+               err = ida_simple_get(&fipsec->halloc, 1, 0, GFP_KERNEL);
+               if (err < 0) {
+                       context = ERR_PTR(err);
+                       goto exists;
+               }
+
+               sa_ctx->sa_handle = err;
+               if (sa_handle)
+                       *sa_handle = sa_ctx->sa_handle;
+       }
        /* This is unbounded fpga_xfrm, try to add to hash */
        mutex_lock(&fipsec->sa_hash_lock);
 
@@ -744,7 +759,8 @@ delete_hash:
                                       rhash_sa));
 unlock_hash:
        mutex_unlock(&fipsec->sa_hash_lock);
-
+       if (accel_xfrm->attrs.action & MLX5_ACCEL_ESP_ACTION_DECRYPT)
+               ida_simple_remove(&fipsec->halloc, sa_ctx->sa_handle);
 exists:
        mutex_unlock(&fpga_xfrm->lock);
        kfree(sa_ctx);
@@ -816,7 +832,7 @@ mlx5_fpga_ipsec_fs_create_sa_ctx(struct mlx5_core_dev *mdev,
        /* create */
        return mlx5_fpga_ipsec_create_sa_ctx(mdev, accel_xfrm,
                                             saddr, daddr,
-                                            spi, is_ipv6);
+                                            spi, is_ipv6, NULL);
 }
 
 static void
@@ -836,6 +852,10 @@ mlx5_fpga_ipsec_release_sa_ctx(struct mlx5_fpga_ipsec_sa_ctx *sa_ctx)
                return;
        }
 
+       if (sa_ctx->fpga_xfrm->accel_xfrm.attrs.action &
+           MLX5_ACCEL_ESP_ACTION_DECRYPT)
+               ida_simple_remove(&fipsec->halloc, sa_ctx->sa_handle);
+
        mutex_lock(&fipsec->sa_hash_lock);
        WARN_ON(rhashtable_remove_fast(&fipsec->sa_hash, &sa_ctx->hash,
                                       rhash_sa));
@@ -1299,6 +1319,8 @@ int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev)
                goto err_destroy_hash;
        }
 
+       ida_init(&fdev->ipsec->halloc);
+
        return 0;
 
 err_destroy_hash:
@@ -1331,6 +1353,7 @@ void mlx5_fpga_ipsec_cleanup(struct mlx5_core_dev *mdev)
        if (!mlx5_fpga_is_ipsec_device(mdev))
                return;
 
+       ida_destroy(&fdev->ipsec->halloc);
        destroy_rules_rb(&fdev->ipsec->rules_rb);
        rhashtable_destroy(&fdev->ipsec->sa_hash);
 
index d01b1fc8e11b77ffbf0185446d0d82eed845ef68..9ba637f0f0f279db80109730e7f1c93fa89f6bbc 100644 (file)
@@ -47,7 +47,8 @@ void *mlx5_fpga_ipsec_create_sa_ctx(struct mlx5_core_dev *mdev,
                                    struct mlx5_accel_esp_xfrm *accel_xfrm,
                                    const __be32 saddr[4],
                                    const __be32 daddr[4],
-                                   const __be32 spi, bool is_ipv6);
+                                   const __be32 spi, bool is_ipv6,
+                                   u32 *sa_handle);
 void mlx5_fpga_ipsec_delete_sa_ctx(void *context);
 
 int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev);