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

Merge branch 'mlx5-hw-managed-flow-steering-in-fs-core-level'

Tariq Toukan says:

====================
mlx5 HW-Managed Flow Steering in FS core level

This patchset by Moshe follows Yevgeny's patchsets [1][2] on subject
"HW-Managed Flow Steering in mlx5 driver". As introduced there in HW
managed Flow Steering mode (HWS) the driver is configuring steering
rules directly to the HW using WQs with a special new type of WQE (Work
Queue Element). This way we can reach higher rule insertion/deletion
rate with much lower CPU utilization compared to SW Managed Flow
Steering (SWS).

This patchset adds API to manage namespace, flow tables, flow groups and
prepare FTE (Flow Table Entry) rules. It also adds caching and pool
mechanisms for HWS actions to allow sharing of steering actions among
different rules. The implementation of this API in FS layer, allows FS
core to use HW Managed Flow Steering in addition to the existing FW or
SW Managed Flow Steering.

Patch 13 of this series adds support for configuring HW Managed Flow
Steering mode through devlink param, similar to configuring SW Managed
Flow Steering mode:

 # devlink dev param set pci/0000:08:00.0 name flow_steering_mode \
      cmode runtime value hmfs

In addition, the series contains 2 HWS patches from Yevgeny that
implement flow update support.

[1] https://lore.kernel.org/netdev/20240903031948.78006-1-saeed@kernel.org/
[2] https://lore.kernel.org/all/20250102181415.1477316-1-tariqt@nvidia.com/
====================

Link: https://patch.msgid.link/20250109160546.1733647-1-tariqt@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents afc66498 3fc44ca4
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -53,6 +53,9 @@ parameters.
       * ``smfs`` Software managed flow steering. In SMFS mode, the HW
         steering entities are created and manage through the driver without
         firmware intervention.
       * ``hmfs`` Hardware managed flow steering. In HMFS mode, the driver
         is configuring steering rules directly to the HW using Work Queues with
         a special new type of WQE (Work Queue Element).

       SMFS mode is faster and provides better rule insertion rate compared to
       default DMFS mode.
+3 −2
Original line number Diff line number Diff line
@@ -151,8 +151,9 @@ mlx5_core-$(CONFIG_MLX5_HW_STEERING) += steering/hws/cmd.o \
					steering/hws/bwc.o \
					steering/hws/debug.o \
					steering/hws/vport.o \
					steering/hws/bwc_complex.o

					steering/hws/bwc_complex.o \
					steering/hws/fs_hws_pools.o \
					steering/hws/fs_hws.o

