net/mlx5e: Added BW check for DIM decision mechanism
authorTal Gilboa <talgi@mellanox.com>
Mon, 15 May 2017 11:13:16 +0000 (14:13 +0300)
committerSaeed Mahameed <saeedm@mellanox.com>
Sun, 11 Jun 2017 10:10:36 +0000 (13:10 +0300)
DIM (Dynamically-tuned Interrupt Moderation) is a mechanism designed for
changing the channel interrupt moderation values in order to reduce CPU
overhead for all traffic types.
Until now only interrupt and packet rate were sampled.
We found a scenario on which we get a false indication since a change in
DIM caused more aggregation and reduced packet rate while increasing BW.

We now regard a change as succesfull iff:
current_BW > (prev_BW + threshold) or
current_BW ~= prev_BW and current_PR > (prev_PR + threshold) or
current_BW ~= prev_BW and current_PR ~= prev_PR and
    current_IR < (prev_IR - threshold)
Where BW = Bandwidth, PR = Packet rate and IR = Interrupt rate

Improvements (ConnectX-4Lx 25GbE, single RX queue, LRO off)
    --------------------------------------------------
    packet size | before[Mb/s] | after[Mb/s] | gain  |
    2B          | 343.4        | 359.4       |  4.5% |
    16B         | 2739.7       | 2814.8      |  2.7% |
    64B         | 9739         | 10185.3     |  4.5% |

Fixes: cb3c7fd4f839 ("net/mlx5e: Support adaptive RX coalescing")
Signed-off-by: Tal Gilboa <talgi@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c

index 2fd044b238750fedc61384fda55bf25206d25b51..429da21a583dde9372f4be5b265f0188892a4af5 100644 (file)
@@ -458,12 +458,14 @@ struct mlx5e_mpw_info {
 
 struct mlx5e_rx_am_stats {
        int ppms; /* packets per msec */
+       int bpms; /* bytes per msec */
        int epms; /* events per msec */
 };
 
 struct mlx5e_rx_am_sample {
        ktime_t         time;
        unsigned int    pkt_ctr;
+       unsigned int    byte_ctr;
        u16             event_ctr;
 };
 
index 02dd3a95ed8f013d0d4795d5054bd79ae4ca1201..54cdda957f9a4bf083632739ebe849ef9fd112d1 100644 (file)
@@ -183,28 +183,27 @@ static void mlx5e_am_exit_parking(struct mlx5e_rx_am *am)
        mlx5e_am_step(am);
 }
 
+#define IS_SIGNIFICANT_DIFF(val, ref) \
+       (((100 * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */
+
 static int mlx5e_am_stats_compare(struct mlx5e_rx_am_stats *curr,
                                  struct mlx5e_rx_am_stats *prev)
 {
-       int diff;
-
-       if (!prev->ppms)
-               return curr->ppms ? MLX5E_AM_STATS_BETTER :
+       if (!prev->bpms)
+               return curr->bpms ? MLX5E_AM_STATS_BETTER :
                                    MLX5E_AM_STATS_SAME;
 
-       diff = curr->ppms - prev->ppms;
-       if (((100 * abs(diff)) / prev->ppms) > 10) /* more than 10% diff */
-               return (diff > 0) ? MLX5E_AM_STATS_BETTER :
-                                   MLX5E_AM_STATS_WORSE;
+       if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms))
+               return (curr->bpms > prev->bpms) ? MLX5E_AM_STATS_BETTER :
+                                                  MLX5E_AM_STATS_WORSE;
 
-       if (!prev->epms)
-               return curr->epms ? MLX5E_AM_STATS_WORSE :
-                                   MLX5E_AM_STATS_SAME;
+       if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms))
+               return (curr->ppms > prev->ppms) ? MLX5E_AM_STATS_BETTER :
+                                                  MLX5E_AM_STATS_WORSE;
 
-       diff = curr->epms - prev->epms;
-       if (((100 * abs(diff)) / prev->epms) > 10) /* more than 10% diff */
-               return (diff < 0) ? MLX5E_AM_STATS_BETTER :
-                                   MLX5E_AM_STATS_WORSE;
+       if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms))
+               return (curr->epms < prev->epms) ? MLX5E_AM_STATS_BETTER :
+                                                  MLX5E_AM_STATS_WORSE;
 
        return MLX5E_AM_STATS_SAME;
 }
@@ -266,6 +265,7 @@ static void mlx5e_am_sample(struct mlx5e_rq *rq,
 {
        s->time      = ktime_get();
        s->pkt_ctr   = rq->stats.packets;
+       s->byte_ctr  = rq->stats.bytes;
        s->event_ctr = rq->cq.event_ctr;
 }
 
@@ -278,12 +278,15 @@ static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,
        /* u32 holds up to 71 minutes, should be enough */
        u32 delta_us = ktime_us_delta(end->time, start->time);
        unsigned int npkts = end->pkt_ctr - start->pkt_ctr;
+       unsigned int nbytes = end->byte_ctr - start->byte_ctr;
 
        if (!delta_us)
                return;
 
-       curr_stats->ppms =            (npkts * USEC_PER_MSEC) / delta_us;
-       curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us;
+       curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
+       curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
+       curr_stats->epms = DIV_ROUND_UP(MLX5E_AM_NEVENTS * USEC_PER_MSEC,
+                                       delta_us);
 }
 
 void mlx5e_rx_am_work(struct work_struct *work)