Skip to content

Commit e4d264e

Browse files
committed
Leon Romanovsky says: ==================== Extend packet offload to fully support libreswan The following patches are an outcome of Raed's work to add packet offload support to libreswan [1]. The series includes: * Priority support to IPsec policies * Statistics per-SA (visible through "ip -s xfrm state ..." command) * Support to IKE policy holes * Fine tuning to acquire logic. [1] libreswan/libreswan#986 Link: https://lore.kernel.org/all/cover.1678714336.git.leon@kernel.org * tag 'ipsec-libreswan-mlx5' of https://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux: net/mlx5e: Update IPsec per SA packets/bytes count net/mlx5e: Use one rule to count all IPsec Tx offloaded traffic net/mlx5e: Support IPsec acquire default SA net/mlx5e: Allow policies with reqid 0, to support IKE policy holes xfrm: copy_to_user_state fetch offloaded SA packets/bytes statistics xfrm: add new device offload acquire flag net/mlx5e: Use chains for IPsec policy priority offload net/mlx5: fs_core: Allow ignore_flow_level on TX dest net/mlx5: fs_chains: Refactor to detach chains from tc usage ==================== Link: https://lore.kernel.org/r/20230320094722.1009304-1-leon@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 3079bfd + 5a6cddb commit e4d264e

File tree

12 files changed

+553
-228
lines changed

12 files changed

+553
-228
lines changed

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

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -308,23 +308,28 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
308308
struct net_device *netdev = x->xso.real_dev;
309309
struct mlx5e_ipsec *ipsec;
310310
struct mlx5e_priv *priv;
311+
gfp_t gfp;
311312
int err;
312313

313314
priv = netdev_priv(netdev);
314315
if (!priv->ipsec)
315316
return -EOPNOTSUPP;
316317

317318
ipsec = priv->ipsec;
318-
err = mlx5e_xfrm_validate_state(priv->mdev, x, extack);
319-
if (err)
320-
return err;
321-
322-
sa_entry = kzalloc(sizeof(*sa_entry), GFP_KERNEL);
319+
gfp = (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) ? GFP_ATOMIC : GFP_KERNEL;
320+
sa_entry = kzalloc(sizeof(*sa_entry), gfp);
323321
if (!sa_entry)
324322
return -ENOMEM;
325323

326324
sa_entry->x = x;
327325
sa_entry->ipsec = ipsec;
326+
/* Check if this SA is originated from acquire flow temporary SA */
327+
if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
328+
goto out;
329+
330+
err = mlx5e_xfrm_validate_state(priv->mdev, x, extack);
331+
if (err)
332+
goto err_xfrm;
328333

329334
/* check esn */
330335
mlx5e_ipsec_update_esn_state(sa_entry);
@@ -353,6 +358,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
353358
mlx5e_ipsec_set_iv_esn : mlx5e_ipsec_set_iv;
354359

355360
INIT_WORK(&sa_entry->modify_work.work, _update_xfrm_state);
361+
out:
356362
x->xso.offload_handle = (unsigned long)sa_entry;
357363
return 0;
358364

@@ -372,6 +378,9 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x)
372378
struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
373379
struct mlx5e_ipsec_sa_entry *old;
374380

381+
if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
382+
return;
383+
375384
old = xa_erase_bh(&ipsec->sadb, sa_entry->ipsec_obj_id);
376385
WARN_ON(old != sa_entry);
377386
}
@@ -380,9 +389,13 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x)
380389
{
381390
struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
382391

392+
if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
393+
goto sa_entry_free;
394+
383395
cancel_work_sync(&sa_entry->modify_work.work);
384396
mlx5e_accel_ipsec_fs_del_rule(sa_entry);
385397
mlx5_ipsec_free_sa_ctx(sa_entry);
398+
sa_entry_free:
386399
kfree(sa_entry);
387400
}
388401

@@ -482,26 +495,26 @@ static void mlx5e_xfrm_advance_esn_state(struct xfrm_state *x)
482495
static void mlx5e_xfrm_update_curlft(struct xfrm_state *x)
483496
{
484497
struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
485-
int err;
498+
struct mlx5e_ipsec_rule *ipsec_rule = &sa_entry->ipsec_rule;
499+
u64 packets, bytes, lastuse;
486500

487-
lockdep_assert_held(&x->lock);
501+
lockdep_assert(lockdep_is_held(&x->lock) ||
502+
lockdep_is_held(&dev_net(x->xso.real_dev)->xfrm.xfrm_cfg_mutex));
488503

489-
if (sa_entry->attrs.soft_packet_limit == XFRM_INF)
490-
/* Limits are not configured, as soft limit
491-
* must be lowever than hard limit.
492-
*/
504+
if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
493505
return;
494506

495-
err = mlx5e_ipsec_aso_query(sa_entry, NULL);
496-
if (err)
497-
return;
498-
499-
mlx5e_ipsec_aso_update_curlft(sa_entry, &x->curlft.packets);
507+
mlx5_fc_query_cached(ipsec_rule->fc, &bytes, &packets, &lastuse);
508+
x->curlft.packets += packets;
509+
x->curlft.bytes += bytes;
500510
}
501511

