diff --git a/bcm/bcm.c b/bcm/bcm.c
index 643e6f85c649cbac669a5f9dbffe9c79bd27f890..805c154cd1dda0e673b109fcad3df798c80a0a94 100644
--- a/bcm/bcm.c
+++ b/bcm/bcm.c
@@ -38,6 +38,13 @@
#include "bcmswapitypes.h"
#include "bcmnet.h"
+/* invalid stat counter values */
+#define INVALID_UINT64 UINT64_MAX
+#define INVALID_UINT32 UINT32_MAX
+#define INVALID_UINT16 UINT16_MAX
+#define INVALID_UINT8 UINT8_MAX
+
+
#define PHYID_2_MII_IOCTL(phy_id, mii_ioctl_data) \
{mii_ioctl_data->val_out = (phy_id >> 24 ) & 0xff; \
mii_ioctl_data->phy_id = phy_id & 0x1f;}
@@ -212,14 +219,124 @@ int bcm_eth_reset_phy(const char *name, int phy_id)
return eth_mii_reset_phy(name, phy_id & 0x1f);
}
+static int bcm_eth_get_stats_from_proc(const char *ifname, struct eth_stats *s)
+{
+ unsigned long rx_bytes, rx_packets, rx_err, rx_drop;
+ unsigned long rx_fifo, rx_frame, rx_comp, rx_multi;
+ unsigned long tx_bytes, tx_packets, tx_err, tx_drop;
+ unsigned long tx_fifo, tx_coll, tx_carr, tx_comp;
+ unsigned long tx_mcast_packets, rx_mcast_bytes, tx_mcast_bytes;
+ unsigned long rx_ucast_packets, tx_ucast_packets;
+ unsigned long rx_bcast_packets, tx_bcast_packets;
+ unsigned long rx_err_unknown;
+ char cmdbuf[512] = {0};
+ char *ptr;
+ int ret;
+
+ chrCmd(cmdbuf, sizeof(cmdbuf),
+ "cat /proc/net/dev_extstats | grep %s:",
+ ifname);
-int bcm_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *tx,
- struct eth_rmon_stats *rx)
+ if (cmdbuf[0] == '\0' || strncmp(cmdbuf, ifname, strlen(ifname)))
+ return -1;
+
+ ptr = cmdbuf + strlen(ifname) + strlen(":");
+ ret = sscanf(ptr,
+ " %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+ " %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+ &rx_bytes, &rx_packets, &rx_err, &rx_drop,
+ &rx_fifo, &rx_frame, &rx_comp, &rx_multi,
+ &tx_bytes, &tx_packets, &tx_err, &tx_drop,
+ &tx_fifo, &tx_coll, &tx_carr, &tx_comp,
+ &tx_mcast_packets, &rx_mcast_bytes, &tx_mcast_bytes,
+ &rx_ucast_packets, &tx_ucast_packets,
+ &rx_bcast_packets, &tx_bcast_packets,
+ &rx_err_unknown);
+
+ if (ret != 12)
+ return -1;
+
+ s->tx_bytes = tx_bytes;
+ s->rx_bytes = rx_bytes;
+ s->tx_packets = tx_packets;
+ s->rx_packets = rx_packets;
+ s->tx_errors = tx_err;
+ s->rx_errors = rx_err;
+ s->tx_ucast_packets = tx_ucast_packets;
+ s->rx_ucast_packets = rx_ucast_packets;
+ s->tx_mcast_packets = tx_mcast_packets;
+ s->rx_mcast_packets = INVALID_UINT32; /* 'rx_mcast_bytes' available */
+ s->tx_bcast_packets = tx_bcast_packets;
+ s->rx_bcast_packets = rx_bcast_packets;
+ s->tx_discard_packets = tx_drop;
+ s->rx_discard_packets = rx_drop;
+ s->rx_unknown_packets = rx_err_unknown;
+
+ return 0;
+}
+
+int bcm_eth_get_stats(const char *ifname, struct eth_stats *s)
{
struct ethswctl_data data;
+ int unit = -1;
+ int port = -1;
+ int ret_proc;
int ret;
+
+ /* get from proc first */
+ ret_proc = bcm_eth_get_stats_from_proc(ifname, s);
+
+ memset(&data, 0, sizeof(struct ethswctl_data));
+ ret = bcm_eth_get_unit_port(ifname, &unit, &port);
+ if (ret)
+ return ret_proc == 0 ? 0 : -1;
+
+ data.op = ETHSWEMACGET;
+ data.port = port;
+ data.unit = unit;
+ data.queue = -1; /* all */
+
+ ret = eth_ioctl(ifname, SIOCETHSWCTLOPS, &data,
+ sizeof(struct ethswctl_data));
+ if (ret != 0) {
+ fprintf(stderr, "ioctl failed! ret = %d\n", ret);
+ return ret_proc == 0 ? 0 : -1;
+ }
+
+ s->tx_bytes = data.emac_stats_s.tx_byte;
+ s->rx_bytes = data.emac_stats_s.rx_byte;
+ s->tx_packets = data.emac_stats_s.tx_packet;
+ s->rx_packets = data.emac_stats_s.rx_packet;
+ s->tx_errors = data.emac_stats_s.tx_error;
+ s->rx_errors = data.emac_stats_s.rx_fcs_error +
+ data.emac_stats_s.rx_alignment_error +
+ data.emac_stats_s.rx_frame_length_error +
+ data.emac_stats_s.rx_code_error +
+ data.emac_stats_s.rx_carrier_sense_error +
+ data.emac_stats_s.rx_undersize_packet +
+ data.emac_stats_s.rx_oversize_packet;
+
+
+ s->tx_ucast_packets = data.emac_stats_s.tx_unicast_packet;
+ s->rx_ucast_packets = data.emac_stats_s.rx_unicast_packet;
+ s->tx_mcast_packets = data.emac_stats_s.tx_multicast_packet;
+ s->rx_mcast_packets = data.emac_stats_s.rx_multicast_packet;
+ s->tx_bcast_packets = data.emac_stats_s.tx_broadcast_packet;
+ s->rx_bcast_packets = data.emac_stats_s.rx_broadcast_packet;
+ s->rx_unknown_packets = data.emac_stats_s.rx_unknown_opcode;
+
+ return 0;
+}
+
+int bcm_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
+{
+ struct ethswctl_data data;
int unit = -1;
int port = -1;
+ int ret;
+
+ if (!rmon)
+ return -1;
memset(&data, 0, sizeof(struct ethswctl_data));
ret = bcm_eth_get_unit_port(ifname, &unit, &port);
@@ -230,7 +347,8 @@ int bcm_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *tx,
data.op = ETHSWEMACGET;
data.port = port;
data.unit = unit;
- data.queue = -1; /* prio_q = -1 */
+ data.queue = rmon->txq < 0 ? -1 : rmon->txq;
+
ret = eth_ioctl(ifname, SIOCETHSWCTLOPS, &data,
sizeof(struct ethswctl_data));
@@ -239,36 +357,33 @@ int bcm_eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *tx,
return -1;
}
- tx->all_q = true;
- tx->bytes = data.emac_stats_s.tx_byte;
- tx->packets = data.emac_stats_s.tx_packet;
- tx->bcast_packets = data.emac_stats_s.tx_broadcast_packet;
- tx->mcast_packets = data.emac_stats_s.tx_multicast_packet;
- tx->crc_err_packets = data.emac_stats_s.tx_fcs_error;
- tx->under_sz_packets = data.emac_stats_s.tx_undersize_frame;
- tx->over_sz_packets = data.emac_stats_s.tx_oversize_frame;
- tx->packets_64bytes = data.emac_stats_s.tx_frame_64;
- tx->packets_65to127bytes = data.emac_stats_s.tx_frame_65_127;
- tx->packets_128to255bytes = data.emac_stats_s.tx_frame_128_255;
- tx->packets_256to511bytes = data.emac_stats_s.tx_frame_256_511;
- tx->packets_512to1023bytes = data.emac_stats_s.tx_frame_512_1023;
- tx->packets_1024to1518bytes = data.emac_stats_s.tx_frame_1024_1518;
-
-
- rx->all_q = true;
- rx->bytes = data.emac_stats_s.rx_byte;
- rx->packets = data.emac_stats_s.rx_packet;
- rx->bcast_packets = data.emac_stats_s.rx_broadcast_packet;
- rx->mcast_packets = data.emac_stats_s.rx_multicast_packet;
- rx->crc_err_packets = data.emac_stats_s.rx_fcs_error;
- rx->under_sz_packets = data.emac_stats_s.rx_undersize_packet;
- rx->over_sz_packets = data.emac_stats_s.rx_oversize_packet;
- rx->packets_64bytes = data.emac_stats_s.rx_frame_64;
- rx->packets_65to127bytes = data.emac_stats_s.rx_frame_65_127;
- rx->packets_128to255bytes = data.emac_stats_s.rx_frame_128_255;
- rx->packets_256to511bytes = data.emac_stats_s.rx_frame_256_511;
- rx->packets_512to1023bytes = data.emac_stats_s.rx_frame_512_1023;
- rx->packets_1024to1518bytes = data.emac_stats_s.rx_frame_1024_1518;
+ rmon->tx.bytes = data.emac_stats_s.tx_byte;
+ rmon->tx.packets = data.emac_stats_s.tx_packet;
+ rmon->tx.bcast_packets = data.emac_stats_s.tx_broadcast_packet;
+ rmon->tx.mcast_packets = data.emac_stats_s.tx_multicast_packet;
+ rmon->tx.crc_err_packets = data.emac_stats_s.tx_fcs_error;
+ rmon->tx.under_sz_packets = data.emac_stats_s.tx_undersize_frame;
+ rmon->tx.over_sz_packets = data.emac_stats_s.tx_oversize_frame;
+ rmon->tx.packets_64bytes = data.emac_stats_s.tx_frame_64;
+ rmon->tx.packets_65to127bytes = data.emac_stats_s.tx_frame_65_127;
+ rmon->tx.packets_128to255bytes = data.emac_stats_s.tx_frame_128_255;
+ rmon->tx.packets_256to511bytes = data.emac_stats_s.tx_frame_256_511;
+ rmon->tx.packets_512to1023bytes = data.emac_stats_s.tx_frame_512_1023;
+ rmon->tx.packets_1024to1518bytes = data.emac_stats_s.tx_frame_1024_1518;
+
+ rmon->rx.bytes = data.emac_stats_s.rx_byte;
+ rmon->rx.packets = data.emac_stats_s.rx_packet;
+ rmon->rx.bcast_packets = data.emac_stats_s.rx_broadcast_packet;
+ rmon->rx.mcast_packets = data.emac_stats_s.rx_multicast_packet;
+ rmon->rx.crc_err_packets = data.emac_stats_s.rx_fcs_error;
+ rmon->rx.under_sz_packets = data.emac_stats_s.rx_undersize_packet;
+ rmon->rx.over_sz_packets = data.emac_stats_s.rx_oversize_packet;
+ rmon->rx.packets_64bytes = data.emac_stats_s.rx_frame_64;
+ rmon->rx.packets_65to127bytes = data.emac_stats_s.rx_frame_65_127;
+ rmon->rx.packets_128to255bytes = data.emac_stats_s.rx_frame_128_255;
+ rmon->rx.packets_256to511bytes = data.emac_stats_s.rx_frame_256_511;
+ rmon->rx.packets_512to1023bytes = data.emac_stats_s.rx_frame_512_1023;
+ rmon->rx.packets_1024to1518bytes = data.emac_stats_s.rx_frame_1024_1518;
return 0;
}
@@ -279,7 +394,7 @@ const struct eth_ops bcm_eth_ops = {
//.down = bcm_eth_down,
.set_link_settings = bcm_eth_set_link_settings,
.get_link_settings = bcm_eth_get_link_settings,
- //.get_stats = bcm_eth_get_stats,
+ .get_stats = bcm_eth_get_stats,
.get_rmon_stats = bcm_eth_get_rmon_stats,
.poweron_phy = bcm_eth_poweron_phy,
.poweroff_phy = bcm_eth_poweroff_phy,
diff --git a/ethernet.c b/ethernet.c
index 7e4ddcb6f554c01af3fa3cf202af235a5cd6f543..6650810397d95ed654fdca305963bc1caed5503d 100644
--- a/ethernet.c
+++ b/ethernet.c
@@ -124,13 +124,12 @@ int eth_get_stats(const char *ifname, struct eth_stats *s)
return -1;
}
-int eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *tx,
- struct eth_rmon_stats *rx)
+int eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon)
{
const struct eth_ops *eth = get_eth_driver(ifname);
if (eth && eth->get_rmon_stats)
- return eth->get_rmon_stats(ifname, tx, rx);
+ return eth->get_rmon_stats(ifname, rmon);
return -1;
}
diff --git a/ethernet.h b/ethernet.h
index 3cf3cf3f93a24c55448f8dc565b3a96c26885b6c..3cb186dd37f2988412d0c8cdd076fa2a0ff2a39e 100644
--- a/ethernet.h
+++ b/ethernet.h
@@ -47,23 +47,26 @@ enum rmon_status {
/* struct eth_rmon_stats - ethernet rmon counters */
struct eth_rmon_stats {
- enum rmon_status status;
+#define ETH_TXQ_ALL -1
+ int txq; /* tx priority queue number or -1 */
uint16_t vlanid; /* 0..4094 */
- bool all_q;
- uint32_t drop_events;
- unsigned long bytes;
- unsigned long packets;
- unsigned long bcast_packets;
- unsigned long mcast_packets;
- uint32_t crc_err_packets;
- uint32_t under_sz_packets;
- uint32_t over_sz_packets;
- unsigned long packets_64bytes;
- unsigned long packets_65to127bytes;
- unsigned long packets_128to255bytes;
- unsigned long packets_256to511bytes;
- unsigned long packets_512to1023bytes;
- unsigned long packets_1024to1518bytes;
+ enum rmon_status status;
+ struct {
+ uint32_t drop_events;
+ unsigned long bytes;
+ unsigned long packets;
+ unsigned long bcast_packets;
+ unsigned long mcast_packets;
+ uint32_t crc_err_packets;
+ uint32_t under_sz_packets;
+ uint32_t over_sz_packets;
+ unsigned long packets_64bytes;
+ unsigned long packets_65to127bytes;
+ unsigned long packets_128to255bytes;
+ unsigned long packets_256to511bytes;
+ unsigned long packets_512to1023bytes;
+ unsigned long packets_1024to1518bytes;
+ } tx, rx;
};
@@ -159,8 +162,7 @@ struct eth_device {
uint32_t num_ifaces;
uint32_t num_links;
uint32_t num_vlans;
- struct eth_rmon_stats tx,
- rx;
+ struct eth_rmon_stats rmon;
struct eth_iface *ifs;
struct eth_link *links;
struct eth_vlan *vlans;
@@ -198,8 +200,7 @@ struct eth_ops {
int (*get_stats)(const char *ifname, struct eth_stats *s);
int (*get_info)(const char *ifname, struct eth_info *info);
- int (*get_rmon_stats)(const char *ifname, struct eth_rmon_stats *tx,
- struct eth_rmon_stats *rx);
+ int (*get_rmon_stats)(const char *ifname, struct eth_rmon_stats *rmon);
};
@@ -212,8 +213,7 @@ int eth_get_operstate(const char *ifname, ifopstatus_t *s);
int eth_set_operstate(const char *ifname, ifopstatus_t s);
int eth_get_stats(const char *ifname, struct eth_stats *c);
int eth_get_info(const char *ifname, struct eth_info *info);
-int eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *tx,
- struct eth_rmon_stats *rx);
+int eth_get_rmon_stats(const char *ifname, struct eth_rmon_stats *rmon);
int eth_reset_phy(const char *ifname, int phy_id);
int eth_poweroff_phy(const char *ifname, struct eth_phy p);