On 10/18/2022 4:12 AM, Eli Cohen wrote:
For each interface, either VLAN tagged or untagged, add two hardware
counters: one for unicast and another for multicast. The counters count
RX packets and bytes and can be read through debugfs:

$ cat /sys/kernel/debug/mlx5/mlx5_core.sf.1/vdpa-0/rx/untagged/mcast/packets
$ cat /sys/kernel/debug/mlx5/mlx5_core.sf.1/vdpa-0/rx/untagged/ucast/bytes

This feature is controlled via the config option
MLX5_VDPA_STEERING_DEBUG. It is off by default as it may have some
impact on performance.

Signed-off-by: Eli Cohen<[email protected]>
---
  drivers/vdpa/Kconfig              | 12 ++++
  drivers/vdpa/mlx5/net/debug.c     | 82 +++++++++++++++++++++++++++
  drivers/vdpa/mlx5/net/mlx5_vnet.c | 94 +++++++++++++++++++++++--------
  drivers/vdpa/mlx5/net/mlx5_vnet.h | 30 ++++++++++
  4 files changed, 195 insertions(+), 23 deletions(-)

diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig
index 50f45d037611..43b716ec2d18 100644
--- a/drivers/vdpa/Kconfig
+++ b/drivers/vdpa/Kconfig
@@ -71,6 +71,18 @@ config MLX5_VDPA_NET
          be executed by the hardware. It also supports a variety of stateless
          offloads depending on the actual device used and firmware version.
+config MLX5_VDPA_STEERING_DEBUG
+       bool "expose steering counters on debugfs"
+       select MLX5_VDPA
+       help
+         Expose RX steering counters in debugfs to aid in debugging. For each 
VLAN
+         or non VLAN interface, two hardware counters are added to the RX flow
+         table: one for unicast and one for multicast.
+         The counters counts the number of packets and bytes and exposes them 
in
+         debugfs. Once can read the counters using, e.g.:
+         cat 
/sys/kernel/debug/mlx5/mlx5_core.sf.1/vdpa-0/rx/untagged/ucast/packets
+         cat 
/sys/kernel/debug/mlx5/mlx5_core.sf.1/vdpa-0/rx/untagged/mcast/bytes
+
  config VP_VDPA
        tristate "Virtio PCI bridge vDPA driver"
        select VIRTIO_PCI_LIB
