On Mon, Nov 09, 2015 at 02:21:49PM +0300, Maxim Uvarov wrote:
> Signed-off-by: Maxim Uvarov <[email protected]>
> ---
> platform/linux-generic/Makefile.am | 1 +
> .../linux-generic/include/odp_packet_io_internal.h | 9 +++
> platform/linux-generic/odp_packet_io.c | 53 +++++++++++++++++
> platform/linux-generic/pktio/socket.c | 59 ++++++++++++++++++
> platform/linux-generic/pktio/socket_mmap.c | 8 +++
> platform/linux-generic/pktio/stats_sysfs.c | 69
> ++++++++++++++++++++++
> 6 files changed, 199 insertions(+)
> create mode 100644 platform/linux-generic/pktio/stats_sysfs.c
>
> diff --git a/platform/linux-generic/Makefile.am
> b/platform/linux-generic/Makefile.am
> index 610c79c..e3e4954 100644
> --- a/platform/linux-generic/Makefile.am
> +++ b/platform/linux-generic/Makefile.am
> @@ -170,6 +170,7 @@ __LIB__libodp_la_SOURCES = \
> pktio/netmap.c \
> pktio/socket.c \
> pktio/socket_mmap.c \
> + pktio/stats_sysfs.c \
> odp_pool.c \
> odp_queue.c \
> odp_rwlock.c \
> diff --git a/platform/linux-generic/include/odp_packet_io_internal.h
> b/platform/linux-generic/include/odp_packet_io_internal.h
> index 1a1118c..ec43e87 100644
> --- a/platform/linux-generic/include/odp_packet_io_internal.h
> +++ b/platform/linux-generic/include/odp_packet_io_internal.h
> @@ -84,6 +84,7 @@ struct pktio_entry {
> STATE_STOP
> } state;
> classifier_t cls; /**< classifier linked with this pktio*/
> + odp_pktio_stats_t stats; /**< statistic counters for pktio */
> char name[PKTIO_NAME_LEN]; /**< name of pktio provided to
> pktio_open() */
> odp_pktio_param_t param;
> @@ -107,6 +108,8 @@ typedef struct pktio_if_ops {
> int (*close)(pktio_entry_t *pktio_entry);
> int (*start)(pktio_entry_t *pktio_entry);
> int (*stop)(pktio_entry_t *pktio_entry);
> + int (*stats)(pktio_entry_t *pktio_entry, odp_pktio_stats_t *stats);
> + int (*stats_reset)(pktio_entry_t *pktio_entry);
> int (*recv)(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[],
> unsigned len);
> int (*send)(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[],
> @@ -159,6 +162,12 @@ extern const pktio_if_ops_t pcap_pktio_ops;
> #endif
> extern const pktio_if_ops_t * const pktio_if_ops[];
>
> +int sysfs_stats(pktio_entry_t *pktio_entry,
> + odp_pktio_stats_t *stats);
> +int sock_stats_reset(pktio_entry_t *pktio_entry);
> +int sock_stats(pktio_entry_t *pktio_entry,
> + odp_pktio_stats_t *stats);
> +
> #ifdef __cplusplus
> }
> #endif
> diff --git a/platform/linux-generic/odp_packet_io.c
> b/platform/linux-generic/odp_packet_io.c
> index 3ef400f..ba97629 100644
> --- a/platform/linux-generic/odp_packet_io.c
> +++ b/platform/linux-generic/odp_packet_io.c
> @@ -862,3 +862,56 @@ void odp_pktio_print(odp_pktio_t id)
>
> ODP_PRINT("\n%s\n", str);
> }
> +
> +int odp_pktio_stats(odp_pktio_t pktio,
> + odp_pktio_stats_t *stats)
> +{
> + pktio_entry_t *entry;
> + int ret = -1;
> +
> + entry = get_pktio_entry(pktio);
> + if (entry == NULL) {
> + ODP_DBG("pktio entry %d does not exist\n", pktio);
> + return -1;
> + }
> +
> + lock_entry(entry);
> +
> + if (odp_unlikely(is_free(entry))) {
> + unlock_entry(entry);
> + ODP_DBG("already freed pktio\n");
> + return -1;
> + }
> +
> + if (entry->s.ops->stats)
> + ret = entry->s.ops->stats(entry, stats);
> + unlock_entry(entry);
> +
> + return ret;
> +}
> +
> +int odp_pktio_stats_reset(odp_pktio_t pktio)
> +{
> + pktio_entry_t *entry;
> + int ret = -1;
> +
> + entry = get_pktio_entry(pktio);
> + if (entry == NULL) {
> + ODP_DBG("pktio entry %d does not exist\n", pktio);
> + return -1;
> + }
> +
> + lock_entry(entry);
> +
> + if (odp_unlikely(is_free(entry))) {
> + unlock_entry(entry);
> + ODP_DBG("already freed pktio\n");
> + return -1;
> + }
> +
> + if (entry->s.ops->stats)
> + ret = entry->s.ops->stats_reset(entry);
> + unlock_entry(entry);
> +
> + return ret;
> +}
> diff --git a/platform/linux-generic/pktio/socket.c
> b/platform/linux-generic/pktio/socket.c
> index 5f5e0ae..0bda57b 100644
> --- a/platform/linux-generic/pktio/socket.c
> +++ b/platform/linux-generic/pktio/socket.c
> @@ -254,6 +254,12 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry,
> const char *netdev,
> goto error;
> }
>
> + err = sock_stats_reset(pktio_entry);
> + if (err != 0) {
> + ODP_ERR("reset stats\n");
> + goto error;
> + }
> +
> return 0;
>
> error:
> @@ -467,6 +473,57 @@ static int sock_promisc_mode_get(pktio_entry_t
> *pktio_entry)
> pktio_entry->s.name);
> }
>
> +int sock_stats(pktio_entry_t *pktio_entry,
> + odp_pktio_stats_t *stats)
> +{
> + odp_pktio_stats_t cur_stats;
> + int ret;
> +
> + memset(&cur_stats, 0, sizeof(odp_pktio_stats_t));
> + ret = sysfs_stats(pktio_entry, &cur_stats);
> + if (ret)
> + ODP_ABORT("sysfs stats error\n");
> +
> + stats->in_octets = cur_stats.in_octets -
> + pktio_entry->s.stats.in_octets;
> + stats->in_ucast_pkts = cur_stats.in_ucast_pkts -
> + pktio_entry->s.stats.in_ucast_pkts;
> + stats->in_discards = cur_stats.in_discards -
> + pktio_entry->s.stats.in_discards;
> + stats->in_errors = cur_stats.in_errors -
> + pktio_entry->s.stats.in_errors;
> + stats->in_unknown_protos = cur_stats.in_unknown_protos -
> + pktio_entry->s.stats.in_unknown_protos;
> +
> + stats->out_octets = cur_stats.out_octets -
> + pktio_entry->s.stats.out_octets;
> + stats->out_ucast_pkts = cur_stats.out_ucast_pkts -
> + pktio_entry->s.stats.out_ucast_pkts;
> + stats->out_discards = cur_stats.out_discards -
> + pktio_entry->s.stats.out_discards;
> + stats->out_errors = cur_stats.out_errors -
> + pktio_entry->s.stats.out_errors;
> +
> + return 0;
> +}
> +
> +int sock_stats_reset(pktio_entry_t *pktio_entry)
> +{
> + int err = 0;
> + odp_pktio_stats_t cur;
> +
> + memset(&cur, 0, sizeof(odp_pktio_stats_t));
> + err = sysfs_stats(pktio_entry, &cur);
> + if (err != 0) {
> + __odp_errno = errno;
> + ODP_ERR("sysfs stats error\n");
> + } else {
> + memcpy(&pktio_entry->s.stats, &cur, sizeof(odp_pktio_stats_t));
> + }
> +
> + return err;
> +}
> +
> const pktio_if_ops_t sock_mmsg_pktio_ops = {
> .init = NULL,
> .term = NULL,
> @@ -474,6 +531,8 @@ const pktio_if_ops_t sock_mmsg_pktio_ops = {
> .close = sock_close,
> .start = NULL,
> .stop = NULL,
> + .stats = sock_stats,
> + .stats_reset = sock_stats_reset,
> .recv = sock_mmsg_recv,
> .send = sock_mmsg_send,
> .mtu_get = sock_mtu_get,
> diff --git a/platform/linux-generic/pktio/socket_mmap.c
> b/platform/linux-generic/pktio/socket_mmap.c
> index 79ff82d..2031485 100644
> --- a/platform/linux-generic/pktio/socket_mmap.c
> +++ b/platform/linux-generic/pktio/socket_mmap.c
> @@ -467,6 +467,12 @@ static int sock_mmap_open(odp_pktio_t id ODP_UNUSED,
> goto error;
> }
>
> + ret = sock_stats_reset(pktio_entry);
> + if (ret != 0) {
> + ODP_ERR("reset stats\n");
> + goto error;
> + }
> +
> return 0;
>
> error:
> @@ -525,6 +531,8 @@ const pktio_if_ops_t sock_mmap_pktio_ops = {
> .close = sock_mmap_close,
> .start = NULL,
> .stop = NULL,
> + .stats = sock_stats,
> + .stats_reset = sock_stats_reset,
> .recv = sock_mmap_recv,
> .send = sock_mmap_send,
> .mtu_get = sock_mmap_mtu_get,
> diff --git a/platform/linux-generic/pktio/stats_sysfs.c
> b/platform/linux-generic/pktio/stats_sysfs.c
> new file mode 100644
> index 0000000..5033b7e
> --- /dev/null
> +++ b/platform/linux-generic/pktio/stats_sysfs.c
> @@ -0,0 +1,69 @@
> +/* Copyright (c) 2015, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier: BSD-3-Clause
> + */
> +
> +#include <odp.h>
> +#include <odp_packet_io_internal.h>
> +#include <stdio.h>
> +
> +static uint64_t sysfs_get_val(const char *fname)
> +{
> + FILE *file;
> + char str[128];
> + uint64_t ret = -1;
> +
> + file = fopen(fname, "rt");
> + if (file == NULL) {
> + /* File not found */
> + return 0;
> + }
> +
> + if (fgets(str, sizeof(str), file) != NULL) {
> + /* Read cache line size */
??
> + if (sscanf(str, "%" SCNx64, &ret) != 1) {
> + ODP_ERR("read %s\n", fname);
> + ret = 0;
> + }
> + }
> +
> + (void)fclose(file);
> + return ret;
> +}
Error handling is a bit broken here, 0 isn't a good failure indication.
It would be better to return an int and take a uint64_t* parameter.
Although I think it would actually be better to use ETHTOOL_GSTATS as
that should work for netmap too, in which case this helper wouldn't be
needed.
> +
> +int sysfs_stats(pktio_entry_t *pktio_entry,
> + odp_pktio_stats_t *stats)
> +{
> + char fname[256];
> + const char *dev = pktio_entry->s.name;
> +
> + sprintf(fname, "/sys/class/net/%s/statistics/rx_bytes", dev);
> + stats->in_octets = sysfs_get_val(fname);
> +
> + sprintf(fname, "/sys/class/net/%s/statistics/rx_packets", dev);
> + stats->in_ucast_pkts = sysfs_get_val(fname);
> +
> + sprintf(fname, "/sys/class/net/%s/statistics/rx_droppped", dev);
> + stats->in_discards = sysfs_get_val(fname);
> +
> + sprintf(fname, "/sys/class/net/%s/statistics/rx_errors", dev);
> + stats->in_errors = sysfs_get_val(fname);
> +
> + stats->in_unknown_protos = 0;
I presume there's no easy way of getting this information, could do with
a comment noting that it's not supported.
> +
> + sprintf(fname, "/sys/class/net/%s/statistics/tx_bytes", dev);
> + stats->out_octets = sysfs_get_val(fname);
> +
> + sprintf(fname, "/sys/class/net/%s/statistics/tx_packets", dev);
> + stats->out_ucast_pkts = sysfs_get_val(fname);
> +
> + sprintf(fname, "/sys/class/net/%s/statistics/tx_dropped", dev);
> + stats->out_discards = sysfs_get_val(fname);
> +
> + sprintf(fname, "/sys/class/net/%s/statistics/tx_errors", dev);
> + stats->out_errors = sysfs_get_val(fname);
> +
> + return 0;
> +}
> +
> --
> 1.9.1
>
--
Stuart.
_______________________________________________
lng-odp mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/lng-odp