net/mlx5e: Set IPsec replay sequence numbers

"ip xfrm state ..." command allows users to configure replay sequence
numbers with replay-seq* arguments for RX and replay-oseq* for TX.

Add the needed driver logic to support setting them.

Link: https://lore.kernel.org/r/a9b17827eff2b29a4951225efa684a6cd38f74fe.1680162300.git.leonro@nvidia.com
Reviewed-by: Raed Salem <raeds@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
This commit is contained in:
Leon Romanovsky 2023-03-30 11:02:28 +03:00 committed by Leon Romanovsky
parent f4979e2667
commit 7db21ef456
3 changed files with 60 additions and 24 deletions

View file

@ -52,18 +52,46 @@ static struct mlx5e_ipsec_pol_entry *to_ipsec_pol_entry(struct xfrm_policy *x)
static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry)
{
struct xfrm_replay_state_esn *replay_esn;
struct xfrm_state *x = sa_entry->x;
u32 seq_bottom = 0;
u32 esn, esn_msb;
u8 overlap;
replay_esn = sa_entry->x->replay_esn;
if (replay_esn->seq >= replay_esn->replay_window)
seq_bottom = replay_esn->seq - replay_esn->replay_window + 1;
switch (x->xso.type) {
case XFRM_DEV_OFFLOAD_PACKET:
switch (x->xso.dir) {
case XFRM_DEV_OFFLOAD_IN:
esn = x->replay_esn->seq;
esn_msb = x->replay_esn->seq_hi;
break;
case XFRM_DEV_OFFLOAD_OUT:
esn = x->replay_esn->oseq;
esn_msb = x->replay_esn->oseq_hi;
break;
default:
WARN_ON(true);
return false;
}
break;
case XFRM_DEV_OFFLOAD_CRYPTO:
/* Already parsed by XFRM core */
esn = x->replay_esn->seq;
break;
default:
WARN_ON(true);
return false;
}
overlap = sa_entry->esn_state.overlap;
sa_entry->esn_state.esn = xfrm_replay_seqhi(sa_entry->x,
htonl(seq_bottom));
if (esn >= x->replay_esn->replay_window)
seq_bottom = esn - x->replay_esn->replay_window + 1;
if (x->xso.type == XFRM_DEV_OFFLOAD_CRYPTO)
esn_msb = xfrm_replay_seqhi(x, htonl(seq_bottom));
sa_entry->esn_state.esn = esn;
sa_entry->esn_state.esn_msb = esn_msb;
if (unlikely(overlap && seq_bottom < MLX5E_IPSEC_ESN_SCOPE_MID)) {
sa_entry->esn_state.overlap = 0;
@ -224,10 +252,10 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry,
/* esn */
if (x->props.flags & XFRM_STATE_ESN) {
attrs->esn_trigger = true;
attrs->esn = sa_entry->esn_state.esn;
attrs->esn_overlap = sa_entry->esn_state.overlap;
attrs->replay_window = x->replay_esn->replay_window;
attrs->replay_esn.trigger = true;
attrs->replay_esn.esn = sa_entry->esn_state.esn;
attrs->replay_esn.esn_msb = sa_entry->esn_state.esn_msb;
attrs->replay_esn.overlap = sa_entry->esn_state.overlap;
}
attrs->dir = x->xso.dir;

View file

@ -67,8 +67,15 @@ struct mlx5_ipsec_lft {
u64 numb_rounds_soft;
};
struct mlx5_replay_esn {
u32 replay_window;
u32 esn;
u32 esn_msb;
u8 overlap : 1;
u8 trigger : 1;
};
struct mlx5_accel_esp_xfrm_attrs {
u32 esn;
u32 spi;
u32 flags;
struct aes_gcm_keymat aes_gcm;
@ -85,11 +92,9 @@ struct mlx5_accel_esp_xfrm_attrs {
struct upspec upspec;
u8 dir : 2;
u8 esn_overlap : 1;
u8 esn_trigger : 1;
u8 type : 2;
u8 family;
u32 replay_window;
struct mlx5_replay_esn replay_esn;
u32 authsize;
u32 reqid;
struct mlx5_ipsec_lft lft;
@ -160,6 +165,7 @@ struct mlx5e_ipsec {
struct mlx5e_ipsec_esn_state {
u32 esn;
u32 esn_msb;
u8 overlap: 1;
};

View file

@ -76,15 +76,17 @@ static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn,
void *aso_ctx;
aso_ctx = MLX5_ADDR_OF(ipsec_obj, obj, ipsec_aso);
if (attrs->esn_trigger) {
if (attrs->replay_esn.trigger) {
MLX5_SET(ipsec_aso, aso_ctx, esn_event_arm, 1);
if (attrs->dir == XFRM_DEV_OFFLOAD_IN) {
MLX5_SET(ipsec_aso, aso_ctx, window_sz,
attrs->replay_window / 64);
attrs->replay_esn.replay_window / 64);
MLX5_SET(ipsec_aso, aso_ctx, mode,
MLX5_IPSEC_ASO_REPLAY_PROTECTION);
}
}
MLX5_SET(ipsec_aso, aso_ctx, mode_parameter,
attrs->replay_esn.esn);
}
/* ASO context */
@ -136,10 +138,10 @@ static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry)
salt_iv_p = MLX5_ADDR_OF(ipsec_obj, obj, implicit_iv);
memcpy(salt_iv_p, &aes_gcm->seq_iv, sizeof(aes_gcm->seq_iv));
/* esn */
if (attrs->esn_trigger) {
if (attrs->replay_esn.trigger) {
MLX5_SET(ipsec_obj, obj, esn_en, 1);
MLX5_SET(ipsec_obj, obj, esn_msb, attrs->esn);
MLX5_SET(ipsec_obj, obj, esn_overlap, attrs->esn_overlap);
MLX5_SET(ipsec_obj, obj, esn_msb, attrs->replay_esn.esn_msb);
MLX5_SET(ipsec_obj, obj, esn_overlap, attrs->replay_esn.overlap);
}
MLX5_SET(ipsec_obj, obj, dekn, sa_entry->enc_key_id);
@ -252,8 +254,8 @@ static int mlx5_modify_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry,
MLX5_SET64(ipsec_obj, obj, modify_field_select,
MLX5_MODIFY_IPSEC_BITMASK_ESN_OVERLAP |
MLX5_MODIFY_IPSEC_BITMASK_ESN_MSB);
MLX5_SET(ipsec_obj, obj, esn_msb, attrs->esn);
MLX5_SET(ipsec_obj, obj, esn_overlap, attrs->esn_overlap);
MLX5_SET(ipsec_obj, obj, esn_msb, attrs->replay_esn.esn_msb);
MLX5_SET(ipsec_obj, obj, esn_overlap, attrs->replay_esn.overlap);
/* general object fields set */
MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT);
@ -290,7 +292,7 @@ static void mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry,
struct mlx5_wqe_aso_ctrl_seg data = {};
if (mode_param < MLX5E_IPSEC_ESN_SCOPE_MID) {
sa_entry->esn_state.esn++;
sa_entry->esn_state.esn_msb++;
sa_entry->esn_state.overlap = 0;
} else {
sa_entry->esn_state.overlap = 1;
@ -434,7 +436,7 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work)
if (ret)
goto unlock;
if (attrs->esn_trigger &&
if (attrs->replay_esn.trigger &&
!MLX5_GET(ipsec_aso, aso->ctx, esn_event_arm)) {
u32 mode_param = MLX5_GET(ipsec_aso, aso->ctx, mode_parameter);