Skip to content
Snippets Groups Projects
Commit 78552f77 authored by Padmalochan Mohapatra's avatar Padmalochan Mohapatra Committed by Rahul Thakur
Browse files

libethernet : Ethernet Stats Update for Linux

parent 30df7467
No related branches found
No related tags found
1 merge request!3libethernet : Ethernet Stats Update for Linux
......@@ -24,12 +24,12 @@ objs_lib += econet/econet.o econet/ecnt_prvt.o
LIBS += -lapi_lib_switchmgr
endif
ifeq ($(PLATFORM),IPQ95XX)
objs_lib += ipq95xx/ipq95xx.o
ifeq ($(PLATFORM),LINUX)
objs_lib += linux/common/common_eth.o linux/linux/linux_eth.o
endif
ifeq ($(PLATFORM),LINUX)
objs_lib += linux/linux_eth.o
ifeq ($(PLATFORM),MEDIATEK)
objs_lib += linux/common/common_eth.o linux/mtk/mtk_eth.o
endif
all: libethernet.so
......
......@@ -47,8 +47,8 @@ extern const struct eth_ops test_eth_ops;
extern const struct eth_ops econet_gen_eth_ops;
extern const struct eth_ops econet_nas_wan_eth_ops;
extern const struct eth_ops econet_ae_wan_eth_ops;
#elif defined(IPQ95XX)
extern const struct eth_ops ipq95xx_eth_ops;
#elif defined(IOPSYS_MEDIATEK)
extern const struct eth_ops mtk_eth_ops;
#elif defined(IOPSYS_LINUX)
extern const struct eth_ops linux_eth_ops;
#else
......@@ -64,8 +64,8 @@ const struct eth_ops *eth_ops[] = {
&econet_gen_eth_ops,
&econet_nas_wan_eth_ops,
&econet_ae_wan_eth_ops,
#elif defined(IPQ95XX)
&ipq95xx_eth_ops,
#elif defined(IOPSYS_MEDIATEK)
&mtk_eth_ops
#elif defined(IOPSYS_LINUX)
&linux_eth_ops,
#else
......
/*
* ipq95xx.c
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <time.h>
#include <syslog.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
#include <easy/easy.h>
#include "../ethernet.h"
#include "ipq95xx.h"
int ipq95xx_eth_set_link_settings(const char *ifname, struct eth_link link)
{
struct {
struct ethtool_link_settings req;
__u32 link_mode_data[3 * 32 * 127];
} ecmd;
memset(&ecmd, 0, sizeof(struct ethtool_link_settings));
if (ipq95xx_eth_get_link_settings(ifname, &link))
return -1;
ecmd.req.cmd = ETHTOOL_SLINKSETTINGS;
ecmd.req.port = link.portid;
ecmd.req.speed = link.speed;
ecmd.req.autoneg = (link.autoneg == 0 ? false : true);
ecmd.req.duplex = (link.fullduplex == 1 ? false : true);
if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
return -1;
return 0;
}
int ipq95xx_eth_get_link_settings(const char *ifname, struct eth_link *link)
{
struct {
struct ethtool_link_settings req;
__u32 link_mode_data[3 * 32 * 127];
} ecmd;
memset(&ecmd, 0, sizeof(struct ethtool_link_settings));
ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
return -1;
if (ecmd.req.link_mode_masks_nwords >= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
return -1;
ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
return -1;
if (ecmd.req.link_mode_masks_nwords <= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
return -1;
link->portid = ecmd.req.port;
link->speed = ecmd.req.speed;
link->autoneg = ecmd.req.autoneg == 0 ? false : true;
link->fullduplex = ecmd.req.duplex == 1 ? false : true;
return 0;
}
int ipq95xx_eth_poweron_phy(const char *ifname, struct eth_phy p)
{
libethernet_err("%s(): TODO\n", __func__);
return 0;
}
int ipq95xx_eth_poweroff_phy(const char *ifname, struct eth_phy p)
{
libethernet_err("%s(): TODO\n", __func__);
return 0;
}
int ipq95xx_eth_reset_phy(const char *ifname, int phy_id)
{
return eth_mii_reset_phy(ifname, phy_id);
}
int ipq95xx_eth_get_stats(const char *ifname, struct eth_stats *s)
{
struct if_stats ifstats;
memset(&ifstats, 0, sizeof(struct if_stats));
if (if_getstats(ifname, &ifstats) < 0)
return -1;
s->rx_packets = ifstats.rx_packets;
s->tx_packets = ifstats.tx_packets;
s->rx_bytes = ifstats.rx_bytes;
s->tx_bytes = ifstats.tx_bytes;
s->rx_errors = ifstats.rx_errors;
s->tx_errors = ifstats.tx_errors;
s->rx_discard_packets = ifstats.rx_dropped;
s->tx_discard_packets = ifstats.tx_dropped;
return 0;
}
int ipq95xx_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
{
libethernet_err("%s(): TODO\n", __func__);
return 0;
}
const struct eth_ops ipq95xx_eth_ops = {
.ifname = "eth",
.set_link_settings = ipq95xx_eth_set_link_settings,
.get_link_settings = ipq95xx_eth_get_link_settings,
.get_stats = ipq95xx_eth_get_stats,
.get_rmon_stats = ipq95xx_eth_get_rmon_stats,
.poweron_phy = ipq95xx_eth_poweron_phy,
.poweroff_phy = ipq95xx_eth_poweroff_phy,
.reset_phy = ipq95xx_eth_reset_phy,
};
#ifndef IPQ95XX
#define IPQ95XX
#ifdef __cplusplus
extern "C" {
#endif
int ipq95xx_eth_set_link_settings(const char *ifname, struct eth_link link);
int ipq95xx_eth_get_link_settings(const char *ifname, struct eth_link *link);
int ipq95xx_eth_poweron_phy(const char *ifname, struct eth_phy p);
int ipq95xx_eth_poweroff_phy(const char *ifname, struct eth_phy p);
int ipq95xx_eth_reset_phy(const char *ifname, int phy_id);
int ipq95xx_eth_get_stats(const char *ifname, struct eth_stats *s);
int ipq95xx_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon);
#ifdef __cplusplus
}
#endif
#endif /* IPQ95XX */
/*
* common_eth.c - Linux based statistics collection ubus methods.
*
* Copyright (C) 2023 iopsys Software Solutions AB. All rights reserved.
*
* Author: padmalochan.mohapatra@iopsys.eu
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <time.h>
#include <syslog.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
#include <easy/easy.h>
#include <easy/if_utils.h>
#include "ethernet.h"
#include "../linux/linux_eth.h"
#include "../mtk/mtk_eth.h"
#if defined(IOPSYS_MEDIATEK)
const struct eth_ops mtk_eth_ops = {
.ifname = "lan",
.get_stats = mtk_eth_get_stats,
.get_rmon_stats = mtk_eth_get_rmon_stats,
#elif defined(IOPSYS_LINUX)
const struct eth_ops linux_eth_ops = {
.ifname = "eth",
.set_link_settings = linux_eth_set_link_settings,
.get_link_settings = linux_eth_get_link_settings,
.poweron_phy = linux_eth_poweron_phy,
.poweroff_phy = linux_eth_poweroff_phy,
.reset_phy = linux_eth_reset_phy,
.get_stats = linux_eth_get_stats,
.get_rmon_stats = linux_eth_get_rmon_stats,
#endif
};
/*
* linux_eth.c
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <time.h>
#include <syslog.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
#include <easy/easy.h>
#include "ethernet.h"
#include "linux_eth.h"
typedef enum {
iow_rx_byte = 0,
iow_rx_packets,
iow_rx_dropped,
iow_rx_fraglist_packets,
iow_rx_nr_frag_packets,
iow_rx_nr_frag_headroom_err,
iow_tx_byte,
iow_tx_packets,
iow_tx_dropped,
iow_tx_nr_frag_packets,
iow_tx_fraglist_packets,
iow_tx_fraglist_nr_frags_packets,
iow_tx_tso_packets,
iow_tx_tso_drop_packets,
iow_rx_frame,
iow_rx_bytes,
iow_rx_bytes_g,
iow_rx_broadcast,
iow_rx_multicast,
iow_rx_crc_err,
iow_rx_runt_err,
iow_rx_jabber_err,
iow_rx_undersize,
iow_rx_oversize,
iow_rx_pkt64,
iow_rx_pkt65to127,
iow_rx_pkt128to255,
iow_rx_pkt256to511,
iow_rx_pkt512to1023,
iow_rx_pkt1024tomax,
iow_rx_unicast,
iow_rx_len_err,
iow_rx_outofrange_err_ctr,
iow_rx_pause,
iow_rx_fifo_overflow,
iow_rx_vlan,
iow_rx_wdog,
iow_rx_lpi_usec_ctr,
iow_rx_lpi_tran_ctr,
iow_rx_drop_frame_ctr,
iow_rx_drop_byte_ctr,
iow_tx_bytes,
iow_tx_frame,
iow_tx_broadcast,
iow_tx_broadcast_gb,
iow_tx_multicast,
iow_tx_multicast_gb,
iow_tx_pkt64,
iow_tx_pkt65to127,
iow_tx_pkt128to255,
iow_tx_pkt256to511,
iow_tx_pkt512to1023,
iow_tx_pkt1024tomax,
iow_tx_unicast,
iow_tx_underflow_err,
iow_tx_bytes_g,
iow_tx_frame_g,
iow_tx_pause,
iow_tx_vlan,
iow_tx_lpi_usec_ctr,
iow_tx_lpi_tran_ctr,
iow_STAT_END,
} g_linux_indx;
static struct ethtool_stats *g_linux_stats = NULL;
static struct eth_stats g_linux_ifstats;
int linux_eth_get_link_settings(const char*, struct eth_link*);
int linux_eth_set_link_settings(const char *ifname, struct eth_link link)
{
struct {
struct ethtool_link_settings req;
__u32 link_mode_data[3 * 32 * 127];
} ecmd;
memset(&ecmd, 0, sizeof(struct ethtool_link_settings));
if (linux_eth_get_link_settings(ifname, &link))
return -1;
ecmd.req.cmd = ETHTOOL_SLINKSETTINGS;
ecmd.req.port = link.portid;
ecmd.req.speed = link.speed;
ecmd.req.autoneg = (link.autoneg == 0 ? false : true);
ecmd.req.duplex = (link.fullduplex == 1 ? false : true);
if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
return -1;
return 0;
}
int linux_eth_get_link_settings(const char *ifname, struct eth_link *link)
{
struct {
struct ethtool_link_settings req;
__u32 link_mode_data[3 * 32 * 127];
} ecmd;
memset(&ecmd, 0, sizeof(struct ethtool_link_settings));
ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
return -1;
if (ecmd.req.link_mode_masks_nwords >= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
return -1;
ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
if (0 != eth_ioctl(ifname, SIOCETHTOOL, &ecmd, sizeof(struct ethtool_link_settings)))
return -1;
if (ecmd.req.link_mode_masks_nwords <= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
return -1;
link->portid = ecmd.req.port;
link->speed = ecmd.req.speed;
link->autoneg = ecmd.req.autoneg == 0 ? false : true;
link->fullduplex = ecmd.req.duplex == 1 ? false : true;
return 0;
}
int linux_eth_poweron_phy(const char *ifname, struct eth_phy p)
{
libethernet_err("%s(): TODO\n", __func__);
return 0;
}
int linux_eth_poweroff_phy(const char *ifname, struct eth_phy p)
{
libethernet_err("%s(): TODO\n", __func__);
return 0;
}
int linux_eth_reset_phy(const char *ifname, int phy_id)
{
return eth_mii_reset_phy(ifname, phy_id);
}
static int linux_get_ifstats(const char *ifname, struct eth_stats *s)
{
struct if_stats easy_ifstat;
if (!s)
return -1;
memset(&easy_ifstat, 0, sizeof(struct if_stats));
if (if_getstats(ifname, &easy_ifstat) < 0) {
return -1;
}
s->tx_bytes = easy_ifstat.tx_bytes;
s->tx_packets = easy_ifstat.tx_packets;
s->tx_errors = easy_ifstat.tx_errors;
/* Some counters set to zero, and will be populated cross referring
* the rmon stats structure.
*/
s->tx_ucast_packets = 0;
s->tx_mcast_packets = 0;
s->tx_bcast_packets = 0;
s->tx_discard_packets = 0;
s->rx_bytes = easy_ifstat.rx_bytes;
s->rx_packets = 0;
s->rx_errors = easy_ifstat.rx_errors;
s->rx_ucast_packets = 0;
s->rx_mcast_packets = 0;
s->rx_bcast_packets = 0;
s->rx_discard_packets = 0;
s->rx_unknown_packets = 0;
return 0;
}
static int linux_get_ethtool_stats(const char *ifname)
{
int fd;
size_t n_stats;
size_t stats_size;
int status;
fd = socket(AF_INET, SOCK_DGRAM, /* protocol = */ 0);
if (fd < 0) {
syslog(LOG_ERR, "%s(%d): Failed"
" to open control socket.\n", __FUNCTION__, __LINE__);
return -1;
}
struct ethtool_drvinfo drvinfo = {.cmd = ETHTOOL_GDRVINFO};
struct ifreq req = {.ifr_data = (void *)&drvinfo};
strncpy(req.ifr_name, ifname, sizeof(req.ifr_name));
status = ioctl(fd, SIOCETHTOOL, &req);
if (status < 0) {
close(fd);
syslog(LOG_ERR, "%s(%d): Failed to get"
"driver information from %s:", __FUNCTION__, __LINE__, ifname);
return -1;
}
n_stats = (size_t)drvinfo.n_stats;
if (n_stats < 1) {
close(fd);
syslog(LOG_ERR, "%s(%d): No stats"
" available for %s", __FUNCTION__, __LINE__, ifname);
return -1;
}
stats_size = sizeof(struct ethtool_stats) + (n_stats * sizeof(uint64_t));
g_linux_stats = malloc(stats_size);
if (!g_linux_stats) {
close(fd);
syslog(LOG_ERR, "%s(%d): malloc failed.",
__FUNCTION__, __LINE__);
return -1;
}
g_linux_stats->cmd = ETHTOOL_GSTATS;
g_linux_stats->n_stats = n_stats;
req.ifr_data = (void *)g_linux_stats;
status = ioctl(fd, SIOCETHTOOL, &req);
if (status < 0) {
close(fd);
if (g_linux_stats)
free(g_linux_stats);
syslog(LOG_ERR, "%s(%d): Reading statistics"
" from %s failed:", __FUNCTION__, __LINE__, ifname);
return -1;
}
close(fd);
return 0;
}
int linux_get_if_stats(const char *ifname)
{
memset(&g_linux_ifstats, 0, sizeof(struct eth_stats));
syslog(LOG_INFO, "%s(%d): ifname is %s", __FUNCTION__, __LINE__, ifname);
if (linux_get_ifstats(ifname, &g_linux_ifstats) < 0)
return -1;
if (linux_get_ethtool_stats(ifname) < 0)
return -1;
return 0;
}
int linux_eth_get_stats(const char *ifname, struct eth_stats *s)
{
if (!s)
return -1;
if (linux_get_if_stats(ifname) < 0)
return -1;
s->tx_bytes = g_linux_ifstats.tx_bytes;
s->tx_packets = g_linux_ifstats.tx_packets;
s->tx_errors = g_linux_ifstats.tx_errors;
s->tx_ucast_packets = (uint64_t)g_linux_stats->data[iow_tx_unicast];
s->tx_mcast_packets = (uint64_t)g_linux_stats->data[iow_tx_multicast];
s->tx_bcast_packets = (uint64_t)g_linux_stats->data[iow_tx_broadcast];
s->tx_discard_packets = (uint64_t)g_linux_stats->data[iow_tx_dropped];
s->rx_bytes = g_linux_ifstats.rx_bytes;
s->rx_packets = (uint64_t)g_linux_stats->data[iow_rx_packets];
s->rx_errors = g_linux_ifstats.rx_errors;
s->rx_ucast_packets = (uint64_t)g_linux_stats->data[iow_rx_unicast];
s->rx_mcast_packets = (uint64_t)g_linux_stats->data[iow_rx_multicast];
s->rx_bcast_packets = (uint64_t)g_linux_stats->data[iow_rx_broadcast];
s->rx_discard_packets = (uint64_t)g_linux_stats->data[iow_rx_dropped];
/*FIXME: Doesn't exist a way to get the counter rx_unknown_packets.*/
s->rx_unknown_packets = 0;
free(g_linux_stats);
return 0;
}
int linux_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
{
int ret = 0;
if (linux_get_if_stats(ifname) < 0)
ret = -1;
rmon->tx.packets = (uint64_t)g_linux_stats->data[iow_tx_packets];
rmon->tx.bytes = (uint64_t)g_linux_stats->data[iow_tx_bytes];
rmon->tx.crc_err_packets = 0;
/* These two counters are marked zero because they dont
* hold much relevancy to Customer
*/
rmon->tx.under_sz_packets = 0;
rmon->tx.over_sz_packets = 0;
rmon->tx.packets_64bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt64];
rmon->tx.packets_65to127bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt65to127];
rmon->tx.packets_128to255bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt128to255];
rmon->tx.packets_256to511bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt256to511];
rmon->tx.packets_512to1023bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt512to1023];
rmon->tx.packets_1024to1518bytes = (uint64_t)g_linux_stats->data[iow_tx_pkt1024tomax];
rmon->rx.bytes = (uint64_t)g_linux_stats->data[iow_rx_byte];
rmon->rx.packets = (uint64_t)g_linux_stats->data[iow_rx_packets];
rmon->rx.bcast_packets = (uint64_t)g_linux_stats->data[iow_rx_broadcast];
rmon->rx.mcast_packets = (uint64_t)g_linux_stats->data[iow_rx_multicast];
rmon->rx.crc_err_packets = (uint64_t)g_linux_stats->data[iow_rx_crc_err];
rmon->rx.under_sz_packets = (uint64_t)g_linux_stats->data[iow_rx_undersize];
rmon->rx.over_sz_packets = (uint64_t)g_linux_stats->data[iow_rx_oversize];
rmon->rx.packets_64bytes = (uint64_t)g_linux_stats->data[iow_rx_pkt64];
rmon->rx.packets_65to127bytes = (uint64_t)g_linux_stats->data[iow_rx_pkt65to127];
free(g_linux_stats);
return ret;
}
......@@ -5,6 +5,11 @@
extern "C" {
#endif
int linux_eth_set_link_settings(const char *ifname, struct eth_link link);
int linux_eth_get_link_settings(const char *ifname, struct eth_link *link);
int linux_eth_poweron_phy(const char *ifname, struct eth_phy p);
int linux_eth_poweroff_phy(const char *ifname, struct eth_phy p);
int linux_eth_reset_phy(const char *ifname, int phy_id);
int linux_eth_get_stats(const char *ifname, struct eth_stats *s);
int linux_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon);
......
/*
* linux_eth.c - Linux based statistics collection ubus methods.
* mtk_eth.c - Linux based statistics collection ubus methods.
*
* Copyright (C) 2023 iopsys Software Solutions AB. All rights reserved.
*
......@@ -39,70 +39,69 @@
#include <linux/sockios.h>
#include <easy/easy.h>
#include <easy/if_utils.h>
#include "../ethernet.h"
#include "linux_eth.h"
#include "ethernet.h"
#include "mtk_eth.h"
typedef enum {
tx_packets = 0,
tx_bytes,
rx_packets,
rx_bytes,
TxDrop,
TxCrcErr,
TxUnicast,
TxMulticast,
TxBroadcast,
TxCollision,
TxSingleCollision,
TxMultipleCollision,
TxDeferred,
TxLateCollision,
TxExcessiveCollistion,
TxPause,
TxPktSz64,
TxPktSz65To127,
TxPktSz128To255,
TxPktSz256To511,
TxPktSz512To1023,
Tx1024ToMax,
TxBytes,
RxDrop,
RxFiltering,
RxUnicast,
RxMulticast,
RxBroadcast,
RxAlignErr,
RxCrcErr,
RxUnderSizeErr,
RxFragErr,
RxOverSzErr,
RxJabberErr,
RxPause,
RxPktSz64,
RxPktSz65To127,
RxPktSz128To255,
RxPktSz256To511,
RxPktSz512To1023,
RxPktSz1024ToMax,
RxBytes,
RxCtrlDrop,
RxIngressDrop,
RxArlDrop,
STATS_END,
} idx;
struct ethnic_stats {
iow_tx_packets = 0,
iow_tx_bytes,
iow_rx_packets,
iow_rx_bytes,
iow_TxDrop,
iow_TxCrcErr,
iow_TxUnicast,
iow_TxMulticast,
iow_TxBroadcast,
iow_TxCollision,
iow_TxSingleCollision,
iow_TxMultipleCollision,
iow_TxDeferred,
iow_TxLateCollision,
iow_TxExcessiveCollistion,
iow_TxPause,
iow_TxPktSz64,
iow_TxPktSz65To127,
iow_TxPktSz128To255,
iow_TxPktSz256To511,
iow_TxPktSz512To1023,
iow_Tx1024ToMax,
iow_TxBytes,
iow_RxDrop,
iow_RxFiltering,
iow_RxUnicast,
iow_RxMulticast,
iow_RxBroadcast,
iow_RxAlignErr,
iow_RxCrcErr,
iow_RxUnderSizeErr,
iow_RxFragErr,
iow_RxOverSzErr,
iow_RxJabberErr,
iow_RxPause,
iow_RxPktSz64,
iow_RxPktSz65To127,
iow_RxPktSz128To255,
iow_RxPktSz256To511,
iow_RxPktSz512To1023,
iow_RxPktSz1024ToMax,
iow_RxBytes,
iow_RxCtrlDrop,
iow_RxIngressDrop,
iow_RxArlDrop,
iow_STATS_END,
} g_indx;
struct mtk_ethnic_stats {
uint32_t cmd;
uint32_t n_stats;
uint64_t data[STATS_END];
} stat;
uint64_t data[iow_STATS_END];
} g_mtk_stat;
static struct eth_stats ifstats;
static struct eth_stats g_mtk_ifstats;
static int get_ifstats(const char *ifname, struct eth_stats *s)
static int mtk_get_ifstats(const char *ifname, struct eth_stats *s)
{
struct if_stats easy_ifstat;
if (!s)
......@@ -135,12 +134,13 @@ static int get_ifstats(const char *ifname, struct eth_stats *s)
return 0;
}
int get_ethtool_stats(const char *ifname)
int mtk_get_ethtool_stats(const char *ifname)
{
int ret = 0;
stat.cmd = ETHTOOL_GSTATS;
if (0 != eth_ioctl(ifname, SIOCETHTOOL, &stat, sizeof(struct ethnic_stats)))
g_mtk_stat.cmd = ETHTOOL_GSTATS;
if (0 != eth_ioctl(ifname, SIOCETHTOOL, &g_mtk_stat, sizeof(struct mtk_ethnic_stats)))
ret = -1;
if (ret)
......@@ -149,90 +149,85 @@ int get_ethtool_stats(const char *ifname)
return ret;
}
int get_stats(const char *ifname)
int mtk_get_if_stats(const char *ifname)
{
memset(&ifstats, 0, sizeof(struct eth_stats));
memset(&stat, 0, sizeof(struct ethnic_stats));
memset(&g_mtk_ifstats, 0, sizeof(struct eth_stats));
memset(&g_mtk_stat, 0, sizeof(struct mtk_ethnic_stats));
syslog(LOG_INFO, "%s(%d): ifname is %s", __FUNCTION__, __LINE__, ifname);
if (get_ifstats(ifname, &ifstats) < 0)
if (mtk_get_ifstats(ifname, &g_mtk_ifstats) < 0)
return -1;
if (get_ethtool_stats(ifname) < 0)
if (mtk_get_ethtool_stats(ifname) < 0)
return -1;
return 0;
}
int linux_eth_get_stats(const char *ifname, struct eth_stats *s)
int mtk_eth_get_stats(const char *ifname, struct eth_stats *s)
{
if (!s)
return -1;
if (get_stats(ifname) < 0)
if (mtk_get_if_stats(ifname) < 0)
return -1;
s->tx_bytes = ifstats.tx_bytes;
s->tx_packets = ifstats.tx_packets;
s->tx_errors = ifstats.tx_errors;
s->tx_ucast_packets = stat.data[TxUnicast];
s->tx_mcast_packets = stat.data[TxMulticast];
s->tx_bcast_packets = stat.data[TxBroadcast];
s->tx_discard_packets = stat.data[TxDrop];
s->rx_bytes = ifstats.rx_bytes;
s->rx_packets = stat.data[rx_packets];
s->rx_errors = ifstats.rx_errors;
s->rx_ucast_packets = stat.data[RxUnicast];
s->rx_mcast_packets = stat.data[RxMulticast];
s->rx_bcast_packets = stat.data[RxBroadcast];
s->rx_discard_packets = stat.data[RxDrop];
s->tx_bytes = g_mtk_ifstats.tx_bytes;
s->tx_packets = g_mtk_ifstats.tx_packets;
s->tx_errors = g_mtk_ifstats.tx_errors;
s->tx_ucast_packets = g_mtk_stat.data[iow_TxUnicast];
s->tx_mcast_packets = g_mtk_stat.data[iow_TxMulticast];
s->tx_bcast_packets = g_mtk_stat.data[iow_TxBroadcast];
s->tx_discard_packets = g_mtk_stat.data[iow_TxDrop];
s->rx_bytes = g_mtk_ifstats.rx_bytes;
s->rx_packets = g_mtk_stat.data[iow_rx_packets];
s->rx_errors = g_mtk_ifstats.rx_errors;
s->rx_ucast_packets = g_mtk_stat.data[iow_RxUnicast];
s->rx_mcast_packets = g_mtk_stat.data[iow_RxMulticast];
s->rx_bcast_packets = g_mtk_stat.data[iow_RxBroadcast];
s->rx_discard_packets = g_mtk_stat.data[iow_RxDrop];
/*FIXME: Doesn't exist a way to get the counter rx_unknown_packets.*/
s->rx_unknown_packets = 0;
return 0;
}
int linux_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
int mtk_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
{
int ret = 0;
if (get_stats(ifname) < 0)
if (mtk_get_if_stats(ifname) < 0)
ret = -1;
rmon->tx.packets = stat.data[tx_packets];
rmon->tx.bytes = stat.data[tx_bytes];
rmon->tx.crc_err_packets = stat.data[TxCrcErr];
rmon->tx.packets = g_mtk_stat.data[iow_tx_packets];
rmon->tx.bytes = g_mtk_stat.data[iow_tx_bytes];
rmon->tx.crc_err_packets = g_mtk_stat.data[iow_TxCrcErr];
/* These two counters are marked zero because they dont
* hold much relevancy to Customer
*/
rmon->tx.under_sz_packets = 0;
rmon->tx.over_sz_packets = 0;
rmon->tx.packets_64bytes = stat.data[TxPktSz64];
rmon->tx.packets_65to127bytes = stat.data[TxPktSz65To127];
rmon->tx.packets_128to255bytes = stat.data[TxPktSz128To255];
rmon->tx.packets_256to511bytes = stat.data[TxPktSz256To511];
rmon->tx.packets_512to1023bytes = stat.data[TxPktSz512To1023];
rmon->tx.packets_1024to1518bytes = stat.data[Tx1024ToMax];
rmon->rx.bytes = stat.data[RxBytes];
rmon->rx.packets = stat.data[rx_packets];
rmon->rx.bcast_packets = stat.data[RxBroadcast];
rmon->rx.mcast_packets = stat.data[RxMulticast];
rmon->rx.crc_err_packets = stat.data[RxCrcErr];
rmon->rx.under_sz_packets = stat.data[RxUnderSizeErr];
rmon->rx.over_sz_packets = stat.data[RxOverSzErr];
rmon->rx.packets_64bytes = stat.data[RxPktSz64];
rmon->rx.packets_65to127bytes = stat.data[RxPktSz65To127];
rmon->rx.packets_128to255bytes = stat.data[RxPktSz128To255];
rmon->rx.packets_256to511bytes = stat.data[RxPktSz256To511];
rmon->rx.packets_512to1023bytes = stat.data[RxPktSz512To1023];
rmon->rx.packets_1024to1518bytes = stat.data[RxPktSz1024ToMax];
rmon->tx.packets_64bytes = g_mtk_stat.data[iow_TxPktSz64];
rmon->tx.packets_65to127bytes = g_mtk_stat.data[iow_TxPktSz65To127];
rmon->tx.packets_128to255bytes = g_mtk_stat.data[iow_TxPktSz128To255];
rmon->tx.packets_256to511bytes = g_mtk_stat.data[iow_TxPktSz256To511];
rmon->tx.packets_512to1023bytes = g_mtk_stat.data[iow_TxPktSz512To1023];
rmon->tx.packets_1024to1518bytes = g_mtk_stat.data[iow_Tx1024ToMax];
rmon->rx.bytes = g_mtk_stat.data[iow_RxBytes];
rmon->rx.packets = g_mtk_stat.data[iow_rx_packets];
rmon->rx.bcast_packets = g_mtk_stat.data[iow_RxBroadcast];
rmon->rx.mcast_packets = g_mtk_stat.data[iow_RxMulticast];
rmon->rx.crc_err_packets = g_mtk_stat.data[iow_RxCrcErr];
rmon->rx.under_sz_packets = g_mtk_stat.data[iow_RxUnderSizeErr];
rmon->rx.over_sz_packets = g_mtk_stat.data[iow_RxOverSzErr];
rmon->rx.packets_64bytes = g_mtk_stat.data[iow_RxPktSz64];
rmon->rx.packets_65to127bytes = g_mtk_stat.data[iow_RxPktSz65To127];
rmon->rx.packets_128to255bytes = g_mtk_stat.data[iow_RxPktSz128To255];
rmon->rx.packets_256to511bytes = g_mtk_stat.data[iow_RxPktSz256To511];
rmon->rx.packets_512to1023bytes = g_mtk_stat.data[iow_RxPktSz512To1023];
rmon->rx.packets_1024to1518bytes = g_mtk_stat.data[iow_RxPktSz1024ToMax];
return ret;
}
const struct eth_ops linux_eth_ops = {
.ifname = "lan",
.get_stats = linux_eth_get_stats,
.get_rmon_stats = linux_eth_get_rmon_stats,
};
#ifndef MTK_ETH_H
#define MTK_ETH_H
#ifdef __cplusplus
extern "C" {
#endif
int mtk_eth_get_stats(const char *ifname, struct eth_stats *s);
int mtk_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon);
#ifdef __cplusplus
}
#endif
#endif /* MTK_ETH_H */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment