Skip to content

Commit 1ed78fc

Browse files
rleonklassert
authored andcommitted
net/mlx5e: Update IPsec soft and hard limits
Implement mlx5 IPsec callback to update current lifetime counters. Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Steffen Klassert <[email protected]>
1 parent 403b383 commit 1ed78fc

File tree

4 files changed

+127
-0
lines changed

4 files changed

+127
-0
lines changed

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

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,31 @@ static bool mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry)
8383
return false;
8484
}
8585

86+
static void mlx5e_ipsec_init_limits(struct mlx5e_ipsec_sa_entry *sa_entry,
87+
struct mlx5_accel_esp_xfrm_attrs *attrs)
88+
{
89+
struct xfrm_state *x = sa_entry->x;
90+
91+
attrs->hard_packet_limit = x->lft.hard_packet_limit;
92+
if (x->lft.soft_packet_limit == XFRM_INF)
93+
return;
94+
95+
/* Hardware decrements hard_packet_limit counter through
96+
* the operation. While fires an event when soft_packet_limit
97+
* is reached. It emans that we need substitute the numbers
98+
* in order to properly count soft limit.
99+
*
100+
* As an example:
101+
* XFRM user sets soft limit is 2 and hard limit is 9 and
102+
* expects to see soft event after 2 packets and hard event
103+
* after 9 packets. In our case, the hard limit will be set
104+
* to 9 and soft limit is comparator to 7 so user gets the
105+
* soft event after 2 packeta
106+
*/
107+
attrs->soft_packet_limit =
108+
x->lft.hard_packet_limit - x->lft.soft_packet_limit;
109+
}
110+
86111
static void
87112
mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry,
88113
struct mlx5_accel_esp_xfrm_attrs *attrs)
@@ -134,6 +159,8 @@ mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry,
134159
attrs->family = x->props.family;
135160
attrs->type = x->xso.type;
136161
attrs->reqid = x->props.reqid;
162+
163+
mlx5e_ipsec_init_limits(sa_entry, attrs);
137164
}
138165

139166
static inline int mlx5e_xfrm_validate_state(struct xfrm_state *x)
@@ -222,6 +249,21 @@ static inline int mlx5e_xfrm_validate_state(struct xfrm_state *x)
222249
netdev_info(netdev, "Cannot offload without reqid\n");
223250
return -EINVAL;
224251
}
252+
253+
if (x->lft.hard_byte_limit != XFRM_INF ||
254+
x->lft.soft_byte_limit != XFRM_INF) {
255+
netdev_info(netdev,
256+
"Device doesn't support limits in bytes\n");
257+
return -EINVAL;
258+
}
259+
260+
if (x->lft.soft_packet_limit >= x->lft.hard_packet_limit &&
261+
x->lft.hard_packet_limit != XFRM_INF) {
262+
/* XFRM stack doesn't prevent such configuration :(. */
263+
netdev_info(netdev,
264+
"Hard packet limit must be greater than soft one\n");
265+
return -EINVAL;
266+
}
225267
}
226268
return 0;
227269
}
@@ -415,6 +457,26 @@ static void mlx5e_xfrm_advance_esn_state(struct xfrm_state *x)
415457
queue_work(sa_entry->ipsec->wq, &modify_work->work);
416458
}
417459

