For many network cards, xstat statistics cannot be queried in the
ovs interface. A new interface is added to retrieve all xstat
information of the network card.

Reported-by: Jun Wang <[email protected]>

Signed-off-by: Jun Wang <[email protected]>
---
 lib/netdev-dpdk.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index a3878d2..59292e3 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -4692,6 +4692,102 @@ out:
     netdev_close(netdev);
 }
 
+static void
+netdev_dpdk_show_port_xstats(struct unixctl_conn *conn,
+                           uint16_t port_id, struct ds * ports_xstats)
+{
+    char *response = NULL;
+    struct rte_eth_xstat_name *xstats_names;
+    uint64_t *values;
+    int len, ret, j;
+    static const char *nic_stats_border = "########################";
+
+    if (!rte_eth_dev_is_valid_port(port_id)) {
+        return;
+    }
+
+    len = rte_eth_xstats_get_names_by_id(port_id, NULL, 0, NULL);
+    if (len < 0) {
+        response = xasprintf("Cannot get xstats count\n");
+        goto err;
+    }
+    values = xmalloc(sizeof(*values) * len);
+    if (values == NULL) {
+        response = xasprintf("Cannot allocate memory for xstats\n");
+        goto err;
+    }
+
+    xstats_names = xmalloc(sizeof(struct rte_eth_xstat_name) * len);
+    if (xstats_names == NULL) {
+        response = xasprintf("Cannot allocate memory for xstat"
+                             " names\n");
+        free(values);
+        goto err;
+    }
+    if (len != rte_eth_xstats_get_names_by_id(port_id, xstats_names,
+                                              len, NULL)) {
+        response = xasprintf("Cannot get xstat names\n");
+        free(values);
+        free(xstats_names);
+        goto err;
+    }
+
+    ds_put_format(ports_xstats, "###### NIC extended statistics for"
+                  " port %-2d #########\n", port_id);
+    ds_put_format(ports_xstats, "%s############################\n",
+                  nic_stats_border);
+    ret = rte_eth_xstats_get_by_id(port_id, NULL, values, len);
+    if (ret < 0 || ret > len) {
+        response = xasprintf("Cannot get xstats\n");
+        free(values);
+        free(xstats_names);
+        goto err;
+    }
+
+    for (j = 0; j < len; j++) {
+        ds_put_format(ports_xstats, "%s: %"PRIu64"\n",
+                      xstats_names[j].name, values[j]);
+    }
+
+    ds_put_format(ports_xstats, "%s############################\n",
+                  nic_stats_border);
+
+    free(values);
+    free(xstats_names);
+    return;
+err:
+    unixctl_command_reply_error(conn, response);
+    free(response);
+}
+
+static void
+netdev_dpdk_show_xstats(struct unixctl_conn *conn, int argc,
+                   const char *argv[], void *aux OVS_UNUSED)
+{
+    int i;
+    struct ds ports_xstats = DS_EMPTY_INITIALIZER;
+    struct netdev *netdev = NULL;
+
+    if (argc == 2) {
+        netdev = netdev_from_name(argv[1]);
+        if (!netdev || !is_dpdk_class(netdev->netdev_class)) {
+            unixctl_command_reply_error(conn, "Not a DPDK Interface");
+            goto xstats;
+        }
+        struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+        netdev_dpdk_show_port_xstats(conn, dev->port_id,
+                                     &ports_xstats);
+    } else {
+        for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+            netdev_dpdk_show_port_xstats(conn, i, &ports_xstats);
+        }
+    }
+    unixctl_command_reply(conn, ds_cstr(&ports_xstats));
+xstats:
+    ds_destroy(&ports_xstats);
+    netdev_close(netdev);
+}
+
 /*
  * Set virtqueue flags so that we do not receive interrupts.
  */
@@ -5164,6 +5260,10 @@ netdev_dpdk_class_init(void)
                                  "[netdev]", 0, 1,
                                  netdev_dpdk_get_mempool_info, NULL);
 
+        unixctl_command_register("netdev-dpdk/show-xstats",
+                                 "[netdev]", 0, 1,
+                                 netdev_dpdk_show_xstats, NULL);
+
         netdev_dpdk_reset_seq = seq_create();
         netdev_dpdk_last_reset_seq = seq_read(netdev_dpdk_reset_seq);
         ret = rte_eth_dev_callback_register(RTE_ETH_ALL,
-- 
1.8.3.1



_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to