From 7808df2e2fd0fd61a27e5a5322dc6dafe40924e5 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Mon, 2 Nov 2020 18:00:32 -0800 Subject: [PATCH] session: allow small pacer bursts 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 Change-Id: I67e38e5b8dc335bd214113b70c68c27ae92bd6da --- src/vnet/session/session_node.c | 3 ++- src/vnet/session/transport.c | 35 +++++++++++++++++++++-------------- src/vnet/session/transport.h | 1 + src/vnet/session/transport_types.h | 8 ++++---- src/vppinfra/clib.h | 8 ++++++++ 5 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c index 8a350d4549f..12080122c8e 100644 --- a/src/vnet/session/session_node.c +++ b/src/vnet/session/session_node.c @@ -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; diff --git a/src/vnet/session/transport.c b/src/vnet/session/transport.c index 967ff5d9cba..a7fd85f5f2e 100644 --- a/src/vnet/session/transport.c +++ b/src/vnet/session/transport.c @@ -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 diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h index c8d4e27be66..9a9b89fc9fd 100644 --- a/src/vnet/session/transport.h +++ b/src/vnet/session/transport.h @@ -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 diff --git a/src/vnet/session/transport_types.h b/src/vnet/session/transport_types.h index ab34d9f3397..2caafea0fbe 100644 --- a/src/vnet/session/transport_types.h +++ b/src/vnet/session/transport_types.h @@ -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) diff --git a/src/vppinfra/clib.h b/src/vppinfra/clib.h index 9474350c6da..22377c61440 100644 --- a/src/vppinfra/clib.h +++ b/src/vppinfra/clib.h @@ -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); \ -- 2.16.6