diff --git a/drivers/vdpa/mlx5/net/debug.c b/drivers/vdpa/mlx5/net/debug.c
index 95e4801df211..35137a36433a 100644
--- a/drivers/vdpa/mlx5/net/debug.c
+++ b/drivers/vdpa/mlx5/net/debug.c
@@ -49,6 +49,88 @@ void mlx5_vdpa_add_rx_flow_table(struct mlx5_vdpa_net *ndev)
                                                  ndev, &rx_flow_table_fops);
  }
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
+static int packets_show(struct seq_file *file, void *priv)
+{
+       struct mlx5_vdpa_counter *counter = file->private;
+       u64 packets;
+       u64 bytes;
+       int err;
+
+       err = mlx5_fc_query(counter->mdev, counter->counter, &packets, &bytes);
+       if (err)
+               return err;
+
+       seq_printf(file, "0x%llx\n", packets);
+       return 0;
+}
+
+static int bytes_show(struct seq_file *file, void *priv)
+{
+       struct mlx5_vdpa_counter *counter = file->private;
+       u64 packets;
+       u64 bytes;
+       int err;
+
+       err = mlx5_fc_query(counter->mdev, counter->counter, &packets, &bytes);
+       if (err)
+               return err;
+
+       seq_printf(file, "0x%llx\n", bytes);
+       return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(packets);
+DEFINE_SHOW_ATTRIBUTE(bytes);
+
+static void add_counter_node(struct mlx5_vdpa_counter *counter,
+                            struct dentry *parent)
+{
+       debugfs_create_file("packets", 0444, parent, counter,
+                           &packets_fops);
+       debugfs_create_file("bytes", 0444, parent, counter,
+                           &bytes_fops);
+}
+
+void mlx5_vdpa_add_rx_counters(struct mlx5_vdpa_net *ndev,
+                              struct macvlan_node *node)
+{
+       static const char *ut = "untagged";
+       char vidstr[9];
+       u16 vid;
+
+       if (node->tagged) {
+               vid = key2vid(node->macvlan);
+               snprintf(vidstr, sizeof(vidstr), "0x%x", vid);
+       } else {
+               strcpy(vidstr, ut);
+       }
+
+       node->dent = debugfs_create_dir(vidstr, ndev->rx_dent);
+       if (IS_ERR(node->dent))
+               return;
+
+       node->ucast_counter.dent = debugfs_create_dir("ucast", node->dent);
+       if (IS_ERR(node->ucast_counter.dent))
+               return;
+
+       add_counter_node(&node->ucast_counter, node->ucast_counter.dent);
+
+       node->mcast_counter.dent = debugfs_create_dir("mcast", node->dent);
+       if (IS_ERR(node->mcast_counter.dent))
+               return;
+
+       add_counter_node(&node->mcast_counter, node->mcast_counter.dent);
+}
+
+void mlx5_vdpa_remove_rx_counters(struct mlx5_vdpa_net *ndev,
+                                 struct macvlan_node *node)
+{
+       if (ndev->debugfs)
+               debugfs_remove_recursive(node->dent);
+}
+#endif
+
  void mlx5_vdpa_add_debugfs(struct mlx5_vdpa_net *ndev)
  {
        struct mlx5_core_dev *mdev;
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c 
b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index ee50da33e25b..1b850d0aee99 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -1404,12 +1404,16 @@ static void destroy_tir(struct mlx5_vdpa_net *ndev)
  #define MAX_STEERING_ENT 0x8000
  #define MAX_STEERING_GROUPS 2
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
+       #define NUM_DESTS 2
+#else
+       #define NUM_DESTS 1
+#endif
+
  static int mlx5_vdpa_add_mac_vlan_rules(struct mlx5_vdpa_net *ndev, u8 *mac,
-                                       u16 vid, bool tagged,
-                                       struct mlx5_flow_handle **ucast,
-                                       struct mlx5_flow_handle **mcast)
+                                       struct macvlan_node *node)
  {
-       struct mlx5_flow_destination dest = {};
+       struct mlx5_flow_destination dests[NUM_DESTS] = {};
        struct mlx5_flow_act flow_act = {};
        struct mlx5_flow_handle *rule;
        struct mlx5_flow_spec *spec;
@@ -1418,11 +1422,13 @@ static int mlx5_vdpa_add_mac_vlan_rules(struct 
mlx5_vdpa_net *ndev, u8 *mac,
        u8 *dmac_c;
        u8 *dmac_v;
        int err;
+       u16 vid;
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
        if (!spec)
                return -ENOMEM;
+ vid = key2vid(node->macvlan);
        spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
        headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 
outer_headers);
        headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, 
outer_headers);
@@ -1431,45 +1437,78 @@ static int mlx5_vdpa_add_mac_vlan_rules(struct 
mlx5_vdpa_net *ndev, u8 *mac,
        eth_broadcast_addr(dmac_c);
        ether_addr_copy(dmac_v, mac);
        MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1);
-       if (tagged) {
+       if (node->tagged) {
                MLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag, 1);
                MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, first_vid);
                MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, vid);
        }
        flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
