octeon: add counters support for port and queue 93/40893/2
authorMonendra Singh Kushwaha <kmonendra@marvell.com>
Thu, 16 May 2024 08:45:40 +0000 (14:15 +0530)
committerDamjan Marion <dmarion@0xa5.net>
Mon, 10 Jun 2024 12:54:36 +0000 (12:54 +0000)
Type: feature

Change-Id: I5d52d78a93c7d0a12b9cee16fe7ebabdc2b19f0a
Signed-off-by: Monendra Singh Kushwaha <kmonendra@marvell.com>
src/plugins/dev_octeon/CMakeLists.txt
src/plugins/dev_octeon/counter.c [new file with mode: 0644]
src/plugins/dev_octeon/octeon.h
src/plugins/dev_octeon/port.c

index 0f6b32b..c6271ec 100644 (file)
@@ -35,6 +35,7 @@ add_vpp_plugin(dev_octeon
   rx_node.c
   tx_node.c
   flow.c
+  counter.c
 
   MULTIARCH_SOURCES
   rx_node.c
diff --git a/src/plugins/dev_octeon/counter.c b/src/plugins/dev_octeon/counter.c
new file mode 100644 (file)
index 0000000..5763237
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2024 Marvell.
+ * SPDX-License-Identifier: Apache-2.0
+ * https://spdx.org/licenses/Apache-2.0.html
+ */
+
+#include <vnet/vnet.h>
+#include <vnet/dev/dev.h>
+#include <vnet/dev/pci.h>
+#include <vnet/dev/counters.h>
+#include <dev_octeon/octeon.h>
+#include <dev_octeon/common.h>
+
+VLIB_REGISTER_LOG_CLASS (oct_log, static) = {
+  .class_name = "oct",
+  .subclass_name = "counters",
+};
+
+typedef enum
+{
+  OCT_PORT_CTR_RX_BYTES,
+  OCT_PORT_CTR_TX_BYTES,
+  OCT_PORT_CTR_RX_PACKETS,
+  OCT_PORT_CTR_TX_PACKETS,
+  OCT_PORT_CTR_RX_DROPS,
+  OCT_PORT_CTR_TX_DROPS,
+  OCT_PORT_CTR_RX_DROP_BYTES,
+  OCT_PORT_CTR_RX_UCAST,
+  OCT_PORT_CTR_TX_UCAST,
+  OCT_PORT_CTR_RX_MCAST,
+  OCT_PORT_CTR_TX_MCAST,
+  OCT_PORT_CTR_RX_BCAST,
+  OCT_PORT_CTR_TX_BCAST,
+  OCT_PORT_CTR_RX_FCS,
+  OCT_PORT_CTR_RX_ERR,
+  OCT_PORT_CTR_RX_DROP_MCAST,
+  OCT_PORT_CTR_RX_DROP_BCAST,
+  OCT_PORT_CTR_RX_DROP_L3_MCAST,
+  OCT_PORT_CTR_RX_DROP_L3_BCAST,
+} oct_port_counter_id_t;
+
+vnet_dev_counter_t oct_port_counters[] = {
+  VNET_DEV_CTR_RX_BYTES (OCT_PORT_CTR_RX_BYTES),
+  VNET_DEV_CTR_RX_PACKETS (OCT_PORT_CTR_RX_PACKETS),
+  VNET_DEV_CTR_RX_DROPS (OCT_PORT_CTR_RX_DROPS),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_RX_DROP_BYTES, RX, BYTES, "drop bytes"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_RX_UCAST, RX, PACKETS, "unicast"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_RX_MCAST, RX, PACKETS, "multicast"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_RX_BCAST, RX, PACKETS, "broadcast"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_RX_FCS, RX, PACKETS, "fcs"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_RX_ERR, RX, PACKETS, "error"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_RX_DROP_MCAST, RX, PACKETS,
+                      "drop multicast"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_RX_DROP_BCAST, RX, PACKETS,
+                      "drop broadcast"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_RX_DROP_L3_MCAST, RX, PACKETS,
+                      "drop L3 multicast"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_RX_DROP_L3_BCAST, RX, PACKETS,
+                      "drop L3 broadcast"),
+
+  VNET_DEV_CTR_TX_BYTES (OCT_PORT_CTR_TX_BYTES),
+  VNET_DEV_CTR_TX_PACKETS (OCT_PORT_CTR_TX_PACKETS),
+  VNET_DEV_CTR_TX_DROPS (OCT_PORT_CTR_TX_DROPS),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_TX_UCAST, TX, PACKETS, "unicast"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_TX_MCAST, TX, PACKETS, "multicast"),
+  VNET_DEV_CTR_VENDOR (OCT_PORT_CTR_TX_BCAST, TX, PACKETS, "broadcast"),
+};
+
+typedef enum
+{
+  OCT_RXQ_CTR_BYTES,
+  OCT_RXQ_CTR_PKTS,
+  OCT_RXQ_CTR_DROPS,
+  OCT_RXQ_CTR_DROP_BYTES,
+  OCT_RXQ_CTR_ERR,
+} oct_rxq_counter_id_t;
+
+vnet_dev_counter_t oct_rxq_counters[] = {
+  VNET_DEV_CTR_RX_BYTES (OCT_RXQ_CTR_BYTES),
+  VNET_DEV_CTR_RX_PACKETS (OCT_RXQ_CTR_PKTS),
+  VNET_DEV_CTR_RX_DROPS (OCT_RXQ_CTR_DROPS),
+  VNET_DEV_CTR_VENDOR (OCT_RXQ_CTR_DROP_BYTES, RX, BYTES, "drop bytes"),
+  VNET_DEV_CTR_VENDOR (OCT_RXQ_CTR_ERR, RX, PACKETS, "error"),
+};
+
+typedef enum
+{
+  OCT_TXQ_CTR_BYTES,
+  OCT_TXQ_CTR_PKTS,
+  OCT_TXQ_CTR_DROPS,
+  OCT_TXQ_CTR_DROP_BYTES,
+} oct_txq_counter_id_t;
+
+vnet_dev_counter_t oct_txq_counters[] = {
+  VNET_DEV_CTR_TX_BYTES (OCT_TXQ_CTR_BYTES),
+  VNET_DEV_CTR_TX_PACKETS (OCT_TXQ_CTR_PKTS),
+  VNET_DEV_CTR_TX_DROPS (OCT_TXQ_CTR_DROPS),
+  VNET_DEV_CTR_VENDOR (OCT_TXQ_CTR_DROP_BYTES, TX, BYTES, "drop bytes"),
+};
+
+static vnet_dev_rv_t
+oct_roc_err (vnet_dev_t *dev, int rv, char *fmt, ...)
+{
+  u8 *s = 0;
+  va_list va;
+
+  va_start (va, fmt);
+  s = va_format (s, fmt, &va);
+  va_end (va);
+
+  log_err (dev, "%v - ROC error %s (%d)", s, roc_error_msg_get (rv), rv);
+
+  vec_free (s);
+  return VNET_DEV_ERR_INTERNAL;
+}
+
+void
+oct_port_add_counters (vlib_main_t *vm, vnet_dev_port_t *port)
+{
+  vnet_dev_port_add_counters (vm, port, oct_port_counters,
+                             ARRAY_LEN (oct_port_counters));
+
+  foreach_vnet_dev_port_rx_queue (rxq, port)
+    {
+      vnet_dev_rx_queue_add_counters (vm, rxq, oct_rxq_counters,
+                                     ARRAY_LEN (oct_rxq_counters));
+    }
+
+  foreach_vnet_dev_port_tx_queue (txq, port)
+    {
+      vnet_dev_tx_queue_add_counters (vm, txq, oct_txq_counters,
+                                     ARRAY_LEN (oct_txq_counters));
+    }
+}
+
+vnet_dev_rv_t
+oct_port_get_stats (vlib_main_t *vm, vnet_dev_port_t *port)
+{
+  vnet_dev_t *dev = port->dev;
+  oct_device_t *cd = vnet_dev_get_data (dev);
+  struct roc_nix *nix = cd->nix;
+  int rrv;
+  struct roc_nix_stats stats;
+
+  if ((rrv = roc_nix_stats_get (nix, &stats)))
+    return oct_roc_err (dev, rrv, "roc_nix_stats_get() failed");
+
+  foreach_vnet_dev_counter (c, port->counter_main)
+    {
+      switch (c->user_data)
+       {
+       case OCT_PORT_CTR_RX_BYTES:
+         vnet_dev_counter_value_update (vm, c, stats.rx_octs);
+         break;
+       case OCT_PORT_CTR_TX_BYTES:
+         vnet_dev_counter_value_update (vm, c, stats.tx_octs);
+         break;
+       case OCT_PORT_CTR_RX_PACKETS:
+         vnet_dev_counter_value_update (
+           vm, c, stats.rx_ucast + stats.rx_bcast + stats.rx_mcast);
+         break;
+       case OCT_PORT_CTR_TX_PACKETS:
+         vnet_dev_counter_value_update (
+           vm, c, stats.tx_ucast + stats.tx_bcast + stats.tx_mcast);
+         break;
+       case OCT_PORT_CTR_RX_DROPS:
+         vnet_dev_counter_value_update (vm, c, stats.rx_drop);
+         break;
+       case OCT_PORT_CTR_TX_DROPS:
+         vnet_dev_counter_value_update (vm, c, stats.tx_drop);
+         break;
+       case OCT_PORT_CTR_RX_DROP_BYTES:
+         vnet_dev_counter_value_update (vm, c, stats.rx_drop_octs);
+         break;
+       case OCT_PORT_CTR_RX_UCAST:
+         vnet_dev_counter_value_update (vm, c, stats.rx_ucast);
+         break;
+       case OCT_PORT_CTR_TX_UCAST:
+         vnet_dev_counter_value_update (vm, c, stats.tx_ucast);
+         break;
+       case OCT_PORT_CTR_RX_MCAST:
+         vnet_dev_counter_value_update (vm, c, stats.rx_mcast);
+         break;
+       case OCT_PORT_CTR_TX_MCAST:
+         vnet_dev_counter_value_update (vm, c, stats.tx_mcast);
+         break;
+       case OCT_PORT_CTR_RX_BCAST:
+         vnet_dev_counter_value_update (vm, c, stats.rx_bcast);
+         break;
+       case OCT_PORT_CTR_TX_BCAST:
+         vnet_dev_counter_value_update (vm, c, stats.tx_bcast);
+         break;
+       case OCT_PORT_CTR_RX_FCS:
+         vnet_dev_counter_value_update (vm, c, stats.rx_fcs);
+         break;
+       case OCT_PORT_CTR_RX_ERR:
+         vnet_dev_counter_value_update (vm, c, stats.rx_err);
+         break;
+       case OCT_PORT_CTR_RX_DROP_MCAST:
+         vnet_dev_counter_value_update (vm, c, stats.rx_drop_mcast);
+         break;
+       case OCT_PORT_CTR_RX_DROP_BCAST:
+         vnet_dev_counter_value_update (vm, c, stats.rx_drop_bcast);
+         break;
+       case OCT_PORT_CTR_RX_DROP_L3_MCAST:
+         vnet_dev_counter_value_update (vm, c, stats.rx_drop_l3_mcast);
+         break;
+       case OCT_PORT_CTR_RX_DROP_L3_BCAST:
+         vnet_dev_counter_value_update (vm, c, stats.rx_drop_l3_bcast);
+         break;
+       default:
+         ASSERT (0);
+       }
+    }
+
+  return VNET_DEV_OK;
+}
+
+vnet_dev_rv_t
+oct_rxq_get_stats (vlib_main_t *vm, vnet_dev_port_t *port,
+                  vnet_dev_rx_queue_t *rxq)
+{
+  oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
+  struct roc_nix_stats_queue qstats;
+  vnet_dev_t *dev = port->dev;
+  oct_device_t *cd = vnet_dev_get_data (dev);
+  struct roc_nix *nix = cd->nix;
+  int rrv;
+
+  if ((rrv = roc_nix_stats_queue_get (nix, crq->rq.qid, 1, &qstats)))
+    return oct_roc_err (dev, rrv, "roc_nix_stats_queue_get() failed");
+
+  foreach_vnet_dev_counter (c, rxq->counter_main)
+    {
+      switch (c->user_data)
+       {
+       case OCT_RXQ_CTR_BYTES:
+         vnet_dev_counter_value_update (vm, c, qstats.rx_octs);
+         break;
+       case OCT_RXQ_CTR_PKTS:
+         vnet_dev_counter_value_update (vm, c, qstats.rx_pkts);
+         break;
+       case OCT_RXQ_CTR_DROPS:
+         vnet_dev_counter_value_update (vm, c, qstats.rx_drop_pkts);
+         break;
+       case OCT_RXQ_CTR_DROP_BYTES:
+         vnet_dev_counter_value_update (vm, c, qstats.rx_drop_octs);
+         break;
+       case OCT_RXQ_CTR_ERR:
+         vnet_dev_counter_value_update (vm, c, qstats.rx_error_pkts);
+         break;
+       default:
+         ASSERT (0);
+       }
+    }
+
+  return VNET_DEV_OK;
+}
+
+vnet_dev_rv_t
+oct_txq_get_stats (vlib_main_t *vm, vnet_dev_port_t *port,
+                  vnet_dev_tx_queue_t *txq)
+{
+  oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
+  struct roc_nix_stats_queue qstats;
+  vnet_dev_t *dev = port->dev;
+  oct_device_t *cd = vnet_dev_get_data (dev);
+  struct roc_nix *nix = cd->nix;
+  int rrv;
+
+  if ((rrv = roc_nix_stats_queue_get (nix, ctq->sq.qid, 0, &qstats)))
+    return oct_roc_err (dev, rrv, "roc_nix_stats_queue_get() failed");
+
+  foreach_vnet_dev_counter (c, txq->counter_main)
+    {
+      switch (c->user_data)
+       {
+       case OCT_TXQ_CTR_BYTES:
+         vnet_dev_counter_value_update (vm, c, qstats.tx_octs);
+         break;
+       case OCT_TXQ_CTR_PKTS:
+         vnet_dev_counter_value_update (vm, c, qstats.tx_pkts);
+         break;
+       case OCT_TXQ_CTR_DROPS:
+         vnet_dev_counter_value_update (vm, c, qstats.tx_drop_pkts);
+         break;
+       case OCT_TXQ_CTR_DROP_BYTES:
+         vnet_dev_counter_value_update (vm, c, qstats.tx_drop_octs);
+         break;
+       default:
+         ASSERT (0);
+       }
+    }
+
+  return VNET_DEV_OK;
+}
index e43cde0..c02b66e 100644 (file)
@@ -141,6 +141,14 @@ vnet_dev_rv_t oct_flow_validate_params (vlib_main_t *, vnet_dev_port_t *,
 vnet_dev_rv_t oct_flow_query (vlib_main_t *, vnet_dev_port_t *, u32, uword,
                              u64 *);
 
+/* counter.c */
+void oct_port_add_counters (vlib_main_t *, vnet_dev_port_t *);
+vnet_dev_rv_t oct_port_get_stats (vlib_main_t *, vnet_dev_port_t *);
+vnet_dev_rv_t oct_rxq_get_stats (vlib_main_t *, vnet_dev_port_t *,
+                                vnet_dev_rx_queue_t *);
+vnet_dev_rv_t oct_txq_get_stats (vlib_main_t *, vnet_dev_port_t *,
+                                vnet_dev_tx_queue_t *);
+
 #define log_debug(dev, f, ...)                                                \
   vlib_log (VLIB_LOG_LEVEL_DEBUG, oct_log.class, "%U: " f,                    \
            format_vnet_dev_addr, (dev), ##__VA_ARGS__)
index 0bbada8..a53fa25 100644 (file)
@@ -124,6 +124,8 @@ oct_port_init (vlib_main_t *vm, vnet_dev_port_t *port)
          return rv;
        }
 
+  oct_port_add_counters (vm, port);
+
   return VNET_DEV_OK;
 }
 
@@ -172,6 +174,21 @@ oct_port_poll (vlib_main_t *vm, vnet_dev_port_t *port)
   vnet_dev_port_state_changes_t changes = {};
   int rrv;
 
+  if (oct_port_get_stats (vm, port))
+    return;
+
+  foreach_vnet_dev_port_rx_queue (q, port)
+    {
+      if (oct_rxq_get_stats (vm, port, q))
+       return;
+    }
+
+  foreach_vnet_dev_port_tx_queue (q, port)
+    {
+      if (oct_txq_get_stats (vm, port, q))
+       return;
+    }
+
   if (roc_nix_is_lbk (nix))
     {
       link_info.status = 1;