mlxsw: spectrum_qdisc: Introduce per-TC ECN counters
authorPetr Machata <petrm@nvidia.com>
Wed, 13 Oct 2021 10:37:47 +0000 (13:37 +0300)
committerJakub Kicinski <kuba@kernel.org>
Thu, 14 Oct 2021 00:47:18 +0000 (17:47 -0700)
The Qdisc code in mlxsw used to report a number of packets ECN-marked on a
port. Because reporting a per-port value as a per-TC value was misleading,
this was removed in commit 8a29581eb001 ("mlxsw: spectrum: Move the
ECN-marked packet counter to ethtool").

On Spectrum-3, a per-TC number of ECN-marked packets is available in per-TC
congestion counter group. Add a new array for the ECN counter, fetch the
values from the per-TC congestion group, and pick the value indicated by
tclass_num as appropriate.

On Spectrum-1 and Spectrum-2, this per-TC value is not available, and
zeroes will be reported, as they currently are.

Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c

index 67529e9537a6d50cb5cb730c252292eab5a722ae..d05850ff3a77801ba46c97727e1702f4f843fd09 100644 (file)
@@ -826,10 +826,14 @@ mlxsw_sp_port_get_hw_xstats(struct net_device *dev,
                err = mlxsw_sp_port_get_stats_raw(dev,
                                                  MLXSW_REG_PPCNT_TC_CONG_CNT,
                                                  i, ppcnt_pl);
-               if (!err)
-                       xstats->wred_drop[i] =
-                               mlxsw_reg_ppcnt_wred_discard_get(ppcnt_pl);
+               if (err)
+                       goto tc_cnt;
+
+               xstats->wred_drop[i] =
+                       mlxsw_reg_ppcnt_wred_discard_get(ppcnt_pl);
+               xstats->tc_ecn[i] = mlxsw_reg_ppcnt_ecn_marked_tc_get(ppcnt_pl);
 
+tc_cnt:
                err = mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_TC_CNT,
                                                  i, ppcnt_pl);
                if (err)
index aae1aed5345b04d623e854240253fef0787d3c77..3ab57e98cad22700537cfc27859083cb5d364828 100644 (file)
@@ -285,6 +285,7 @@ struct mlxsw_sp_port_vlan {
 /* No need an internal lock; At worse - miss a single periodic iteration */
 struct mlxsw_sp_port_xstats {
        u64 ecn;
+       u64 tc_ecn[TC_MAX_QUEUE];
        u64 wred_drop[TC_MAX_QUEUE];
        u64 tail_drop[TC_MAX_QUEUE];
        u64 backlog[TC_MAX_QUEUE];
index e367c63e72bfb95c732d9302e59c2da094463059..6d1431fa31d7ed3cf088d4f7f8310ff61b761e76 100644 (file)
@@ -519,6 +519,7 @@ mlxsw_sp_setup_tc_qdisc_red_clean_stats(struct mlxsw_sp_port *mlxsw_sp_port,
                                               mlxsw_sp_qdisc->prio_bitmap,
                                               &stats_base->tx_packets,
                                               &stats_base->tx_bytes);
+       red_base->prob_mark = xstats->tc_ecn[tclass_num];
        red_base->prob_drop = xstats->wred_drop[tclass_num];
        red_base->pdrop = mlxsw_sp_xstats_tail_drop(xstats, tclass_num);
 
@@ -618,19 +619,22 @@ mlxsw_sp_qdisc_get_red_xstats(struct mlxsw_sp_port *mlxsw_sp_port,
        int tclass_num = mlxsw_sp_qdisc->tclass_num;
        struct mlxsw_sp_port_xstats *xstats;
        struct red_stats *res = xstats_ptr;
-       int early_drops, pdrops;
+       int early_drops, marks, pdrops;
 
        xstats = &mlxsw_sp_port->periodic_hw_stats.xstats;
 
        early_drops = xstats->wred_drop[tclass_num] - xstats_base->prob_drop;
+       marks = xstats->tc_ecn[tclass_num] - xstats_base->prob_mark;
        pdrops = mlxsw_sp_xstats_tail_drop(xstats, tclass_num) -
                 xstats_base->pdrop;
 
        res->pdrop += pdrops;
        res->prob_drop += early_drops;
+       res->prob_mark += marks;
 
        xstats_base->pdrop += pdrops;
        xstats_base->prob_drop += early_drops;
+       xstats_base->prob_mark += marks;
        return 0;
 }
 
@@ -648,7 +652,8 @@ mlxsw_sp_qdisc_get_red_stats(struct mlxsw_sp_port *mlxsw_sp_port,
        stats_base = &mlxsw_sp_qdisc->stats_base;
 
        mlxsw_sp_qdisc_get_tc_stats(mlxsw_sp_port, mlxsw_sp_qdisc, stats_ptr);
-       overlimits = xstats->wred_drop[tclass_num] - stats_base->overlimits;
+       overlimits = xstats->wred_drop[tclass_num] +
+                    xstats->tc_ecn[tclass_num] - stats_base->overlimits;
 
        stats_ptr->qstats->overlimits += overlimits;
        stats_base->overlimits += overlimits;