Commit 15b103df authored by Patrisious Haddad's avatar Patrisious Haddad Committed by Leon Romanovsky
Browse files

net/mlx5: fs, add RDMA TRANSPORT steering domain support



Add RX and TX RDMA_TRANSPORT flow table namespace, and the ability
to create flow tables in those namespaces.

The RDMA_TRANSPORT RX and TX are per vport.

Packets will traverse through RDMA_TRANSPORT_RX after RDMA_RX and through
RDMA_TRANSPORT_TX before RDMA_TX, ensuring proper control and management.

RDMA_TRANSPORT domains are managed by the vport group manager.

Signed-off-by: default avatarPatrisious Haddad <phaddad@nvidia.com>
Reviewed-by: default avatarMark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/a6b550d9859a197eafa804b9a8d76916ca481da9.1740574103.git.leon@kernel.org


Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
parent ab7d228c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ esw_acl_table_create(struct mlx5_eswitch *esw, struct mlx5_vport *vport, int ns,
	esw_debug(dev, "Create vport[%d] %s ACL table\n", vport_num,
		  ns == MLX5_FLOW_NAMESPACE_ESW_INGRESS ? "ingress" : "egress");

	root_ns = mlx5_get_flow_vport_acl_namespace(dev, ns, vport->index);
	root_ns = mlx5_get_flow_vport_namespace(dev, ns, vport->index);
	if (!root_ns) {
		esw_warn(dev, "Failed to get E-Switch root namespace for vport (%d)\n",
			 vport_num);
+3 −3
Original line number Diff line number Diff line
@@ -2828,7 +2828,7 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master,
	if (IS_ERR(vport))
		return PTR_ERR(vport);

	egress_ns = mlx5_get_flow_vport_acl_namespace(master,
	egress_ns = mlx5_get_flow_vport_namespace(master,
						  MLX5_FLOW_NAMESPACE_ESW_EGRESS,
						  vport->index);
	if (!egress_ns)
+2 −0
Original line number Diff line number Diff line
@@ -1142,6 +1142,8 @@ const struct mlx5_flow_cmds *mlx5_fs_cmd_get_default(enum fs_flow_table_type typ
	case FS_FT_RDMA_RX:
	case FS_FT_RDMA_TX:
	case FS_FT_PORT_SEL:
	case FS_FT_RDMA_TRANSPORT_RX:
	case FS_FT_RDMA_TRANSPORT_TX:
		return mlx5_fs_cmd_get_fw_cmds();
	default:
		return mlx5_fs_cmd_get_stub_cmds();
+166 −12
Original line number Diff line number Diff line
@@ -1456,7 +1456,7 @@ mlx5_create_auto_grouped_flow_table(struct mlx5_flow_namespace *ns,
	struct mlx5_flow_table *ft;
	int autogroups_max_fte;

	ft = mlx5_create_flow_table(ns, ft_attr);
	ft = mlx5_create_vport_flow_table(ns, ft_attr, ft_attr->vport);
	if (IS_ERR(ft))
		return ft;

@@ -2764,9 +2764,9 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
}
EXPORT_SYMBOL(mlx5_get_flow_namespace);

struct mlx5_flow_namespace *mlx5_get_flow_vport_acl_namespace(struct mlx5_core_dev *dev,
							      enum mlx5_flow_namespace_type type,
							      int vport)
struct mlx5_flow_namespace *
mlx5_get_flow_vport_namespace(struct mlx5_core_dev *dev,
			      enum mlx5_flow_namespace_type type, int vport_idx)
{
	struct mlx5_flow_steering *steering = dev->priv.steering;

@@ -2775,25 +2775,43 @@ struct mlx5_flow_namespace *mlx5_get_flow_vport_acl_namespace(struct mlx5_core_d

	switch (type) {
	case MLX5_FLOW_NAMESPACE_ESW_EGRESS:
		if (vport >= steering->esw_egress_acl_vports)
		if (vport_idx >= steering->esw_egress_acl_vports)
			return NULL;
		if (steering->esw_egress_root_ns &&
		    steering->esw_egress_root_ns[vport])
			return &steering->esw_egress_root_ns[vport]->ns;
		    steering->esw_egress_root_ns[vport_idx])
			return &steering->esw_egress_root_ns[vport_idx]->ns;
		else
			return NULL;
	case MLX5_FLOW_NAMESPACE_ESW_INGRESS:
		if (vport >= steering->esw_ingress_acl_vports)
		if (vport_idx >= steering->esw_ingress_acl_vports)
			return NULL;
		if (steering->esw_ingress_root_ns &&
		    steering->esw_ingress_root_ns[vport])
			return &steering->esw_ingress_root_ns[vport]->ns;
		    steering->esw_ingress_root_ns[vport_idx])
			return &steering->esw_ingress_root_ns[vport_idx]->ns;
		else
			return NULL;
	case MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX:
		if (vport_idx >= steering->rdma_transport_rx_vports)
			return NULL;
		if (steering->rdma_transport_rx_root_ns &&
		    steering->rdma_transport_rx_root_ns[vport_idx])
			return &steering->rdma_transport_rx_root_ns[vport_idx]->ns;
		else
			return NULL;
	case MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX:
		if (vport_idx >= steering->rdma_transport_tx_vports)
			return NULL;

		if (steering->rdma_transport_tx_root_ns &&
		    steering->rdma_transport_tx_root_ns[vport_idx])
			return &steering->rdma_transport_tx_root_ns[vport_idx]->ns;
		else
			return NULL;
	default:
		return NULL;
	}
}
EXPORT_SYMBOL(mlx5_get_flow_vport_namespace);

static struct fs_prio *_fs_create_prio(struct mlx5_flow_namespace *ns,
				       unsigned int prio,
@@ -3199,6 +3217,127 @@ static int init_rdma_tx_root_ns(struct mlx5_flow_steering *steering)
	return err;
}

static int
init_rdma_transport_rx_root_ns_one(struct mlx5_flow_steering *steering,
				   int vport_idx)
{
	struct fs_prio *prio;

	steering->rdma_transport_rx_root_ns[vport_idx] =
		create_root_ns(steering, FS_FT_RDMA_TRANSPORT_RX);
	if (!steering->rdma_transport_rx_root_ns[vport_idx])
		return -ENOMEM;

	/* create 1 prio*/
	prio = fs_create_prio(&steering->rdma_transport_rx_root_ns[vport_idx]->ns,
			      MLX5_RDMA_TRANSPORT_BYPASS_PRIO, 1);
	return PTR_ERR_OR_ZERO(prio);
}

static int
init_rdma_transport_tx_root_ns_one(struct mlx5_flow_steering *steering,
				   int vport_idx)
{
	struct fs_prio *prio;

	steering->rdma_transport_tx_root_ns[vport_idx] =
		create_root_ns(steering, FS_FT_RDMA_TRANSPORT_TX);
	if (!steering->rdma_transport_tx_root_ns[vport_idx])
		return -ENOMEM;

	/* create 1 prio*/
	prio = fs_create_prio(&steering->rdma_transport_tx_root_ns[vport_idx]->ns,
			      MLX5_RDMA_TRANSPORT_BYPASS_PRIO, 1);
	return PTR_ERR_OR_ZERO(prio);
}

static int init_rdma_transport_rx_root_ns(struct mlx5_flow_steering *steering)
{
	struct mlx5_core_dev *dev = steering->dev;
	int total_vports;
	int err;
	int i;

	/* In case eswitch not supported and working in legacy mode */
	total_vports = mlx5_eswitch_get_total_vports(dev) ?: 1;

	steering->rdma_transport_rx_root_ns =
			kcalloc(total_vports,
				sizeof(*steering->rdma_transport_rx_root_ns),
				GFP_KERNEL);
	if (!steering->rdma_transport_rx_root_ns)
		return -ENOMEM;

	for (i = 0; i < total_vports; i++) {
		err = init_rdma_transport_rx_root_ns_one(steering, i);
		if (err)
			goto cleanup_root_ns;
	}
	steering->rdma_transport_rx_vports = total_vports;
	return 0;

cleanup_root_ns:
	while (i--)
		cleanup_root_ns(steering->rdma_transport_rx_root_ns[i]);
	kfree(steering->rdma_transport_rx_root_ns);
	steering->rdma_transport_rx_root_ns = NULL;
	return err;
}

static int init_rdma_transport_tx_root_ns(struct mlx5_flow_steering *steering)
{
	struct mlx5_core_dev *dev = steering->dev;
	int total_vports;
	int err;
	int i;

	/* In case eswitch not supported and working in legacy mode */
	total_vports = mlx5_eswitch_get_total_vports(dev) ?: 1;

	steering->rdma_transport_tx_root_ns =
			kcalloc(total_vports,
				sizeof(*steering->rdma_transport_tx_root_ns),
				GFP_KERNEL);
	if (!steering->rdma_transport_tx_root_ns)
		return -ENOMEM;

	for (i = 0; i < total_vports; i++) {
		err = init_rdma_transport_tx_root_ns_one(steering, i);
		if (err)
			goto cleanup_root_ns;
	}
	steering->rdma_transport_tx_vports = total_vports;
	return 0;

cleanup_root_ns:
	while (i--)
		cleanup_root_ns(steering->rdma_transport_tx_root_ns[i]);
	kfree(steering->rdma_transport_tx_root_ns);
	steering->rdma_transport_tx_root_ns = NULL;
	return err;
}

static void cleanup_rdma_transport_roots_ns(struct mlx5_flow_steering *steering)
{
	int i;

	if (steering->rdma_transport_rx_root_ns) {
		for (i = 0; i < steering->rdma_transport_rx_vports; i++)
			cleanup_root_ns(steering->rdma_transport_rx_root_ns[i]);

		kfree(steering->rdma_transport_rx_root_ns);
		steering->rdma_transport_rx_root_ns = NULL;
	}

	if (steering->rdma_transport_tx_root_ns) {
		for (i = 0; i < steering->rdma_transport_tx_vports; i++)
			cleanup_root_ns(steering->rdma_transport_tx_root_ns[i]);

		kfree(steering->rdma_transport_tx_root_ns);
		steering->rdma_transport_tx_root_ns = NULL;
	}
}

/* FT and tc chains are stored in the same array so we can re-use the
 * mlx5_get_fdb_sub_ns() and tc api for FT chains.
 * When creating a new ns for each chain store it in the first available slot.
@@ -3631,6 +3770,7 @@ void mlx5_fs_core_cleanup(struct mlx5_core_dev *dev)
	cleanup_root_ns(steering->rdma_rx_root_ns);
	cleanup_root_ns(steering->rdma_tx_root_ns);
	cleanup_root_ns(steering->egress_root_ns);
	cleanup_rdma_transport_roots_ns(steering);

	devl_params_unregister(priv_to_devlink(dev), mlx5_fs_params,
			       ARRAY_SIZE(mlx5_fs_params));
@@ -3700,6 +3840,18 @@ int mlx5_fs_core_init(struct mlx5_core_dev *dev)
			goto err;
	}

	if (MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_RX(dev, ft_support)) {
		err = init_rdma_transport_rx_root_ns(steering);
		if (err)
			goto err;
	}

	if (MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_TX(dev, ft_support)) {
		err = init_rdma_transport_tx_root_ns(steering);
		if (err)
			goto err;
	}

	return 0;

err:
@@ -3850,8 +4002,10 @@ mlx5_get_root_namespace(struct mlx5_core_dev *dev, enum mlx5_flow_namespace_type
	struct mlx5_flow_namespace *ns;

	if (ns_type == MLX5_FLOW_NAMESPACE_ESW_EGRESS ||
	    ns_type == MLX5_FLOW_NAMESPACE_ESW_INGRESS)
		ns = mlx5_get_flow_vport_acl_namespace(dev, ns_type, 0);
	    ns_type == MLX5_FLOW_NAMESPACE_ESW_INGRESS ||
	    ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_TX ||
	    ns_type == MLX5_FLOW_NAMESPACE_RDMA_TRANSPORT_RX)
		ns = mlx5_get_flow_vport_namespace(dev, ns_type, 0);
	else
		ns = mlx5_get_flow_namespace(dev, ns_type);
	if (!ns)
+10 −2
Original line number Diff line number Diff line
@@ -115,7 +115,9 @@ enum fs_flow_table_type {
	FS_FT_PORT_SEL		= 0X9,
	FS_FT_FDB_RX		= 0xa,
	FS_FT_FDB_TX		= 0xb,
	FS_FT_MAX_TYPE = FS_FT_FDB_TX,
	FS_FT_RDMA_TRANSPORT_RX	= 0xd,
	FS_FT_RDMA_TRANSPORT_TX	= 0xe,
	FS_FT_MAX_TYPE = FS_FT_RDMA_TRANSPORT_TX,
};

enum fs_flow_table_op_mod {
@@ -158,6 +160,10 @@ struct mlx5_flow_steering {
	struct mlx5_flow_root_namespace	*port_sel_root_ns;
	int esw_egress_acl_vports;
	int esw_ingress_acl_vports;
	struct mlx5_flow_root_namespace **rdma_transport_rx_root_ns;
	struct mlx5_flow_root_namespace **rdma_transport_tx_root_ns;
	int rdma_transport_rx_vports;
	int rdma_transport_tx_vports;
};

struct fs_node {
@@ -434,7 +440,9 @@ struct mlx5_flow_root_namespace *find_root(struct fs_node *node);
	(type == FS_FT_PORT_SEL) ? MLX5_CAP_FLOWTABLE_PORT_SELECTION(mdev, cap) :      \
	(type == FS_FT_FDB_RX) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) :      \
	(type == FS_FT_FDB_TX) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) :      \
	(BUILD_BUG_ON_ZERO(FS_FT_FDB_TX != FS_FT_MAX_TYPE))\
	(type == FS_FT_RDMA_TRANSPORT_RX) ? MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_RX(mdev, cap) :      \
	(type == FS_FT_RDMA_TRANSPORT_TX) ? MLX5_CAP_FLOWTABLE_RDMA_TRANSPORT_TX(mdev, cap) :      \
	(BUILD_BUG_ON_ZERO(FS_FT_RDMA_TRANSPORT_TX != FS_FT_MAX_TYPE))\
	)

#endif
Loading