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

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
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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);
}
......
// 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);
}
......@@ -4,10 +4,18 @@
#ifndef __MLX5_EN_TC_SAMPLE_H__
#define __MLX5_EN_TC_SAMPLE_H__
#include "en.h"
struct mlx5_sample_attr {
u32 group_num;
u32 rate;
u32 trunc_size;
};
struct mlx5_esw_psample *
mlx5_esw_sample_init(struct mlx5e_priv *priv);
void
mlx5_esw_sample_cleanup(struct mlx5_esw_psample *esw_psample);
#endif /* __MLX5_EN_TC_SAMPLE_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment