Skip to contentSkip to conversation

Extend packet offload to fully support libreswan

PATCH In review Leon Romanovsky 3 participants 15 messages Mar 14, 2023 – Mar 20, 2023

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

cover Extend packet offload to fully support libreswan

From: Leon Romanovsky <[email protected]>

Hi Steffen,

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.

--------------------------
Future submission roadmap, which can be seen here [2]:
* Support packet offload in IPsec tunnel mode
* Rework lifetime counters support to avoid HW bugs/limitations
* Some general cleanup.

So how do you want me to route the patches, as they have a dependency between them? xfrm-next/net-next/mlx5-next?

Thanks

[1] https://github.com/libreswan/libreswan/pull/986q
[2] https://git.kernel.org/pub/scm/linux/kernel/git/leon/linux-rdma.git/log/?h=xfrm-next

Paul Blakey (3):
net/mlx5: fs_chains: Refactor to detach chains from tc usage net/mlx5: fs_core: Allow ignore_flow_level on TX dest net/mlx5e: Use chains for IPsec policy priority offload

Raed Salem (6):
xfrm: add new device offload acquire flag
xfrm: copy_to_user_state fetch offloaded SA packets/bytes statistics net/mlx5e: Allow policies with reqid 0, to support IKE policy holes net/mlx5e: Support IPsec acquire default SA
net/mlx5e: Use one rule to count all IPsec Tx offloaded traffic net/mlx5e: Update IPsec per SA packets/bytes count

 .../mellanox/mlx5/core/en_accel/ipsec.c       |  71 ++-
 .../mellanox/mlx5/core/en_accel/ipsec.h       |  13 +-
 .../mellanox/mlx5/core/en_accel/ipsec_fs.c    | 528 ++++++++++++++----
 .../mlx5/core/en_accel/ipsec_offload.c        |  32 +-
 .../net/ethernet/mellanox/mlx5/core/en_tc.c   |  20 +-
 .../mellanox/mlx5/core/eswitch_offloads.c     |   6 +-
 .../net/ethernet/mellanox/mlx5/core/fs_core.c |   5 +-
 .../mellanox/mlx5/core/lib/fs_chains.c        |  89 ++-
 .../mellanox/mlx5/core/lib/fs_chains.h        |   9 +-
 include/net/xfrm.h                            |   5 +
 net/xfrm/xfrm_state.c                         |   1 +
 net/xfrm/xfrm_user.c                          |   2 +
 12 files changed, 553 insertions(+), 228 deletions(-)
Signature · 1 line
2.39.2
#1 lore raw

PATCH 1/9 net/mlx5: fs_chains: Refactor to detach chains from tc usage

From: Paul Blakey <[email protected]>

To support more generic chains that will be used on other namespaces and without tc, refactor to remove the dependency on tc terms.

---
 .../net/ethernet/mellanox/mlx5/core/en_tc.c   | 20 +----
 .../mellanox/mlx5/core/eswitch_offloads.c     |  6 +-
 .../mellanox/mlx5/core/lib/fs_chains.c        | 89 +++++++++----------
 .../mellanox/mlx5/core/lib/fs_chains.h        |  9 +-
 4 files changed, 55 insertions(+), 69 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +3 -17
index 70b8d2dfa751..98c9befb7803 100644
@@ -5186,22 +5186,6 @@ static int mlx5e_tc_netdev_event(struct notifier_block *this,
 	return NOTIFY_DONE;
 }
 
-static int mlx5e_tc_nic_get_ft_size(struct mlx5_core_dev *dev)
-{
-	int tc_grp_size, tc_tbl_size;
-	u32 max_flow_counter;
-
-	max_flow_counter = (MLX5_CAP_GEN(dev, max_flow_counter_31_16) << 16) |
-			    MLX5_CAP_GEN(dev, max_flow_counter_15_0);
-
-	tc_grp_size = min_t(int, max_flow_counter, MLX5E_TC_TABLE_MAX_GROUP_SIZE);
-
-	tc_tbl_size = min_t(int, tc_grp_size * MLX5E_TC_TABLE_NUM_GROUPS,
-			    BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev, log_max_ft_size)));
-
-	return tc_tbl_size;
-}
-
 static int mlx5e_tc_nic_create_miss_table(struct mlx5e_priv *priv)
 {
 	struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
@@ -5274,10 +5258,10 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
 		attr.flags = MLX5_CHAINS_AND_PRIOS_SUPPORTED |
 			MLX5_CHAINS_IGNORE_FLOW_LEVEL_SUPPORTED;
 	attr.ns = MLX5_FLOW_NAMESPACE_KERNEL;
-	attr.max_ft_sz = mlx5e_tc_nic_get_ft_size(dev);
 	attr.max_grp_num = MLX5E_TC_TABLE_NUM_GROUPS;
 	attr.default_ft = tc->miss_t;
 	attr.mapping = chains_mapping;
+	attr.fs_base_prio = MLX5E_TC_PRIO;
 
 	tc->chains = mlx5_chains_create(dev, &attr);
 	if (IS_ERR(tc->chains)) {
@@ -5285,6 +5269,8 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
 		goto err_miss;
 	}
 
+	mlx5_chains_print_info(tc->chains);
+
 	tc->post_act = mlx5e_tc_post_act_init(priv, tc->chains, MLX5_FLOW_NAMESPACE_KERNEL);
 	tc->ct = mlx5_tc_ct_init(priv, tc->chains, &tc->mod_hdr,
 				 MLX5_FLOW_NAMESPACE_KERNEL, tc->post_act);
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +2 -4
index d766a64b1823..5b02880dfa20 100644
@@ -1374,14 +1374,11 @@ esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb)
 	struct mlx5_flow_table *nf_ft, *ft;
 	struct mlx5_chains_attr attr = {};
 	struct mlx5_fs_chains *chains;
