@@ -131,12 +131,14 @@ __LIB__libodp_la_SOURCES = \
odp_packet.c \
odp_packet_flags.c \
odp_packet_io.c \
+ pktio/ethtool.c \
pktio/io_ops.c \
pktio/pktio_common.c \
pktio/loop.c \
pktio/netmap.c \
pktio/socket.c \
pktio/socket_mmap.c \
+ pktio/sysfs.c \
pktio/tap.c \
odp_pkt_queue.c \
odp_pool.c \
@@ -90,6 +90,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_t id;
@@ -129,6 +132,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[],
@@ -218,6 +223,12 @@ extern const pktio_if_ops_t pcap_pktio_ops;
extern const pktio_if_ops_t tap_pktio_ops;
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
@@ -163,4 +163,9 @@ int rss_conf_set_fd(int fd, const char *name,
*/
void rss_conf_print(const odp_pktin_hash_proto_t *hash_proto);
+/**
+ * Get ethtool statistics of a packet socket
+ */
+int ethtool_stats_get_fd(int fd, const char *name, odp_pktio_stats_t *stats);
+
#endif
@@ -941,6 +941,59 @@ int odp_pktio_capability(odp_pktio_t pktio, odp_pktio_capability_t *capa)
return single_capability(capa);
}
+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;
+}
+
int odp_pktio_input_queues_config(odp_pktio_t pktio,
const odp_pktio_input_queue_param_t *param)
{
@@ -432,6 +432,10 @@ static int netmap_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry,
odp_ticketlock_init(&pkt_nm->tx_desc_ring[i].s.lock);
}
+ /* netmap uses only ethtool to get statistics counters */
+ pktio_entry->s.use_ethtool = 1;
+ (void)sock_stats_reset(pktio_entry);
+
return 0;
error:
@@ -853,6 +857,8 @@ const pktio_if_ops_t netmap_pktio_ops = {
.close = netmap_close,
.start = netmap_start,
.stop = netmap_stop,
+ .stats = sock_stats,
+ .stats_reset = sock_stats_reset,
.recv = netmap_recv,
.send = netmap_send,
.mtu_get = netmap_mtu_get,
@@ -459,6 +459,7 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev,
char shm_name[ODP_SHM_NAME_LEN];
pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock;
uint8_t *addr;
+ odp_pktio_stats_t cur_stats;
/* Init pktio entry */
memset(pkt_sock, 0, sizeof(*pkt_sock));
@@ -517,6 +518,23 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev,
ODP_ERR("bind(to IF): %s\n", strerror(errno));
goto error;
}
+
+ err = ethtool_stats_get_fd(pktio_entry->s.pkt_sock.sockfd,
+ pktio_entry->s.name,
+ &cur_stats);
+ if (err != 0) {
+ err = sysfs_stats(pktio_entry, &cur_stats);
+ if (err != 0)
+ ODP_ABORT("statistic counters are not reachable\n");
+ pktio_entry->s.use_ethtool = 0;
+ } else {
+ pktio_entry->s.use_ethtool = 1;
+ }
+
+ err = sock_stats_reset(pktio_entry);
+ if (err != 0)
+ goto error;
+
return 0;
error:
@@ -767,6 +785,71 @@ 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));
+ if (pktio_entry->s.use_ethtool) {
+ ret = ethtool_stats_get_fd(pktio_entry->s.pkt_sock.sockfd,
+ pktio_entry->s.name,
+ &cur_stats);
+ } else {
+ ret = sysfs_stats(pktio_entry, &cur_stats);
+ }
+ if (ret)
+ ODP_ABORT("getting statistics 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_stats;
+
+ memset(&cur_stats, 0, sizeof(odp_pktio_stats_t));
+
+ if (pktio_entry->s.use_ethtool) {
+ err = ethtool_stats_get_fd(pktio_entry->s.pkt_sock.sockfd,
+ pktio_entry->s.name,
+ &cur_stats);
+ } else {
+ err = sysfs_stats(pktio_entry, &cur_stats);
+ }
+
+ if (err != 0) {
+ ODP_ERR("stats error\n");
+ } else {
+ memcpy(&pktio_entry->s.stats, &cur_stats,
+ sizeof(odp_pktio_stats_t));
+ }
+
+ return err;
+}
+
const pktio_if_ops_t sock_mmsg_pktio_ops = {
.name = "socket",
.init = NULL,
@@ -775,6 +858,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,
@@ -445,6 +445,7 @@ static int sock_mmap_open(odp_pktio_t id ODP_UNUSED,
{
int if_idx;
int ret = 0;
+ odp_pktio_stats_t cur_stats;
if (getenv("ODP_PKTIO_DISABLE_SOCKET_MMAP"))
return -1;
@@ -504,6 +505,22 @@ static int sock_mmap_open(odp_pktio_t id ODP_UNUSED,
goto error;
}
+ ret = ethtool_stats_get_fd(pktio_entry->s.pkt_sock.sockfd,
+ pktio_entry->s.name,
+ &cur_stats);
+ if (ret != 0) {
+ ret = sysfs_stats(pktio_entry, &cur_stats);
+ if (ret != 0)
+ ODP_ABORT("statistic counters are not reachable\n");
+ pktio_entry->s.use_ethtool = 0;
+ } else {
+ pktio_entry->s.use_ethtool = 1;
+ }
+
+ ret = sock_stats_reset(pktio_entry);
+ if (ret != 0)
+ goto error;
+
return 0;
error:
@@ -562,6 +579,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,
Signed-off-by: Maxim Uvarov <maxim.uvarov@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 | 5 ++ platform/linux-generic/odp_packet_io.c | 53 ++++++++++++++ platform/linux-generic/pktio/netmap.c | 6 ++ platform/linux-generic/pktio/socket.c | 85 ++++++++++++++++++++++ platform/linux-generic/pktio/socket_mmap.c | 19 +++++ 7 files changed, 181 insertions(+)