get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/63692/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 63692,
    "url": "http://patches.dpdk.org/api/patches/63692/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20191209214656.27347-16-cardigliano@ntop.org/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20191209214656.27347-16-cardigliano@ntop.org>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20191209214656.27347-16-cardigliano@ntop.org",
    "date": "2019-12-09T21:46:54",
    "name": "[v3,15/17] net/ionic: add stats",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "bbc1e09b3a6e745908054c0825dece88f5758f67",
    "submitter": {
        "id": 1465,
        "url": "http://patches.dpdk.org/api/people/1465/?format=api",
        "name": "Alfredo Cardigliano",
        "email": "cardigliano@ntop.org"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20191209214656.27347-16-cardigliano@ntop.org/mbox/",
    "series": [
        {
            "id": 7760,
            "url": "http://patches.dpdk.org/api/series/7760/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=7760",
            "date": "2019-12-09T21:46:39",
            "name": "Introduces net/ionic PMD",
            "version": 3,
            "mbox": "http://patches.dpdk.org/series/7760/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/63692/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/63692/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id F3D65A04B3;\n\tMon,  9 Dec 2019 22:51:20 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id B71F81BFC9;\n\tMon,  9 Dec 2019 22:49:02 +0100 (CET)",
            "from mail.ntop.org (mail-digitalocean.ntop.org [167.99.215.164])\n by dpdk.org (Postfix) with ESMTP id 998241BDFD\n for <dev@dpdk.org>; Mon,  9 Dec 2019 22:48:35 +0100 (CET)",
            "from devele.ntop.org (net-93-145-196-230.cust.vodafonedsl.it\n [93.145.196.230])\n by mail.ntop.org (Postfix) with ESMTPSA id 4516641BAC;\n Mon,  9 Dec 2019 22:48:35 +0100 (CET)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ntop.org; s=mail;\n t=1575928115; bh=sVpnnUs3Cs7joLy1PZfW3ovYG8LtMkbf/aIG149lP/o=;\n h=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n b=toUkH6nUtWqXk9SBsokv7RDhqP/m2hj1nU977nebbjpD11qchgOS7bypU9ofFaO5b\n wcb+5GT9pheMhomQSPzGGP+ELd7XJsX+mrpl7qQNagktMwXyWgDhgoKOfHowXa0Uwm\n zl1Rhzohku+LbWS560Ket0nZS3+3piJ5YJo9xTO4=",
        "From": "Alfredo Cardigliano <cardigliano@ntop.org>",
        "To": "Alfredo Cardigliano <cardigliano@ntop.org>,\n John McNamara <john.mcnamara@intel.com>,\n Marko Kovacevic <marko.kovacevic@intel.com>",
        "Cc": "dev@dpdk.org",
        "Date": "Mon,  9 Dec 2019 22:46:54 +0100",
        "Message-Id": "<20191209214656.27347-16-cardigliano@ntop.org>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20191209214656.27347-1-cardigliano@ntop.org>",
        "References": "<20191209214656.27347-1-cardigliano@ntop.org>",
        "Subject": "[dpdk-dev] [PATCH v3 15/17] net/ionic: add stats",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Add basic, per queue and extended statistics for\nRX and TX, both from the adapter and the driver.\n\nSigned-off-by: Alfredo Cardigliano <cardigliano@ntop.org>\nReviewed-by: Shannon Nelson <snelson@pensando.io>\n---\n doc/guides/nics/features/ionic.ini |   3 +\n drivers/net/ionic/ionic_ethdev.c   | 253 +++++++++++++++++++++++++++++\n drivers/net/ionic/ionic_lif.c      | 148 +++++++++++++++++\n drivers/net/ionic/ionic_lif.h      |   9 +\n 4 files changed, 413 insertions(+)",
    "diff": "diff --git a/doc/guides/nics/features/ionic.ini b/doc/guides/nics/features/ionic.ini\nindex 83e0b5054..f4ec04c73 100644\n--- a/doc/guides/nics/features/ionic.ini\n+++ b/doc/guides/nics/features/ionic.ini\n@@ -27,6 +27,9 @@ VLAN offload         = Y\n L3 checksum offload  = Y\n L4 checksum offload  = Y\n Packet type parsing  = Y\n+Basic stats          = Y\n+Extended stats       = Y\n+Stats per queue      = Y\n Linux UIO            = Y\n Linux VFIO           = Y\n x86-64               = Y\ndiff --git a/drivers/net/ionic/ionic_ethdev.c b/drivers/net/ionic/ionic_ethdev.c\nindex 352890ef1..bf76aeae7 100644\n--- a/drivers/net/ionic/ionic_ethdev.c\n+++ b/drivers/net/ionic/ionic_ethdev.c\n@@ -43,6 +43,19 @@ static int  ionic_dev_rss_hash_conf_get(struct rte_eth_dev *eth_dev,\n \tstruct rte_eth_rss_conf *rss_conf);\n static int  ionic_dev_rss_hash_update(struct rte_eth_dev *eth_dev,\n \tstruct rte_eth_rss_conf *rss_conf);\n+static int  ionic_dev_stats_get(struct rte_eth_dev *eth_dev,\n+\tstruct rte_eth_stats *stats);\n+static int  ionic_dev_stats_reset(struct rte_eth_dev *eth_dev);\n+static int  ionic_dev_xstats_get(struct rte_eth_dev *dev,\n+\tstruct rte_eth_xstat *xstats, unsigned int n);\n+static int  ionic_dev_xstats_get_by_id(struct rte_eth_dev *dev,\n+\tconst uint64_t *ids, uint64_t *values, unsigned int n);\n+static int  ionic_dev_xstats_reset(struct rte_eth_dev *dev);\n+static int  ionic_dev_xstats_get_names(struct rte_eth_dev *dev,\n+\tstruct rte_eth_xstat_name *xstats_names, unsigned int size);\n+static int  ionic_dev_xstats_get_names_by_id(struct rte_eth_dev *dev,\n+\tstruct rte_eth_xstat_name *xstats_names, const uint64_t *ids,\n+\tunsigned int limit);\n \n int ionic_logtype_driver;\n \n@@ -102,6 +115,13 @@ static const struct eth_dev_ops ionic_eth_dev_ops = {\n \t.reta_query             = ionic_dev_rss_reta_query,\n \t.rss_hash_conf_get      = ionic_dev_rss_hash_conf_get,\n \t.rss_hash_update        = ionic_dev_rss_hash_update,\n+\t.stats_get              = ionic_dev_stats_get,\n+\t.stats_reset            = ionic_dev_stats_reset,\n+\t.xstats_get             = ionic_dev_xstats_get,\n+\t.xstats_get_by_id       = ionic_dev_xstats_get_by_id,\n+\t.xstats_reset           = ionic_dev_xstats_reset,\n+\t.xstats_get_names       = ionic_dev_xstats_get_names,\n+\t.xstats_get_names_by_id = ionic_dev_xstats_get_names_by_id,\n };\n \n /*\n@@ -112,6 +132,93 @@ static LIST_HEAD(ionic_pci_adapters_list, ionic_adapter) ionic_pci_adapters =\n \t\tLIST_HEAD_INITIALIZER(ionic_pci_adapters);\n static rte_spinlock_t ionic_pci_adapters_lock = RTE_SPINLOCK_INITIALIZER;\n \n+struct rte_ionic_xstats_name_off {\n+\tchar name[RTE_ETH_XSTATS_NAME_SIZE];\n+\tunsigned int offset;\n+};\n+\n+static const struct rte_ionic_xstats_name_off rte_ionic_xstats_strings[] = {\n+\t/* RX */\n+\t{\"rx_ucast_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_ucast_bytes)},\n+\t{\"rx_ucast_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_ucast_packets)},\n+\t{\"rx_mcast_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_mcast_bytes)},\n+\t{\"rx_mcast_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_mcast_packets)},\n+\t{\"rx_bcast_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_bcast_bytes)},\n+\t{\"rx_bcast_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_bcast_packets)},\n+\t/* RX drops */\n+\t{\"rx_ucast_drop_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_ucast_drop_bytes)},\n+\t{\"rx_ucast_drop_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_ucast_drop_packets)},\n+\t{\"rx_mcast_drop_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_mcast_drop_bytes)},\n+\t{\"rx_mcast_drop_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_mcast_drop_packets)},\n+\t{\"rx_bcast_drop_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_bcast_drop_bytes)},\n+\t{\"rx_bcast_drop_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_bcast_drop_packets)},\n+\t{\"rx_dma_error\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_dma_error)},\n+\t/* TX */\n+\t{\"tx_ucast_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_ucast_bytes)},\n+\t{\"tx_ucast_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_ucast_packets)},\n+\t{\"tx_mcast_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_mcast_bytes)},\n+\t{\"tx_mcast_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_mcast_packets)},\n+\t{\"tx_bcast_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_bcast_bytes)},\n+\t{\"tx_bcast_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_bcast_packets)},\n+\t/* TX drops */\n+\t{\"tx_ucast_drop_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_ucast_drop_bytes)},\n+\t{\"tx_ucast_drop_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_ucast_drop_packets)},\n+\t{\"tx_mcast_drop_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_mcast_drop_bytes)},\n+\t{\"tx_mcast_drop_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_mcast_drop_packets)},\n+\t{\"tx_bcast_drop_bytes\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_bcast_drop_bytes)},\n+\t{\"tx_bcast_drop_packets\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_bcast_drop_packets)},\n+\t{\"tx_dma_error\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_dma_error)},\n+\t/* Rx Queue/Ring drops */\n+\t{\"rx_queue_disabled\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_queue_disabled)},\n+\t{\"rx_queue_empty\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_queue_empty)},\n+\t{\"rx_queue_error\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_queue_error)},\n+\t{\"rx_desc_fetch_error\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_desc_fetch_error)},\n+\t{\"rx_desc_data_error\", offsetof(struct ionic_lif_stats,\n+\t\t\trx_desc_data_error)},\n+\t/* Tx Queue/Ring drops */\n+\t{\"tx_queue_disabled\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_queue_disabled)},\n+\t{\"tx_queue_error\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_queue_error)},\n+\t{\"tx_desc_fetch_error\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_desc_fetch_error)},\n+\t{\"tx_desc_data_error\", offsetof(struct ionic_lif_stats,\n+\t\t\ttx_desc_data_error)},\n+};\n+\n+#define IONIC_NB_HW_STATS (sizeof(rte_ionic_xstats_strings) / \\\n+\t\tsizeof(rte_ionic_xstats_strings[0]))\n+\n /*\n  * Set device link up, enable tx.\n  */\n@@ -586,6 +693,152 @@ ionic_dev_rss_hash_update(struct rte_eth_dev *eth_dev,\n \treturn 0;\n }\n \n+static int\n+ionic_dev_stats_get(struct rte_eth_dev *eth_dev,\n+\t\tstruct rte_eth_stats *stats)\n+{\n+\tstruct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);\n+\n+\tionic_lif_get_stats(lif, stats);\n+\n+\treturn 0;\n+}\n+\n+static int\n+ionic_dev_stats_reset(struct rte_eth_dev *eth_dev)\n+{\n+\tstruct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);\n+\n+\tIONIC_PRINT_CALL();\n+\n+\tionic_lif_reset_stats(lif);\n+\n+\treturn 0;\n+}\n+\n+static int\n+ionic_dev_xstats_get_names(__rte_unused struct rte_eth_dev *eth_dev,\n+\t\tstruct rte_eth_xstat_name *xstats_names,\n+\t\t__rte_unused unsigned int size)\n+{\n+\tunsigned int i;\n+\n+\tif (xstats_names != NULL) {\n+\t\tfor (i = 0; i < IONIC_NB_HW_STATS; i++) {\n+\t\t\tsnprintf(xstats_names[i].name,\n+\t\t\t\t\tsizeof(xstats_names[i].name),\n+\t\t\t\t\t\"%s\", rte_ionic_xstats_strings[i].name);\n+\t\t}\n+\t}\n+\n+\treturn IONIC_NB_HW_STATS;\n+}\n+\n+static int\n+ionic_dev_xstats_get_names_by_id(struct rte_eth_dev *eth_dev,\n+\t\tstruct rte_eth_xstat_name *xstats_names, const uint64_t *ids,\n+\t\tunsigned int limit)\n+{\n+\tstruct rte_eth_xstat_name xstats_names_copy[IONIC_NB_HW_STATS];\n+\tuint16_t i;\n+\n+\tif (!ids) {\n+\t\tif (xstats_names != NULL) {\n+\t\t\tfor (i = 0; i < IONIC_NB_HW_STATS; i++) {\n+\t\t\t\tsnprintf(xstats_names[i].name,\n+\t\t\t\t\tsizeof(xstats_names[i].name),\n+\t\t\t\t\t\"%s\", rte_ionic_xstats_strings[i].name);\n+\t\t\t}\n+\t\t}\n+\n+\t\treturn IONIC_NB_HW_STATS;\n+\t}\n+\n+\tionic_dev_xstats_get_names_by_id(eth_dev, xstats_names_copy, NULL,\n+\t\tIONIC_NB_HW_STATS);\n+\n+\tfor (i = 0; i < limit; i++) {\n+\t\tif (ids[i] >= IONIC_NB_HW_STATS) {\n+\t\t\tIONIC_PRINT(ERR, \"id value isn't valid\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tstrcpy(xstats_names[i].name, xstats_names_copy[ids[i]].name);\n+\t}\n+\n+\treturn limit;\n+}\n+\n+static int\n+ionic_dev_xstats_get(struct rte_eth_dev *eth_dev, struct rte_eth_xstat *xstats,\n+\t\tunsigned int n)\n+{\n+\tstruct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);\n+\tstruct ionic_lif_stats hw_stats;\n+\tuint16_t i;\n+\n+\tif (n < IONIC_NB_HW_STATS)\n+\t\treturn IONIC_NB_HW_STATS;\n+\n+\tionic_lif_get_hw_stats(lif, &hw_stats);\n+\n+\tfor (i = 0; i < IONIC_NB_HW_STATS; i++) {\n+\t\txstats[i].value = *(uint64_t *)(((char *)&hw_stats) +\n+\t\t\t\trte_ionic_xstats_strings[i].offset);\n+\t\txstats[i].id = i;\n+\t}\n+\n+\treturn IONIC_NB_HW_STATS;\n+}\n+\n+static int\n+ionic_dev_xstats_get_by_id(struct rte_eth_dev *eth_dev, const uint64_t *ids,\n+\t\tuint64_t *values, unsigned int n)\n+{\n+\tstruct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);\n+\tstruct ionic_lif_stats hw_stats;\n+\tuint64_t values_copy[IONIC_NB_HW_STATS];\n+\tuint16_t i;\n+\n+\tif (!ids) {\n+\t\tif (!ids && n < IONIC_NB_HW_STATS)\n+\t\t\treturn IONIC_NB_HW_STATS;\n+\n+\t\tionic_lif_get_hw_stats(lif, &hw_stats);\n+\n+\t\tfor (i = 0; i < IONIC_NB_HW_STATS; i++) {\n+\t\t\tvalues[i] = *(uint64_t *)(((char *)&hw_stats) +\n+\t\t\t\t\trte_ionic_xstats_strings[i].offset);\n+\t\t}\n+\n+\t\treturn IONIC_NB_HW_STATS;\n+\t}\n+\n+\tionic_dev_xstats_get_by_id(eth_dev, NULL, values_copy,\n+\t\t\tIONIC_NB_HW_STATS);\n+\n+\tfor (i = 0; i < n; i++) {\n+\t\tif (ids[i] >= IONIC_NB_HW_STATS) {\n+\t\t\tIONIC_PRINT(ERR, \"id value isn't valid\");\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tvalues[i] = values_copy[ids[i]];\n+\t}\n+\n+\treturn n;\n+}\n+\n+static int\n+ionic_dev_xstats_reset(struct rte_eth_dev *eth_dev)\n+{\n+\tstruct ionic_lif *lif = IONIC_ETH_DEV_TO_LIF(eth_dev);\n+\n+\tionic_lif_reset_hw_stats(lif);\n+\n+\treturn 0;\n+}\n+\n static int\n ionic_dev_configure(struct rte_eth_dev *eth_dev)\n {\ndiff --git a/drivers/net/ionic/ionic_lif.c b/drivers/net/ionic/ionic_lif.c\nindex 9631fdb6c..2290debf5 100644\n--- a/drivers/net/ionic/ionic_lif.c\n+++ b/drivers/net/ionic/ionic_lif.c\n@@ -84,6 +84,152 @@ ionic_lif_reset(struct ionic_lif *lif)\n \tionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);\n }\n \n+static void\n+ionic_lif_get_abs_stats(struct ionic_lif *lif, struct rte_eth_stats *stats)\n+{\n+\tstruct ionic_lif_stats *ls = &lif->info->stats;\n+\tuint32_t i;\n+\tuint32_t num_rx_q_counters = RTE_MIN(lif->nrxqcqs, (uint32_t)\n+\t\t\tRTE_ETHDEV_QUEUE_STAT_CNTRS);\n+\tuint32_t num_tx_q_counters = RTE_MIN(lif->ntxqcqs, (uint32_t)\n+\t\t\tRTE_ETHDEV_QUEUE_STAT_CNTRS);\n+\n+\tmemset(stats, 0, sizeof(*stats));\n+\n+\tif (ls == NULL) {\n+\t\tIONIC_PRINT(DEBUG, \"Stats on port %u not yet initialized\",\n+\t\t\tlif->port_id);\n+\t\treturn;\n+\t}\n+\n+\t/* RX */\n+\n+\tstats->ipackets = ls->rx_ucast_packets +\n+\t\tls->rx_mcast_packets +\n+\t\tls->rx_bcast_packets;\n+\n+\tstats->ibytes = ls->rx_ucast_bytes +\n+\t\tls->rx_mcast_bytes +\n+\t\tls->rx_bcast_bytes;\n+\n+\tfor (i = 0; i < lif->nrxqcqs; i++) {\n+\t\tstruct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;\n+\t\tstats->imissed +=\n+\t\t\trx_stats->no_cb_arg +\n+\t\t\trx_stats->bad_cq_status +\n+\t\t\trx_stats->no_room +\n+\t\t\trx_stats->bad_len;\n+\t}\n+\n+\tstats->imissed +=\n+\t\tls->rx_ucast_drop_packets +\n+\t\tls->rx_mcast_drop_packets +\n+\t\tls->rx_bcast_drop_packets;\n+\n+\tstats->imissed +=\n+\t\tls->rx_queue_empty +\n+\t\tls->rx_dma_error +\n+\t\tls->rx_queue_disabled +\n+\t\tls->rx_desc_fetch_error +\n+\t\tls->rx_desc_data_error;\n+\n+\tfor (i = 0; i < num_rx_q_counters; i++) {\n+\t\tstruct ionic_rx_stats *rx_stats = &lif->rxqcqs[i]->stats.rx;\n+\t\tstats->q_ipackets[i] = rx_stats->packets;\n+\t\tstats->q_ibytes[i] = rx_stats->bytes;\n+\t\tstats->q_errors[i] =\n+\t\t\trx_stats->no_cb_arg +\n+\t\t\trx_stats->bad_cq_status +\n+\t\t\trx_stats->no_room +\n+\t\t\trx_stats->bad_len;\n+\t}\n+\n+\t/* TX */\n+\n+\tstats->opackets = ls->tx_ucast_packets +\n+\t\tls->tx_mcast_packets +\n+\t\tls->tx_bcast_packets;\n+\n+\tstats->obytes = ls->tx_ucast_bytes +\n+\t\tls->tx_mcast_bytes +\n+\t\tls->tx_bcast_bytes;\n+\n+\tfor (i = 0; i < lif->ntxqcqs; i++) {\n+\t\tstruct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;\n+\t\tstats->oerrors += tx_stats->drop;\n+\t}\n+\n+\tstats->oerrors +=\n+\t\tls->tx_ucast_drop_packets +\n+\t\tls->tx_mcast_drop_packets +\n+\t\tls->tx_bcast_drop_packets;\n+\n+\tstats->oerrors +=\n+\t\tls->tx_dma_error +\n+\t\tls->tx_queue_disabled +\n+\t\tls->tx_desc_fetch_error +\n+\t\tls->tx_desc_data_error;\n+\n+\tfor (i = 0; i < num_tx_q_counters; i++) {\n+\t\tstruct ionic_tx_stats *tx_stats = &lif->txqcqs[i]->stats.tx;\n+\t\tstats->q_opackets[i] = tx_stats->packets;\n+\t\tstats->q_obytes[i] = tx_stats->bytes;\n+\t}\n+}\n+\n+void\n+ionic_lif_get_stats(struct ionic_lif *lif, struct rte_eth_stats *stats)\n+{\n+\tionic_lif_get_abs_stats(lif, stats);\n+\n+\tstats->ipackets  -= lif->stats_base.ipackets;\n+\tstats->opackets  -= lif->stats_base.opackets;\n+\tstats->ibytes    -= lif->stats_base.ibytes;\n+\tstats->obytes    -= lif->stats_base.obytes;\n+\tstats->imissed   -= lif->stats_base.imissed;\n+\tstats->ierrors   -= lif->stats_base.ierrors;\n+\tstats->oerrors   -= lif->stats_base.oerrors;\n+\tstats->rx_nombuf -= lif->stats_base.rx_nombuf;\n+}\n+\n+void\n+ionic_lif_reset_stats(struct ionic_lif *lif)\n+{\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < lif->nrxqcqs; i++) {\n+\t\tmemset(&lif->rxqcqs[i]->stats.rx, 0,\n+\t\t\tsizeof(struct ionic_rx_stats));\n+\t\tmemset(&lif->txqcqs[i]->stats.tx, 0,\n+\t\t\tsizeof(struct ionic_tx_stats));\n+\t}\n+\n+\tionic_lif_get_abs_stats(lif, &lif->stats_base);\n+}\n+\n+void\n+ionic_lif_get_hw_stats(struct ionic_lif *lif, struct ionic_lif_stats *stats)\n+{\n+\tuint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);\n+\tuint64_t *stats64 = (uint64_t *)stats;\n+\tuint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;\n+\tuint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;\n+\n+\tfor (i = 0; i < count; i++)\n+\t\tstats64[i] = lif_stats64[i] - lif_stats64_base[i];\n+}\n+\n+void\n+ionic_lif_reset_hw_stats(struct ionic_lif *lif)\n+{\n+\tuint16_t i, count = sizeof(struct ionic_lif_stats) / sizeof(uint64_t);\n+\tuint64_t *lif_stats64 = (uint64_t *)&lif->info->stats;\n+\tuint64_t *lif_stats64_base = (uint64_t *)&lif->lif_stats_base;\n+\n+\tfor (i = 0; i < count; i++)\n+\t\tlif_stats64_base[i] = lif_stats64[i];\n+}\n+\n static int\n ionic_lif_addr_add(struct ionic_lif *lif, const uint8_t *addr)\n {\n@@ -1338,6 +1484,8 @@ ionic_lif_init(struct ionic_lif *lif)\n \tstruct ionic_q_init_comp comp;\n \tint err;\n \n+\tmemset(&lif->stats_base, 0, sizeof(lif->stats_base));\n+\n \tionic_dev_cmd_lif_init(idev, lif->index, lif->info_pa);\n \terr = ionic_dev_cmd_wait_check(idev, IONIC_DEVCMD_TIMEOUT);\n \tionic_dev_cmd_comp(idev, &comp);\ndiff --git a/drivers/net/ionic/ionic_lif.h b/drivers/net/ionic/ionic_lif.h\nindex a6f579d1c..dd7bd11e3 100644\n--- a/drivers/net/ionic/ionic_lif.h\n+++ b/drivers/net/ionic/ionic_lif.h\n@@ -113,6 +113,8 @@ struct ionic_lif {\n \tstruct ionic_lif_info *info;\n \trte_iova_t info_pa;\n \tconst struct rte_memzone *info_z;\n+\tstruct rte_eth_stats stats_base;\n+\tstruct ionic_lif_stats lif_stats_base;\n };\n \n int ionic_lif_identify(struct ionic_adapter *adapter);\n@@ -174,6 +176,13 @@ int ionic_lif_rss_config(struct ionic_lif *lif, const uint16_t types,\n \n int ionic_lif_set_features(struct ionic_lif *lif);\n \n+void ionic_lif_get_stats(struct ionic_lif *lif, struct rte_eth_stats *stats);\n+void ionic_lif_reset_stats(struct ionic_lif *lif);\n+\n+void ionic_lif_get_hw_stats(struct ionic_lif *lif,\n+\tstruct ionic_lif_stats *stats);\n+void ionic_lif_reset_hw_stats(struct ionic_lif *lif);\n+\n int ionic_notifyq_handler(struct ionic_lif *lif, int budget);\n \n #endif /* _IONIC_LIF_H_ */\n",
    "prefixes": [
        "v3",
        "15/17"
    ]
}