-	u32 fdb_max;
 	int err;
 
-	fdb_max = 1 << MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size);
-
 	esw_init_chains_offload_flags(esw, &attr.flags);
 	attr.ns = MLX5_FLOW_NAMESPACE_FDB;
-	attr.max_ft_sz = fdb_max;
+	attr.fs_base_prio = FDB_TC_OFFLOAD;
 	attr.max_grp_num = esw->params.large_group_num;
 	attr.default_ft = miss_fdb;
 	attr.mapping = esw->offloads.reg_c0_obj_pool;
@@ -1392,6 +1389,7 @@ esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb)
 		esw_warn(dev, "Failed to create fdb chains err(%d)\n", err);
 		return err;
 	}
+	mlx5_chains_print_info(chains);
 
 	esw->fdb_table.offloads.esw_chains_priv = chains;
 
drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c +43 -46

186 lines not on this page · raw message

drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.h +7 -2
index d50bdb226cef..8972fe05723a 100644
@@ -17,8 +17,9 @@ enum mlx5_chains_flags {
 
 struct mlx5_chains_attr {
 	enum mlx5_flow_namespace_type ns;
+	int fs_base_prio;
+	int fs_base_level;
 	u32 flags;
-	u32 max_ft_sz;
 	u32 max_grp_num;
 	struct mlx5_flow_table *default_ft;
 	struct mapping_ctx *mapping;
@@ -68,6 +69,8 @@ void mlx5_chains_destroy(struct mlx5_fs_chains *chains);
 void
 mlx5_chains_set_end_ft(struct mlx5_fs_chains *chains,
 		       struct mlx5_flow_table *ft);
+void
+mlx5_chains_print_info(struct mlx5_fs_chains *chains);
 
 #else /* CONFIG_MLX5_CLS_ACT */
 
@@ -89,7 +92,9 @@ static inline struct mlx5_fs_chains *
 mlx5_chains_create(struct mlx5_core_dev *dev, struct mlx5_chains_attr *attr)
 { return NULL; }
 static inline void
-mlx5_chains_destroy(struct mlx5_fs_chains *chains) {};
+mlx5_chains_destroy(struct mlx5_fs_chains *chains) {}
+static inline void
+mlx5_chains_print_info(struct mlx5_fs_chains *chains) {}
 
 #endif /* CONFIG_MLX5_CLS_ACT */
 
Signature · 1 line
2.39.2
#2 lore raw

PATCH 2/9 net/mlx5: fs_core: Allow ignore_flow_level on TX dest

In reply to Leon Romanovsky

From: Paul Blakey <[email protected]>

ignore_flow_level is also supported by firmware on TX, remove this limitation.

---
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +2 -1
index 731acbe22dc7..3ade166073fa 100644
@@ -1762,7 +1762,8 @@ static bool dest_is_valid(struct mlx5_flow_destination *dest,
 
 	if (ignore_level) {
 		if (ft->type != FS_FT_FDB &&
-		    ft->type != FS_FT_NIC_RX)
+		    ft->type != FS_FT_NIC_RX &&
+		    ft->type != FS_FT_NIC_TX)
 			return false;
 
 		if (dest->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE &&
Signature · 1 line
2.39.2
#3 lore raw

PATCH 3/9 net/mlx5e: Use chains for IPsec policy priority offload

In reply to Leon Romanovsky

From: Paul Blakey <[email protected]>

Currently, policy priority field is ignored and so order of matching is unpredictable.

Use chains for RX/TX policy offload to support the priority field.

---
 .../mellanox/mlx5/core/en_accel/ipsec.c       |  18 +-
 .../mellanox/mlx5/core/en_accel/ipsec.h       |   2 +
 .../mellanox/mlx5/core/en_accel/ipsec_fs.c    | 362 ++++++++++++++----
 .../mlx5/core/en_accel/ipsec_offload.c        |  17 +-
 4 files changed, 315 insertions(+), 84 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +16 -2
index 7b0d3de0ec6c..83012bece548 100644
@@ -499,7 +499,8 @@ static void mlx5e_xfrm_update_curlft(struct xfrm_state *x)
 	mlx5e_ipsec_aso_update_curlft(sa_entry, &x->curlft.packets);
 }
 
-static int mlx5e_xfrm_validate_policy(struct xfrm_policy *x,
+static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev,
+				      struct xfrm_policy *x,
 				      struct netlink_ext_ack *extack)
 {
 	if (x->type != XFRM_POLICY_TYPE_MAIN) {
@@ -535,6 +536,18 @@ static int mlx5e_xfrm_validate_policy(struct xfrm_policy *x,
 		return -EINVAL;
 	}
 
+	if (x->priority) {
+		if (!(mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PRIO)) {
+			NL_SET_ERR_MSG_MOD(extack, "Device does not support policy priority");
+			return -EINVAL;
+		}
+
+		if (x->priority == U32_MAX) {
+			NL_SET_ERR_MSG_MOD(extack, "Device does not support requested policy priority");
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
@@ -560,6 +573,7 @@ mlx5e_ipsec_build_accel_pol_attrs(struct mlx5e_ipsec_pol_entry *pol_entry,
 	attrs->upspec.sport = ntohs(sel->sport);
 	attrs->upspec.sport_mask = ntohs(sel->sport_mask);
 	attrs->upspec.proto = sel->proto;
+	attrs->prio = x->priority;
 }
 
 static int mlx5e_xfrm_add_policy(struct xfrm_policy *x,
@@ -576,7 +590,7 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x,
 		return -EOPNOTSUPP;
 	}
 
-	err = mlx5e_xfrm_validate_policy(x, extack);
+	err = mlx5e_xfrm_validate_policy(priv->mdev, x, extack);
 	if (err)
 		return err;
 
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +2 -0
index 12f044330639..b36e047396da 100644
@@ -94,6 +94,7 @@ enum mlx5_ipsec_cap {
 	MLX5_IPSEC_CAP_ESN		= 1 << 1,
 	MLX5_IPSEC_CAP_PACKET_OFFLOAD	= 1 << 2,
 	MLX5_IPSEC_CAP_ROCE             = 1 << 3,
+	MLX5_IPSEC_CAP_PRIO             = 1 << 4,
 };
 
 struct mlx5e_priv;
@@ -198,6 +199,7 @@ struct mlx5_accel_pol_xfrm_attrs {
 	u8 type : 2;
 	u8 dir : 2;
 	u32 reqid;
+	u32 prio;
 };
 
 struct mlx5e_ipsec_pol_entry {
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +285 -77

554 lines not on this page · raw message

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +12 -5
index 5fa7a4c40429..67be8d36bb76 100644
@@ -36,11 +36,18 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev)
 	    MLX5_CAP_ETH(mdev, insert_trailer) && MLX5_CAP_ETH(mdev, swp))
 		caps |= MLX5_IPSEC_CAP_CRYPTO;
 
-	if (MLX5_CAP_IPSEC(mdev, ipsec_full_offload) &&
-	    MLX5_CAP_FLOWTABLE_NIC_TX(mdev, reformat_add_esp_trasport) &&
-	    MLX5_CAP_FLOWTABLE_NIC_RX(mdev, reformat_del_esp_trasport) &&
-	    MLX5_CAP_FLOWTABLE_NIC_RX(mdev, decap))
-		caps |= MLX5_IPSEC_CAP_PACKET_OFFLOAD;
+	if (MLX5_CAP_IPSEC(mdev, ipsec_full_offload)) {
+		if (MLX5_CAP_FLOWTABLE_NIC_TX(mdev,
+					      reformat_add_esp_trasport) &&
+		    MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
+					      reformat_del_esp_trasport) &&
+		    MLX5_CAP_FLOWTABLE_NIC_RX(mdev, decap))
+			caps |= MLX5_IPSEC_CAP_PACKET_OFFLOAD;
+
+		if (MLX5_CAP_FLOWTABLE_NIC_TX(mdev, ignore_flow_level) &&
+		    MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ignore_flow_level))
+			caps |= MLX5_IPSEC_CAP_PRIO;
+	}
 
 	if (mlx5_get_roce_state(mdev) &&
 	    MLX5_CAP_GEN_2(mdev, flow_table_type_2_type) & MLX5_FT_NIC_RX_2_NIC_RX_RDMA &&
Signature · 1 line
2.39.2
#4 lore raw

PATCH 4/9 xfrm: add new device offload acquire flag

In reply to Leon Romanovsky

From: Raed Salem <[email protected]>

During XFRM acquire flow, a default SA is created to be updated later, once acquire netlink message is handled in user space. When the relevant policy is offloaded this default SA is also offloaded to IPsec offload supporting driver, however this SA does not have context suitable for offloading in HW, nor is interesting to offload to HW, consequently needs a special driver handling apart from other offloaded SA(s). Add a special flag that marks such SA so driver can handle it correctly.

---
 include/net/xfrm.h    | 5 +++++
 net/xfrm/xfrm_state.c | 1 +
 2 files changed, 6 insertions(+)
include/net/xfrm.h +5 -0
index 3e1f70e8e424..33ee3f5936e6 100644
@@ -138,6 +138,10 @@ enum {
 	XFRM_DEV_OFFLOAD_PACKET,
 };
 
+enum {
+	XFRM_DEV_OFFLOAD_FLAG_ACQ = 1,
+};
+
 struct xfrm_dev_offload {
 	struct net_device	*dev;
 	netdevice_tracker	dev_tracker;
@@ -145,6 +149,7 @@ struct xfrm_dev_offload {
 	unsigned long		offload_handle;
 	u8			dir : 2;
 	u8			type : 2;
+	u8			flags : 2;
 };
 
 struct xfrm_mode {
net/xfrm/xfrm_state.c +1 -0
index 2ab3e09e2227..7cca0a1fa5ff 100644
@@ -1272,6 +1272,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
 			xso->dir = xdo->dir;
 			xso->dev = xdo->dev;
 			xso->real_dev = xdo->real_dev;
+			xso->flags = XFRM_DEV_OFFLOAD_FLAG_ACQ;
 			netdev_tracker_alloc(xso->dev, &xso->dev_tracker,
 					     GFP_ATOMIC);
 			error = xso->dev->xfrmdev_ops->xdo_dev_state_add(x, NULL);
Signature · 1 line
2.39.2
maintainer Acked-by on v1 4/9
#5 lore raw

Re: [PATCH xfrm-next 4/9] xfrm: add new device offload acquire flag

Quoted 10 lines · Leon Romanovsky

From: Raed Salem <[email protected]>

During XFRM acquire flow, a default SA is created to be updated later, once acquire netlink message is handled in user space. When the relevant policy is offloaded this default SA is also offloaded to IPsec offload supporting driver, however this SA does not have context suitable for offloading in HW, nor is interesting to offload to HW, consequently needs a special driver handling apart from other offloaded SA(s). Add a special flag that marks such SA so driver can handle it correctly.

Quoted 2 lines
#6 lore raw

PATCH 5/9 xfrm: copy_to_user_state fetch offloaded SA packets/bytes statistics

In reply to Leon Romanovsky

From: Raed Salem <[email protected]>

Both in RX and TX, the traffic that performs IPsec packet offload transformation is accounted by HW only. Consequently, the HW should be queried for packets/bytes statistics when user asks for such transformation data.

---
 net/xfrm/xfrm_user.c | 2 ++
 1 file changed, 2 insertions(+)
net/xfrm/xfrm_user.c +2 -0
index cf5172d4ce68..5eee905b2450 100644
@@ -901,6 +901,8 @@ static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
 	memcpy(&p->id, &x->id, sizeof(p->id));
 	memcpy(&p->sel, &x->sel, sizeof(p->sel));
 	memcpy(&p->lft, &x->lft, sizeof(p->lft));
+	if (x->xso.dev)
+		xfrm_dev_state_update_curlft(x);
 	memcpy(&p->curlft, &x->curlft, sizeof(p->curlft));
 	put_unaligned(x->stats.replay_window, &p->stats.replay_window);
 	put_unaligned(x->stats.replay, &p->stats.replay);
Signature · 1 line
2.39.2
maintainer Acked-by on v1 5/9
#7 lore raw

Re: [PATCH xfrm-next 5/9] xfrm: copy_to_user_state fetch offloaded SA packets/bytes statistics

Quoted 9 lines · Leon Romanovsky

From: Raed Salem <[email protected]>

Both in RX and TX, the traffic that performs IPsec packet offload transformation is accounted by HW only. Consequently, the HW should be queried for packets/bytes statistics when user asks for such transformation data.

#8 lore raw

PATCH 6/9 net/mlx5e: Allow policies with reqid 0, to support IKE policy holes

In reply to Leon Romanovsky

From: Raed Salem <[email protected]>

IKE policies hole, is special policy that exists to allow for IKE traffic to bypass IPsec encryption even though there is already a policies and SA(s) configured on same endpoints, these policies does not nessecarly have the reqid configured, so need to add an exception for such policies. These kind of policies are allowed under the condition that at least upper protocol and/or ips are not 0.

---
 .../mellanox/mlx5/core/en_accel/ipsec.c       | 11 +--
 .../mellanox/mlx5/core/en_accel/ipsec.h       |  7 ++
 .../mellanox/mlx5/core/en_accel/ipsec_fs.c    | 68 ++++++++++++-------
 3 files changed, 59 insertions(+), 27 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +7 -4
index 83012bece548..9cc59dc8b592 100644
@@ -503,6 +503,8 @@ static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev,
 				      struct xfrm_policy *x,
 				      struct netlink_ext_ack *extack)
 {
+	struct xfrm_selector *sel = &x->selector;
+
 	if (x->type != XFRM_POLICY_TYPE_MAIN) {
 		NL_SET_ERR_MSG_MOD(extack, "Cannot offload non-main policy types");
 		return -EINVAL;
@@ -520,8 +522,9 @@ static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev,
 		return -EINVAL;
 	}
 
-	if (!x->xfrm_vec[0].reqid) {
-		NL_SET_ERR_MSG_MOD(extack, "Cannot offload policy without reqid");
+	if (!x->xfrm_vec[0].reqid && sel->proto == IPPROTO_IP &&
+	    addr6_all_zero(sel->saddr.a6) && addr6_all_zero(sel->daddr.a6)) {
+		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");
 		return -EINVAL;
 	}
 
@@ -530,8 +533,8 @@ static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev,
 		return -EINVAL;
 	}
 
-	if (x->selector.proto != IPPROTO_IP &&
-	    (x->selector.proto != IPPROTO_UDP || x->xdo.dir != XFRM_DEV_OFFLOAD_OUT)) {
+	if (sel->proto != IPPROTO_IP &&
+	    (sel->proto != IPPROTO_UDP || x->xdo.dir != XFRM_DEV_OFFLOAD_OUT)) {
 		NL_SET_ERR_MSG_MOD(extack, "Device does not support upper protocol other than UDP, and only Tx direction");
 		return -EINVAL;
 	}
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +7 -0
index b36e047396da..f3e81c3383e5 100644
@@ -254,6 +254,13 @@ mlx5e_ipsec_pol2dev(struct mlx5e_ipsec_pol_entry *pol_entry)
 {
 	return pol_entry->ipsec->mdev;
 }
+
+static inline bool addr6_all_zero(__be32 *addr6)
+{
+	static const __be32 zaddr6[4] = {};
+
+	return !memcmp(addr6, zaddr6, sizeof(*zaddr6));
+}
 #else
 static inline void mlx5e_ipsec_init(struct mlx5e_priv *priv)
 {
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +45 -23

113 lines not on this page · raw message

Signature · 1 line
2.39.2
#9 lore raw

PATCH 7/9 net/mlx5e: Support IPsec acquire default SA

In reply to Leon Romanovsky

From: Raed Salem <[email protected]>

During XFRM stack acquire flow, a default SA is created to be updated later, once acquire netlink message is handled in user space.

This SA is also passed to IPsec offload supporting driver, however this SA acts only as placeholder and does not have context suitable for offloading in HW yet. Identify this kind of SA by special offload flag (XFRM_DEV_OFFLOAD_FLAG_ACQ), and create a SW only context.

In such cases with special mark so it won't be installed in HW in addition flow and on remove/delete free this SW only context.

---
 .../mellanox/mlx5/core/en_accel/ipsec.c       | 26 +++++++++++++++----
 1 file changed, 21 insertions(+), 5 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +21 -5
index 9cc59dc8b592..20a6bd1c03a3 100644
@@ -308,6 +308,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
 	struct net_device *netdev = x->xso.real_dev;
 	struct mlx5e_ipsec *ipsec;
 	struct mlx5e_priv *priv;
+	gfp_t gfp;
 	int err;
 
 	priv = netdev_priv(netdev);
@@ -315,16 +316,20 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
 		return -EOPNOTSUPP;
 
 	ipsec = priv->ipsec;
-	err = mlx5e_xfrm_validate_state(priv->mdev, x, extack);
-	if (err)
-		return err;
-
-	sa_entry = kzalloc(sizeof(*sa_entry), GFP_KERNEL);
+	gfp = (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) ? GFP_ATOMIC : GFP_KERNEL;
+	sa_entry = kzalloc(sizeof(*sa_entry), gfp);
 	if (!sa_entry)
 		return -ENOMEM;
 
 	sa_entry->x = x;
 	sa_entry->ipsec = ipsec;
+	/* Check if this SA is originated from acquire flow temporary SA */
+	if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
+		goto out;
+
+	err = mlx5e_xfrm_validate_state(priv->mdev, x, extack);
+	if (err)
+		goto err_xfrm;
 
 	/* check esn */
 	mlx5e_ipsec_update_esn_state(sa_entry);
@@ -353,6 +358,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
 				mlx5e_ipsec_set_iv_esn : mlx5e_ipsec_set_iv;
 
 	INIT_WORK(&sa_entry->modify_work.work, _update_xfrm_state);
+out:
 	x->xso.offload_handle = (unsigned long)sa_entry;
 	return 0;
 
@@ -372,6 +378,9 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x)
 	struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
 	struct mlx5e_ipsec_sa_entry *old;
 
+	if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
+		return;
+
 	old = xa_erase_bh(&ipsec->sadb, sa_entry->ipsec_obj_id);
 	WARN_ON(old != sa_entry);
 }
@@ -380,9 +389,13 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x)
 {
 	struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
 
+	if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
+		goto sa_entry_free;
+
 	cancel_work_sync(&sa_entry->modify_work.work);
 	mlx5e_accel_ipsec_fs_del_rule(sa_entry);
 	mlx5_ipsec_free_sa_ctx(sa_entry);
+sa_entry_free:
 	kfree(sa_entry);
 }
 
@@ -486,6 +499,9 @@ static void mlx5e_xfrm_update_curlft(struct xfrm_state *x)
 
 	lockdep_assert_held(&x->lock);
 
+	if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
+		return;
+
 	if (sa_entry->attrs.soft_packet_limit == XFRM_INF)
 		/* Limits are not configured, as soft limit
 		 * must be lowever than hard limit.
Signature · 1 line
2.39.2
#10 lore raw

PATCH 8/9 net/mlx5e: Use one rule to count all IPsec Tx offloaded traffic

In reply to Leon Romanovsky

From: Raed Salem <[email protected]>

Currently one counter is shared between all IPsec Tx offloaded rules to count the total amount of packets/bytes that was IPsec Tx offloaded, replace this scheme by adding a new flow table (ft) with one rule that counts all flows that passes through this table (like Rx status ft), this ft is pointed by all IPsec Tx offloaded rules. The above allows to have a counter per tx flow rule in while keeping a separate global counter that store the aggregation outcome of all these per flow counters.

---
 .../mellanox/mlx5/core/en_accel/ipsec_fs.c    | 58 +++++++++++++++++--
 .../net/ethernet/mellanox/mlx5/core/fs_core.c |  2 +-
 2 files changed, 55 insertions(+), 5 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +54 -4
index 9f694a8e21fd..d1e4fd1e21d5 100644
@@ -41,6 +41,7 @@ struct mlx5e_ipsec_rx {
 struct mlx5e_ipsec_tx {
 	struct mlx5e_ipsec_ft ft;
 	struct mlx5e_ipsec_miss pol;
+	struct mlx5e_ipsec_rule status;
 	struct mlx5_flow_namespace *ns;
 	struct mlx5e_ipsec_fc *fc;
 	struct mlx5_fs_chains *chains;
@@ -455,6 +456,39 @@ static void rx_ft_put_policy(struct mlx5e_ipsec *ipsec, u32 family, u32 prio)
 	mutex_unlock(&rx->ft.mutex);
 }
 
+static int ipsec_counter_rule_tx(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx)
+{
+	struct mlx5_flow_destination dest = {};
+	struct mlx5_flow_act flow_act = {};
+	struct mlx5_flow_handle *fte;
+	struct mlx5_flow_spec *spec;
+	int err;
+
+	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+	if (!spec)
+		return -ENOMEM;
+
+	/* create fte */
+	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW |
+			  MLX5_FLOW_CONTEXT_ACTION_COUNT;
+	dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+	dest.counter_id = mlx5_fc_id(tx->fc->cnt);
+	fte = mlx5_add_flow_rules(tx->ft.status, spec, &flow_act, &dest, 1);
+	if (IS_ERR(fte)) {
+		err = PTR_ERR(fte);
+		mlx5_core_err(mdev, "Fail to add ipsec tx counter rule err=%d\n", err);
+		goto err_rule;
+	}
+
+	kvfree(spec);
+	tx->status.rule = fte;
+	return 0;
+
+err_rule:
+	kvfree(spec);
+	return err;
+}
+
 /* IPsec TX flow steering */
 static void tx_destroy(struct mlx5e_ipsec_tx *tx, struct mlx5_ipsec_fs *roce)
 {
@@ -468,6 +502,8 @@ static void tx_destroy(struct mlx5e_ipsec_tx *tx, struct mlx5_ipsec_fs *roce)
 	}
 
 	mlx5_destroy_flow_table(tx->ft.sa);
+	mlx5_del_flow_rules(tx->status.rule);
+	mlx5_destroy_flow_table(tx->ft.status);
 }
 
 static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx,
@@ -477,10 +513,20 @@ static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx,
 	struct mlx5_flow_table *ft;
 	int err;
 
-	ft = ipsec_ft_create(tx->ns, 1, 0, 4);
+	ft = ipsec_ft_create(tx->ns, 2, 0, 1);
 	if (IS_ERR(ft))
 		return PTR_ERR(ft);
+	tx->ft.status = ft;
 
+	err = ipsec_counter_rule_tx(mdev, tx);
+	if (err)
+		goto err_status_rule;
+
+	ft = ipsec_ft_create(tx->ns, 1, 0, 4);
+	if (IS_ERR(ft)) {
+		err = PTR_ERR(ft);
+		goto err_sa_ft;
+	}
 	tx->ft.sa = ft;
 
 	if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PRIO) {
@@ -525,6 +571,10 @@ static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx,
 	}
 err_pol_ft:
 	mlx5_destroy_flow_table(tx->ft.sa);
+err_sa_ft:
+	mlx5_del_flow_rules(tx->status.rule);
+err_status_rule:
+	mlx5_destroy_flow_table(tx->ft.status);
 	return err;
 }
 
@@ -949,11 +999,11 @@ static int tx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
 	flow_act.crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_IPSEC;
 	flow_act.crypto.obj_id = sa_entry->ipsec_obj_id;
 	flow_act.flags |= FLOW_ACT_NO_APPEND;
-	flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW |
+	flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
 			   MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT |
 			   MLX5_FLOW_CONTEXT_ACTION_COUNT;
-	dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
-	dest.counter_id = mlx5_fc_id(tx->fc->cnt);
+	dest.ft = tx->ft.status;
+	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
 	rule = mlx5_add_flow_rules(tx->ft.sa, spec, &flow_act, &dest, 1);
 	if (IS_ERR(rule)) {
 		err = PTR_ERR(rule);
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +1 -1
index 3ade166073fa..8e3da9d4fe1c 100644
@@ -137,7 +137,7 @@
 #define LAG_MIN_LEVEL (OFFLOADS_MIN_LEVEL + KERNEL_RX_MACSEC_MIN_LEVEL + 1)
 
 #define KERNEL_TX_IPSEC_NUM_PRIOS  1
-#define KERNEL_TX_IPSEC_NUM_LEVELS 2
+#define KERNEL_TX_IPSEC_NUM_LEVELS 3
 #define KERNEL_TX_IPSEC_MIN_LEVEL        (KERNEL_TX_IPSEC_NUM_LEVELS)
 
 #define KERNEL_TX_MACSEC_NUM_PRIOS  1
Signature · 1 line
2.39.2
#11 lore raw

PATCH 9/9 net/mlx5e: Update IPsec per SA packets/bytes count

In reply to Leon Romanovsky

From: Raed Salem <[email protected]>

Providing per SA packets/bytes statistics mandates creating unique counter per SA flow for Rx/Tx, whenever offloaded SA statistics is desired query the specific SA counter to provide the stack with the needed data.

---
 .../mellanox/mlx5/core/en_accel/ipsec.c       | 20 +++------
 .../mellanox/mlx5/core/en_accel/ipsec.h       |  4 +-
 .../mellanox/mlx5/core/en_accel/ipsec_fs.c    | 44 ++++++++++++++-----
 .../mlx5/core/en_accel/ipsec_offload.c        | 15 -------
 4 files changed, 42 insertions(+), 41 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +7 -13
index 20a6bd1c03a3..91fa0a366316 100644
@@ -495,24 +495,18 @@ static void mlx5e_xfrm_advance_esn_state(struct xfrm_state *x)
 static void mlx5e_xfrm_update_curlft(struct xfrm_state *x)
 {
 	struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
-	int err;
+	struct mlx5e_ipsec_rule *ipsec_rule = &sa_entry->ipsec_rule;
+	u64 packets, bytes, lastuse;
 
-	lockdep_assert_held(&x->lock);
+	lockdep_assert(lockdep_is_held(&x->lock) ||
+		       lockdep_is_held(&dev_net(x->xso.real_dev)->xfrm.xfrm_cfg_mutex));
 
 	if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
 		return;
 
-	if (sa_entry->attrs.soft_packet_limit == XFRM_INF)
-		/* Limits are not configured, as soft limit
-		 * must be lowever than hard limit.
-		 */
-		return;
-
-	err = mlx5e_ipsec_aso_query(sa_entry, NULL);
-	if (err)
-		return;
-
-	mlx5e_ipsec_aso_update_curlft(sa_entry, &x->curlft.packets);
+	mlx5_fc_query_cached(ipsec_rule->fc, &bytes, &packets, &lastuse);
+	x->curlft.packets += packets;
+	x->curlft.bytes += bytes;
 }
 
 static int mlx5e_xfrm_validate_policy(struct mlx5_core_dev *mdev,
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h +1 -3
index f3e81c3383e5..68ae5230eb75 100644
@@ -162,6 +162,7 @@ struct mlx5e_ipsec_rule {
 	struct mlx5_flow_handle *rule;
 	struct mlx5_modify_hdr *modify_hdr;
 	struct mlx5_pkt_reformat *pkt_reformat;
+	struct mlx5_fc *fc;
 };
 
 struct mlx5e_ipsec_modify_state_work {
@@ -235,9 +236,6 @@ void mlx5e_ipsec_aso_cleanup(struct mlx5e_ipsec *ipsec);
 
 int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
 			  struct mlx5_wqe_aso_ctrl_seg *data);
-void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry,
-				   u64 *packets);
-
 void mlx5e_accel_ipsec_fs_read_stats(struct mlx5e_priv *priv,
 				     void *ipsec_stats);
 
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +34 -10

112 lines not on this page · raw message

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +0 -15
index 67be8d36bb76..5342b0b07681 100644
@@ -489,18 +489,3 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
 	spin_unlock_bh(&aso->lock);
 	return ret;
 }
-
-void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry,
-				   u64 *packets)
-{
-	struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
-	struct mlx5e_ipsec_aso *aso = ipsec->aso;
-	u64 hard_cnt;
-
-	hard_cnt = MLX5_GET(ipsec_aso, aso->ctx, remove_flow_pkt_cnt);
-	/* HW decresases the limit till it reaches zero to fire an avent.
-	 * We need to fix the calculations, so the returned count is a total
-	 * number of passed packets and not how much left.
-	 */
-	*packets = sa_entry->attrs.hard_packet_limit - hard_cnt;
-}
Signature · 1 line
2.39.2
maintainer
#12 lore raw
In reply to Leon Romanovsky
Quoted 3 lines · Leon Romanovsky

From: Leon Romanovsky <[email protected]>

Hi Steffen,

<...>

Quoted 2 lines

So how do you want me to route the patches, as they have a dependency between them? xfrm-next/net-next/mlx5-next?

Can you please share your opinion and/or ack/nack xfrm patches, so we will be able to progress?

Thanks

Quoted 36 lines

Thanks

[1] https://github.com/libreswan/libreswan/pull/986q
[2] https://git.kernel.org/pub/scm/linux/kernel/git/leon/linux-rdma.git/log/?h=xfrm-next

Paul Blakey (3):
net/mlx5: fs_chains: Refactor to detach chains from tc usage net/mlx5: fs_core: Allow ignore_flow_level on TX dest net/mlx5e: Use chains for IPsec policy priority offload

Raed Salem (6):
xfrm: add new device offload acquire flag
xfrm: copy_to_user_state fetch offloaded SA packets/bytes statistics net/mlx5e: Allow policies with reqid 0, to support IKE policy holes net/mlx5e: Support IPsec acquire default SA
net/mlx5e: Use one rule to count all IPsec Tx offloaded traffic net/mlx5e: Update IPsec per SA packets/bytes count

 .../mellanox/mlx5/core/en_accel/ipsec.c       |  71 ++-
 .../mellanox/mlx5/core/en_accel/ipsec.h       |  13 +-
 .../mellanox/mlx5/core/en_accel/ipsec_fs.c    | 528 ++++++++++++++----
 .../mlx5/core/en_accel/ipsec_offload.c        |  32 +-
 .../net/ethernet/mellanox/mlx5/core/en_tc.c   |  20 +-
 .../mellanox/mlx5/core/eswitch_offloads.c     |   6 +-
 .../net/ethernet/mellanox/mlx5/core/fs_core.c |   5 +-
 .../mellanox/mlx5/core/lib/fs_chains.c        |  89 ++-
 .../mellanox/mlx5/core/lib/fs_chains.h        |   9 +-
 include/net/xfrm.h                            |   5 +
 net/xfrm/xfrm_state.c                         |   1 +
 net/xfrm/xfrm_user.c                          |   2 +
 12 files changed, 553 insertions(+), 228 deletions(-)
Signature · 1 line
2.39.2
maintainer
#13 lore raw
In reply to Leon Romanovsky
Quoted 13 lines · Leon Romanovsky

From: Leon Romanovsky <[email protected]>

Hi Steffen,

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.

Quoted 8 lines

--------------------------
Future submission roadmap, which can be seen here [2]:
* Support packet offload in IPsec tunnel mode
* Rework lifetime counters support to avoid HW bugs/limitations
* Some general cleanup.

So how do you want me to route the patches, as they have a dependency between them? xfrm-next/net-next/mlx5-next?

As the changes to the xfrm core are just minor compared to the rest of the patchset, I'd not absolutely require to route it through ipsec-next. Do it as you prefer, but let me know how you plan to do it.

#14 lore raw
Quoted 20 lines · Steffen Klassert
Quoted 19 lines · Leon Romanovsky

From: Leon Romanovsky <[email protected]>

Hi Steffen,

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.

--------------------------
Future submission roadmap, which can be seen here [2]:
* Support packet offload in IPsec tunnel mode
* Rework lifetime counters support to avoid HW bugs/limitations
* Some general cleanup.

Quoted 7 lines
Quoted 2 lines

So how do you want me to route the patches, as they have a dependency between them? xfrm-next/net-next/mlx5-next?

As the changes to the xfrm core are just minor compared to the rest of the patchset, I'd not absolutely require to route it through ipsec-next. Do it as you prefer, but let me know how you plan to do it.

I prefer to prepare and send PR directly to netdev, but I need your Acked-by on xfrm patches first, before doing it.

Thanks