-       dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
-       dest.tir_num = ndev->res.tirn;
-       rule = mlx5_add_flow_rules(ndev->rxft, spec, &flow_act, &dest, 1);
+       dests[0].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
+       dests[0].tir_num = ndev->res.tirn;
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
+       node->ucast_counter.counter = mlx5_fc_create(ndev->mvdev.mdev, false);
+       if (IS_ERR(node->ucast_counter.counter)) {
+               err = PTR_ERR(node->ucast_counter.counter);
+               goto err_ucast_counter;
+       }
+       node->mcast_counter.counter = mlx5_fc_create(ndev->mvdev.mdev, false);
+       if (IS_ERR(node->mcast_counter.counter)) {
+               err = PTR_ERR(node->mcast_counter.counter);
+               goto err_mcast_counter;
+       }
+
+       dests[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+       dests[1].counter_id = mlx5_fc_id(node->ucast_counter.counter);
+       flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
+#endif
+       node->ucast_rule = mlx5_add_flow_rules(ndev->rxft, spec, &flow_act, 
dests, NUM_DESTS);
        if (IS_ERR(rule))
                return PTR_ERR(rule);
There'll be leakage on counters and flow spec if using direct return.

- *ucast = rule;
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
+       dests[1].counter_id = mlx5_fc_id(node->mcast_counter.counter);
+#endif
memset(dmac_c, 0, ETH_ALEN);
        memset(dmac_v, 0, ETH_ALEN);
        dmac_c[0] = 1;
        dmac_v[0] = 1;
-       rule = mlx5_add_flow_rules(ndev->rxft, spec, &flow_act, &dest, 1);
+       node->mcast_rule = mlx5_add_flow_rules(ndev->rxft, spec, &flow_act, 
dests, NUM_DESTS);
        kvfree(spec);
Move kvfree a couple of lines under (after the IS_ERR check).
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
                goto err_mcast;
        }
- *mcast = rule;
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
+       node->ucast_counter.mdev = ndev->mvdev.mdev;
+       node->mcast_counter.mdev = ndev->mvdev.mdev;
+#endif
+       mlx5_vdpa_add_rx_counters(ndev, node);
+
        return 0;
err_mcast:
-       mlx5_del_flow_rules(*ucast);
+       mlx5_del_flow_rules(node->ucast_rule);
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
No corresponding mlx5_fc_destroy() for mcast_counter.
+err_mcast_counter:
+       mlx5_fc_destroy(ndev->mvdev.mdev, node->ucast_counter.counter);
+err_ucast_counter:
+       kfree(spec);
kvfree?

Regards,
-Siwei
+#endif
        return err;
  }
static void mlx5_vdpa_del_mac_vlan_rules(struct mlx5_vdpa_net *ndev,
-                                        struct mlx5_flow_handle *ucast,
-                                        struct mlx5_flow_handle *mcast)
+                                        struct macvlan_node *node)
  {
-       mlx5_del_flow_rules(ucast);
-       mlx5_del_flow_rules(mcast);
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
+       if (node->dent && !IS_ERR(node->dent))
+               mlx5_vdpa_remove_rx_counters(ndev, node);
+#endif
+
+       mlx5_del_flow_rules(node->ucast_rule);
+       mlx5_del_flow_rules(node->mcast_rule);
  }
static u64 search_val(u8 *mac, u16 vlan, bool tagged)
@@ -1503,14 +1542,14 @@ static struct macvlan_node *mac_vlan_lookup(struct 
mlx5_vdpa_net *ndev, u64 valu
        return NULL;
  }
