> -----Original Message----- > From: Jiawei Wang <jiaw...@mellanox.com> > Sent: Monday, March 30, 2020 6:02 > To: Slava Ovsiienko <viachesl...@mellanox.com>; Matan Azrad > <ma...@mellanox.com>; Jiawei(Jonny) Wang <jiaw...@mellanox.com> > Cc: Raslan Darawsheh <rasl...@mellanox.com>; dev@dpdk.org; > sta...@dpdk.org > Subject: [PATCH] net/mlx5: fix imissed counter overflow issue > > The Hw counters is defined as 32bit unsigned value and read from the sysfs. > Firstly read the base value while application start, then fetch the new value > while do query and minus the base value. > If the new value is less than base value, will result in the a negative value > and > convert to the big value as unsigned 64bit. > > PMD add xstats field to store the last successfully read counter, use it if > failed > to read hw counter from sysfs. > PMD also record the last output value to handle the wrap around case, if > overflow happened, increase the wrap count by 1 and save into the higher > 32bit, and update the new value into lower 32bit, finally return the 64bit > counter value. > > Fixes: ce9494d76c4 ("net/mlx5: report imissed statistics") > Cc: sta...@dpdk.org > > Signed-off-by: Jiawei Wang <jiaw...@mellanox.com> Acked-by: Viacheslav Ovsiienko <viachesl...@mellanox.com>
> --- > drivers/net/mlx5/mlx5.h | 3 ++ > drivers/net/mlx5/mlx5_stats.c | 57 ++++++++++++++++++++++++++++++----- > 2 files changed, 52 insertions(+), 8 deletions(-) > > diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index > d7c519bae0..c01fae8c8e 100644 > --- a/drivers/net/mlx5/mlx5.h > +++ b/drivers/net/mlx5/mlx5.h > @@ -112,12 +112,15 @@ struct mlx5_xstats_ctrl { > /* Index in the device counters table. */ > uint16_t dev_table_idx[MLX5_MAX_XSTATS]; > uint64_t base[MLX5_MAX_XSTATS]; > + uint64_t xstats[MLX5_MAX_XSTATS]; > + uint64_t hw_stats[MLX5_MAX_XSTATS]; > struct mlx5_counter_ctrl info[MLX5_MAX_XSTATS]; }; > > struct mlx5_stats_ctrl { > /* Base for imissed counter. */ > uint64_t imissed_base; > + uint64_t imissed; > }; > > /* Flow list . */ > diff --git a/drivers/net/mlx5/mlx5_stats.c b/drivers/net/mlx5/mlx5_stats.c > index 7603502967..5bc6fa6aa1 100644 > --- a/drivers/net/mlx5/mlx5_stats.c > +++ b/drivers/net/mlx5/mlx5_stats.c > @@ -139,7 +139,7 @@ static const struct mlx5_counter_ctrl > mlx5_counters_init[] = { > > static const unsigned int xstats_n = RTE_DIM(mlx5_counters_init); > > -static inline void > +static inline int > mlx5_read_ib_stat(struct mlx5_priv *priv, const char *ctr_name, uint64_t > *stat) { > FILE *file; > @@ -155,10 +155,11 @@ mlx5_read_ib_stat(struct mlx5_priv *priv, const > char *ctr_name, uint64_t *stat) > > fclose(file); > if (n == 1) > - return; > + return 0; > } > } > *stat = 0; > + return 1; > } > > /** > @@ -197,8 +198,14 @@ mlx5_read_dev_counters(struct rte_eth_dev *dev, > uint64_t *stats) > } > for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) { > if (xstats_ctrl->info[i].ib) { > - mlx5_read_ib_stat(priv, xstats_ctrl->info[i].ctr_name, > - &stats[i]); > + ret = mlx5_read_ib_stat(priv, > + xstats_ctrl->info[i].ctr_name, > + &stats[i]); > + /* return last xstats counter if fail to read. */ > + if (ret == 0) > + xstats_ctrl->xstats[i] = stats[i]; > + else > + stats[i] = xstats_ctrl->xstats[i]; > } else { > stats[i] = (uint64_t) > et_stats->data[xstats_ctrl->dev_table_idx[i]]; > @@ -304,6 +311,7 @@ mlx5_stats_init(struct rte_eth_dev *dev) > unsigned int idx = xstats_ctrl->mlx5_stats_n++; > > xstats_ctrl->info[idx] = mlx5_counters_init[i]; > + xstats_ctrl->hw_stats[idx] = 0; > } > } > MLX5_ASSERT(xstats_ctrl->mlx5_stats_n <= MLX5_MAX_XSTATS); @@ > -314,6 +322,7 @@ mlx5_stats_init(struct rte_eth_dev *dev) > DRV_LOG(ERR, "port %u cannot read device counters: %s", > dev->data->port_id, strerror(rte_errno)); > mlx5_read_ib_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base); > + stats_ctrl->imissed = 0; > free: > rte_free(strings); > } > @@ -356,7 +365,23 @@ mlx5_xstats_get(struct rte_eth_dev *dev, struct > rte_eth_xstat *stats, > return ret; > for (i = 0; i != mlx5_stats_n; ++i) { > stats[i].id = i; > - stats[i].value = (counters[i] - xstats_ctrl->base[i]); > + if (xstats_ctrl->info[i].ib) { > + uint64_t wrap_n; > + uint64_t hw_stat = xstats_ctrl->hw_stats[i]; > + > + stats[i].value = (counters[i] - > + xstats_ctrl->base[i]) & > + (uint64_t)UINT32_MAX; > + wrap_n = hw_stat >> 32; > + if (stats[i].value < > + (hw_stat & > (uint64_t)UINT32_MAX)) > + wrap_n++; > + stats[i].value |= (wrap_n) << 32; > + xstats_ctrl->hw_stats[i] = stats[i].value; > + } else { > + stats[i].value = > + (counters[i] - xstats_ctrl->base[i]); > + } > } > } > return mlx5_stats_n; > @@ -378,9 +403,12 @@ int > mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats) { > struct mlx5_priv *priv = dev->data->dev_private; > + struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl; > struct rte_eth_stats tmp; > unsigned int i; > unsigned int idx; > + uint64_t wrap_n; > + int ret; > > memset(&tmp, 0, sizeof(tmp)); > /* Add software counters. */ > @@ -423,8 +451,18 @@ mlx5_stats_get(struct rte_eth_dev *dev, struct > rte_eth_stats *stats) #endif > tmp.oerrors += txq->stats.oerrors; > } > - mlx5_read_ib_stat(priv, "out_of_buffer", &tmp.imissed); > - tmp.imissed -= priv->stats_ctrl.imissed_base; > + ret = mlx5_read_ib_stat(priv, "out_of_buffer", &tmp.imissed); > + if (ret == 0) { > + tmp.imissed = (tmp.imissed - stats_ctrl->imissed_base) & > + (uint64_t)UINT32_MAX; > + wrap_n = stats_ctrl->imissed >> 32; > + if (tmp.imissed < (stats_ctrl->imissed & > (uint64_t)UINT32_MAX)) > + wrap_n++; > + tmp.imissed |= (wrap_n) << 32; > + stats_ctrl->imissed = tmp.imissed; > + } else { > + tmp.imissed = stats_ctrl->imissed; > + } > #ifndef MLX5_PMD_SOFT_COUNTERS > /* FIXME: retrieve and add hardware counters. */ #endif @@ -461,6 > +499,7 @@ mlx5_stats_reset(struct rte_eth_dev *dev) > sizeof(struct mlx5_txq_stats)); > } > mlx5_read_ib_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base); > + stats_ctrl->imissed = 0; > #ifndef MLX5_PMD_SOFT_COUNTERS > /* FIXME: reset hardware counters. */ > #endif > @@ -503,8 +542,10 @@ mlx5_xstats_reset(struct rte_eth_dev *dev) > dev->data->port_id, strerror(rte_errno)); > return ret; > } > - for (i = 0; i != n; ++i) > + for (i = 0; i != n; ++i) { > xstats_ctrl->base[i] = counters[i]; > + xstats_ctrl->hw_stats[i] = 0; > + } > > return 0; > } > -- > 2.21.0