From aa8bd0c9518cc5902d88510bf007e451699221f2 Mon Sep 17 00:00:00 2001 From: Raed Salem Date: Tue, 14 Mar 2023 10:58:42 +0200 Subject: [PATCH] net/mlx5e: Support IPsec acquire default SA During XFRM stack acquire flow, a default SA is created to be updated later, once acquire netlink message is handled in user space. This SA is also passed to IPsec offload supporting driver, however this SA acts only as placeholder and does not have context suitable for offloading in HW yet. Identify this kind of SA by special offload flag (XFRM_DEV_OFFLOAD_FLAG_ACQ), and create a SW only context. In such cases with special mark so it won't be installed in HW in addition flow and on remove/delete free this SW only context. Signed-off-by: Raed Salem Link: https://lore.kernel.org/r/8f36d6b61631dcd73fef0a0ac623456030bc9db0.1678714336.git.leon@kernel.org Signed-off-by: Leon Romanovsky --- .../mellanox/mlx5/core/en_accel/ipsec.c | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c index 9cc59dc8b592..20a6bd1c03a3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c @@ -308,6 +308,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, struct net_device *netdev = x->xso.real_dev; struct mlx5e_ipsec *ipsec; struct mlx5e_priv *priv; + gfp_t gfp; int err; priv = netdev_priv(netdev); @@ -315,16 +316,20 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, return -EOPNOTSUPP; ipsec = priv->ipsec; - err = mlx5e_xfrm_validate_state(priv->mdev, x, extack); - if (err) - return err; - - sa_entry = kzalloc(sizeof(*sa_entry), GFP_KERNEL); + gfp = (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) ? GFP_ATOMIC : GFP_KERNEL; + sa_entry = kzalloc(sizeof(*sa_entry), gfp); if (!sa_entry) return -ENOMEM; sa_entry->x = x; sa_entry->ipsec = ipsec; + /* Check if this SA is originated from acquire flow temporary SA */ + if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) + goto out; + + err = mlx5e_xfrm_validate_state(priv->mdev, x, extack); + if (err) + goto err_xfrm; /* check esn */ mlx5e_ipsec_update_esn_state(sa_entry); @@ -353,6 +358,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, mlx5e_ipsec_set_iv_esn : mlx5e_ipsec_set_iv; INIT_WORK(&sa_entry->modify_work.work, _update_xfrm_state); +out: x->xso.offload_handle = (unsigned long)sa_entry; return 0; @@ -372,6 +378,9 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x) struct mlx5e_ipsec *ipsec = sa_entry->ipsec; struct mlx5e_ipsec_sa_entry *old; + if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) + return; + old = xa_erase_bh(&ipsec->sadb, sa_entry->ipsec_obj_id); WARN_ON(old != sa_entry); } @@ -380,9 +389,13 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x) { struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x); + if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) + goto sa_entry_free; + cancel_work_sync(&sa_entry->modify_work.work); mlx5e_accel_ipsec_fs_del_rule(sa_entry); mlx5_ipsec_free_sa_ctx(sa_entry); +sa_entry_free: kfree(sa_entry); } @@ -486,6 +499,9 @@ static void mlx5e_xfrm_update_curlft(struct xfrm_state *x) lockdep_assert_held(&x->lock); + if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) + return; + if (sa_entry->attrs.soft_packet_limit == XFRM_INF) /* Limits are not configured, as soft limit * must be lowever than hard limit.