Skip to content

Commit b2f7b01

Browse files
committed
net/mlx5e: Simulate missing IPsec TX limits hardware functionality
ConnectX-7 devices don't have ability to send TX hard/soft limits events. As a possible workaround, let's rely on existing infrastructure and use periodic check of cached flow counter. In these periodic checks, we call to xfrm_state_check_expire() to check and mark state accordingly. Once the state is marked as XFRM_STATE_EXPIRED, the SA flow rule is changed to drop all the traffic. Link: https://lore.kernel.org/r/94a5d82c0c399747117d8a558f9beebfbcf26154.1680162300.git.leonro@nvidia.com Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
1 parent 4562116 commit b2f7b01

File tree

3 files changed

+99
-5
lines changed

3 files changed

+99
-5
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#include "ipsec.h"
4141
#include "ipsec_rxtx.h"
4242

43+
#define MLX5_IPSEC_RESCHED msecs_to_jiffies(1000)
44+
4345
static struct mlx5e_ipsec_sa_entry *to_ipsec_sa_entry(struct xfrm_state *x)
4446
{
4547
return (struct mlx5e_ipsec_sa_entry *)x->xso.offload_handle;
@@ -50,6 +52,28 @@ static struct mlx5e_ipsec_pol_entry *to_ipsec_pol_entry(struct xfrm_policy *x)
5052
return (struct mlx5e_ipsec_pol_entry *)x->xdo.offload_handle;
5153
}
5254

55+
static void mlx5e_ipsec_handle_tx_limit(struct work_struct *_work)
56+
{
57+
struct mlx5e_ipsec_dwork *dwork =
58+
container_of(_work, struct mlx5e_ipsec_dwork, dwork.work);
59+
struct mlx5e_ipsec_sa_entry *sa_entry = dwork->sa_entry;
60+
struct xfrm_state *x = sa_entry->x;
61+
62+
spin_lock(&x->lock);
63+
xfrm_state_check_expire(x);
64+
if (x->km.state == XFRM_STATE_EXPIRED) {
65+
sa_entry->attrs.drop = true;
66+
mlx5e_accel_ipsec_fs_modify(sa_entry);
67+
}
68+
spin_unlock(&x->lock);
69+
70+
if (sa_entry->attrs.drop)
71+
return;
72+
73+
queue_delayed_work(sa_entry->ipsec->wq, &dwork->dwork,
74+
MLX5_IPSEC_RESCHED);
75+
}
76+
5377
static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry)
5478
{
5579
struct xfrm_state *x = sa_entry->x;
@@ -464,6 +488,31 @@ static int mlx5_ipsec_create_work(struct mlx5e_ipsec_sa_entry *sa_entry)
464488
return 0;
465489
}
466490

491+
static int mlx5e_ipsec_create_dwork(struct mlx5e_ipsec_sa_entry *sa_entry)
492+
{
493+
struct xfrm_state *x = sa_entry->x;
494+
struct mlx5e_ipsec_dwork *dwork;
495+
496+
if (x->xso.type != XFRM_DEV_OFFLOAD_PACKET)
497+
return 0;
498+
499+
if (x->xso.dir != XFRM_DEV_OFFLOAD_OUT)
500+
return 0;
501+
502+
if (x->lft.soft_packet_limit == XFRM_INF &&
503+
x->lft.hard_packet_limit == XFRM_INF)
504+
return 0;
505+
506+
dwork = kzalloc(sizeof(*dwork), GFP_KERNEL);
507+
if (!dwork)
508+
return -ENOMEM;
509+
510+
dwork->sa_entry = sa_entry;
511+
INIT_DELAYED_WORK(&dwork->dwork, mlx5e_ipsec_handle_tx_limit);
512+
sa_entry->dwork = dwork;
513+
return 0;
514+
}
515+
467516
static int mlx5e_xfrm_add_state(struct xfrm_state *x,
468517
struct netlink_ext_ack *extack)
469518
{
@@ -504,10 +553,14 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
504553
if (err)
505554
goto err_xfrm;
506555

556+
err = mlx5e_ipsec_create_dwork(sa_entry);
557+
if (err)
558+
goto release_work;
559+
507560
/* create hw context */
508561
err = mlx5_ipsec_create_sa_ctx(sa_entry);
509562
if (err)
510-
goto release_work;
563+
goto release_dwork;
511564

512565
err = mlx5e_accel_ipsec_fs_add_rule(sa_entry);
513566
if (err)
@@ -523,6 +576,10 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
523576
goto err_add_rule;
524577

525578
mlx5e_ipsec_set_esn_ops(sa_entry);
579+
580+
if (sa_entry->dwork)
581+
queue_delayed_work(ipsec->wq, &sa_entry->dwork->dwork,
582+
MLX5_IPSEC_RESCHED);
526583
out:
527584
x->xso.offload_handle = (unsigned long)sa_entry;
528585
return 0;
@@ -531,6 +588,8 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
531588
mlx5e_accel_ipsec_fs_del_rule(sa_entry);
532589
err_hw_ctx:
533590
mlx5_ipsec_free_sa_ctx(sa_entry);
591+
release_dwork:
592+
kfree(sa_entry->dwork);
534593
release_work:
535594
kfree(sa_entry->work->data);
536595
kfree(sa_entry->work);
@@ -563,8 +622,12 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x)
563622
if (sa_entry->work)
564623
cancel_work_sync(&sa_entry->work->work);
565624

