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: Chris Mi <cmi@nvidia.com> Reviewed-by: Oz Shlomo <ozsh@nvidia.com> Reviewed-by: Mark Bloch <mbloch@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
This commit is contained in:
parent
41c2fd9498
commit
2a9ab10a56
@ -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);
|
||||
}
|
||||
|
||||
|
96
drivers/net/ethernet/mellanox/mlx5/core/esw/sample.c
Normal file
96
drivers/net/ethernet/mellanox/mlx5/core/esw/sample.c
Normal file
@ -0,0 +1,96 @@
|
||||
// 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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user