From 335d1567b73beeff50f358bd20a47abf761305f7 Mon Sep 17 00:00:00 2001 From: arybchik Date: Fri, 11 Dec 2015 06:41:01 +0000 Subject: [PATCH] sfxge: implement interface statistics shown by netstat PR: 202907 Submitted by: Boris Misenov Reviewed by: gnn, philip Sponsored by: Solarflare Communications, Inc. Differential Revision: https://reviews.freebsd.org/D4317 git-svn-id: svn://svn.freebsd.org/base/stable/10@292089 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/sfxge/sfxge.c | 31 +++++++++++++++++++++++++++++-- sys/dev/sfxge/sfxge.h | 5 +++++ sys/dev/sfxge/sfxge_port.c | 35 +++++++++++++++++++++++++++++++++++ sys/dev/sfxge/sfxge_tx.c | 29 +++++++++++++++++++++++++++++ sys/dev/sfxge/sfxge_tx.h | 1 + sys/dev/sfxge/sfxge_version.h | 2 +- 6 files changed, 100 insertions(+), 3 deletions(-) diff --git a/sys/dev/sfxge/sfxge.c b/sys/dev/sfxge/sfxge.c index 46b138f46..f78d175ca 100644 --- a/sys/dev/sfxge/sfxge.c +++ b/sys/dev/sfxge/sfxge.c @@ -69,10 +69,10 @@ __FBSDID("$FreeBSD$"); IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6 | \ IFCAP_TSO4 | IFCAP_TSO6 | \ IFCAP_JUMBO_MTU | \ - IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE) + IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE | IFCAP_HWSTATS) #define SFXGE_CAP_ENABLE SFXGE_CAP #define SFXGE_CAP_FIXED (IFCAP_VLAN_MTU | \ - IFCAP_JUMBO_MTU | IFCAP_LINKSTATE) + IFCAP_JUMBO_MTU | IFCAP_LINKSTATE | IFCAP_HWSTATS) MALLOC_DEFINE(M_SFXGE, "sfxge", "Solarflare 10GigE driver"); @@ -94,6 +94,14 @@ SYSCTL_INT(_hw_sfxge, OID_AUTO, tx_ring, CTLFLAG_RDTUN, &sfxge_tx_ring_entries, 0, "Maximum number of descriptors in a transmit ring"); +#define SFXGE_PARAM_STATS_UPDATE_PERIOD SFXGE_PARAM(stats_update_period) +static int sfxge_stats_update_period = SFXGE_CALLOUT_TICKS; +TUNABLE_INT(SFXGE_PARAM_STATS_UPDATE_PERIOD, + &sfxge_stats_update_period); +SYSCTL_INT(_hw_sfxge, OID_AUTO, stats_update_period, CTLFLAG_RDTUN, + &sfxge_stats_update_period, 0, + "netstat interface statistics update period in ticks"); + static void sfxge_reset(void *arg, int npending); @@ -505,11 +513,25 @@ sfxge_if_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data) return (error); } +static void +sfxge_tick(void *arg) +{ + struct sfxge_softc *sc = arg; + + sfxge_port_update_stats(sc); + sfxge_tx_update_stats(sc); + + callout_reset(&sc->tick_callout, sfxge_stats_update_period, + sfxge_tick, sc); +} + static void sfxge_ifnet_fini(struct ifnet *ifp) { struct sfxge_softc *sc = ifp->if_softc; + callout_drain(&sc->tick_callout); + SFXGE_ADAPTER_LOCK(sc); sfxge_stop(sc); SFXGE_ADAPTER_UNLOCK(sc); @@ -555,10 +577,15 @@ sfxge_ifnet_init(struct ifnet *ifp, struct sfxge_softc *sc) ifp->if_transmit = sfxge_if_transmit; ifp->if_qflush = sfxge_if_qflush; + callout_init(&sc->tick_callout, B_TRUE); + DBGPRINT(sc->dev, "ifmedia_init"); if ((rc = sfxge_port_ifmedia_init(sc)) != 0) goto fail; + callout_reset(&sc->tick_callout, sfxge_stats_update_period, + sfxge_tick, sc); + return (0); fail: diff --git a/sys/dev/sfxge/sfxge.h b/sys/dev/sfxge/sfxge.h index aa1830d15..cfaf06d85 100644 --- a/sys/dev/sfxge/sfxge.h +++ b/sys/dev/sfxge/sfxge.h @@ -121,6 +121,8 @@ enum sfxge_evq_state { #define SFXGE_EV_BATCH 16384 +#define SFXGE_CALLOUT_TICKS 100 + struct sfxge_evq { /* Structure members below are sorted by usage order */ struct sfxge_softc *sc; @@ -274,6 +276,8 @@ struct sfxge_softc { size_t rx_buffer_align; uma_zone_t rx_buffer_zone; + struct callout tick_callout; + unsigned int evq_max; unsigned int evq_count; unsigned int rxq_count; @@ -349,6 +353,7 @@ extern void sfxge_mac_link_update(struct sfxge_softc *sc, efx_link_mode_t mode); extern int sfxge_mac_filter_set(struct sfxge_softc *sc); extern int sfxge_port_ifmedia_init(struct sfxge_softc *sc); +extern void sfxge_port_update_stats(struct sfxge_softc *sc); #define SFXGE_MAX_MTU (9 * 1024) diff --git a/sys/dev/sfxge/sfxge_port.c b/sys/dev/sfxge/sfxge_port.c index 420aaad29..277752ae1 100644 --- a/sys/dev/sfxge/sfxge_port.c +++ b/sys/dev/sfxge/sfxge_port.c @@ -87,6 +87,41 @@ sfxge_mac_stat_update(struct sfxge_softc *sc) return (rc); } +void +sfxge_port_update_stats(struct sfxge_softc *sc) +{ + struct ifnet *ifp; + uint64_t *mac_stats; + + SFXGE_PORT_LOCK(&sc->port); + + /* Ignore error and use old values */ + (void)sfxge_mac_stat_update(sc); + + ifp = sc->ifnet; + mac_stats = (uint64_t *)sc->port.mac_stats.decode_buf; + + ifp->if_ipackets = mac_stats[EFX_MAC_RX_PKTS]; + ifp->if_ierrors = mac_stats[EFX_MAC_RX_ERRORS]; + ifp->if_opackets = mac_stats[EFX_MAC_TX_PKTS]; + ifp->if_oerrors = mac_stats[EFX_MAC_TX_ERRORS]; + ifp->if_collisions = + mac_stats[EFX_MAC_TX_SGL_COL_PKTS] + + mac_stats[EFX_MAC_TX_MULT_COL_PKTS] + + mac_stats[EFX_MAC_TX_EX_COL_PKTS] + + mac_stats[EFX_MAC_TX_LATE_COL_PKTS]; + ifp->if_ibytes = mac_stats[EFX_MAC_RX_OCTETS]; + ifp->if_obytes = mac_stats[EFX_MAC_TX_OCTETS]; + /* if_imcasts is maintained in net/if_ethersubr.c */ + ifp->if_omcasts = + mac_stats[EFX_MAC_TX_MULTICST_PKTS] + + mac_stats[EFX_MAC_TX_BRDCST_PKTS]; + /* if_iqdrops is maintained in net/if_ethersubr.c */ + /* if_noproto is maintained in net/if_ethersubr.c */ + + SFXGE_PORT_UNLOCK(&sc->port); +} + static int sfxge_mac_stat_handler(SYSCTL_HANDLER_ARGS) { diff --git a/sys/dev/sfxge/sfxge_tx.c b/sys/dev/sfxge/sfxge_tx.c index 957997552..398272d52 100644 --- a/sys/dev/sfxge/sfxge_tx.c +++ b/sys/dev/sfxge/sfxge_tx.c @@ -1683,6 +1683,35 @@ sfxge_tx_stat_init(struct sfxge_softc *sc) } } +static uint64_t +sfxge_tx_get_drops(struct sfxge_softc *sc) +{ + unsigned int index; + uint64_t drops = 0; + struct sfxge_txq *txq; + + /* Sum across all TX queues */ + for (index = 0; index < sc->txq_count; index++) { + txq = sc->txq[index]; + /* + * In theory, txq->put_overflow and txq->netdown_drops + * should use atomic operation and other should be + * obtained under txq lock, but it is just statistics. + */ + drops += txq->drops + txq->get_overflow + + txq->get_non_tcp_overflow + + txq->put_overflow + txq->netdown_drops + + txq->tso_pdrop_too_many + txq->tso_pdrop_no_rsrc; + } + return (drops); +} + +void +sfxge_tx_update_stats(struct sfxge_softc *sc) +{ + sc->ifnet->if_oerrors += sfxge_tx_get_drops(sc); +} + void sfxge_tx_fini(struct sfxge_softc *sc) { diff --git a/sys/dev/sfxge/sfxge_tx.h b/sys/dev/sfxge/sfxge_tx.h index 67bedc2c2..9d411eadd 100644 --- a/sys/dev/sfxge/sfxge_tx.h +++ b/sys/dev/sfxge/sfxge_tx.h @@ -220,6 +220,7 @@ struct sfxge_txq { struct sfxge_evq; +extern void sfxge_tx_update_stats(struct sfxge_softc *sc); extern int sfxge_tx_init(struct sfxge_softc *sc); extern void sfxge_tx_fini(struct sfxge_softc *sc); diff --git a/sys/dev/sfxge/sfxge_version.h b/sys/dev/sfxge/sfxge_version.h index f5f4882b4..9d93e79e3 100644 --- a/sys/dev/sfxge/sfxge_version.h +++ b/sys/dev/sfxge/sfxge_version.h @@ -36,6 +36,6 @@ #ifndef _SFXGE_VERSION_H #define _SFXGE_VERSION_H -#define SFXGE_VERSION_STRING "v4.5.2.1000" +#define SFXGE_VERSION_STRING "v4.5.3.1002" #endif /* _SFXGE_DRIVER_VERSION_H */ -- 2.45.0