Commit b1346219 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

net/mlx5e: Add PSP stats support for Rx/Tx flows



Add all statistics described under the "Implementation Requirements"
section of the PSP Architecture Specification:

Rx successfully decrypted PSP packets:
psp_rx_pkts  : Number of packets decrypted successfully
psp_rx_bytes : Number of bytes decrypted successfully

Rx PSP authentication failure statistics:
psp_rx_pkts_auth_fail  : Number of PSP packets that failed authentication
psp_rx_bytes_auth_fail : Number of PSP bytes that failed authentication

Rx PSP bad frame error statistics:
psp_rx_pkts_frame_err;
psp_rx_bytes_frame_err;

Rx PSP drop statistics:
psp_rx_pkts_drop  : Number of PSP packets dropped
psp_rx_bytes_drop : Number of PSP bytes dropped

Tx successfully encrypted PSP packets:
psp_tx_pkts  : Number of packets encrypted successfully
psp_tx_bytes : Number of bytes encrypted successfully

Tx drops:
tx_drop : Number of misc psp related drops

The above can be seen using the ynl cli:
./pyynl/cli.py  --spec netlink/specs/psp.yaml --dump get-stats

Signed-off-by: default avatarRaed Salem <raeds@nvidia.com>
Signed-off-by: default avatarRahul Rameshbabu <rrameshbabu@nvidia.com>
Signed-off-by: default avatarDaniel Zahka <daniel.zahka@gmail.com>
Link: https://patch.msgid.link/20251106002608.1578518-5-daniel.zahka@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f05d2619
Loading
Loading
Loading
Loading
+218 −15
Original line number Diff line number Diff line
@@ -28,12 +28,15 @@ struct mlx5e_psp_tx {
	struct mlx5_flow_handle *rule;
	struct mutex mutex; /* Protect PSP TX steering */
	u32 refcnt;
	struct mlx5_fc *tx_counter;
};

struct mlx5e_psp_rx_err {
	struct mlx5_flow_table *ft;
	struct mlx5_flow_handle *rule;
	struct mlx5_flow_handle *drop_rule;
	struct mlx5_flow_handle *auth_fail_rule;
	struct mlx5_flow_handle *err_rule;
	struct mlx5_flow_handle *bad_rule;
	struct mlx5_modify_hdr *copy_modify_hdr;
};

