From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-we0-f170.google.com (mail-we0-f170.google.com [74.125.82.170]) by dpdk.org (Postfix) with ESMTP id 2000C594D for ; Wed, 23 Jul 2014 14:27:39 +0200 (CEST) Received: by mail-we0-f170.google.com with SMTP id w62so1128679wes.1 for ; Wed, 23 Jul 2014 05:29:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=79IrNNyjuq0/r28B6bjGdCnDAETKlHZT1RREyRL7sVY=; b=RvvsWQ+oG6gl3SuvyY+jn3dRvg7GiIqjJ3Gzq/v4liWbW/1bNfAW2hBb3z4JfHyvV9 ZOCLMS27guFIcrpexaYL4BH1hWln3TuqQP3T2soUnsGmtGMZ1vVaU7XIh3AAQhbIrSKn 07Qextr5njckSznnW4WHmVLwG6v8Qeq3AgdWibWkTHf7W2H366lxsii+euSJuzegGzhG D28mOma8Sln0deaqmR5rb5SSmJOpUzQJCr1AuvZmY/0q+ve+ND3cLv0hBFQ1MRcfbgp/ URqsARTljVQ+wpPcLnlCMRvbx2fnnwopNui5aargm1//HTE4XRlSkLb3GZpNREbXBMpI ThKw== X-Gm-Message-State: ALoCoQmKKMUOJmKEm+ZGc+v8IJMF49QJ+O13z40MFOvwBZ4n8Zl8KTLfKEj7RZ3f1GzT5PoKzdXm X-Received: by 10.194.87.134 with SMTP id ay6mr1443385wjb.84.1406118541613; Wed, 23 Jul 2014 05:29:01 -0700 (PDT) Received: from glumotte.dev.6wind.com (guy78-3-82-239-227-177.fbx.proxad.net. [82.239.227.177]) by mx.google.com with ESMTPSA id ch5sm5882484wjb.18.2014.07.23.05.29.00 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 23 Jul 2014 05:29:01 -0700 (PDT) From: Olivier Matz To: dev@dpdk.org Date: Wed, 23 Jul 2014 14:28:53 +0200 Message-Id: <1406118534-6169-2-git-send-email-olivier.matz@6wind.com> X-Mailer: git-send-email 2.0.1 In-Reply-To: <1406118534-6169-1-git-send-email-olivier.matz@6wind.com> References: <1406118534-6169-1-git-send-email-olivier.matz@6wind.com> Subject: [dpdk-dev] [PATCH 1/2] ethdev: add a new rte_eth_xstats_get method to retrieve extended statistics X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Jul 2014 12:27:39 -0000 This method can be implemented by a poll mode driver to provide non-standard statistics (which are not part of the generic statistics structure). Each statistic is returned in a generic form: "name" and "value" and can be used to dump PMD-specific statistics in the same way than ethtool in linux kernel. If the PMD does not provide the xstats_get and xstats_set functions, the ethdev API will return the generic statistics in the xstats format (name, value). This commit opens the door for a clean-up of the generic statistics structure, only keeping statistics that are really common to all PMDs and moving specific ones into the xstats API. Reviewed-by: David Marchand Signed-off-by: Olivier Matz --- lib/librte_ether/rte_ethdev.c | 137 ++++++++++++++++++++++++++++++++++++++++++ lib/librte_ether/rte_ethdev.h | 60 +++++++++++++++++- 2 files changed, 195 insertions(+), 2 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index fd1010a..b71b679 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -114,6 +114,48 @@ static uint8_t nb_ports = 0; /* spinlock for eth device callbacks */ static rte_spinlock_t rte_eth_dev_cb_lock = RTE_SPINLOCK_INITIALIZER; +/* store statistics names and its offset in stats structure */ +struct rte_eth_xstats_name_off { + char name[RTE_ETH_XSTATS_NAME_SIZE]; + unsigned offset; +}; + +static struct rte_eth_xstats_name_off rte_stats_strings[] = { + {"rx_packets", offsetof(struct rte_eth_stats, ipackets)}, + {"tx_packets", offsetof(struct rte_eth_stats, opackets)}, + {"rx_bytes", offsetof(struct rte_eth_stats, ibytes)}, + {"tx_bytes", offsetof(struct rte_eth_stats, obytes)}, + {"tx_errors", offsetof(struct rte_eth_stats, oerrors)}, + {"rx_missed_errors", offsetof(struct rte_eth_stats, imissed)}, + {"rx_crc_errors", offsetof(struct rte_eth_stats, ibadcrc)}, + {"rx_bad_length_errors", offsetof(struct rte_eth_stats, ibadlen)}, + {"rx_errors", offsetof(struct rte_eth_stats, ierrors)}, + {"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)}, + {"fdir_match", offsetof(struct rte_eth_stats, fdirmatch)}, + {"fdir_miss", offsetof(struct rte_eth_stats, fdirmiss)}, + {"tx_flow_control_xon", offsetof(struct rte_eth_stats, tx_pause_xon)}, + {"rx_flow_control_xon", offsetof(struct rte_eth_stats, rx_pause_xon)}, + {"tx_flow_control_xoff", offsetof(struct rte_eth_stats, tx_pause_xoff)}, + {"rx_flow_control_xoff", offsetof(struct rte_eth_stats, rx_pause_xoff)}, +}; +#define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0])) + +static struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = { + {"rx_packets", offsetof(struct rte_eth_stats, q_ipackets)}, + {"rx_bytes", offsetof(struct rte_eth_stats, q_ibytes)}, +}; +#define RTE_NB_RXQ_STATS (sizeof(rte_rxq_stats_strings) / \ + sizeof(rte_rxq_stats_strings[0])) + +static struct rte_eth_xstats_name_off rte_txq_stats_strings[] = { + {"tx_packets", offsetof(struct rte_eth_stats, q_opackets)}, + {"tx_bytes", offsetof(struct rte_eth_stats, q_obytes)}, + {"tx_errors", offsetof(struct rte_eth_stats, q_errors)}, +}; +#define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) / \ + sizeof(rte_txq_stats_strings[0])) + + /** * The user application callback description. * @@ -1201,6 +1243,101 @@ rte_eth_stats_reset(uint8_t port_id) (*dev->dev_ops->stats_reset)(dev); } +/* retrieve ethdev extended statistics */ +int +rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, + unsigned n) +{ + struct rte_eth_stats eth_stats; + struct rte_eth_dev *dev; + unsigned count, i, q; + uint64_t val; + char *stats_ptr; + + if (port_id >= nb_ports) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return -1; + } + dev = &rte_eth_devices[port_id]; + + /* implemented by the driver */ + if (dev->dev_ops->xstats_get != NULL) + return (*dev->dev_ops->xstats_get)(dev, xstats, n); + + /* else, return generic statistics */ + count = RTE_NB_STATS; + count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS; + count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS; + if (n < count) + return count; + + /* now fill the xstats structure */ + + count = 0; + memset(ð_stats, 0, sizeof(eth_stats)); + rte_eth_stats_get(port_id, ð_stats); + + /* global stats */ + for (i = 0; i < RTE_NB_STATS; i++) { + stats_ptr = (char *)ð_stats + rte_stats_strings[i].offset; + val = *(uint64_t *)stats_ptr; + snprintf(xstats[count].name, sizeof(xstats[count].name), + "%s", rte_stats_strings[i].name); + xstats[count++].value = val; + } + + /* per-rxq stats */ + for (q = 0; q < dev->data->nb_rx_queues; q++) { + for (i = 0; i < RTE_NB_RXQ_STATS; i++) { + stats_ptr = (char *)ð_stats; + stats_ptr += rte_rxq_stats_strings[i].offset; + stats_ptr += q * sizeof(uint64_t); + val = *(uint64_t *)stats_ptr; + snprintf(xstats[count].name, sizeof(xstats[count].name), + "rx_queue_%u_%s", q, + rte_rxq_stats_strings[i].name); + xstats[count++].value = val; + } + } + + /* per-txq stats */ + for (q = 0; q < dev->data->nb_tx_queues; q++) { + for (i = 0; i < RTE_NB_TXQ_STATS; i++) { + stats_ptr = (char *)ð_stats; + stats_ptr += rte_txq_stats_strings[i].offset; + stats_ptr += q * sizeof(uint64_t); + val = *(uint64_t *)stats_ptr; + snprintf(xstats[count].name, sizeof(xstats[count].name), + "tx_queue_%u_%s", q, + rte_txq_stats_strings[i].name); + xstats[count++].value = val; + } + } + + return count; +} + +/* reset ethdev extended statistics */ +void +rte_eth_xstats_reset(uint8_t port_id) +{ + struct rte_eth_dev *dev; + + if (port_id >= nb_ports) { + PMD_DEBUG_TRACE("Invalid port_id=%d\n", port_id); + return; + } + dev = &rte_eth_devices[port_id]; + + /* implemented by the driver */ + if (dev->dev_ops->xstats_reset != NULL) { + (*dev->dev_ops->xstats_reset)(dev); + return; + } + + /* fallback to default */ + rte_eth_stats_reset(port_id); +} static int set_queue_stats_mapping(uint8_t port_id, uint16_t queue_id, uint8_t stat_idx, diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 50df654..4076c33 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -908,6 +908,21 @@ struct rte_eth_dev_info { uint32_t tx_offload_capa; /**< Device TX offload capabilities. */ }; +/** Maximum name length for a extended statitics counter */ +#define RTE_ETH_XSTATS_NAME_SIZE 64 + +/** + * An Ethernet device extended statistic structure + * + * This structure is used by ethdev->eth_xstats_get() to provide + * statistics that are not provided in the generic rte_eth_stats + * structure. + */ +struct rte_eth_xstats { + char name[RTE_ETH_XSTATS_NAME_SIZE]; + uint64_t value; +}; + struct rte_eth_dev; struct rte_eth_dev_callback; @@ -1028,6 +1043,13 @@ typedef void (*eth_stats_get_t)(struct rte_eth_dev *dev, typedef void (*eth_stats_reset_t)(struct rte_eth_dev *dev); /**< @internal Reset global I/O statistics of an Ethernet device to 0. */ +typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev, + struct rte_eth_xstats *stats, unsigned n); +/**< @internal Get extended stats of an Ethernet device. */ + +typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev); +/**< @internal Reset extended stats of an Ethernet device. */ + typedef int (*eth_queue_stats_mapping_set_t)(struct rte_eth_dev *dev, uint16_t queue_id, uint8_t stat_idx, @@ -1376,8 +1398,10 @@ struct eth_dev_ops { eth_allmulticast_enable_t allmulticast_enable;/**< RX multicast ON. */ eth_allmulticast_disable_t allmulticast_disable;/**< RX multicast OF. */ eth_link_update_t link_update; /**< Get device link state. */ - eth_stats_get_t stats_get; /**< Get device statistics. */ - eth_stats_reset_t stats_reset; /**< Reset device statistics. */ + eth_stats_get_t stats_get; /**< Get generic device statistics. */ + eth_stats_reset_t stats_reset; /**< Reset generic device statistics. */ + eth_xstats_get_t xstats_get; /**< Get extended device statistics. */ + eth_xstats_reset_t xstats_reset; /**< Reset extended device statistics. */ eth_queue_stats_mapping_set_t queue_stats_mapping_set; /**< Configure per queue stat counter mapping. */ eth_dev_infos_get_t dev_infos_get; /**< Get device info. */ @@ -2005,6 +2029,38 @@ extern void rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats); extern void rte_eth_stats_reset(uint8_t port_id); /** + * Retrieve extended statistics of an Ethernet device. + * + * @param port_id + * The port identifier of the Ethernet device. + * @param stats + * A pointer to a table of structure of type *rte_eth_xstats* + * to be filled with the values of device statistics names and value. + * This parameter can be set to NULL if n is 0. + * @param n + * The size of the stats table, which should be large enough to store + * all the statistics of the device. + * @return + * - positive value lower or equal to n: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than n: error, the given statistics table + * is too small. Thereturn value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + * - negative value on error (invalid port id) + */ +extern int rte_eth_xstats_get(uint8_t port_id, + struct rte_eth_xstats *xstats, unsigned n); + +/** + * Reset extended statistics of an Ethernet device. + * + * @param port_id + * The port identifier of the Ethernet device. + */ +extern void rte_eth_xstats_reset(uint8_t port_id); + +/** * Set a mapping for the specified transmit queue to the specified per-queue * statistics counter. * -- 2.0.1