Add a new sysctl node 'dev.bfe.N.stats' that shows various MAC

counters for Rx/Tx statistics. Various counters in ifnet is also
updated with these hardware counters.

Tested by:	kib, Gleb Kurtsou gleb.kurtsou at gmail dot com
		Ulrich Spoerlein uspoerlein at gmail dot com
This commit is contained in:
Pyun YongHyeon 2008-08-22 06:46:55 +00:00
parent 7dc843ca92
commit 861cf54c59
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=181994
2 changed files with 300 additions and 53 deletions

View File

@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <net/bpf.h>
#include <net/if.h>
@ -125,6 +126,7 @@ static int bfe_dma_alloc (struct bfe_softc *);
static void bfe_dma_free (struct bfe_softc *sc);
static void bfe_dma_map (void *, bus_dma_segment_t *, int, int);
static void bfe_cam_write (struct bfe_softc *, u_char *, int);
static int sysctl_bfe_stats (SYSCTL_HANDLER_ARGS);
static device_method_t bfe_methods[] = {
/* Device interface */
@ -473,6 +475,11 @@ bfe_attach(device_t dev)
goto fail;
}
SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
"stats", CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_bfe_stats,
"I", "Statistics");
/* Set up ifnet structure */
ifp = sc->bfe_ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
@ -877,7 +884,7 @@ bfe_pci_setup(struct bfe_softc *sc, u_int32_t cores)
static void
bfe_clear_stats(struct bfe_softc *sc)
{
u_long reg;
uint32_t reg;
BFE_LOCK_ASSERT(sc);
@ -1082,6 +1089,8 @@ bfe_set_rx_mode(struct bfe_softc *sc)
u_int32_t val;
int i = 0;
BFE_LOCK_ASSERT(sc);
val = CSR_READ_4(sc, BFE_RXCONF);
if (ifp->if_flags & IFF_PROMISC)
@ -1241,17 +1250,89 @@ bfe_setupphy(struct bfe_softc *sc)
static void
bfe_stats_update(struct bfe_softc *sc)
{
u_long reg;
u_int32_t *val;
struct bfe_hw_stats *stats;
struct ifnet *ifp;
uint32_t mib[BFE_MIB_CNT];
uint32_t reg, *val;
val = &sc->bfe_hwstats.tx_good_octets;
for (reg = BFE_TX_GOOD_O; reg <= BFE_TX_PAUSE; reg += 4) {
*val++ += CSR_READ_4(sc, reg);
}
val = &sc->bfe_hwstats.rx_good_octets;
for (reg = BFE_RX_GOOD_O; reg <= BFE_RX_NPAUSE; reg += 4) {
*val++ += CSR_READ_4(sc, reg);
}
BFE_LOCK_ASSERT(sc);
val = mib;
CSR_WRITE_4(sc, BFE_MIB_CTRL, BFE_MIB_CLR_ON_READ);
for (reg = BFE_TX_GOOD_O; reg <= BFE_TX_PAUSE; reg += 4)
*val++ = CSR_READ_4(sc, reg);
for (reg = BFE_RX_GOOD_O; reg <= BFE_RX_NPAUSE; reg += 4)
*val++ = CSR_READ_4(sc, reg);
ifp = sc->bfe_ifp;
stats = &sc->bfe_stats;
/* Tx stat. */
stats->tx_good_octets += mib[MIB_TX_GOOD_O];
stats->tx_good_frames += mib[MIB_TX_GOOD_P];
stats->tx_octets += mib[MIB_TX_O];
stats->tx_frames += mib[MIB_TX_P];
stats->tx_bcast_frames += mib[MIB_TX_BCAST];
stats->tx_mcast_frames += mib[MIB_TX_MCAST];
stats->tx_pkts_64 += mib[MIB_TX_64];
stats->tx_pkts_65_127 += mib[MIB_TX_65_127];
stats->tx_pkts_128_255 += mib[MIB_TX_128_255];
stats->tx_pkts_256_511 += mib[MIB_TX_256_511];
stats->tx_pkts_512_1023 += mib[MIB_TX_512_1023];
stats->tx_pkts_1024_max += mib[MIB_TX_1024_MAX];
stats->tx_jabbers += mib[MIB_TX_JABBER];
stats->tx_oversize_frames += mib[MIB_TX_OSIZE];
stats->tx_frag_frames += mib[MIB_TX_FRAG];
stats->tx_underruns += mib[MIB_TX_URUNS];
stats->tx_colls += mib[MIB_TX_TCOLS];
stats->tx_single_colls += mib[MIB_TX_SCOLS];
stats->tx_multi_colls += mib[MIB_TX_MCOLS];
stats->tx_excess_colls += mib[MIB_TX_ECOLS];
stats->tx_late_colls += mib[MIB_TX_LCOLS];
stats->tx_deferrals += mib[MIB_TX_DEFERED];
stats->tx_carrier_losts += mib[MIB_TX_CLOST];
stats->tx_pause_frames += mib[MIB_TX_PAUSE];
/* Rx stat. */
stats->rx_good_octets += mib[MIB_RX_GOOD_O];
stats->rx_good_frames += mib[MIB_RX_GOOD_P];
stats->rx_octets += mib[MIB_RX_O];
stats->rx_frames += mib[MIB_RX_P];
stats->rx_bcast_frames += mib[MIB_RX_BCAST];
stats->rx_mcast_frames += mib[MIB_RX_MCAST];
stats->rx_pkts_64 += mib[MIB_RX_64];
stats->rx_pkts_65_127 += mib[MIB_RX_65_127];
stats->rx_pkts_128_255 += mib[MIB_RX_128_255];
stats->rx_pkts_256_511 += mib[MIB_RX_256_511];
stats->rx_pkts_512_1023 += mib[MIB_RX_512_1023];
stats->rx_pkts_1024_max += mib[MIB_RX_1024_MAX];
stats->rx_jabbers += mib[MIB_RX_JABBER];
stats->rx_oversize_frames += mib[MIB_RX_OSIZE];
stats->rx_frag_frames += mib[MIB_RX_FRAG];
stats->rx_missed_frames += mib[MIB_RX_MISS];
stats->rx_crc_align_errs += mib[MIB_RX_CRCA];
stats->rx_runts += mib[MIB_RX_USIZE];
stats->rx_crc_errs += mib[MIB_RX_CRC];
stats->rx_align_errs += mib[MIB_RX_ALIGN];
stats->rx_symbol_errs += mib[MIB_RX_SYM];
stats->rx_pause_frames += mib[MIB_RX_PAUSE];
stats->rx_control_frames += mib[MIB_RX_NPAUSE];
/* Update counters in ifnet. */
ifp->if_opackets += (u_long)mib[MIB_TX_GOOD_P];
ifp->if_collisions += (u_long)mib[MIB_TX_TCOLS];
ifp->if_oerrors += (u_long)mib[MIB_TX_URUNS] +
(u_long)mib[MIB_TX_ECOLS] +
(u_long)mib[MIB_TX_DEFERED] +
(u_long)mib[MIB_TX_CLOST];
ifp->if_ipackets += (u_long)mib[MIB_RX_GOOD_P];
ifp->if_ierrors += mib[MIB_RX_JABBER] +
mib[MIB_RX_MISS] +
mib[MIB_RX_CRCA] +
mib[MIB_RX_USIZE] +
mib[MIB_RX_CRC] +
mib[MIB_RX_ALIGN] +
mib[MIB_RX_SYM];
}
static void
@ -1283,7 +1364,6 @@ bfe_txeof(struct bfe_softc *sc)
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->bfe_txmbuf_tag, r->bfe_map);
ifp->if_opackets++;
m_freem(r->bfe_mbuf);
r->bfe_mbuf = NULL;
}
@ -1343,9 +1423,6 @@ bfe_rxeof(struct bfe_softc *sc)
/* flag an error and try again */
if ((len > ETHER_MAX_LEN+32) || (flags & BFE_RX_FLAG_ERRORS)) {
ifp->if_ierrors++;
if (flags & BFE_RX_FLAG_SERR)
ifp->if_collisions++;
m_freem(m);
continue;
}
@ -1354,7 +1431,6 @@ bfe_rxeof(struct bfe_softc *sc)
m_adj(m, BFE_RX_OFFSET);
m->m_len = m->m_pkthdr.len = len;
ifp->if_ipackets++;
m->m_pkthdr.rcvif = ifp;
BFE_UNLOCK(sc);
(*ifp->if_input)(ifp, m);
@ -1373,7 +1449,7 @@ bfe_intr(void *xsc)
{
struct bfe_softc *sc = xsc;
struct ifnet *ifp;
u_int32_t istat, flag;
u_int32_t istat;
ifp = sc->bfe_ifp;
@ -1396,6 +1472,14 @@ bfe_intr(void *xsc)
return;
}
/* A packet was received */
if (istat & BFE_ISTAT_RX)
bfe_rxeof(sc);
/* A packet was sent */
if (istat & BFE_ISTAT_TX)
bfe_txeof(sc);
if (istat & BFE_ISTAT_ERRORS) {
if (istat & BFE_ISTAT_DSCE) {
@ -1412,27 +1496,10 @@ bfe_intr(void *xsc)
BFE_UNLOCK(sc);
return;
}
flag = CSR_READ_4(sc, BFE_DMATX_STAT);
if (flag & BFE_STAT_EMASK)
ifp->if_oerrors++;
flag = CSR_READ_4(sc, BFE_DMARX_STAT);
if (flag & BFE_RX_FLAG_ERRORS)
ifp->if_ierrors++;
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
bfe_init_locked(sc);
}
/* A packet was received */
if (istat & BFE_ISTAT_RX)
bfe_rxeof(sc);
/* A packet was sent */
if (istat & BFE_ISTAT_TX)
bfe_txeof(sc);
/* We have packets pending, fire them out */
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
bfe_start_locked(ifp);
@ -1805,3 +1872,103 @@ bfe_stop(struct bfe_softc *sc)
bfe_tx_ring_free(sc);
bfe_rx_ring_free(sc);
}
static int
sysctl_bfe_stats(SYSCTL_HANDLER_ARGS)
{
struct bfe_softc *sc;
struct bfe_hw_stats *stats;
int error, result;
result = -1;
error = sysctl_handle_int(oidp, &result, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
if (result != 1)
return (error);
sc = (struct bfe_softc *)arg1;
stats = &sc->bfe_stats;
printf("%s statistics:\n", device_get_nameunit(sc->bfe_dev));
printf("Transmit good octets : %ju\n",
(uintmax_t)stats->tx_good_octets);
printf("Transmit good frames : %ju\n",
(uintmax_t)stats->tx_good_frames);
printf("Transmit octets : %ju\n",
(uintmax_t)stats->tx_octets);
printf("Transmit frames : %ju\n",
(uintmax_t)stats->tx_frames);
printf("Transmit broadcast frames : %ju\n",
(uintmax_t)stats->tx_bcast_frames);
printf("Transmit multicast frames : %ju\n",
(uintmax_t)stats->tx_mcast_frames);
printf("Transmit frames 64 bytes : %ju\n",
(uint64_t)stats->tx_pkts_64);
printf("Transmit frames 65 to 127 bytes : %ju\n",
(uint64_t)stats->tx_pkts_65_127);
printf("Transmit frames 128 to 255 bytes : %ju\n",
(uint64_t)stats->tx_pkts_128_255);
printf("Transmit frames 256 to 511 bytes : %ju\n",
(uint64_t)stats->tx_pkts_256_511);
printf("Transmit frames 512 to 1023 bytes : %ju\n",
(uint64_t)stats->tx_pkts_512_1023);
printf("Transmit frames 1024 to max bytes : %ju\n",
(uint64_t)stats->tx_pkts_1024_max);
printf("Transmit jabber errors : %u\n", stats->tx_jabbers);
printf("Transmit oversized frames : %ju\n",
(uint64_t)stats->tx_oversize_frames);
printf("Transmit fragmented frames : %ju\n",
(uint64_t)stats->tx_frag_frames);
printf("Transmit underruns : %u\n", stats->tx_colls);
printf("Transmit total collisions : %u\n", stats->tx_single_colls);
printf("Transmit single collisions : %u\n", stats->tx_single_colls);
printf("Transmit multiple collisions : %u\n", stats->tx_multi_colls);
printf("Transmit excess collisions : %u\n", stats->tx_excess_colls);
printf("Transmit late collisions : %u\n", stats->tx_late_colls);
printf("Transmit deferrals : %u\n", stats->tx_deferrals);
printf("Transmit carrier losts : %u\n", stats->tx_carrier_losts);
printf("Transmit pause frames : %u\n", stats->tx_pause_frames);
printf("Receive good octets : %ju\n",
(uintmax_t)stats->rx_good_octets);
printf("Receive good frames : %ju\n",
(uintmax_t)stats->rx_good_frames);
printf("Receive octets : %ju\n",
(uintmax_t)stats->rx_octets);
printf("Receive frames : %ju\n",
(uintmax_t)stats->rx_frames);
printf("Receive broadcast frames : %ju\n",
(uintmax_t)stats->rx_bcast_frames);
printf("Receive multicast frames : %ju\n",
(uintmax_t)stats->rx_mcast_frames);
printf("Receive frames 64 bytes : %ju\n",
(uint64_t)stats->rx_pkts_64);
printf("Receive frames 65 to 127 bytes : %ju\n",
(uint64_t)stats->rx_pkts_65_127);
printf("Receive frames 128 to 255 bytes : %ju\n",
(uint64_t)stats->rx_pkts_128_255);
printf("Receive frames 256 to 511 bytes : %ju\n",
(uint64_t)stats->rx_pkts_256_511);
printf("Receive frames 512 to 1023 bytes : %ju\n",
(uint64_t)stats->rx_pkts_512_1023);
printf("Receive frames 1024 to max bytes : %ju\n",
(uint64_t)stats->rx_pkts_1024_max);
printf("Receive jabber errors : %u\n", stats->rx_jabbers);
printf("Receive oversized frames : %ju\n",
(uint64_t)stats->rx_oversize_frames);
printf("Receive fragmented frames : %ju\n",
(uint64_t)stats->rx_frag_frames);
printf("Receive missed frames : %u\n", stats->rx_missed_frames);
printf("Receive CRC align errors : %u\n", stats->rx_crc_align_errs);
printf("Receive undersized frames : %u\n", stats->rx_runts);
printf("Receive CRC errors : %u\n", stats->rx_crc_errs);
printf("Receive align errors : %u\n", stats->rx_align_errs);
printf("Receive symbol errors : %u\n", stats->rx_symbol_errs);
printf("Receive pause frames : %u\n", stats->rx_pause_frames);
printf("Receive control frames : %u\n", stats->rx_control_frames);
return (error);
}

View File

@ -479,25 +479,105 @@ struct bfe_rxheader {
u_int16_t pad[12];
};
struct bfe_hw_stats {
u_int32_t tx_good_octets, tx_good_pkts, tx_octets;
u_int32_t tx_pkts, tx_broadcast_pkts, tx_multicast_pkts;
u_int32_t tx_len_64, tx_len_65_to_127, tx_len_128_to_255;
u_int32_t tx_len_256_to_511, tx_len_512_to_1023, tx_len_1024_to_max;
u_int32_t tx_jabber_pkts, tx_oversize_pkts, tx_fragment_pkts;
u_int32_t tx_underruns, tx_total_cols, tx_single_cols;
u_int32_t tx_multiple_cols, tx_excessive_cols, tx_late_cols;
u_int32_t tx_defered, tx_carrier_lost, tx_pause_pkts;
u_int32_t __pad1[8];
#define MIB_TX_GOOD_O 0
#define MIB_TX_GOOD_P 1
#define MIB_TX_O 2
#define MIB_TX_P 3
#define MIB_TX_BCAST 4
#define MIB_TX_MCAST 5
#define MIB_TX_64 6
#define MIB_TX_65_127 7
#define MIB_TX_128_255 8
#define MIB_TX_256_511 9
#define MIB_TX_512_1023 10
#define MIB_TX_1024_MAX 11
#define MIB_TX_JABBER 12
#define MIB_TX_OSIZE 13
#define MIB_TX_FRAG 14
#define MIB_TX_URUNS 15
#define MIB_TX_TCOLS 16
#define MIB_TX_SCOLS 17
#define MIB_TX_MCOLS 18
#define MIB_TX_ECOLS 19
#define MIB_TX_LCOLS 20
#define MIB_TX_DEFERED 21
#define MIB_TX_CLOST 22
#define MIB_TX_PAUSE 23
#define MIB_RX_GOOD_O 24
#define MIB_RX_GOOD_P 25
#define MIB_RX_O 26
#define MIB_RX_P 27
#define MIB_RX_BCAST 28
#define MIB_RX_MCAST 29
#define MIB_RX_64 30
#define MIB_RX_65_127 31
#define MIB_RX_128_255 32
#define MIB_RX_256_511 33
#define MIB_RX_512_1023 34
#define MIB_RX_1024_MAX 35
#define MIB_RX_JABBER 36
#define MIB_RX_OSIZE 37
#define MIB_RX_FRAG 38
#define MIB_RX_MISS 39
#define MIB_RX_CRCA 40
#define MIB_RX_USIZE 41
#define MIB_RX_CRC 42
#define MIB_RX_ALIGN 43
#define MIB_RX_SYM 44
#define MIB_RX_PAUSE 45
#define MIB_RX_NPAUSE 46
u_int32_t rx_good_octets, rx_good_pkts, rx_octets;
u_int32_t rx_pkts, rx_broadcast_pkts, rx_multicast_pkts;
u_int32_t rx_len_64, rx_len_65_to_127, rx_len_128_to_255;
u_int32_t rx_len_256_to_511, rx_len_512_to_1023, rx_len_1024_to_max;
u_int32_t rx_jabber_pkts, rx_oversize_pkts, rx_fragment_pkts;
u_int32_t rx_missed_pkts, rx_crc_align_errs, rx_undersize;
u_int32_t rx_crc_errs, rx_align_errs, rx_symbol_errs;
u_int32_t rx_pause_pkts, rx_nonpause_pkts;
#define BFE_MIB_CNT (MIB_RX_NPAUSE - MIB_TX_GOOD_O + 1)
struct bfe_hw_stats {
uint64_t tx_good_octets;
uint64_t tx_good_frames;
uint64_t tx_octets;
uint64_t tx_frames;
uint64_t tx_bcast_frames;
uint64_t tx_mcast_frames;
uint64_t tx_pkts_64;
uint64_t tx_pkts_65_127;
uint64_t tx_pkts_128_255;
uint64_t tx_pkts_256_511;
uint64_t tx_pkts_512_1023;
uint64_t tx_pkts_1024_max;
uint32_t tx_jabbers;
uint64_t tx_oversize_frames;
uint64_t tx_frag_frames;
uint32_t tx_underruns;
uint32_t tx_colls;
uint32_t tx_single_colls;
uint32_t tx_multi_colls;
uint32_t tx_excess_colls;
uint32_t tx_late_colls;
uint32_t tx_deferrals;
uint32_t tx_carrier_losts;
uint32_t tx_pause_frames;
uint64_t rx_good_octets;
uint64_t rx_good_frames;
uint64_t rx_octets;
uint64_t rx_frames;
uint64_t rx_bcast_frames;
uint64_t rx_mcast_frames;
uint64_t rx_pkts_64;
uint64_t rx_pkts_65_127;
uint64_t rx_pkts_128_255;
uint64_t rx_pkts_256_511;
uint64_t rx_pkts_512_1023;
uint64_t rx_pkts_1024_max;
uint32_t rx_jabbers;
uint64_t rx_oversize_frames;
uint64_t rx_frag_frames;
uint32_t rx_missed_frames;
uint32_t rx_crc_align_errs;
uint32_t rx_runts;
uint32_t rx_crc_errs;
uint32_t rx_align_errs;
uint32_t rx_symbol_errs;
uint32_t rx_pause_frames;
uint32_t rx_control_frames;
};
struct bfe_softc
@ -515,7 +595,7 @@ struct bfe_softc
struct resource *bfe_irq;
struct resource *bfe_res;
struct callout bfe_stat_co;
struct bfe_hw_stats bfe_hwstats;
struct bfe_hw_stats bfe_stats;
struct bfe_desc *bfe_tx_list, *bfe_rx_list;
struct bfe_tx_data bfe_tx_ring[BFE_TX_LIST_CNT]; /* XXX */
struct bfe_rx_data bfe_rx_ring[BFE_RX_LIST_CNT]; /* XXX */