@@ -50,6 +53,10 @@ struct mlx5e_accel_fs_psp_prot {

struct mlx5e_accel_fs_psp {
	struct mlx5e_accel_fs_psp_prot fs_prot[ACCEL_FS_PSP_NUM_TYPES];
	struct mlx5_fc *rx_counter;
	struct mlx5_fc *rx_auth_fail_counter;
	struct mlx5_fc *rx_err_counter;
	struct mlx5_fc *rx_bad_counter;
};

struct mlx5e_psp_fs {
@@ -72,9 +79,19 @@ static enum mlx5_traffic_types fs_psp2tt(enum accel_fs_psp_type i)
static void accel_psp_fs_rx_err_del_rules(struct mlx5e_psp_fs *fs,
					  struct mlx5e_psp_rx_err *rx_err)
{
	if (rx_err->drop_rule) {
		mlx5_del_flow_rules(rx_err->drop_rule);
		rx_err->drop_rule = NULL;
	if (rx_err->bad_rule) {
		mlx5_del_flow_rules(rx_err->bad_rule);
		rx_err->bad_rule = NULL;
	}

	if (rx_err->err_rule) {
		mlx5_del_flow_rules(rx_err->err_rule);
		rx_err->err_rule = NULL;
	}

	if (rx_err->auth_fail_rule) {
		mlx5_del_flow_rules(rx_err->auth_fail_rule);
		rx_err->auth_fail_rule = NULL;
	}

	if (rx_err->rule) {
@@ -117,6 +134,7 @@ static int accel_psp_fs_rx_err_add_rule(struct mlx5e_psp_fs *fs,
{
	u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
	struct mlx5_core_dev *mdev = fs->mdev;
	struct mlx5_flow_destination dest[2];
	struct mlx5_flow_act flow_act = {};
	struct mlx5_modify_hdr *modify_hdr;
	struct mlx5_flow_handle *fte;
@@ -147,10 +165,14 @@ static int accel_psp_fs_rx_err_add_rule(struct mlx5e_psp_fs *fs,
	accel_psp_setup_syndrome_match(spec, PSP_OK);
	/* create fte */
	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_MOD_HDR |
		MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
			  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
			  MLX5_FLOW_CONTEXT_ACTION_COUNT;
	flow_act.modify_hdr = modify_hdr;
	fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act,
				  &fs_prot->default_dest, 1);
	dest[0].type = fs_prot->default_dest.type;
	dest[0].ft = fs_prot->default_dest.ft;
	dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
	dest[1].counter = fs->rx_fs->rx_counter;
	fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, dest, 2);
	if (IS_ERR(fte)) {
		err = PTR_ERR(fte);
		mlx5_core_err(mdev, "fail to add psp rx err copy rule err=%d\n", err);
@@ -158,22 +180,69 @@ static int accel_psp_fs_rx_err_add_rule(struct mlx5e_psp_fs *fs,
	}
	rx_err->rule = fte;

	/* add default drop rule */
	/* add auth fail drop rule */
	memset(spec, 0, sizeof(*spec));
	memset(&flow_act, 0, sizeof(flow_act));
	accel_psp_setup_syndrome_match(spec, PSP_ICV_FAIL);
	/* create fte */
	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
	fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, NULL, 0);
	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP |
			  MLX5_FLOW_CONTEXT_ACTION_COUNT;
	dest[0].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
	dest[0].counter = fs->rx_fs->rx_auth_fail_counter;
	fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, dest, 1);
	if (IS_ERR(fte)) {
		err = PTR_ERR(fte);
		mlx5_core_err(mdev, "fail to add psp rx err drop rule err=%d\n", err);
		mlx5_core_err(mdev, "fail to add psp rx auth fail drop rule err=%d\n",
			      err);
		goto out_drop_rule;
	}
	rx_err->drop_rule = fte;
	rx_err->auth_fail_rule = fte;

	/* add framing drop rule */
	memset(spec, 0, sizeof(*spec));
	memset(&flow_act, 0, sizeof(flow_act));
	accel_psp_setup_syndrome_match(spec, PSP_BAD_TRAILER);
	/* create fte */
	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP |
			  MLX5_FLOW_CONTEXT_ACTION_COUNT;
	dest[0].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
	dest[0].counter = fs->rx_fs->rx_err_counter;
	fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, dest, 1);
	if (IS_ERR(fte)) {
		err = PTR_ERR(fte);
		mlx5_core_err(mdev, "fail to add psp rx framing err drop rule err=%d\n",
			      err);
		goto out_drop_auth_fail_rule;
	}
	rx_err->err_rule = fte;

	/* add misc. errors drop rule */
	memset(spec, 0, sizeof(*spec));
	memset(&flow_act, 0, sizeof(flow_act));
	/* create fte */
	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP |
			  MLX5_FLOW_CONTEXT_ACTION_COUNT;
	dest[0].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
	dest[0].counter = fs->rx_fs->rx_bad_counter;
	fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, dest, 1);
	if (IS_ERR(fte)) {
		err = PTR_ERR(fte);
		mlx5_core_err(mdev, "fail to add psp rx misc. err drop rule err=%d\n",
			      err);
		goto out_drop_error_rule;
	}
	rx_err->bad_rule = fte;

	rx_err->copy_modify_hdr = modify_hdr;

	goto out_spec;

out_drop_error_rule:
	mlx5_del_flow_rules(rx_err->err_rule);
	rx_err->err_rule = NULL;
out_drop_auth_fail_rule:
	mlx5_del_flow_rules(rx_err->auth_fail_rule);
	rx_err->auth_fail_rule = NULL;
out_drop_rule:
	mlx5_del_flow_rules(rx_err->rule);
	rx_err->rule = NULL;
@@ -461,6 +530,10 @@ static void accel_psp_fs_cleanup_rx(struct mlx5e_psp_fs *fs)
		return;

	accel_psp = fs->rx_fs;
	mlx5_fc_destroy(fs->mdev, accel_psp->rx_bad_counter);
	mlx5_fc_destroy(fs->mdev, accel_psp->rx_err_counter);
	mlx5_fc_destroy(fs->mdev, accel_psp->rx_auth_fail_counter);
	mlx5_fc_destroy(fs->mdev, accel_psp->rx_counter);
	for (i = 0; i < ACCEL_FS_PSP_NUM_TYPES; i++) {
		fs_prot = &accel_psp->fs_prot[i];
		mutex_destroy(&fs_prot->prot_mutex);
@@ -474,7 +547,10 @@ static int accel_psp_fs_init_rx(struct mlx5e_psp_fs *fs)
{
	struct mlx5e_accel_fs_psp_prot *fs_prot;
	struct mlx5e_accel_fs_psp *accel_psp;
	struct mlx5_core_dev *mdev = fs->mdev;
	struct mlx5_fc *flow_counter;
	enum accel_fs_psp_type i;
	int err;

	accel_psp = kzalloc(sizeof(*accel_psp), GFP_KERNEL);
	if (!accel_psp)
@@ -485,9 +561,68 @@ static int accel_psp_fs_init_rx(struct mlx5e_psp_fs *fs)
		mutex_init(&fs_prot->prot_mutex);
	}

	flow_counter = mlx5_fc_create(mdev, false);
	if (IS_ERR(flow_counter)) {
		mlx5_core_warn(mdev,
			       "fail to create psp rx flow counter err=%pe\n",
			       flow_counter);
		err = PTR_ERR(flow_counter);
		goto out_err;
	}
	accel_psp->rx_counter = flow_counter;

	flow_counter = mlx5_fc_create(mdev, false);
	if (IS_ERR(flow_counter)) {
		mlx5_core_warn(mdev,
			       "fail to create psp rx auth fail flow counter err=%pe\n",
			       flow_counter);
		err = PTR_ERR(flow_counter);
		goto out_counter_err;
	}
	accel_psp->rx_auth_fail_counter = flow_counter;

	flow_counter = mlx5_fc_create(mdev, false);
	if (IS_ERR(flow_counter)) {
		mlx5_core_warn(mdev,
			       "fail to create psp rx error flow counter err=%pe\n",
			       flow_counter);
		err = PTR_ERR(flow_counter);
		goto out_auth_fail_counter_err;
	}
	accel_psp->rx_err_counter = flow_counter;

	flow_counter = mlx5_fc_create(mdev, false);
	if (IS_ERR(flow_counter)) {
		mlx5_core_warn(mdev,
			       "fail to create psp rx bad flow counter err=%pe\n",
			       flow_counter);
		err = PTR_ERR(flow_counter);
		goto out_err_counter_err;
	}
	accel_psp->rx_bad_counter = flow_counter;

	fs->rx_fs = accel_psp;

	return 0;

out_err_counter_err:
	mlx5_fc_destroy(mdev, accel_psp->rx_err_counter);
	accel_psp->rx_err_counter = NULL;
out_auth_fail_counter_err:
	mlx5_fc_destroy(mdev, accel_psp->rx_auth_fail_counter);
	accel_psp->rx_auth_fail_counter = NULL;
out_counter_err:
	mlx5_fc_destroy(mdev, accel_psp->rx_counter);
	accel_psp->rx_counter = NULL;
out_err:
	for (i = 0; i < ACCEL_FS_PSP_NUM_TYPES; i++) {
		fs_prot = &accel_psp->fs_prot[i];
		mutex_destroy(&fs_prot->prot_mutex);
	}
	kfree(accel_psp);
	fs->rx_fs = NULL;

	return err;
}

void mlx5_accel_psp_fs_cleanup_rx_tables(struct mlx5e_priv *priv)
@@ -532,6 +667,7 @@ static int accel_psp_fs_tx_create_ft_table(struct mlx5e_psp_fs *fs)
{
	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
	struct mlx5_flow_table_attr ft_attr = {};
	struct mlx5_flow_destination dest = {};
	struct mlx5_core_dev *mdev = fs->mdev;
	struct mlx5_flow_act flow_act = {};
	u32 *in, *mc, *outer_headers_c;
@@ -580,8 +716,11 @@ static int accel_psp_fs_tx_create_ft_table(struct mlx5e_psp_fs *fs)
	flow_act.crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_PSP;
	flow_act.flags |= FLOW_ACT_NO_APPEND;
	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW |
			  MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT;
	rule = mlx5_add_flow_rules(ft, spec, &flow_act, NULL, 0);
			  MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT |
			  MLX5_FLOW_CONTEXT_ACTION_COUNT;
	dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
	dest.counter = tx_fs->tx_counter;
	rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
	if (IS_ERR(rule)) {
		err = PTR_ERR(rule);
		mlx5_core_err(mdev, "PSP: fail to add psp tx flow rule, err = %d\n", err);
@@ -650,6 +789,7 @@ static void accel_psp_fs_cleanup_tx(struct mlx5e_psp_fs *fs)
	if (!tx_fs)
		return;

	mlx5_fc_destroy(fs->mdev, tx_fs->tx_counter);
	mutex_destroy(&tx_fs->mutex);
	WARN_ON(tx_fs->refcnt);
	kfree(tx_fs);
@@ -658,10 +798,12 @@ static void accel_psp_fs_cleanup_tx(struct mlx5e_psp_fs *fs)

static int accel_psp_fs_init_tx(struct mlx5e_psp_fs *fs)
{
	struct mlx5_core_dev *mdev = fs->mdev;
	struct mlx5_flow_namespace *ns;
	struct mlx5_fc *flow_counter;
	struct mlx5e_psp_tx *tx_fs;

	ns = mlx5_get_flow_namespace(fs->mdev, MLX5_FLOW_NAMESPACE_EGRESS_IPSEC);
	ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_EGRESS_IPSEC);
	if (!ns)
		return -EOPNOTSUPP;

@@ -669,12 +811,55 @@ static int accel_psp_fs_init_tx(struct mlx5e_psp_fs *fs)
	if (!tx_fs)
		return -ENOMEM;

	flow_counter = mlx5_fc_create(mdev, false);
	if (IS_ERR(flow_counter)) {
		mlx5_core_warn(mdev,
			       "fail to create psp tx flow counter err=%pe\n",
			       flow_counter);
		kfree(tx_fs);
		return PTR_ERR(flow_counter);
	}
	tx_fs->tx_counter = flow_counter;
	mutex_init(&tx_fs->mutex);
	tx_fs->ns = ns;
	fs->tx_fs = tx_fs;
	return 0;
}

static void
mlx5e_accel_psp_fs_get_stats_fill(struct mlx5e_priv *priv,
				  struct mlx5e_psp_stats *stats)
{
	struct mlx5e_psp_tx *tx_fs = priv->psp->fs->tx_fs;
	struct mlx5_core_dev *mdev = priv->mdev;
	struct mlx5e_accel_fs_psp *accel_psp;

	accel_psp = (struct mlx5e_accel_fs_psp *)priv->psp->fs->rx_fs;

	if (tx_fs->tx_counter)
		mlx5_fc_query(mdev, tx_fs->tx_counter, &stats->psp_tx_pkts,
			      &stats->psp_tx_bytes);

	if (accel_psp->rx_counter)
		mlx5_fc_query(mdev, accel_psp->rx_counter, &stats->psp_rx_pkts,
			      &stats->psp_rx_bytes);

	if (accel_psp->rx_auth_fail_counter)
		mlx5_fc_query(mdev, accel_psp->rx_auth_fail_counter,
			      &stats->psp_rx_pkts_auth_fail,
			      &stats->psp_rx_bytes_auth_fail);

	if (accel_psp->rx_err_counter)
		mlx5_fc_query(mdev, accel_psp->rx_err_counter,
			      &stats->psp_rx_pkts_frame_err,
			      &stats->psp_rx_bytes_frame_err);

	if (accel_psp->rx_bad_counter)
		mlx5_fc_query(mdev, accel_psp->rx_bad_counter,
			      &stats->psp_rx_pkts_drop,
			      &stats->psp_rx_bytes_drop);
}

void mlx5_accel_psp_fs_cleanup_tx_tables(struct mlx5e_priv *priv)
{
	if (!priv->psp)
@@ -849,12 +1034,30 @@ mlx5e_psp_key_rotate(struct psp_dev *psd, struct netlink_ext_ack *exack)
	return mlx5e_psp_rotate_key(priv->mdev);
}

static void
mlx5e_psp_get_stats(struct psp_dev *psd, struct psp_dev_stats *stats)
{
	struct mlx5e_priv *priv = netdev_priv(psd->main_netdev);
	struct mlx5e_psp_stats nstats;

	mlx5e_accel_psp_fs_get_stats_fill(priv, &nstats);
	stats->rx_packets = nstats.psp_rx_pkts;
	stats->rx_bytes = nstats.psp_rx_bytes;
	stats->rx_auth_fail = nstats.psp_rx_pkts_auth_fail;
	stats->rx_error = nstats.psp_rx_pkts_frame_err;
	stats->rx_bad = nstats.psp_rx_pkts_drop;
	stats->tx_packets = nstats.psp_tx_pkts;
	stats->tx_bytes = nstats.psp_tx_bytes;
	stats->tx_error = atomic_read(&priv->psp->tx_drop);
}

static struct psp_dev_ops mlx5_psp_ops = {
	.set_config   = mlx5e_psp_set_config,
	.rx_spi_alloc = mlx5e_psp_rx_spi_alloc,
	.tx_key_add   = mlx5e_psp_assoc_add,
	.tx_key_del   = mlx5e_psp_assoc_del,
	.key_rotate   = mlx5e_psp_key_rotate,
	.get_stats    = mlx5e_psp_get_stats,
};

void mlx5e_psp_unregister(struct mlx5e_priv *priv)
+16 −0
Original line number Diff line number Diff line
@@ -7,11 +7,27 @@
#include <net/psp/types.h>
#include "en.h"

struct mlx5e_psp_stats {
	u64 psp_rx_pkts;
	u64 psp_rx_bytes;
	u64 psp_rx_pkts_auth_fail;
	u64 psp_rx_bytes_auth_fail;
	u64 psp_rx_pkts_frame_err;
	u64 psp_rx_bytes_frame_err;
	u64 psp_rx_pkts_drop;
	u64 psp_rx_bytes_drop;
	u64 psp_tx_pkts;
	u64 psp_tx_bytes;
	u64 psp_tx_pkts_drop;
	u64 psp_tx_bytes_drop;
};

struct mlx5e_psp {
	struct psp_dev *psp;
	struct psp_dev_caps caps;
	struct mlx5e_psp_fs *fs;
	atomic_t tx_key_cnt;
	atomic_t tx_drop;
};

static inline bool mlx5_is_psp_device(struct mlx5_core_dev *mdev)
+1 −0
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ bool mlx5e_psp_handle_tx_skb(struct net_device *netdev,
	/* psp_encap of the packet */
	if (!psp_dev_encapsulate(net, skb, psp_st->spi, psp_st->ver, 0)) {
		kfree_skb_reason(skb, SKB_DROP_REASON_PSP_OUTPUT);
		atomic_inc(&priv->psp->tx_drop);
		return false;
	}
	if (skb_is_gso(skb)) {
+5 −0
Original line number Diff line number Diff line
@@ -4025,6 +4025,11 @@ void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s)
		s->rx_bytes     += rq_stats->bytes;
		s->multicast    += rq_stats->mcast_packets;
	}

#ifdef CONFIG_MLX5_EN_PSP
	if (priv->psp)
		s->tx_dropped	+= atomic_read(&priv->psp->tx_drop);
#endif
}

void