Commit aa8bd0c9 authored by Raed Salem's avatar Raed Salem Committed by Leon Romanovsky

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: default avatarRaed Salem <raeds@nvidia.com>
Link: https://lore.kernel.org/r/8f36d6b61631dcd73fef0a0ac623456030bc9db0.1678714336.git.leon@kernel.orgSigned-off-by: default avatarLeon Romanovsky <leon@kernel.org>
parent b3beba1f
...@@ -308,6 +308,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, ...@@ -308,6 +308,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
struct net_device *netdev = x->xso.real_dev; struct net_device *netdev = x->xso.real_dev;
struct mlx5e_ipsec *ipsec; struct mlx5e_ipsec *ipsec;
struct mlx5e_priv *priv; struct mlx5e_priv *priv;
gfp_t gfp;
int err; int err;
priv = netdev_priv(netdev); priv = netdev_priv(netdev);
...@@ -315,16 +316,20 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, ...@@ -315,16 +316,20 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
return -EOPNOTSUPP; return -EOPNOTSUPP;
ipsec = priv->ipsec; ipsec = priv->ipsec;
err = mlx5e_xfrm_validate_state(priv->mdev, x, extack); gfp = (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) ? GFP_ATOMIC : GFP_KERNEL;
if (err) sa_entry = kzalloc(sizeof(*sa_entry), gfp);
return err;
sa_entry = kzalloc(sizeof(*sa_entry), GFP_KERNEL);
if (!sa_entry) if (!sa_entry)
return -ENOMEM; return -ENOMEM;
sa_entry->x = x; sa_entry->x = x;
sa_entry->ipsec = ipsec; 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 */ /* check esn */
mlx5e_ipsec_update_esn_state(sa_entry); mlx5e_ipsec_update_esn_state(sa_entry);
...@@ -353,6 +358,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, ...@@ -353,6 +358,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
mlx5e_ipsec_set_iv_esn : mlx5e_ipsec_set_iv; mlx5e_ipsec_set_iv_esn : mlx5e_ipsec_set_iv;
INIT_WORK(&sa_entry->modify_work.work, _update_xfrm_state); INIT_WORK(&sa_entry->modify_work.work, _update_xfrm_state);
out:
x->xso.offload_handle = (unsigned long)sa_entry; x->xso.offload_handle = (unsigned long)sa_entry;
return 0; return 0;
...@@ -372,6 +378,9 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x) ...@@ -372,6 +378,9 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x)
struct mlx5e_ipsec *ipsec = sa_entry->ipsec; struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
struct mlx5e_ipsec_sa_entry *old; 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); old = xa_erase_bh(&ipsec->sadb, sa_entry->ipsec_obj_id);
WARN_ON(old != sa_entry); WARN_ON(old != sa_entry);
} }
...@@ -380,9 +389,13 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x) ...@@ -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); 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); cancel_work_sync(&sa_entry->modify_work.work);
mlx5e_accel_ipsec_fs_del_rule(sa_entry); mlx5e_accel_ipsec_fs_del_rule(sa_entry);
mlx5_ipsec_free_sa_ctx(sa_entry); mlx5_ipsec_free_sa_ctx(sa_entry);
sa_entry_free:
kfree(sa_entry); kfree(sa_entry);
} }
...@@ -486,6 +499,9 @@ static void mlx5e_xfrm_update_curlft(struct xfrm_state *x) ...@@ -486,6 +499,9 @@ static void mlx5e_xfrm_update_curlft(struct xfrm_state *x)
lockdep_assert_held(&x->lock); lockdep_assert_held(&x->lock);
if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
return;
if (sa_entry->attrs.soft_packet_limit == XFRM_INF) if (sa_entry->attrs.soft_packet_limit == XFRM_INF)
/* Limits are not configured, as soft limit /* Limits are not configured, as soft limit
* must be lowever than hard limit. * must be lowever than hard limit.
......
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