92 memset (bts, 0xfc,
sizeof (*bts));
148 while (seq != cur->
key)
288 u32 available_bytes, flight_size;
294 if (available_bytes + flight_size + tc->snd_mss < tc->cwnd
296 && tc->sack_sb.lost_bytes <= tc->snd_rxt_bytes)
297 tc->app_limited = tc->delivered + flight_size ? : 1;
308 if (tail && tail->
max_seq == tc->snd_nxt
316 if (tc->snd_una == tc->snd_nxt)
319 tc->first_tx_time = tc->delivered_time;
327 tail->
next = bts_index;
329 bt->
tail = bts_index;
342 u32 bts_index, cur_index, next_index, prev_index, max_seq;
343 u8 is_end = end == tc->snd_nxt;
348 if (bts && bts->
max_seq == start
362 bts_flags = bts->
flags;
373 prev_index = bts->
prev;
382 cur->
next = next_index;
383 cur->
prev = prev_index;
390 next->
prev = cur_index;
394 bt->
tail = cur_index;
400 prev->
next = cur_index;
404 bt->
head = cur_index;
424 cur->
prev = bts_index;
428 if (
seq_lt (end, max_seq))
460 next->
prev = cur_index;
463 bt->
tail = cur_index;
466 bts->
next = cur_index;
489 tc->first_tx_time = bts->
tx_time;
522 for (i = 0; i <
vec_len (blks); i++)
527 if (
seq_lt (blk->end, tc->snd_una))
603 tc->lost += tc->sack_sb.last_lost_bytes;
605 delivered = tc->bytes_acked + tc->sack_sb.last_sacked_bytes;
607 delivered -= tc->sack_sb.last_bytes_delivered;
611 tc->delivered += delivered;
614 if (tc->app_limited && tc->delivered > tc->app_limited)
620 if (tc->sack_sb.last_sacked_bytes)
627 rs->
last_lost = tc->sack_sb.last_lost_bytes;
636 u32 *samples = 0, *
si;
686 s =
format (s,
"[%u, %u] d %u dt %.3f txt %.3f ftxt %.3f flags 0x%x",
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
static tcp_bt_sample_t * bt_next_sample(tcp_byte_tracker_t *bt, tcp_bt_sample_t *bts)
#define TCP_BTS_INVALID_INDEX
u64 tx_lost
Lost at tx time.
f64 tx_time
Transmit time for the burst.
u8 * format_tcp_bt_sample(u8 *s, va_list *args)
struct _sack_block sack_block_t
int tcp_bt_is_sane(tcp_byte_tracker_t *bt)
Check if the byte tracker is in sane state.
u8 * format_tcp_bt(u8 *s, va_list *args)
u32 prev
Previous sample index in list.
f64 first_tx_time
Connection first tx time at tx.
static tcp_bt_sample_t * bt_split_sample(tcp_byte_tracker_t *bt, tcp_bt_sample_t *bts, u32 seq)
static rb_node_t * rb_node_left(rb_tree_t *rt, rb_node_t *n)
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
#define pool_foreach(VAR, POOL)
Iterate through pool.
static void bt_free_sample(tcp_byte_tracker_t *bt, tcp_bt_sample_t *bts)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static tcp_bt_sample_t * bt_lookup_seq(tcp_byte_tracker_t *bt, u32 seq)
struct _tcp_connection tcp_connection_t
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
f64 prior_time
Delivered time of sample used for rate.
static rb_node_t * rb_node(rb_tree_t *rt, rb_node_index_t ri)
enum tcp_bts_flags_ tcp_bts_flags_t
static rb_node_t * rb_node_right(rb_tree_t *rt, rb_node_t *n)
u32 head
Head of samples linked list.
static void tcp_bt_sample_to_rate_sample(tcp_connection_t *tc, tcp_bt_sample_t *bts, tcp_rate_sample_t *rs)
static void tcp_bt_walk_samples(tcp_connection_t *tc, tcp_rate_sample_t *rs)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
__clib_export rb_node_t * rb_tree_predecessor(rb_tree_t *rt, rb_node_t *x)
__clib_export void rb_tree_free_nodes(rb_tree_t *rt)
static tcp_bt_sample_t * bt_prev_sample(tcp_byte_tracker_t *bt, tcp_bt_sample_t *bts)
void tcp_bt_sample_delivery_rate(tcp_connection_t *tc, tcp_rate_sample_t *rs)
Generate a delivery rate sample from recently acked bytes.
#define seq_leq(_s1, _s2)
static tcp_bt_sample_t * bt_alloc_sample(tcp_byte_tracker_t *bt, u32 min_seq, u32 max_seq)
description fragment has unexpected format
__clib_export rb_node_index_t rb_tree_add_custom(rb_tree_t *rt, u32 key, uword opaque, rb_tree_lt_fn ltfn)
static tcp_bt_sample_t * bt_get_sample(tcp_byte_tracker_t *bt, u32 bts_index)
u32 max_seq
Max seq number.
void tcp_bt_init(tcp_connection_t *tc)
Byte tracker initialize.
u32 lost
Number of bytes lost over interval.
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
u32 delivered
Bytes delivered in interval_time.
uword opaque
value stored by node
rb_tree_t sample_lookup
Rbtree for sample lookup by min_seq.
tcp_bt_sample_t * samples
Pool of samples.
f64 interval_time
Time to ack the bytes delivered.
void tcp_bt_cleanup(tcp_connection_t *tc)
Byte tracker cleanup.
#define pool_put(P, E)
Free an object E in pool P.
__clib_export void rb_tree_del_custom(rb_tree_t *rt, u32 key, rb_tree_lt_fn ltfn)
u32 next
Next sample index in list.
tcp_bts_flags_t flags
Sample flag.
f64 delivered_time
Delivered time when sample taken.
#define pool_free(p)
Free a pool.
static u32 tcp_flight_size(const tcp_connection_t *tc)
Our estimate of the number of bytes in flight (pipe size)
void tcp_bt_track_tx(tcp_connection_t *tc, u32 len)
Track a tcp tx burst.
sll srl srl sll sra u16x4 i
#define vec_free(V)
Free vector's memory (no header).
#define clib_warning(format, args...)
static u32 bt_sample_index(tcp_byte_tracker_t *bt, tcp_bt_sample_t *bts)
f64 rtt_time
RTT for sample.
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
static int bt_seq_lt(u32 a, u32 b)
static u32 transport_max_tx_dequeue(transport_connection_t *tc)
#define seq_geq(_s1, _s2)
void tcp_bt_check_app_limited(tcp_connection_t *tc)
Check if sample to be generated is app limited.
void tcp_bt_track_rxt(tcp_connection_t *tc, u32 start, u32 end)
Track a tcp retransmission.
static tcp_bt_sample_t * bt_merge_sample(tcp_byte_tracker_t *bt, tcp_bt_sample_t *prev, tcp_bt_sample_t *cur)
static void clib_mem_free(void *p)
u32 last_lost
Bytes lost now.
u32 last_ooo
Cached last ooo sample.
static void * clib_mem_alloc(uword size)
u64 tx_lost
Lost over interval.
__clib_export void rb_tree_init(rb_tree_t *rt)
u64 delivered
Total delivered bytes for sample.
static u8 rb_node_is_tnil(rb_tree_t *rt, rb_node_t *n)
u32 tail
Tail of samples linked list.
u64 tx_in_flight
In flight at (re)transmit time.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void bt_update_sample(tcp_byte_tracker_t *bt, tcp_bt_sample_t *bts, u32 seq)
static f64 tcp_time_now_us(u32 thread_index)
u32 min_seq
Min seq number in sample.
void tcp_bt_flush_samples(tcp_connection_t *tc)
Flush byte tracker samples.
u64 prior_delivered
Delivered of sample used for rate, i.e., total bytes delivered at prior_time.
static tcp_bt_sample_t * bt_fix_overlapped(tcp_byte_tracker_t *bt, tcp_bt_sample_t *start, u32 seq, u8 is_end)
#define vec_foreach(var, vec)
Vector iterator.
f64 end
end of the time range
rb_node_t * nodes
pool of nodes
tcp_bts_flags_t flags
Rate sample flags from bt sample.
static tcp_bt_sample_t * tcp_bt_alloc_tx_sample(tcp_connection_t *tc, u32 min_seq, u32 max_seq)
static void tcp_bt_walk_samples_ooo(tcp_connection_t *tc, tcp_rate_sample_t *rs)
rb_node_index_t root
root index
u32 acked_and_sacked
Bytes acked + sacked now.
u64 tx_in_flight
In flight at tx time.
static uword pool_elts(void *v)
Number of active elements in a pool.