Skip to content

Commit

Permalink
mlxsw: spectrum: qdiscs: Collect stats for sch_red based on priomap
Browse files Browse the repository at this point in the history
Priority counters count packets according to their packet priority.
Collect the stats for sch_red based on these counters, so the qdisc bstats
will be the sum of counters matching the priorities marked in the qdisc
priomap.
Changing the mapping of the priorities to bands while traffic is running
can result in losing the stats of the bands qdiscs from their last dump
call to this change, as if the qdisc was unoffloaded and re-offloaded. It
will not affect the traffic behaviour according to sch_red.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Reviewed-by: Yuval Mintz <yuvalm@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Nogah Frankel authored and David S. Miller committed Feb 28, 2018
1 parent 1631ab2 commit 04cc0bf
Showing 1 changed file with 50 additions and 19 deletions.
69 changes: 50 additions & 19 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,23 @@ mlxsw_sp_qdisc_get_xstats(struct mlxsw_sp_port *mlxsw_sp_port,
return -EOPNOTSUPP;
}

static void
mlxsw_sp_qdisc_bstats_per_priority_get(struct mlxsw_sp_port_xstats *xstats,
u8 prio_bitmap, u64 *tx_packets,
u64 *tx_bytes)
{
int i;

*tx_packets = 0;
*tx_bytes = 0;
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
if (prio_bitmap & BIT(i)) {
*tx_packets += xstats->tx_packets[i];
*tx_bytes += xstats->tx_bytes[i];
}
}
}

static int
mlxsw_sp_tclass_congestion_enable(struct mlxsw_sp_port *mlxsw_sp_port,
int tclass_num, u32 min, u32 max,
Expand Down Expand Up @@ -253,17 +270,16 @@ mlxsw_sp_setup_tc_qdisc_red_clean_stats(struct mlxsw_sp_port *mlxsw_sp_port,
u8 tclass_num = mlxsw_sp_qdisc->tclass_num;
struct mlxsw_sp_qdisc_stats *stats_base;
struct mlxsw_sp_port_xstats *xstats;
struct rtnl_link_stats64 *stats;
struct red_stats *red_base;

xstats = &mlxsw_sp_port->periodic_hw_stats.xstats;
stats = &mlxsw_sp_port->periodic_hw_stats.stats;
stats_base = &mlxsw_sp_qdisc->stats_base;
red_base = &mlxsw_sp_qdisc->xstats_base.red;

stats_base->tx_packets = stats->tx_packets;
stats_base->tx_bytes = stats->tx_bytes;

mlxsw_sp_qdisc_bstats_per_priority_get(xstats,
mlxsw_sp_qdisc->prio_bitmap,
&stats_base->tx_packets,
&stats_base->tx_bytes);
red_base->prob_mark = xstats->ecn;
red_base->prob_drop = xstats->wred_drop[tclass_num];
red_base->pdrop = xstats->tail_drop[tclass_num];
Expand Down Expand Up @@ -380,14 +396,16 @@ mlxsw_sp_qdisc_get_red_stats(struct mlxsw_sp_port *mlxsw_sp_port,
u8 tclass_num = mlxsw_sp_qdisc->tclass_num;
struct mlxsw_sp_qdisc_stats *stats_base;
struct mlxsw_sp_port_xstats *xstats;
struct rtnl_link_stats64 *stats;

xstats = &mlxsw_sp_port->periodic_hw_stats.xstats;
stats = &mlxsw_sp_port->periodic_hw_stats.stats;
stats_base = &mlxsw_sp_qdisc->stats_base;

tx_bytes = stats->tx_bytes - stats_base->tx_bytes;
tx_packets = stats->tx_packets - stats_base->tx_packets;
mlxsw_sp_qdisc_bstats_per_priority_get(xstats,
mlxsw_sp_qdisc->prio_bitmap,
&tx_packets, &tx_bytes);
tx_bytes = tx_bytes - stats_base->tx_bytes;
tx_packets = tx_packets - stats_base->tx_packets;

overlimits = xstats->wred_drop[tclass_num] + xstats->ecn -
stats_base->overlimits;
drops = xstats->wred_drop[tclass_num] + xstats->tail_drop[tclass_num] -
Expand Down Expand Up @@ -493,18 +511,31 @@ mlxsw_sp_qdisc_prio_replace(struct mlxsw_sp_port *mlxsw_sp_port,
void *params)
{
struct tc_prio_qopt_offload_params *p = params;
int tclass, i;
struct mlxsw_sp_qdisc *child_qdisc;
int tclass, i, band;
u8 old_priomap;
int err;

for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
mlxsw_sp_port->tclass_qdiscs[i].prio_bitmap = 0;

for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
tclass = MLXSW_SP_PRIO_BAND_TO_TCLASS(p->priomap[i]);
err = mlxsw_sp_port_prio_tc_set(mlxsw_sp_port, i, tclass);
if (err)
return err;
mlxsw_sp_port->tclass_qdiscs[tclass].prio_bitmap |= BIT(i);
for (band = 0; band < p->bands; band++) {
tclass = MLXSW_SP_PRIO_BAND_TO_TCLASS(band);
child_qdisc = &mlxsw_sp_port->tclass_qdiscs[tclass];
old_priomap = child_qdisc->prio_bitmap;
child_qdisc->prio_bitmap = 0;
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
if (p->priomap[i] == band) {
child_qdisc->prio_bitmap |= BIT(i);
if (BIT(i) & old_priomap)
continue;
err = mlxsw_sp_port_prio_tc_set(mlxsw_sp_port,
i, tclass);
if (err)
return err;
}
}
if (old_priomap != child_qdisc->prio_bitmap &&
child_qdisc->ops && child_qdisc->ops->clean_stats)
child_qdisc->ops->clean_stats(mlxsw_sp_port,
child_qdisc);
}

return 0;
Expand Down

0 comments on commit 04cc0bf

Please sign in to comment.