net/sfc: fix Rx packets counter reported by basic stats

Message ID 1547705852-13974-1-git-send-email-arybchenko@solarflare.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series net/sfc: fix Rx packets counter reported by basic stats |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Andrew Rybchenko Jan. 17, 2019, 6:17 a.m. UTC
  Errors, missed and pauses should not be included in delivered
good Rx packets reported by ipackets.

Fixes: 1caab2f1e684 ("net/sfc: add basic statistics")
Cc: stable@dpdk.org

Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
 drivers/net/sfc/sfc.h        |  2 ++
 drivers/net/sfc/sfc_ethdev.c | 31 ++++++++++++++++++++++++++++++-
 drivers/net/sfc/sfc_port.c   | 14 ++++++++++++++
 3 files changed, 46 insertions(+), 1 deletion(-)
  

Comments

Ferruh Yigit Jan. 17, 2019, 3:29 p.m. UTC | #1
On 1/17/2019 6:17 AM, Andrew Rybchenko wrote:
> Errors, missed and pauses should not be included in delivered
> good Rx packets reported by ipackets.
> 
> Fixes: 1caab2f1e684 ("net/sfc: add basic statistics")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>

Applied to dpdk-next-net/master, thanks.
  

Patch

diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 0b852340f..a94ca8e75 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -149,6 +149,8 @@  struct sfc_port {
 	uint64_t			mac_stats_last_request_timestamp;
 
 	uint32_t		mac_stats_mask[EFX_MAC_STATS_MASK_NPAGES];
+
+	uint64_t			ipackets;
 };
 
 struct sfc_rss_hf_rte_to_efx {
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index 08d3271cb..a7322a1eb 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -503,6 +503,29 @@  sfc_tx_queue_release(void *queue)
 	sfc_adapter_unlock(sa);
 }
 
+/*
+ * Some statistics are computed as A - B where A and B each increase
+ * monotonically with some hardware counter(s) and the counters are read
+ * asynchronously.
+ *
+ * If packet X is counted in A, but not counted in B yet, computed value is
+ * greater than real.
+ *
+ * If packet X is not counted in A at the moment of reading the counter,
+ * but counted in B at the moment of reading the counter, computed value
+ * is less than real.
+ *
+ * However, counter which grows backward is worse evil than slightly wrong
+ * value. So, let's try to guarantee that it never happens except may be
+ * the case when the MAC stats are zeroed as a result of a NIC reset.
+ */
+static void
+sfc_update_diff_stat(uint64_t *stat, uint64_t newval)
+{
+	if ((int64_t)(newval - *stat) > 0 || newval == 0)
+		*stat = newval;
+}
+
 static int
 sfc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 {
@@ -540,7 +563,6 @@  sfc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 		stats->imissed = mac_stats[EFX_MAC_VADAPTER_RX_BAD_PACKETS];
 		stats->oerrors = mac_stats[EFX_MAC_VADAPTER_TX_BAD_PACKETS];
 	} else {
-		stats->ipackets = mac_stats[EFX_MAC_RX_PKTS];
 		stats->opackets = mac_stats[EFX_MAC_TX_PKTS];
 		stats->ibytes = mac_stats[EFX_MAC_RX_OCTETS];
 		stats->obytes = mac_stats[EFX_MAC_TX_OCTETS];
@@ -566,6 +588,13 @@  sfc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 			mac_stats[EFX_MAC_RX_ALIGN_ERRORS] +
 			mac_stats[EFX_MAC_RX_JABBER_PKTS];
 		/* no oerrors counters supported on EF10 */
+
+		/* Exclude missed, errors and pauses from Rx packets */
+		sfc_update_diff_stat(&port->ipackets,
+			mac_stats[EFX_MAC_RX_PKTS] -
+			mac_stats[EFX_MAC_RX_PAUSE_PKTS] -
+			stats->imissed - stats->ierrors);
+		stats->ipackets = port->ipackets;
 	}
 
 unlock:
diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c
index 5384dbbdb..5eb4b3aca 100644
--- a/drivers/net/sfc/sfc_port.c
+++ b/drivers/net/sfc/sfc_port.c
@@ -87,6 +87,18 @@  sfc_port_update_mac_stats(struct sfc_adapter *sa)
 	return 0;
 }
 
+static void
+sfc_port_reset_sw_stats(struct sfc_adapter *sa)
+{
+	struct sfc_port *port = &sa->port;
+
+	/*
+	 * Reset diff stats explicitly since check which does not allow
+	 * the statistics to grow backward could deny it.
+	 */
+	port->ipackets = 0;
+}
+
 int
 sfc_port_reset_mac_stats(struct sfc_adapter *sa)
 {
@@ -95,6 +107,8 @@  sfc_port_reset_mac_stats(struct sfc_adapter *sa)
 
 	rte_spinlock_lock(&port->mac_stats_lock);
 	rc = efx_mac_stats_clear(sa->nic);
+	if (rc == 0)
+		sfc_port_reset_sw_stats(sa);
 	rte_spinlock_unlock(&port->mac_stats_lock);
 
 	return rc;