Skip to content

Commit

Permalink
net/mlx5e: Set IPsec replay sequence numbers
Browse files Browse the repository at this point in the history
"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>
  • Loading branch information
rleon committed Apr 6, 2023
1 parent f4979e2 commit 7db21ef
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 24 deletions.
48 changes: 38 additions & 10 deletions drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
14 changes: 10 additions & 4 deletions drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -160,6 +165,7 @@ struct mlx5e_ipsec {

struct mlx5e_ipsec_esn_state {
u32 esn;
u32 esn_msb;
u8 overlap: 1;
};

Expand Down
22 changes: 12 additions & 10 deletions drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit 7db21ef

Please sign in to comment.