/* * Copyright (c) 2024 Marvell. * SPDX-License-Identifier: Apache-2.0 * https://spdx.org/licenses/Apache-2.0.html */ #include #include #include #include #include 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; } void oct_port_clear_counters (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; if ((rrv = roc_nix_stats_reset (nix))) oct_roc_err (dev, rrv, "roc_nix_stats_reset() failed"); } void oct_rxq_clear_counters (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq) { oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq); vnet_dev_t *dev = rxq->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_reset (nix, crq->rq.qid, 1))) oct_roc_err (dev, rrv, "roc_nix_stats_queue_reset() failed for rx queue %u", rxq->queue_id); } void oct_txq_clear_counters (vlib_main_t *vm, vnet_dev_tx_queue_t *txq) { oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq); vnet_dev_t *dev = txq->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_reset (nix, ctq->sq.qid, 0))) oct_roc_err (dev, rrv, "roc_nix_stats_queue_reset() failed for tx queue %u", txq->queue_id); }