-static int mac_vlan_add(struct mlx5_vdpa_net *ndev, u8 *mac, u16 vlan, bool tagged) // vlan -> vid
+static int mac_vlan_add(struct mlx5_vdpa_net *ndev, u8 *mac, u16 vid, bool 
tagged)
  {
        struct macvlan_node *ptr;
        u64 val;
        u32 idx;
        int err;
- val = search_val(mac, vlan, tagged);
+       val = search_val(mac, vid, tagged);
        if (mac_vlan_lookup(ndev, val))
                return -EEXIST;
@@ -1518,12 +1557,13 @@ static int mac_vlan_add(struct mlx5_vdpa_net *ndev, u8 *mac, u16 vlan, bool tagg
        if (!ptr)
                return -ENOMEM;
- err = mlx5_vdpa_add_mac_vlan_rules(ndev, ndev->config.mac, vlan, tagged,
-                                          &ptr->ucast_rule, &ptr->mcast_rule);
+       ptr->tagged = tagged;
+       ptr->macvlan = val;
+       ptr->ndev = ndev;
+       err = mlx5_vdpa_add_mac_vlan_rules(ndev, ndev->config.mac, ptr);
        if (err)
                goto err_add;
- ptr->macvlan = val;
        idx = hash_64(val, 8);
        hlist_add_head(&ptr->hlist, &ndev->macvlan_hash[idx]);
        return 0;
@@ -1542,7 +1582,11 @@ static void mac_vlan_del(struct mlx5_vdpa_net *ndev, u8 
*mac, u16 vlan, bool tag
                return;
hlist_del(&ptr->hlist);
-       mlx5_vdpa_del_mac_vlan_rules(ndev, ptr->ucast_rule, ptr->mcast_rule);
+       mlx5_vdpa_del_mac_vlan_rules(ndev, ptr);
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
+                       mlx5_fc_destroy(ndev->mvdev.mdev, 
ptr->mcast_counter.counter);
+                       mlx5_fc_destroy(ndev->mvdev.mdev, 
ptr->ucast_counter.counter);
+#endif
        kfree(ptr);
  }
@@ -1555,7 +1599,11 @@ static void clear_mac_vlan_table(struct mlx5_vdpa_net *ndev)
        for (i = 0; i < MLX5V_MACVLAN_SIZE; i++) {
                hlist_for_each_entry_safe(pos, n, &ndev->macvlan_hash[i], 
hlist) {
                        hlist_del(&pos->hlist);
-                       mlx5_vdpa_del_mac_vlan_rules(ndev, pos->ucast_rule, 
pos->mcast_rule);
+                       mlx5_vdpa_del_mac_vlan_rules(ndev, pos);
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
+                       mlx5_fc_destroy(ndev->mvdev.mdev, 
pos->mcast_counter.counter);
+                       mlx5_fc_destroy(ndev->mvdev.mdev, 
pos->ucast_counter.counter);
+#endif
                        kfree(pos);
                }
        }
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.h 
b/drivers/vdpa/mlx5/net/mlx5_vnet.h
index f2cef3925e5b..706c83016b71 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.h
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.h
@@ -21,6 +21,11 @@ struct mlx5_vdpa_net_resources {
#define MLX5V_MACVLAN_SIZE 256 +static inline u16 key2vid(u64 key)
+{
+       return (u16)(key >> 48);
+}
+
  struct mlx5_vdpa_net {
        struct mlx5_vdpa_dev mvdev;
        struct mlx5_vdpa_net_resources res;
@@ -47,11 +52,24 @@ struct mlx5_vdpa_net {
        struct dentry *debugfs;
  };
+struct mlx5_vdpa_counter {
+       struct mlx5_fc *counter;
+       struct dentry *dent;
+       struct mlx5_core_dev *mdev;
+};
+
  struct macvlan_node {
        struct hlist_node hlist;
        struct mlx5_flow_handle *ucast_rule;
        struct mlx5_flow_handle *mcast_rule;
        u64 macvlan;
+       struct mlx5_vdpa_net *ndev;
+       bool tagged;
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
+       struct dentry *dent;
+       struct mlx5_vdpa_counter ucast_counter;
+       struct mlx5_vdpa_counter mcast_counter;
+#endif
  };
void mlx5_vdpa_add_debugfs(struct mlx5_vdpa_net *ndev);
@@ -60,5 +78,17 @@ void mlx5_vdpa_add_rx_flow_table(struct mlx5_vdpa_net *ndev);
  void mlx5_vdpa_remove_rx_flow_table(struct mlx5_vdpa_net *ndev);
  void mlx5_vdpa_add_tirn(struct mlx5_vdpa_net *ndev);
  void mlx5_vdpa_remove_tirn(struct mlx5_vdpa_net *ndev);
+#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
+void mlx5_vdpa_add_rx_counters(struct mlx5_vdpa_net *ndev,
+                              struct macvlan_node *node);
+void mlx5_vdpa_remove_rx_counters(struct mlx5_vdpa_net *ndev,
+                                 struct macvlan_node *node);
+#else
+static inline void mlx5_vdpa_add_rx_counters(struct mlx5_vdpa_net *ndev,
+                                            struct macvlan_node *node) {}
+static inline void mlx5_vdpa_remove_rx_counters(struct mlx5_vdpa_net *ndev,
+                                               struct macvlan_node *node) {}
+#endif
+
#endif /* __MLX5_VNET_H__ */
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

Reply via email to