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