Commit 8efd7b17 authored by Leon Romanovsky's avatar Leon Romanovsky Committed by Jakub Kicinski

net/mlx5: Provide an interface to block change of IPsec capabilities

mlx5 HW can't perform IPsec offload operation simultaneously both on PF
and VFs at the same time. While the previous patches added devlink knobs
to change IPsec capabilities dynamically, there is a need to add a logic
to block such IPsec capabilities for the cases when IPsec is already
configured.
Signed-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
Link: https://lore.kernel.org/r/20230825062836.103744-7-saeed@kernel.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 17c8da5a
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <net/netevent.h> #include <net/netevent.h>
#include "en.h" #include "en.h"
#include "eswitch.h"
#include "ipsec.h" #include "ipsec.h"
#include "ipsec_rxtx.h" #include "ipsec_rxtx.h"
#include "en_rep.h" #include "en_rep.h"
...@@ -670,6 +671,11 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, ...@@ -670,6 +671,11 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
if (err) if (err)
goto err_xfrm; goto err_xfrm;
if (!mlx5_eswitch_block_ipsec(priv->mdev)) {
err = -EBUSY;
goto err_xfrm;
}
/* check esn */ /* check esn */
if (x->props.flags & XFRM_STATE_ESN) if (x->props.flags & XFRM_STATE_ESN)
mlx5e_ipsec_update_esn_state(sa_entry); mlx5e_ipsec_update_esn_state(sa_entry);
...@@ -678,7 +684,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, ...@@ -678,7 +684,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
err = mlx5_ipsec_create_work(sa_entry); err = mlx5_ipsec_create_work(sa_entry);
if (err) if (err)
goto err_xfrm; goto unblock_ipsec;
err = mlx5e_ipsec_create_dwork(sa_entry); err = mlx5e_ipsec_create_dwork(sa_entry);
if (err) if (err)
...@@ -735,6 +741,8 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, ...@@ -735,6 +741,8 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
if (sa_entry->work) if (sa_entry->work)
kfree(sa_entry->work->data); kfree(sa_entry->work->data);
kfree(sa_entry->work); kfree(sa_entry->work);
unblock_ipsec:
mlx5_eswitch_unblock_ipsec(priv->mdev);
err_xfrm: err_xfrm:
kfree(sa_entry); kfree(sa_entry);
NL_SET_ERR_MSG_WEAK_MOD(extack, "Device failed to offload this state"); NL_SET_ERR_MSG_WEAK_MOD(extack, "Device failed to offload this state");
...@@ -764,6 +772,7 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x) ...@@ -764,6 +772,7 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x)
static void mlx5e_xfrm_free_state(struct xfrm_state *x) 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);
struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
goto sa_entry_free; goto sa_entry_free;
...@@ -780,6 +789,7 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x) ...@@ -780,6 +789,7 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x)
if (sa_entry->work) if (sa_entry->work)
kfree(sa_entry->work->data); kfree(sa_entry->work->data);
kfree(sa_entry->work); kfree(sa_entry->work);
mlx5_eswitch_unblock_ipsec(ipsec->mdev);
sa_entry_free: sa_entry_free:
kfree(sa_entry); kfree(sa_entry);
} }
...@@ -1055,6 +1065,11 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x, ...@@ -1055,6 +1065,11 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x,
pol_entry->x = x; pol_entry->x = x;
pol_entry->ipsec = priv->ipsec; pol_entry->ipsec = priv->ipsec;
if (!mlx5_eswitch_block_ipsec(priv->mdev)) {
err = -EBUSY;
goto ipsec_busy;
}
mlx5e_ipsec_build_accel_pol_attrs(pol_entry, &pol_entry->attrs); mlx5e_ipsec_build_accel_pol_attrs(pol_entry, &pol_entry->attrs);
err = mlx5e_accel_ipsec_fs_add_pol(pol_entry); err = mlx5e_accel_ipsec_fs_add_pol(pol_entry);
if (err) if (err)
...@@ -1064,6 +1079,8 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x, ...@@ -1064,6 +1079,8 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x,
return 0; return 0;
err_fs: err_fs:
mlx5_eswitch_unblock_ipsec(priv->mdev);
ipsec_busy:
kfree(pol_entry); kfree(pol_entry);
NL_SET_ERR_MSG_MOD(extack, "Device failed to offload this policy"); NL_SET_ERR_MSG_MOD(extack, "Device failed to offload this policy");
return err; return err;
...@@ -1074,6 +1091,7 @@ static void mlx5e_xfrm_del_policy(struct xfrm_policy *x) ...@@ -1074,6 +1091,7 @@ static void mlx5e_xfrm_del_policy(struct xfrm_policy *x)
struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x); struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x);
mlx5e_accel_ipsec_fs_del_pol(pol_entry); mlx5e_accel_ipsec_fs_del_pol(pol_entry);
mlx5_eswitch_unblock_ipsec(pol_entry->ipsec->mdev);
} }
static void mlx5e_xfrm_free_policy(struct xfrm_policy *x) static void mlx5e_xfrm_free_policy(struct xfrm_policy *x)
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "devlink.h" #include "devlink.h"
#include "ecpf.h" #include "ecpf.h"
#include "en/mod_hdr.h" #include "en/mod_hdr.h"
#include "en_accel/ipsec.h"
enum { enum {
MLX5_ACTION_NONE = 0, MLX5_ACTION_NONE = 0,
...@@ -2336,3 +2337,34 @@ struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw) ...@@ -2336,3 +2337,34 @@ struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw)
return mlx5_esw_allowed(esw) ? esw->dev : NULL; return mlx5_esw_allowed(esw) ? esw->dev : NULL;
} }
EXPORT_SYMBOL(mlx5_eswitch_get_core_dev); EXPORT_SYMBOL(mlx5_eswitch_get_core_dev);
bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev)
{
struct mlx5_eswitch *esw = dev->priv.eswitch;
if (!mlx5_esw_allowed(esw))
return true;
mutex_lock(&esw->state_lock);
if (esw->enabled_ipsec_vf_count) {
mutex_unlock(&esw->state_lock);
return false;
}
dev->num_ipsec_offloads++;
mutex_unlock(&esw->state_lock);
return true;
}
void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev)
{
struct mlx5_eswitch *esw = dev->priv.eswitch;
if (!mlx5_esw_allowed(esw))
/* Failure means no eswitch => core dev is not a PF */
return;
mutex_lock(&esw->state_lock);
dev->num_ipsec_offloads--;
mutex_unlock(&esw->state_lock);
}
...@@ -380,6 +380,7 @@ struct mlx5_eswitch { ...@@ -380,6 +380,7 @@ struct mlx5_eswitch {
struct blocking_notifier_head n_head; struct blocking_notifier_head n_head;
struct xarray paired; struct xarray paired;
struct mlx5_devcom_comp_dev *devcom; struct mlx5_devcom_comp_dev *devcom;
u16 enabled_ipsec_vf_count;
}; };
void esw_offloads_disable(struct mlx5_eswitch *esw); void esw_offloads_disable(struct mlx5_eswitch *esw);
...@@ -855,6 +856,8 @@ mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw) ...@@ -855,6 +856,8 @@ mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw)
int mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handle *rule, int mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handle *rule,
struct mlx5_esw_flow_attr *esw_attr, int attr_idx); struct mlx5_esw_flow_attr *esw_attr, int attr_idx);
bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev);
void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev);
#else /* CONFIG_MLX5_ESWITCH */ #else /* CONFIG_MLX5_ESWITCH */
/* eswitch API stubs */ /* eswitch API stubs */
static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; }
...@@ -916,6 +919,12 @@ static inline void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev) ...@@ -916,6 +919,12 @@ static inline void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev)
static inline int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev) { return 0; } static inline int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev) { return 0; }
static inline void mlx5_eswitch_unblock_mode(struct mlx5_core_dev *dev) {} static inline void mlx5_eswitch_unblock_mode(struct mlx5_core_dev *dev) {}
static inline bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev)
{
return false;
}
static inline void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev) {}
#endif /* CONFIG_MLX5_ESWITCH */ #endif /* CONFIG_MLX5_ESWITCH */
#endif /* __MLX5_ESWITCH_H__ */ #endif /* __MLX5_ESWITCH_H__ */
...@@ -813,6 +813,7 @@ struct mlx5_core_dev { ...@@ -813,6 +813,7 @@ struct mlx5_core_dev {
/* MACsec notifier chain to sync MACsec core and IB database */ /* MACsec notifier chain to sync MACsec core and IB database */
struct blocking_notifier_head macsec_nh; struct blocking_notifier_head macsec_nh;
#endif #endif
u64 num_ipsec_offloads;
}; };
struct mlx5_db { struct mlx5_db {
......
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