summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMonendra Singh Kushwaha <kmonendra@marvell.com>2024-05-16 14:15:40 +0530
committerDamjan Marion <dmarion@0xa5.net>2024-06-10 12:54:36 +0000
commitb26b2bcd43500f2cf8b988874c7e0feb29e99afa (patch)
treeadc90be2d35acf0bcca71f4da0b875b012c3ccfa
parentafd03ffff561b05ab5e9f4be8bfe5630283028ad (diff)
octeon: add counters support for port and queue
Type: feature Change-Id: I5d52d78a93c7d0a12b9cee16fe7ebabdc2b19f0a Signed-off-by: Monendra Singh Kushwaha <kmonendra@marvell.com>
-rw-r--r--src/plugins/dev_octeon/CMakeLists.txt1
-rw-r--r--src/plugins/dev_octeon/counter.c296
-rw-r--r--src/plugins/dev_octeon/octeon.h8
-rw-r--r--src/plugins/dev_octeon/port.c17
4 files changed, 322 insertions, 0 deletions
diff --git a/src/plugins/dev_octeon/CMakeLists.txt b/src/plugins/dev_octeon/CMakeLists.txt
index 0f6b32bbecd..c6271ecdfba 100644
--- a/src/plugins/dev_octeon/CMakeLists.txt
+++ b/src/plugins/dev_octeon/CMakeLists.txt
@@ -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
index 00000000000..5763237d105
--- /dev/null
+++ b/src/plugins/dev_octeon/counter.c
@@ -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;
+}
diff --git a/src/plugins/dev_octeon/octeon.h b/src/plugins/dev_octeon/octeon.h
index e43cde0a35f..c02b66e7cdb 100644
--- a/src/plugins/dev_octeon/octeon.h
+++ b/src/plugins/dev_octeon/octeon.h
@@ -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__)
diff --git a/src/plugins/dev_octeon/port.c b/src/plugins/dev_octeon/port.c
index 0bbada8ecc1..a53fa256884 100644
--- a/src/plugins/dev_octeon/port.c
+++ b/src/plugins/dev_octeon/port.c
@@ -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;