#
# SF device
+34 −16
Original line number Diff line number Diff line
@@ -3535,35 +3535,42 @@ static int mlx5_fs_mode_validate(struct devlink *devlink, u32 id,
{
	struct mlx5_core_dev *dev = devlink_priv(devlink);
	char *value = val.vstr;
	int err = 0;
	u8 eswitch_mode;

	if (!strcmp(value, "dmfs")) {
	if (!strcmp(value, "dmfs"))
		return 0;
	} else if (!strcmp(value, "smfs")) {
		u8 eswitch_mode;
		bool smfs_cap;

		eswitch_mode = mlx5_eswitch_mode(dev);
		smfs_cap = mlx5_fs_dr_is_supported(dev);
	if (!strcmp(value, "smfs")) {
		bool smfs_cap = mlx5_fs_dr_is_supported(dev);

		if (!smfs_cap) {
			err = -EOPNOTSUPP;
			NL_SET_ERR_MSG_MOD(extack,
					   "Software managed steering is not supported by current device");
			return -EOPNOTSUPP;
		}
	} else if (!strcmp(value, "hmfs")) {
		bool hmfs_cap = mlx5_fs_hws_is_supported(dev);

		else if (eswitch_mode == MLX5_ESWITCH_OFFLOADS) {
		if (!hmfs_cap) {
			NL_SET_ERR_MSG_MOD(extack,
					   "Software managed steering is not supported when eswitch offloads enabled.");
			err = -EOPNOTSUPP;
					   "Hardware steering is not supported by current device");
			return -EOPNOTSUPP;
		}
	} else {
		NL_SET_ERR_MSG_MOD(extack,
				   "Bad parameter: supported values are [\"dmfs\", \"smfs\"]");
		err = -EINVAL;
				   "Bad parameter: supported values are [\"dmfs\", \"smfs\", \"hmfs\"]");
		return -EINVAL;
	}

	return err;
	eswitch_mode = mlx5_eswitch_mode(dev);
	if (eswitch_mode == MLX5_ESWITCH_OFFLOADS) {
		NL_SET_ERR_MSG_FMT_MOD(extack,
				       "Moving to %s is not supported when eswitch offloads enabled.",
				       value);
		return -EOPNOTSUPP;
	}

	return 0;
}

static int mlx5_fs_mode_set(struct devlink *devlink, u32 id,
@@ -3575,6 +3582,8 @@ static int mlx5_fs_mode_set(struct devlink *devlink, u32 id,

	if (!strcmp(ctx->val.vstr, "smfs"))
		mode = MLX5_FLOW_STEERING_MODE_SMFS;
	else if (!strcmp(ctx->val.vstr, "hmfs"))
		mode = MLX5_FLOW_STEERING_MODE_HMFS;
	else
		mode = MLX5_FLOW_STEERING_MODE_DMFS;
	dev->priv.steering->mode = mode;
@@ -3587,10 +3596,17 @@ static int mlx5_fs_mode_get(struct devlink *devlink, u32 id,
{
	struct mlx5_core_dev *dev = devlink_priv(devlink);

	if (dev->priv.steering->mode == MLX5_FLOW_STEERING_MODE_SMFS)
	switch (dev->priv.steering->mode) {
	case MLX5_FLOW_STEERING_MODE_SMFS:
		strscpy(ctx->val.vstr, "smfs", sizeof(ctx->val.vstr));
	else
		break;
	case MLX5_FLOW_STEERING_MODE_HMFS:
		strscpy(ctx->val.vstr, "hmfs", sizeof(ctx->val.vstr));
		break;
	default:
		strscpy(ctx->val.vstr, "dmfs", sizeof(ctx->val.vstr));
	}

	return 0;
}

@@ -4009,6 +4025,8 @@ int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns,

	if (mode == MLX5_FLOW_STEERING_MODE_SMFS)
		cmds = mlx5_fs_cmd_get_dr_cmds();
	else if (mode == MLX5_FLOW_STEERING_MODE_HMFS)
		cmds = mlx5_fs_cmd_get_hws_cmds();
	else
		cmds = mlx5_fs_cmd_get_fw_cmds();
	if (!cmds)
+57 −5
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
#include <linux/rhashtable.h>
#include <linux/llist.h>
#include <steering/sws/fs_dr.h>
#include <steering/hws/fs_hws.h>

#define FDB_TC_MAX_CHAIN 3
#define FDB_FT_CHAIN (FDB_TC_MAX_CHAIN + 1)
@@ -64,6 +65,7 @@ struct mlx5_modify_hdr {
	enum mlx5_flow_resource_owner owner;
	union {
		struct mlx5_fs_dr_action fs_dr_action;
		struct mlx5_fs_hws_action fs_hws_action;
		u32 id;
	};
};
@@ -74,6 +76,7 @@ struct mlx5_pkt_reformat {
	enum mlx5_flow_resource_owner owner;
	union {
		struct mlx5_fs_dr_action fs_dr_action;
		struct mlx5_fs_hws_action fs_hws_action;
		u32 id;
	};
};
@@ -126,7 +129,8 @@ enum fs_fte_status {

enum mlx5_flow_steering_mode {
	MLX5_FLOW_STEERING_MODE_DMFS,
	MLX5_FLOW_STEERING_MODE_SMFS
	MLX5_FLOW_STEERING_MODE_SMFS,
	MLX5_FLOW_STEERING_MODE_HMFS,
};

enum mlx5_flow_steering_capabilty {
@@ -190,7 +194,10 @@ struct mlx5_flow_handle {
/* Type of children is mlx5_flow_group */
struct mlx5_flow_table {
	struct fs_node			node;
	union {
		struct mlx5_fs_dr_table		fs_dr_table;
		struct mlx5_fs_hws_table	fs_hws_table;
	};
	u32				id;
	u16				vport;
	unsigned int			max_fte;
@@ -247,7 +254,10 @@ struct fs_fte_dup {
/* Type of children is mlx5_flow_rule */
struct fs_fte {
	struct fs_node			node;
	union {
		struct mlx5_fs_dr_rule		fs_dr_rule;
		struct mlx5_fs_hws_rule		fs_hws_rule;
	};
	u32				val[MLX5_ST_SZ_DW_MATCH_PARAM];
	struct fs_fte_action		act_dests;
	struct fs_fte_dup		*dup;
@@ -280,7 +290,10 @@ struct mlx5_flow_group_mask {
/* Type of children is fs_fte */
struct mlx5_flow_group {
	struct fs_node			node;
	union {
		struct mlx5_fs_dr_matcher	fs_dr_matcher;
		struct mlx5_fs_hws_matcher	fs_hws_matcher;
	};
	struct mlx5_flow_group_mask	mask;
	u32				start_index;
	u32				max_ftes;
@@ -293,7 +306,10 @@ struct mlx5_flow_group {
struct mlx5_flow_root_namespace {
	struct mlx5_flow_namespace	ns;
	enum   mlx5_flow_steering_mode	mode;
	union {
		struct mlx5_fs_dr_domain	fs_dr_domain;
		struct mlx5_fs_hws_context	fs_hws_context;
	};
	enum   fs_flow_table_type	table_type;
	struct mlx5_core_dev		*dev;
	struct mlx5_flow_table		*root_ft;
@@ -303,6 +319,42 @@ struct mlx5_flow_root_namespace {
	const struct mlx5_flow_cmds	*cmds;
};

enum mlx5_fc_type {
	MLX5_FC_TYPE_ACQUIRED = 0,
	MLX5_FC_TYPE_LOCAL,
};

struct mlx5_fc_cache {
	u64 packets;
	u64 bytes;
	u64 lastuse;
};

struct mlx5_fc {
	u32 id;
	bool aging;
	enum mlx5_fc_type type;
	struct mlx5_fc_bulk *bulk;
	struct mlx5_fc_cache cache;
	/* last{packets,bytes} are used for calculating deltas since last reading. */
	u64 lastpackets;
	u64 lastbytes;
};

struct mlx5_fc_bulk_hws_data {
	struct mlx5hws_action *hws_action;
	struct mutex lock; /* protects hws_action */
	refcount_t hws_action_refcount;
};

struct mlx5_fc_bulk {
	struct mlx5_fs_bulk fs_bulk;
	u32 base_id;
	struct mlx5_fc_bulk_hws_data hws_data;
	struct mlx5_fc fcs[];
};

u32 mlx5_fc_get_base_id(struct mlx5_fc *counter);
int mlx5_init_fc_stats(struct mlx5_core_dev *dev);
void mlx5_cleanup_fc_stats(struct mlx5_core_dev *dev);
void mlx5_fc_queue_stats_work(struct mlx5_core_dev *dev,
+11 −31
Original line number Diff line number Diff line
@@ -44,28 +44,6 @@
#define MLX5_FC_POOL_MAX_THRESHOLD BIT(18)
#define MLX5_FC_POOL_USED_BUFF_RATIO 10

enum mlx5_fc_type {
	MLX5_FC_TYPE_ACQUIRED = 0,
	MLX5_FC_TYPE_LOCAL,
};

struct mlx5_fc_cache {
	u64 packets;
	u64 bytes;
	u64 lastuse;
};

struct mlx5_fc {
	u32 id;
	bool aging;
	enum mlx5_fc_type type;
	struct mlx5_fc_bulk *bulk;
	struct mlx5_fc_cache cache;
	/* last{packets,bytes} are used for calculating deltas since last reading. */
	u64 lastpackets;
	u64 lastbytes;
};

struct mlx5_fc_stats {
	struct xarray counters;

@@ -434,13 +412,7 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev,
					    fc_stats->sampling_interval);
}

/* Flow counter bluks */

struct mlx5_fc_bulk {
	struct mlx5_fs_bulk fs_bulk;
	u32 base_id;
	struct mlx5_fc fcs[];
};
/* Flow counter bulks */

static void mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk,
			 u32 id)
@@ -449,7 +421,13 @@ static void mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk,
	counter->id = id;
}

static struct mlx5_fs_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
u32 mlx5_fc_get_base_id(struct mlx5_fc *counter)
{
	return counter->bulk->base_id;
}

static struct mlx5_fs_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev,
						void *pool_ctx)
{
	enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask;
	struct mlx5_fc_bulk *fc_bulk;
@@ -473,6 +451,8 @@ static struct mlx5_fs_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
	for (i = 0; i < bulk_len; i++)
		mlx5_fc_init(&fc_bulk->fcs[i], fc_bulk, base_id + i);

	refcount_set(&fc_bulk->hws_data.hws_action_refcount, 0);
	mutex_init(&fc_bulk->hws_data.lock);
	return &fc_bulk->fs_bulk;

fs_bulk_cleanup:
@@ -518,7 +498,7 @@ static const struct mlx5_fs_pool_ops mlx5_fc_pool_ops = {
static void
mlx5_fc_pool_init(struct mlx5_fs_pool *fc_pool, struct mlx5_core_dev *dev)
{
	mlx5_fs_pool_init(fc_pool, dev, &mlx5_fc_pool_ops);
	mlx5_fs_pool_init(fc_pool, dev, &mlx5_fc_pool_ops, NULL);
}

static void mlx5_fc_pool_cleanup(struct mlx5_fs_pool *fc_pool)
Loading