460+
static void mlx5e_xfrm_update_curlft(struct xfrm_state *x)
461+
{
462+
struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
463+
int err;
464+
465+
lockdep_assert_held(&x->lock);
466+
467+
if (sa_entry->attrs.soft_packet_limit == XFRM_INF)
468+
/* Limits are not configured, as soft limit
469+
* must be lowever than hard limit.
470+
*/
471+
return;
472+
473+
err = mlx5e_ipsec_aso_query(sa_entry);
474+
if (err)
475+
return;
476+
477+
mlx5e_ipsec_aso_update_curlft(sa_entry, &x->curlft.packets);
478+
}
479+
418480
static int mlx5e_xfrm_validate_policy(struct xfrm_policy *x)
419481
{
420482
struct net_device *netdev = x->xdo.real_dev;
@@ -526,6 +588,7 @@ static const struct xfrmdev_ops mlx5e_ipsec_packet_xfrmdev_ops = {
526588
.xdo_dev_offload_ok = mlx5e_ipsec_offload_ok,
527589
.xdo_dev_state_advance_esn = mlx5e_xfrm_advance_esn_state,
528590

591+
.xdo_dev_state_update_curlft = mlx5e_xfrm_update_curlft,
529592
.xdo_dev_policy_add = mlx5e_xfrm_add_policy,
530593
.xdo_dev_policy_free = mlx5e_xfrm_free_policy,
531594
};

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ struct mlx5_accel_esp_xfrm_attrs {
7878
u32 replay_window;
7979
u32 authsize;
8080
u32 reqid;
81+
u64 hard_packet_limit;
82+
u64 soft_packet_limit;
8183
};
8284

8385
enum mlx5_ipsec_cap {
@@ -208,6 +210,10 @@ void mlx5_accel_esp_modify_xfrm(struct mlx5e_ipsec_sa_entry *sa_entry,
208210
int mlx5e_ipsec_aso_init(struct mlx5e_ipsec *ipsec);
209211
void mlx5e_ipsec_aso_cleanup(struct mlx5e_ipsec *ipsec);
210212

213+
int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry);
214+
void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry,
215+
u64 *packets);
216+
211217
void mlx5e_accel_ipsec_fs_read_stats(struct mlx5e_priv *priv,
212218
void *ipsec_stats);
213219

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@ static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn,
8383
MLX5_SET(ipsec_obj, obj, aso_return_reg, MLX5_IPSEC_ASO_REG_C_4_5);
8484
if (attrs->dir == XFRM_DEV_OFFLOAD_OUT)
8585
MLX5_SET(ipsec_aso, aso_ctx, mode, MLX5_IPSEC_ASO_INC_SN);
86+
87+
if (attrs->hard_packet_limit != XFRM_INF) {
88+
MLX5_SET(ipsec_aso, aso_ctx, remove_flow_pkt_cnt,
89+
lower_32_bits(attrs->hard_packet_limit));
90+
MLX5_SET(ipsec_aso, aso_ctx, hard_lft_arm, 1);
91+
MLX5_SET(ipsec_aso, aso_ctx, remove_flow_enable, 1);
92+
}
93+
94+
if (attrs->soft_packet_limit != XFRM_INF) {
95+
MLX5_SET(ipsec_aso, aso_ctx, remove_flow_soft_lft,
96+
lower_32_bits(attrs->soft_packet_limit));
97+
98+
MLX5_SET(ipsec_aso, aso_ctx, soft_lft_arm, 1);
99+
}
86100
}
87101

88102
static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry)
@@ -298,3 +312,46 @@ void mlx5e_ipsec_aso_cleanup(struct mlx5e_ipsec *ipsec)
298312
DMA_BIDIRECTIONAL);
299313
kfree(aso);
300314
}
315+
316+
int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry)
317+
{
318+
struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
319+
struct mlx5e_ipsec_aso *aso = ipsec->aso;
320+
struct mlx5_core_dev *mdev = ipsec->mdev;
321+
struct mlx5_wqe_aso_ctrl_seg *ctrl;
322+
struct mlx5e_hw_objs *res;
323+
struct mlx5_aso_wqe *wqe;
324+
u8 ds_cnt;
325+
326+
res = &mdev->mlx5e_res.hw_objs;
327+
328+
memset(aso->ctx, 0, sizeof(aso->ctx));
329+
wqe = mlx5_aso_get_wqe(aso->aso);
330+
ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS);
331+
mlx5_aso_build_wqe(aso->aso, ds_cnt, wqe, sa_entry->ipsec_obj_id,
332+
MLX5_ACCESS_ASO_OPC_MOD_IPSEC);
333+
334+
ctrl = &wqe->aso_ctrl;
335+
ctrl->va_l =
336+
cpu_to_be32(lower_32_bits(aso->dma_addr) | ASO_CTRL_READ_EN);
337+
ctrl->va_h = cpu_to_be32(upper_32_bits(aso->dma_addr));
338+
ctrl->l_key = cpu_to_be32(res->mkey);
339+
340+
mlx5_aso_post_wqe(aso->aso, false, &wqe->ctrl);
341+
return mlx5_aso_poll_cq(aso->aso, false);
342+
}
343+
344+
void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry,
345+
u64 *packets)
346+
{
347+
struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
348+
struct mlx5e_ipsec_aso *aso = ipsec->aso;
349+
u64 hard_cnt;
350+
351+
hard_cnt = MLX5_GET(ipsec_aso, aso->ctx, remove_flow_pkt_cnt);
352+
/* HW decresases the limit till it reaches zero to fire an avent.
353+
* We need to fix the calculations, so the returned count is a total
354+
* number of passed packets and not how much left.
355+
*/
356+
*packets = sa_entry->attrs.hard_packet_limit - hard_cnt;
357+
}

drivers/net/ethernet/mellanox/mlx5/core/lib/aso.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define MLX5_WQE_CTRL_WQE_OPC_MOD_SHIFT 24
1616
#define MLX5_MACSEC_ASO_DS_CNT (DIV_ROUND_UP(sizeof(struct mlx5_aso_wqe), MLX5_SEND_WQE_DS))
1717

18+
#define ASO_CTRL_READ_EN BIT(0)
1819
struct mlx5_wqe_aso_ctrl_seg {
1920
__be32 va_h;
2021
__be32 va_l; /* include read_enable */

0 commit comments

Comments
 (0)