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);