On Wed, Nov 18, 2015 at 12:34:24PM +0300, Maxim Uvarov wrote:
> Signed-off-by: Maxim Uvarov <maxim.uva...@linaro.org>
> ---
>  platform/linux-generic/Makefile.am                 |   2 +
>  .../linux-generic/include/odp_packet_io_internal.h |  11 ++
>  platform/linux-generic/include/odp_packet_socket.h |   6 +
>  platform/linux-generic/odp_packet_io.c             |  53 +++++++
>  platform/linux-generic/pktio/ethtool.c             | 160 
> +++++++++++++++++++++
>  platform/linux-generic/pktio/socket.c              |  84 +++++++++++
>  platform/linux-generic/pktio/socket_mmap.c         |  19 +++
>  platform/linux-generic/pktio/sysfs.c               |  71 +++++++++
>  8 files changed, 406 insertions(+)
>  create mode 100644 platform/linux-generic/pktio/ethtool.c
>  create mode 100644 platform/linux-generic/pktio/sysfs.c
> 
> diff --git a/platform/linux-generic/Makefile.am 
> b/platform/linux-generic/Makefile.am
> index 610c79c..71b030e 100644
> --- a/platform/linux-generic/Makefile.am
> +++ b/platform/linux-generic/Makefile.am
> @@ -165,11 +165,13 @@ __LIB__libodp_la_SOURCES = \
>                          odp_packet.c \
>                          odp_packet_flags.c \
>                          odp_packet_io.c \
> +                        pktio/ethtool.c \
>                          pktio/io_ops.c \
>                          pktio/loop.c \
>                          pktio/netmap.c \
>                          pktio/socket.c \
>                          pktio/socket_mmap.c \
> +                        pktio/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..6566978 100644
> --- a/platform/linux-generic/include/odp_packet_io_internal.h
> +++ b/platform/linux-generic/include/odp_packet_io_internal.h
> @@ -84,6 +84,9 @@ struct pktio_entry {
>               STATE_STOP
>       } state;
>       classifier_t cls;               /**< classifier linked with this pktio*/
> +     odp_pktio_stats_t stats;        /**< statistic counters for pktio */
> +     int use_ethtool;                /**< 1 - use ethtool,
> +                                          0 - sysfs for statistics */
>       char name[PKTIO_NAME_LEN];      /**< name of pktio provided to
>                                          pktio_open() */
>       odp_pktio_param_t param;
> @@ -107,6 +110,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 +164,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/include/odp_packet_socket.h 
> b/platform/linux-generic/include/odp_packet_socket.h
> index a5e0eb3..0836e3c 100644
> --- a/platform/linux-generic/include/odp_packet_socket.h
> +++ b/platform/linux-generic/include/odp_packet_socket.h
> @@ -18,6 +18,7 @@
>  #include <odp/debug.h>
>  #include <odp/pool.h>
>  #include <odp/packet.h>
> +#include <odp/packet_io.h>
>  
>  #include <linux/version.h>
>  
> @@ -114,4 +115,9 @@ int promisc_mode_set_fd(int fd, const char *name, int 
> enable);
>   */
>  int promisc_mode_get_fd(int fd, const char *name);
>  
> +/**
> + * Get ethtool statistics of a packet socket
> + */
> +int ethtool_stats_get_fd(int fd, const char *name, odp_pktio_stats_t *stats);
> +
>  #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/ethtool.c 
> b/platform/linux-generic/pktio/ethtool.c
> new file mode 100644
> index 0000000..b689015
> --- /dev/null
> +++ b/platform/linux-generic/pktio/ethtool.c
> @@ -0,0 +1,160 @@
> +/* Copyright (c) 2015, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +#include <sys/ioctl.h>
> +#include <netinet/in.h>
> +#include <linux/sockios.h>
> +#include <linux/if.h>
> +#include <linux/ethtool.h>
> +#include <errno.h>
> +#include <net/if.h>
> +
> +#include <odp.h>
> +#include <odp_packet_socket.h>
> +#include <odp_debug_internal.h>
> +
> +static struct ethtool_gstrings *get_stringset(int fd, struct ifreq *ifr)
> +{
> +     struct {
> +             struct ethtool_sset_info hdr;
> +             uint32_t buf[1];
> +     } sset_info;
> +     struct ethtool_drvinfo drvinfo;
> +     uint32_t len;
> +     struct ethtool_gstrings *strings;
> +     ptrdiff_t drvinfo_offset = offsetof(struct ethtool_drvinfo, n_stats);
> +
> +     sset_info.hdr.cmd = ETHTOOL_GSSET_INFO;
> +     sset_info.hdr.reserved = 0;
> +     sset_info.hdr.sset_mask = 1ULL << ETH_SS_STATS;
> +     ifr->ifr_data =  &sset_info;
> +     if (ioctl(fd, SIOCETHTOOL, ifr) == 0) {
> +             len = sset_info.hdr.sset_mask ? sset_info.hdr.data[0] : 0;
> +     } else if (errno == EOPNOTSUPP && drvinfo_offset != 0) {
> +             /* Fallback for old kernel versions */
> +             drvinfo.cmd = ETHTOOL_GDRVINFO;
> +             ifr->ifr_data = &drvinfo;
> +             if (ioctl(fd, SIOCETHTOOL, ifr)) {
> +                     __odp_errno = errno;
> +                     ODP_ERR("Cannot get stats information\n");
> +                     return NULL;
> +             }
> +             len = *(uint32_t *)((char *)&drvinfo + drvinfo_offset);
> +     } else {
> +             __odp_errno = errno;
> +             return NULL;
> +     }
> +
> +     if (!len) {
> +             ODP_ERR("len is zero");
> +             return NULL;
> +     }
> +
> +     strings = calloc(1, sizeof(*strings) + len * ETH_GSTRING_LEN);
> +     if (!strings) {
> +             ODP_ERR("alloc failed\n");
> +             return NULL;
> +     }
> +
> +     strings->cmd = ETHTOOL_GSTRINGS;
> +     strings->string_set = ETH_SS_STATS;
> +     strings->len = len;
> +     ifr->ifr_data = strings;
> +     if (ioctl(fd, SIOCETHTOOL, ifr)) {
> +             __odp_errno = errno;
> +             ODP_ERR("Cannot get stats information\n");
> +             free(strings);
> +             return NULL;
> +     }
> +
> +     return strings;
> +}
> +
> +static int ethtool_stats(int fd, struct ifreq *ifr, odp_pktio_stats_t *stats)
> +{
> +     struct ethtool_gstrings *strings;
> +     struct ethtool_stats *estats;
> +     unsigned int n_stats, i;
> +     int err;
> +     int cnts;
> +
> +     strings = get_stringset(fd, ifr);
> +     if (!strings)
> +             return -1;
> +
> +     n_stats = strings->len;
> +     if (n_stats < 1) {
> +             ODP_ERR("no stats available\n");
> +             free(strings);
> +             return -1;
> +     }
> +
> +     estats = calloc(1, n_stats * sizeof(uint64_t) +
> +                     sizeof(struct ethtool_stats));
> +     if (!estats) {
> +             free(strings);
> +             return -1;
> +     }
> +
> +     estats->cmd = ETHTOOL_GSTATS;
> +     estats->n_stats = n_stats;
> +     ifr->ifr_data = stats;

Should be estats

-- 
Stuart.
_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to