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: 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>
This commit is contained in:
Raed Salem 2019-10-23 17:04:13 +03:00 committed by Saeed Mahameed
parent 0aab3e1b04
commit 7dfee4b1d7
5 changed files with 63 additions and 48 deletions

View 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)

View 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;
}

View 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);
}

View 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);

View 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);