Commit 2a9ab10a authored by Chris Mi's avatar Chris Mi Committed by Saeed Mahameed
Browse files

net/mlx5e: TC, Add sampler termination table API



Sampled packets are sent to software using termination tables. There
is only one rule in that table that is to forward sampled packets to
the e-switch management vport.

Create a sampler termination table and rule for each eswitch.

Signed-off-by: default avatarChris Mi <cmi@nvidia.com>
Reviewed-by: default avatarOz Shlomo <ozsh@nvidia.com>
Reviewed-by: default avatarMark Bloch <mbloch@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent 41c2fd94
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -104,6 +104,18 @@ config MLX5_TC_CT

	  If unsure, set to Y

config MLX5_TC_SAMPLE
	bool "MLX5 TC sample offload support"
	depends on MLX5_CLS_ACT
	default y
	help
	  Say Y here if you want to support offloading sample rules via tc
	  sample action.
	  If set to N, will not be able to configure tc rules with sample
	  action.

	  If unsure, set to Y

config MLX5_CORE_EN_DCB
	bool "Data Center Bridging (DCB) Support"
	default y
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/acl/helper.o \
				      esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \
				      esw/acl/ingress_lgcy.o esw/acl/ingress_ofld.o \
				      esw/devlink_port.o esw/vporttbl.o
mlx5_core-$(CONFIG_MLX5_TC_SAMPLE) += esw/sample.o

mlx5_core-$(CONFIG_MLX5_MPFS)      += lib/mpfs.o
mlx5_core-$(CONFIG_VXLAN)          += lib/vxlan.o
+1 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ struct mlx5_rep_uplink_priv {
	struct mapping_ctx *tunnel_enc_opts_mapping;

	struct mlx5_tc_ct_priv *ct_priv;
	struct mlx5_esw_psample *esw_psample;

	/* support eswitch vports bonding */
	struct mlx5e_rep_bond *bond;
+11 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@
#include "en/mod_hdr.h"
#include "en/tc_priv.h"
#include "en/tc_tun_encap.h"
#include "esw/sample.h"
#include "lib/devcom.h"
#include "lib/geneve.h"
#include "lib/fs_chains.h"
@@ -4876,6 +4877,10 @@ int mlx5e_tc_esw_init(struct rhashtable *tc_ht)
					       &esw->offloads.mod_hdr,
					       MLX5_FLOW_NAMESPACE_FDB);

#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE)
	uplink_priv->esw_psample = mlx5_esw_sample_init(netdev_priv(priv->netdev));
#endif

	mapping = mapping_create(sizeof(struct tunnel_match_key),
				 TUNNEL_INFO_BITS_MASK, true);
	if (IS_ERR(mapping)) {
@@ -4913,6 +4918,9 @@ int mlx5e_tc_esw_init(struct rhashtable *tc_ht)
err_enc_opts_mapping:
	mapping_destroy(uplink_priv->tunnel_mapping);
err_tun_mapping:
#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE)
	mlx5_esw_sample_cleanup(uplink_priv->esw_psample);
#endif
	mlx5_tc_ct_clean(uplink_priv->ct_priv);
	netdev_warn(priv->netdev,
		    "Failed to initialize tc (eswitch), err: %d", err);
@@ -4931,6 +4939,9 @@ void mlx5e_tc_esw_cleanup(struct rhashtable *tc_ht)
	mapping_destroy(uplink_priv->tunnel_enc_opts_mapping);
	mapping_destroy(uplink_priv->tunnel_mapping);

#if IS_ENABLED(CONFIG_MLX5_TC_SAMPLE)
	mlx5_esw_sample_cleanup(uplink_priv->esw_psample);
#endif
	mlx5_tc_ct_clean(uplink_priv->ct_priv);
}

+96 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2021 Mellanox Technologies. */

#include "esw/sample.h"
#include "eswitch.h"

struct mlx5_esw_psample {
	struct mlx5e_priv *priv;
	struct mlx5_flow_table *termtbl;
	struct mlx5_flow_handle *termtbl_rule;
};

static int
sampler_termtbl_create(struct mlx5_esw_psample *esw_psample)
{
	struct mlx5_core_dev *dev = esw_psample->priv->mdev;
	struct mlx5_eswitch *esw = dev->priv.eswitch;
	struct mlx5_flow_table_attr ft_attr = {};
	struct mlx5_flow_destination dest = {};
	struct mlx5_flow_namespace *root_ns;
	struct mlx5_flow_act act = {};
	int err;

	if (!MLX5_CAP_ESW_FLOWTABLE_FDB(dev, termination_table))  {
		mlx5_core_warn(dev, "termination table is not supported\n");
		return -EOPNOTSUPP;
	}

	root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
	if (!root_ns) {
		mlx5_core_warn(dev, "failed to get FDB flow namespace\n");
		return -EOPNOTSUPP;
	}

	ft_attr.flags = MLX5_FLOW_TABLE_TERMINATION | MLX5_FLOW_TABLE_UNMANAGED;
	ft_attr.autogroup.max_num_groups = 1;
	ft_attr.prio = FDB_SLOW_PATH;
	ft_attr.max_fte = 1;
	ft_attr.level = 1;
	esw_psample->termtbl = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
	if (IS_ERR(esw_psample->termtbl)) {
		err = PTR_ERR(esw_psample->termtbl);
		mlx5_core_warn(dev, "failed to create termtbl, err: %d\n", err);
		return err;
	}

	act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
	dest.vport.num = esw->manager_vport;
	esw_psample->termtbl_rule = mlx5_add_flow_rules(esw_psample->termtbl, NULL, &act, &dest, 1);
	if (IS_ERR(esw_psample->termtbl_rule)) {
		err = PTR_ERR(esw_psample->termtbl_rule);
		mlx5_core_warn(dev, "failed to create termtbl rule, err: %d\n", err);
		mlx5_destroy_flow_table(esw_psample->termtbl);
		return err;
	}

	return 0;
}

static void
sampler_termtbl_destroy(struct mlx5_esw_psample *esw_psample)
{
	mlx5_del_flow_rules(esw_psample->termtbl_rule);
	mlx5_destroy_flow_table(esw_psample->termtbl);
}

struct mlx5_esw_psample *
mlx5_esw_sample_init(struct mlx5e_priv *priv)
{
	struct mlx5_esw_psample *esw_psample;
	int err;

	esw_psample = kzalloc(sizeof(*esw_psample), GFP_KERNEL);
	if (!esw_psample)
		return ERR_PTR(-ENOMEM);
	esw_psample->priv = priv;
	err = sampler_termtbl_create(esw_psample);
	if (err)
		goto err_termtbl;

	return esw_psample;

err_termtbl:
	kfree(esw_psample);
	return ERR_PTR(err);
}

void
mlx5_esw_sample_cleanup(struct mlx5_esw_psample *esw_psample)
{
	if (IS_ERR_OR_NULL(esw_psample))
		return;

	sampler_termtbl_destroy(esw_psample);
	kfree(esw_psample);
}
Loading