net/mlx5e: TC, Add sampler termination table API
authorChris Mi <cmi@nvidia.com>
Fri, 18 Sep 2020 09:46:57 +0000 (17:46 +0800)
committerSaeed Mahameed <saeedm@nvidia.com>
Wed, 7 Apr 2021 04:36:03 +0000 (21:36 -0700)
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>
drivers/net/ethernet/mellanox/mlx5/core/Kconfig
drivers/net/ethernet/mellanox/mlx5/core/Makefile
drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/esw/sample.c [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx5/core/esw/sample.h

index 9d623e3..461a43f 100644 (file)
@@ -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
index 5bedc2c..8bde583 100644 (file)
@@ -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
index 931fa61..2258501 100644 (file)
@@ -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;
index 85782d1..1a40311 100644 (file)
@@ -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 @@ err_ht_init:
 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);
 }
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/sample.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/sample.c
new file mode 100644 (file)
index 0000000..9bd996e
--- /dev/null
@@ -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);
+}
index 35a5e6d..e42e3cb 100644 (file)
@@ -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__ */