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