502-
static int mlx5e_xfrm_validate_policy(struct xfrm_policy *x,
512+
static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev,
513+
struct xfrm_policy *x,
503514
struct netlink_ext_ack *extack)
504515
{
516+
struct xfrm_selector *sel = &x->selector;
517+
505518
if (x->type != XFRM_POLICY_TYPE_MAIN) {
506519
NL_SET_ERR_MSG_MOD(extack, "Cannot offload non-main policy types");
507520
return -EINVAL;
@@ -519,8 +532,9 @@ static int mlx5e_xfrm_validate_policy(struct xfrm_policy *x,
519532
return -EINVAL;
520533
}
521534

522-
if (!x->xfrm_vec[0].reqid) {
523-
NL_SET_ERR_MSG_MOD(extack, "Cannot offload policy without reqid");
535+
if (!x->xfrm_vec[0].reqid && sel->proto == IPPROTO_IP &&
536+
addr6_all_zero(sel->saddr.a6) && addr6_all_zero(sel->daddr.a6)) {
537+
NL_SET_ERR_MSG_MOD(extack, "Unsupported policy with reqid 0 without at least one of upper protocol or ip addr(s) different than 0");
524538
return -EINVAL;
525539
}
526540

@@ -529,12 +543,24 @@ static int mlx5e_xfrm_validate_policy(struct xfrm_policy *x,
529543
return -EINVAL;
530544
}
531545

532-
if (x->selector.proto != IPPROTO_IP &&
533-
(x->selector.proto != IPPROTO_UDP || x->xdo.dir != XFRM_DEV_OFFLOAD_OUT)) {
546+
if (sel->proto != IPPROTO_IP &&
547+
(sel->proto != IPPROTO_UDP || x->xdo.dir != XFRM_DEV_OFFLOAD_OUT)) {
534548
NL_SET_ERR_MSG_MOD(extack, "Device does not support upper protocol other than UDP, and only Tx direction");
535549
return -EINVAL;
536550
}
537551

552+
if (x->priority) {
553+
if (!(mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PRIO)) {
554+
NL_SET_ERR_MSG_MOD(extack, "Device does not support policy priority");
555+
return -EINVAL;
556+
}
557+
558+
if (x->priority == U32_MAX) {
559+
NL_SET_ERR_MSG_MOD(extack, "Device does not support requested policy priority");
560+
return -EINVAL;
561+
}
562+
}
563+
538564
return 0;
539565
}
540566

@@ -560,6 +586,7 @@ mlx5e_ipsec_build_accel_pol_attrs(struct mlx5e_ipsec_pol_entry *pol_entry,
560586
attrs->upspec.sport = ntohs(sel->sport);
561587
attrs->upspec.sport_mask = ntohs(sel->sport_mask);
562588
attrs->upspec.proto = sel->proto;
589+
attrs->prio = x->priority;
563590
}
564591

565592
static int mlx5e_xfrm_add_policy(struct xfrm_policy *x,
@@ -576,7 +603,7 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x,
576603
return -EOPNOTSUPP;
577604
}
578605

579-
err = mlx5e_xfrm_validate_policy(x, extack);
606+
err = mlx5e_xfrm_validate_policy(priv->mdev, x, extack);
580607
if (err)
581608
return err;
582609

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ enum mlx5_ipsec_cap {
9494
MLX5_IPSEC_CAP_ESN = 1 << 1,
9595
MLX5_IPSEC_CAP_PACKET_OFFLOAD = 1 << 2,
9696
MLX5_IPSEC_CAP_ROCE = 1 << 3,
97+
MLX5_IPSEC_CAP_PRIO = 1 << 4,
9798
};
9899

99100
struct mlx5e_priv;
@@ -161,6 +162,7 @@ struct mlx5e_ipsec_rule {
161162
struct mlx5_flow_handle *rule;
162163
struct mlx5_modify_hdr *modify_hdr;
163164
struct mlx5_pkt_reformat *pkt_reformat;
165+
struct mlx5_fc *fc;
164166
};
165167

166168
struct mlx5e_ipsec_modify_state_work {
@@ -198,6 +200,7 @@ struct mlx5_accel_pol_xfrm_attrs {
198200
u8 type : 2;
199201
u8 dir : 2;
200202
u32 reqid;
203+
u32 prio;
201204
};
202205

203206
struct mlx5e_ipsec_pol_entry {
@@ -233,9 +236,6 @@ void mlx5e_ipsec_aso_cleanup(struct mlx5e_ipsec *ipsec);
233236

234237
int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
235238
struct mlx5_wqe_aso_ctrl_seg *data);
236-
void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry,
237-
u64 *packets);
238-
239239
void mlx5e_accel_ipsec_fs_read_stats(struct mlx5e_priv *priv,
240240
void *ipsec_stats);
241241

@@ -252,6 +252,13 @@ mlx5e_ipsec_pol2dev(struct mlx5e_ipsec_pol_entry *pol_entry)
252252
{
253253
return pol_entry->ipsec->mdev;
254254
}
255+
256+
static inline bool addr6_all_zero(__be32 *addr6)
257+
{
258+
static const __be32 zaddr6[4] = {};
259+
260+
return !memcmp(addr6, zaddr6, sizeof(*zaddr6));
261+
}
255262
#else
256263
static inline void mlx5e_ipsec_init(struct mlx5e_priv *priv)
257264
{

0 commit comments

Comments
 (0)