625+
if (sa_entry->dwork)
626+
cancel_delayed_work_sync(&sa_entry->dwork->dwork);
627+
566628
mlx5e_accel_ipsec_fs_del_rule(sa_entry);
567629
mlx5_ipsec_free_sa_ctx(sa_entry);
630+
kfree(sa_entry->dwork);
568631
kfree(sa_entry->work->data);
569632
kfree(sa_entry->work);
570633
sa_entry_free:

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ struct mlx5_accel_esp_xfrm_attrs {
9393
struct upspec upspec;
9494
u8 dir : 2;
9595
u8 type : 2;
96+
u8 drop : 1;
9697
u8 family;
9798
struct mlx5_replay_esn replay_esn;
9899
u32 authsize;
@@ -140,6 +141,11 @@ struct mlx5e_ipsec_work {
140141
void *data;
141142
};
142143

144+
struct mlx5e_ipsec_dwork {
145+
struct delayed_work dwork;
146+
struct mlx5e_ipsec_sa_entry *sa_entry;
147+
};
148+
143149
struct mlx5e_ipsec_aso {
144150
u8 __aligned(64) ctx[MLX5_ST_SZ_BYTES(ipsec_aso)];
145151
dma_addr_t dma_addr;
@@ -193,6 +199,7 @@ struct mlx5e_ipsec_sa_entry {
193199
u32 enc_key_id;
194200
struct mlx5e_ipsec_rule ipsec_rule;
195201
struct mlx5e_ipsec_work *work;
202+
struct mlx5e_ipsec_dwork *dwork;
196203
struct mlx5e_ipsec_limits limits;
197204
};
198205

@@ -235,6 +242,7 @@ int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry);
235242
void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry);
236243
int mlx5e_accel_ipsec_fs_add_pol(struct mlx5e_ipsec_pol_entry *pol_entry);
237244
void mlx5e_accel_ipsec_fs_del_pol(struct mlx5e_ipsec_pol_entry *pol_entry);
245+
void mlx5e_accel_ipsec_fs_modify(struct mlx5e_ipsec_sa_entry *sa_entry);
238246

239247
int mlx5_ipsec_create_sa_ctx(struct mlx5e_ipsec_sa_entry *sa_entry);
240248
void mlx5_ipsec_free_sa_ctx(struct mlx5e_ipsec_sa_entry *sa_entry);

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -926,9 +926,12 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
926926
flow_act.crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_IPSEC;
927927
flow_act.crypto.obj_id = sa_entry->ipsec_obj_id;
928928
flow_act.flags |= FLOW_ACT_NO_APPEND;
929-
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
930-
MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT |
929+
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_CRYPTO_DECRYPT |
931930
MLX5_FLOW_CONTEXT_ACTION_COUNT;
931+
if (attrs->drop)
932+
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
933+
else
934+
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
932935
dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
933936
dest[0].ft = rx->ft.status;
934937
dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
@@ -1018,9 +1021,13 @@ static int tx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
10181021
flow_act.crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_IPSEC;
10191022
flow_act.crypto.obj_id = sa_entry->ipsec_obj_id;
10201023
flow_act.flags |= FLOW_ACT_NO_APPEND;
1021-
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
1022-
MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT |
1024+
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT |
10231025
MLX5_FLOW_CONTEXT_ACTION_COUNT;
1026+
if (attrs->drop)
1027+
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
1028+
else
1029+
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
1030+
10241031
dest[0].ft = tx->ft.status;
10251032
dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
10261033
dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
@@ -1430,3 +1437,19 @@ int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec)
14301437
kfree(ipsec->tx);
14311438
return err;
14321439
}
1440+
1441+
void mlx5e_accel_ipsec_fs_modify(struct mlx5e_ipsec_sa_entry *sa_entry)
1442+
{
1443+
struct mlx5e_ipsec_sa_entry sa_entry_shadow = {};
1444+
int err;
1445+
1446+
memcpy(&sa_entry_shadow, sa_entry, sizeof(*sa_entry));
1447+
memset(&sa_entry_shadow.ipsec_rule, 0x00, sizeof(sa_entry->ipsec_rule));
1448+
1449+
err = mlx5e_accel_ipsec_fs_add_rule(&sa_entry_shadow);
1450+
if (err)
1451+
return;
1452+
1453+
mlx5e_accel_ipsec_fs_del_rule(sa_entry);
1454+
memcpy(sa_entry, &sa_entry_shadow, sizeof(*sa_entry));
1455+
}

0 commit comments

Comments
 (0)