Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Mar 2014 14:00:43 +0400
From:      Andrew Rybchenko <Andrew.Rybchenko@oktetlabs.ru>
To:        net@FreeBSD.org
Subject:   [PATCH 6/6] sfxge: implement interface statistics shown by netstat
Message-ID:  <5328194B.60707@oktetlabs.ru>

next in thread | raw e-mail | index | archive | help
sfxge: implement interface statistics shown by netstat

netstat directly reads interface statistics collected
in the ifnet structure members: if_ipackets, if_ierrors, if_iqdrops,
if_opackets, if_oerrors, if_collisions.
The if_oerrors counter should include both errors reported by hardware
and errors happened in software before posting to hardware.
Since statistics is retrieved periodically its counters could be smaller
than counters provided by kernel for IP addresses.
Report IFCAP_HWSTATS capability since driver manages if_ibytes.

Submitted-by:   Boris Misenov <Boris.Misenov@oktetlabs.ru>
Sponsored by:   Solarflare Communications, Inc.

diff -r 7f58b1a5ea60 -r a3ab0749ffa3 src/driver/freebsd/sfxge.c
--- a/head/sys/dev/sfxge/sfxge.c    Mon Mar 10 11:37:12 2014 +0400
+++ b/head/sys/dev/sfxge/sfxge.c    Mon Mar 10 11:37:12 2014 +0400
@@ -60,10 +60,10 @@
  #define SFXGE_CAP (IFCAP_VLAN_MTU | \
             IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM | IFCAP_TSO |    \
             IFCAP_JUMBO_MTU | IFCAP_LRO |            \
-           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_HWCSUM | 
IFCAP_VLAN_HWCSUM | \
-             IFCAP_JUMBO_MTU | IFCAP_LINKSTATE)
+             IFCAP_JUMBO_MTU | IFCAP_LINKSTATE | IFCAP_HWSTATS)

  MALLOC_DEFINE(M_SFXGE, "sfxge", "Solarflare 10GigE driver");

@@ -274,10 +274,23 @@
  }

  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_CALLOUT_TICKS, sfxge_tick, sc);
+}
+
+static void
  sfxge_ifnet_fini(struct ifnet *ifp)
  {
      struct sfxge_softc *sc = ifp->if_softc;

+    callout_drain(&sc->tick_callout);
+
      sx_xlock(&sc->softc_lock);
      sfxge_stop(sc);
      sx_xunlock(&sc->softc_lock);
@@ -321,9 +334,12 @@
      mtx_init(&sc->tx_lock, "txq", NULL, MTX_DEF);
  #endif

+    callout_init(&sc->tick_callout, TRUE);
+
      if ((rc = sfxge_port_ifmedia_init(sc)) != 0)
          goto fail;

+    callout_reset(&sc->tick_callout, SFXGE_CALLOUT_TICKS, sfxge_tick, sc);
      return 0;

  fail:
diff -r 7f58b1a5ea60 -r a3ab0749ffa3 src/driver/freebsd/sfxge.h
--- a/head/sys/dev/sfxge/sfxge.h    Mon Mar 10 11:37:12 2014 +0400
+++ b/head/sys/dev/sfxge/sfxge.h    Mon Mar 10 11:37:12 2014 +0400
@@ -61,6 +61,9 @@
  #ifndef IFCAP_VLAN_HWTSO
  #define IFCAP_VLAN_HWTSO 0
  #endif
+#ifndef IFCAP_HWSTATS
+#define IFCAP_HWSTATS 0
+#endif
  #ifndef IFM_10G_T
  #define IFM_10G_T IFM_UNKNOWN
  #endif
@@ -100,6 +103,8 @@

  #define    SFXGE_EV_BATCH    16384

+#define    SFXGE_CALLOUT_TICKS 10
+
  struct sfxge_evq {
      struct sfxge_softc    *sc  __aligned(CACHE_LINE_SIZE);
      struct mtx        lock __aligned(CACHE_LINE_SIZE);
@@ -241,6 +246,7 @@
  #ifndef SFXGE_HAVE_MQ
      struct mtx            tx_lock __aligned(CACHE_LINE_SIZE);
  #endif
+    struct callout            tick_callout;
  };

  #define SFXGE_LINK_UP(sc) ((sc)->port.link_mode != EFX_LINK_DOWN)
@@ -298,6 +304,7 @@
      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 -r 7f58b1a5ea60 -r a3ab0749ffa3 src/driver/freebsd/sfxge_port.c
--- a/head/sys/dev/sfxge/sfxge_port.c    Mon Mar 10 11:37:12 2014 +0400
+++ b/head/sys/dev/sfxge/sfxge_port.c    Mon Mar 10 11:37:12 2014 +0400
@@ -85,6 +85,40 @@
      return rc;
  }

+void
+sfxge_port_update_stats(struct sfxge_softc *sc)
+{
+    struct ifnet *ifp;
+    uint64_t *mac_stats;
+
+    mtx_lock(&sc->port.lock);
+    /* 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 */
+
+    mtx_unlock(&sc->port.lock);
+}
+
  static int
  sfxge_mac_stat_handler(SYSCTL_HANDLER_ARGS)
  {
diff -r 7f58b1a5ea60 -r a3ab0749ffa3 src/driver/freebsd/sfxge_tx.c
--- a/head/sys/dev/sfxge/sfxge_tx.c    Mon Mar 10 11:37:12 2014 +0400
+++ b/head/sys/dev/sfxge/sfxge_tx.c    Mon Mar 10 11:37:12 2014 +0400
@@ -1436,6 +1436,28 @@
  }

  void
+sfxge_tx_update_stats(struct sfxge_softc *sc)
+{
+    unsigned int index;
+    u_long oerrors = 0;
+    struct sfxge_txq *txq;
+
+    /* Sum across all TX queues */
+    for (index = 0;
+         index < SFXGE_TXQ_IP_TCP_UDP_CKSUM + SFXGE_TX_SCALE(sc);
+         index++) {
+        txq = sc->txq[index];
+        /*
+         * In theory, txq->drops should be obtained under txq lock,
+         * and txq->early_drops should use atomic operation,
+         * but it is just statistics.
+         */
+        oerrors += txq->drops + txq->early_drops;
+    }
+    sc->ifnet->if_oerrors += oerrors;
+}
+
+void
  sfxge_tx_fini(struct sfxge_softc *sc)
  {
      int index;
diff -r 7f58b1a5ea60 -r a3ab0749ffa3 src/driver/freebsd/sfxge_tx.h
--- a/head/sys/dev/sfxge/sfxge_tx.h    Mon Mar 10 11:37:12 2014 +0400
+++ b/head/sys/dev/sfxge/sfxge_tx.h    Mon Mar 10 11:37:12 2014 +0400
@@ -170,6 +170,7 @@
  };

  extern int sfxge_tx_packet_add(struct sfxge_txq *, struct mbuf *);
+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);




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5328194B.60707>