s = format (s, "%U", tp_vft->format_connection, conn_index, thread_index,
verbose);
tc = tp_vft->get_connection (conn_index, thread_index);
- if (tc && transport_connection_is_tx_paced (tc) && verbose > 1)
+ if (tc && verbose > 1)
{
indent = format_get_indent (s) + 1;
- s = format (s, "%Upacer: %U\n", format_white_space, indent,
- format_transport_pacer, &tc->pacer, tc->thread_index);
+ if (transport_connection_is_tx_paced (tc))
+ s = format (s, "%Upacer: %U\n", format_white_space, indent,
+ format_transport_pacer, &tc->pacer, tc->thread_index);
s = format (s, "%Utransport: flags 0x%x\n", format_white_space, indent,
tc->flags);
}
}
}
+int
+transport_connection_attribute (transport_proto_t tp, u32 conn_index,
+ u8 thread_index, u8 is_get,
+ transport_endpt_attr_t *attr)
+{
+ if (!tp_vfts[tp].attribute)
+ return -1;
+
+ return tp_vfts[tp].attribute (conn_index, thread_index, is_get, attr);
+}
+
#define PORT_MASK ((1 << 16)- 1)
void
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 %ld 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;
}
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;
}
static inline void
spacer_set_pace_rate (spacer_t * pacer, u64 rate_bytes_per_sec,
- clib_us_time_t rtt)
+ clib_us_time_t rtt, clib_time_type_t sec_per_loop)
{
+ 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 = clib_max (rtt / TRANSPORT_PACER_BURSTS_PER_RTT,
+ (clib_us_time_t) (sec_per_loop * CLIB_US_TIME_FREQ));
+ 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
u64 rate_bytes_per_sec, u32 start_bucket,
clib_us_time_t rtt)
{
- spacer_set_pace_rate (&tc->pacer, rate_bytes_per_sec, rtt);
+ spacer_set_pace_rate (&tc->pacer, rate_bytes_per_sec, rtt,
+ transport_seconds_per_loop (tc->thread_index));
spacer_reset (&tc->pacer, transport_us_time_now (tc->thread_index),
start_bucket);
}
transport_connection_tx_pacer_update (transport_connection_t * tc,
u64 bytes_per_sec, clib_us_time_t rtt)
{
- spacer_set_pace_rate (&tc->pacer, bytes_per_sec, rtt);
+ spacer_set_pace_rate (&tc->pacer, bytes_per_sec, rtt,
+ transport_seconds_per_loop (tc->thread_index));
}
u32
spacer_update_bucket (&tc->pacer, bytes);
}
+void
+transport_update_pacer_time (u32 thread_index, clib_time_type_t now)
+{
+ session_wrk_update_time (session_main_get_worker (thread_index), now);
+}
+
void
transport_connection_reschedule (transport_connection_t * tc)
{
}
}
+void
+transport_fifos_init_ooo (transport_connection_t * tc)
+{
+ session_t *s = session_get (tc->s_index, tc->thread_index);
+ svm_fifo_init_ooo_lookup (s->rx_fifo, 0 /* ooo enq */ );
+ svm_fifo_init_ooo_lookup (s->tx_fifo, 1 /* ooo deq */ );
+}
+
void
transport_update_time (clib_time_type_t time_now, u8 thread_index)
{