session: allow small pacer bursts 27/29727/13
authorFlorin Coras <fcoras@cisco.com>
Tue, 3 Nov 2020 02:00:32 +0000 (18:00 -0800)
committerDave Barach <openvpp@barachs.net>
Tue, 1 Dec 2020 18:49:38 +0000 (18:49 +0000)
Instead of enforcing a "strict" release of data, which relies on
frequent rescheduling of sessions, allow some pacer coalescing, i.e.,
short bursts, that can minimize load on scheduler/session layer and
potentially leverage tso.

Type: improvement

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: I67e38e5b8dc335bd214113b70c68c27ae92bd6da

src/vnet/session/session_node.c
src/vnet/session/transport.c
src/vnet/session/transport.h
src/vnet/session/transport_types.h
src/vppinfra/clib.h

index 8a350d4..1208012 100644 (file)
@@ -1037,7 +1037,8 @@ session_tx_fifo_read_and_snd_i (session_worker_t * wrk,
       return SESSION_TX_NO_BUFFERS;
     }
 
-  transport_connection_update_tx_bytes (ctx->tc, ctx->max_len_to_snd);
+  if (transport_connection_is_tx_paced (ctx->tc))
+    transport_connection_tx_pacer_update_bytes (ctx->tc, ctx->max_len_to_snd);
 
   ctx->left_to_snd = ctx->max_len_to_snd;
   n_left = ctx->n_segs_per_evt;
index 967ff5d..a7fd85f 100644 (file)
@@ -632,9 +632,9 @@ format_transport_pacer (u8 * s, va_list * args)
 
   now = transport_us_time_now (thread_index);
   diff = now - pacer->last_update;
-  s = format (s, "rate %lu bucket %lu t/p %.3f last_update %U idle %u",
+  s = format (s, "rate %lu bucket %lu t/p %.3f last_update %U burst %u",
              pacer->bytes_per_sec, pacer->bucket, pacer->tokens_per_period,
-             format_clib_us_time, diff, pacer->idle_timeout_us);
+             format_clib_us_time, diff, pacer->max_burst);
   return s;
 }
 
@@ -644,26 +644,18 @@ spacer_max_burst (spacer_t * pacer, clib_us_time_t time_now)
   u64 n_periods = (time_now - pacer->last_update);
   u64 inc;
 
-  if (PREDICT_FALSE (n_periods > pacer->idle_timeout_us))
-    {
-      pacer->last_update = time_now;
-      pacer->bucket = TRANSPORT_PACER_MIN_BURST;
-      return TRANSPORT_PACER_MIN_BURST;
-    }
-
   if ((inc = (f32) n_periods * pacer->tokens_per_period) > 10)
     {
       pacer->last_update = time_now;
-      pacer->bucket = clib_min (pacer->bucket + inc, pacer->bytes_per_sec);
+      pacer->bucket = clib_min (pacer->bucket + inc, pacer->max_burst);
     }
 
-  return clib_min (pacer->bucket, TRANSPORT_PACER_MAX_BURST);
+  return pacer->bucket > 0 ? pacer->max_burst : 0;
 }
 
 static inline void
 spacer_update_bucket (spacer_t * pacer, u32 bytes)
 {
-  ASSERT (pacer->bucket >= bytes);
   pacer->bucket -= bytes;
 }
 
@@ -671,11 +663,26 @@ static inline void
 spacer_set_pace_rate (spacer_t * pacer, u64 rate_bytes_per_sec,
                      clib_us_time_t rtt)
 {
+  clib_us_time_t max_time;
+
   ASSERT (rate_bytes_per_sec != 0);
   pacer->bytes_per_sec = rate_bytes_per_sec;
   pacer->tokens_per_period = rate_bytes_per_sec * CLIB_US_TIME_PERIOD;
-  pacer->idle_timeout_us = clib_max (rtt * TRANSPORT_PACER_IDLE_FACTOR,
-                                    TRANSPORT_PACER_MIN_IDLE);
+
+  /* Allow a min number of bursts per rtt, if their size is acceptable. Goal
+   * is to spread the sending of data over the rtt but to also allow for some
+   * coalescing that can potentially
+   * 1) reduce load on session layer by reducing scheduling frequency for a
+   *    session and
+   * 2) optimize sending when tso if available
+   *
+   * Max "time-length" of a burst cannot be less than 1us or more than 1ms.
+   */
+  max_time = rtt / TRANSPORT_PACER_BURSTS_PER_RTT;
+  max_time = clib_clamp (max_time, 1 /* 1us */ , 1000 /* 1ms */ );
+  pacer->max_burst = (rate_bytes_per_sec * max_time) * CLIB_US_TIME_PERIOD;
+  pacer->max_burst = clib_clamp (pacer->max_burst, TRANSPORT_PACER_MIN_BURST,
+                                TRANSPORT_PACER_MAX_BURST);
 }
 
 static inline u64
index c8d4e27..9a9b89f 100644 (file)
@@ -23,6 +23,7 @@
 #define TRANSPORT_PACER_MIN_BURST      TRANSPORT_PACER_MIN_MSS
 #define TRANSPORT_PACER_MAX_BURST      (43 * TRANSPORT_PACER_MIN_MSS)
 #define TRANSPORT_PACER_MAX_BURST_PKTS 43
+#define TRANSPORT_PACER_BURSTS_PER_RTT 20
 #define TRANSPORT_PACER_MIN_IDLE       100
 #define TRANSPORT_PACER_IDLE_FACTOR    0.05
 
index ab34d9f..2caafea 100644 (file)
@@ -65,10 +65,10 @@ typedef enum transport_connection_flags_
 typedef struct _spacer
 {
   u64 bytes_per_sec;
-  u64 bucket;
+  i64 bucket;
   clib_us_time_t last_update;
   f32 tokens_per_period;
-  u32 idle_timeout_us;
+  u32 max_burst;
 } spacer_t;
 
 #define TRANSPORT_CONN_ID_LEN  44
@@ -146,8 +146,8 @@ typedef struct _transport_connection
 #define c_stats connection.stats
 #define c_pacer connection.pacer
 #define c_flags connection.flags
-#define s_ho_handle pacer.bucket
-#define c_s_ho_handle connection.pacer.bucket
+#define s_ho_handle pacer.bytes_per_sec
+#define c_s_ho_handle connection.pacer.bytes_per_sec
 } transport_connection_t;
 
 STATIC_ASSERT (STRUCT_OFFSET_OF (transport_connection_t, s_index)
index 9474350..22377c6 100644 (file)
@@ -332,6 +332,14 @@ extract_bits (uword x, int start, int count)
   _x < _y ? _x : _y;                           \
 })
 
+#define clib_clamp(x,lo,hi)                    \
+({                                             \
+  __typeof__ (x) _x = (x);                     \
+  __typeof__ (lo) _lo = (lo);                  \
+  __typeof__ (hi) _hi = (hi);                  \
+  _x < _lo ? _lo : (_x > _hi ? _hi : _x);      \
+})
+
 #define clib_abs(x)                            \
 ({                                             \
   __typeof__ (x) _x = (x);                     \