Commit 7dfee4b1 authored by Raed Salem's avatar Raed Salem Committed by Saeed Mahameed

net/mlx5: IPsec, Refactor SA handle creation and destruction

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: default avatarRaed Salem <raeds@mellanox.com>
Reviewed-by: default avatarBoris Pismenny <borisp@mellanox.com>
Reviewed-by: default avatarHuy Nguyen <huyn@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 0aab3e1b
...@@ -57,7 +57,8 @@ int mlx5_accel_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters, ...@@ -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, 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] = {}; __be32 saddr[4] = {}, daddr[4] = {};
...@@ -71,7 +72,7 @@ void *mlx5_accel_esp_create_hw_context(struct mlx5_core_dev *mdev, ...@@ -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, return mlx5_fpga_ipsec_create_sa_ctx(mdev, xfrm, saddr,
daddr, xfrm->attrs.spi, daddr, xfrm->attrs.spi,
xfrm->attrs.is_ipv6); xfrm->attrs.is_ipv6, sa_handle);
} }
void mlx5_accel_esp_free_hw_context(void *context) void mlx5_accel_esp_free_hw_context(void *context)
......
...@@ -47,7 +47,8 @@ int mlx5_accel_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters, ...@@ -47,7 +47,8 @@ int mlx5_accel_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters,
unsigned int count); unsigned int count);
void *mlx5_accel_esp_create_hw_context(struct mlx5_core_dev *mdev, 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); void mlx5_accel_esp_free_hw_context(void *context);
int mlx5_accel_ipsec_init(struct mlx5_core_dev *mdev); int mlx5_accel_ipsec_init(struct mlx5_core_dev *mdev);
...@@ -60,7 +61,8 @@ void mlx5_accel_ipsec_cleanup(struct mlx5_core_dev *mdev); ...@@ -60,7 +61,8 @@ void mlx5_accel_ipsec_cleanup(struct mlx5_core_dev *mdev);
static inline void * static inline void *
mlx5_accel_esp_create_hw_context(struct mlx5_core_dev *mdev, 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; return NULL;
} }
......
...@@ -75,18 +75,23 @@ struct xfrm_state *mlx5e_ipsec_sadb_rx_lookup(struct mlx5e_ipsec *ipsec, ...@@ -75,18 +75,23 @@ struct xfrm_state *mlx5e_ipsec_sadb_rx_lookup(struct mlx5e_ipsec *ipsec,
return ret; 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 *ipsec = sa_entry->ipsec;
struct mlx5e_ipsec_sa_entry *_sa_entry;
unsigned long flags; unsigned long flags;
int ret;
ret = ida_simple_get(&ipsec->halloc, 1, 0, GFP_KERNEL); rcu_read_lock();
if (ret < 0) hash_for_each_possible_rcu(ipsec->sadb_rx, _sa_entry, hlist, handle)
return ret; if (_sa_entry->handle == handle) {
rcu_read_unlock();
return -EEXIST;
}
rcu_read_unlock();
spin_lock_irqsave(&ipsec->sadb_rx_lock, flags); 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); hash_add_rcu(ipsec->sadb_rx, &sa_entry->hlist, sa_entry->handle);
spin_unlock_irqrestore(&ipsec->sadb_rx_lock, flags); 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) ...@@ -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); 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) static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry)
{ {
struct xfrm_replay_state_esn *replay_esn; struct xfrm_replay_state_esn *replay_esn;
...@@ -292,6 +288,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x) ...@@ -292,6 +288,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x)
struct net_device *netdev = x->xso.dev; struct net_device *netdev = x->xso.dev;
struct mlx5_accel_esp_xfrm_attrs attrs; struct mlx5_accel_esp_xfrm_attrs attrs;
struct mlx5e_priv *priv; struct mlx5e_priv *priv;
unsigned int sa_handle;
int err; int err;
priv = netdev_priv(netdev); priv = netdev_priv(netdev);
...@@ -309,20 +306,6 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x) ...@@ -309,20 +306,6 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x)
sa_entry->x = x; sa_entry->x = x;
sa_entry->ipsec = priv->ipsec; 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 */ /* check esn */
mlx5e_ipsec_update_esn_state(sa_entry); mlx5e_ipsec_update_esn_state(sa_entry);
...@@ -333,30 +316,38 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x) ...@@ -333,30 +316,38 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x)
MLX5_ACCEL_XFRM_FLAG_REQUIRE_METADATA); MLX5_ACCEL_XFRM_FLAG_REQUIRE_METADATA);
if (IS_ERR(sa_entry->xfrm)) { if (IS_ERR(sa_entry->xfrm)) {
err = PTR_ERR(sa_entry->xfrm); err = PTR_ERR(sa_entry->xfrm);
goto err_sadb_rx; goto err_sa_entry;
} }
/* create hw context */ /* create hw context */
sa_entry->hw_context = sa_entry->hw_context =
mlx5_accel_esp_create_hw_context(priv->mdev, mlx5_accel_esp_create_hw_context(priv->mdev,
sa_entry->xfrm); sa_entry->xfrm,
&sa_handle);
if (IS_ERR(sa_entry->hw_context)) { if (IS_ERR(sa_entry->hw_context)) {
err = PTR_ERR(sa_entry->hw_context); err = PTR_ERR(sa_entry->hw_context);
goto err_xfrm; 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; x->xso.offload_handle = (unsigned long)sa_entry;
goto out; goto out;
err_hw_ctx:
mlx5_accel_esp_free_hw_context(sa_entry->hw_context);
err_xfrm: err_xfrm:
mlx5_accel_esp_destroy_xfrm(sa_entry->xfrm); mlx5_accel_esp_destroy_xfrm(sa_entry->xfrm);
err_sadb_rx: err_sa_entry:
if (x->xso.flags & XFRM_OFFLOAD_INBOUND) {
mlx5e_ipsec_sadb_rx_del(sa_entry);
mlx5e_ipsec_sadb_rx_free(sa_entry);
}
err_entry:
kfree(sa_entry); kfree(sa_entry);
out: out:
return err; return err;
} }
...@@ -385,9 +376,6 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x) ...@@ -385,9 +376,6 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x)
mlx5_accel_esp_destroy_xfrm(sa_entry->xfrm); 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); kfree(sa_entry);
} }
......
...@@ -65,6 +65,7 @@ struct mlx5_fpga_esp_xfrm; ...@@ -65,6 +65,7 @@ struct mlx5_fpga_esp_xfrm;
struct mlx5_fpga_ipsec_sa_ctx { struct mlx5_fpga_ipsec_sa_ctx {
struct rhash_head hash; struct rhash_head hash;
struct mlx5_ifc_fpga_ipsec_sa hw_sa; struct mlx5_ifc_fpga_ipsec_sa hw_sa;
u32 sa_handle;
struct mlx5_core_dev *dev; struct mlx5_core_dev *dev;
struct mlx5_fpga_esp_xfrm *fpga_xfrm; struct mlx5_fpga_esp_xfrm *fpga_xfrm;
}; };
...@@ -119,6 +120,8 @@ struct mlx5_fpga_ipsec { ...@@ -119,6 +120,8 @@ struct mlx5_fpga_ipsec {
*/ */
struct rb_root rules_rb; struct rb_root rules_rb;
struct mutex rules_rb_lock; /* rules lock */ struct mutex rules_rb_lock; /* rules lock */
struct ida halloc;
}; };
static bool mlx5_fpga_is_ipsec_device(struct mlx5_core_dev *mdev) 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, ...@@ -666,7 +669,8 @@ void *mlx5_fpga_ipsec_create_sa_ctx(struct mlx5_core_dev *mdev,
struct mlx5_accel_esp_xfrm *accel_xfrm, struct mlx5_accel_esp_xfrm *accel_xfrm,
const __be32 saddr[4], const __be32 saddr[4],
const __be32 daddr[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_ipsec_sa_ctx *sa_ctx;
struct mlx5_fpga_esp_xfrm *fpga_xfrm = struct mlx5_fpga_esp_xfrm *fpga_xfrm =
...@@ -704,6 +708,17 @@ void *mlx5_fpga_ipsec_create_sa_ctx(struct mlx5_core_dev *mdev, ...@@ -704,6 +708,17 @@ void *mlx5_fpga_ipsec_create_sa_ctx(struct mlx5_core_dev *mdev,
goto exists; 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 */ /* This is unbounded fpga_xfrm, try to add to hash */
mutex_lock(&fipsec->sa_hash_lock); mutex_lock(&fipsec->sa_hash_lock);
...@@ -744,7 +759,8 @@ void *mlx5_fpga_ipsec_create_sa_ctx(struct mlx5_core_dev *mdev, ...@@ -744,7 +759,8 @@ void *mlx5_fpga_ipsec_create_sa_ctx(struct mlx5_core_dev *mdev,
rhash_sa)); rhash_sa));
unlock_hash: unlock_hash:
mutex_unlock(&fipsec->sa_hash_lock); 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: exists:
mutex_unlock(&fpga_xfrm->lock); mutex_unlock(&fpga_xfrm->lock);
kfree(sa_ctx); kfree(sa_ctx);
...@@ -816,7 +832,7 @@ mlx5_fpga_ipsec_fs_create_sa_ctx(struct mlx5_core_dev *mdev, ...@@ -816,7 +832,7 @@ mlx5_fpga_ipsec_fs_create_sa_ctx(struct mlx5_core_dev *mdev,
/* create */ /* create */
return mlx5_fpga_ipsec_create_sa_ctx(mdev, accel_xfrm, return mlx5_fpga_ipsec_create_sa_ctx(mdev, accel_xfrm,
saddr, daddr, saddr, daddr,
spi, is_ipv6); spi, is_ipv6, NULL);
} }
static void static void
...@@ -836,6 +852,10 @@ mlx5_fpga_ipsec_release_sa_ctx(struct mlx5_fpga_ipsec_sa_ctx *sa_ctx) ...@@ -836,6 +852,10 @@ mlx5_fpga_ipsec_release_sa_ctx(struct mlx5_fpga_ipsec_sa_ctx *sa_ctx)
return; 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); mutex_lock(&fipsec->sa_hash_lock);
WARN_ON(rhashtable_remove_fast(&fipsec->sa_hash, &sa_ctx->hash, WARN_ON(rhashtable_remove_fast(&fipsec->sa_hash, &sa_ctx->hash,
rhash_sa)); rhash_sa));
...@@ -1299,6 +1319,8 @@ int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev) ...@@ -1299,6 +1319,8 @@ int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev)
goto err_destroy_hash; goto err_destroy_hash;
} }
ida_init(&fdev->ipsec->halloc);
return 0; return 0;
err_destroy_hash: err_destroy_hash:
...@@ -1331,6 +1353,7 @@ void mlx5_fpga_ipsec_cleanup(struct mlx5_core_dev *mdev) ...@@ -1331,6 +1353,7 @@ void mlx5_fpga_ipsec_cleanup(struct mlx5_core_dev *mdev)
if (!mlx5_fpga_is_ipsec_device(mdev)) if (!mlx5_fpga_is_ipsec_device(mdev))
return; return;
ida_destroy(&fdev->ipsec->halloc);
destroy_rules_rb(&fdev->ipsec->rules_rb); destroy_rules_rb(&fdev->ipsec->rules_rb);
rhashtable_destroy(&fdev->ipsec->sa_hash); rhashtable_destroy(&fdev->ipsec->sa_hash);
......
...@@ -47,7 +47,8 @@ void *mlx5_fpga_ipsec_create_sa_ctx(struct mlx5_core_dev *mdev, ...@@ -47,7 +47,8 @@ void *mlx5_fpga_ipsec_create_sa_ctx(struct mlx5_core_dev *mdev,
struct mlx5_accel_esp_xfrm *accel_xfrm, struct mlx5_accel_esp_xfrm *accel_xfrm,
const __be32 saddr[4], const __be32 saddr[4],
const __be32 daddr[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); void mlx5_fpga_ipsec_delete_sa_ctx(void *context);
int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev); int mlx5_fpga_ipsec_init(struct mlx5_core_dev *mdev);
......
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