* seq_lt (tc->snd_una, ack). This is a condition for calling update_rtt */
else if (tcp_opts_tstamp (&tc->rcv_opts) && tc->rcv_opts.tsecr)
{
- u32 now = tcp_time_now_w_thread (tc->c_thread_index);
+ u32 now = tcp_tstamp (tc);
mrtt = clib_max (now - tc->rcv_opts.tsecr, 1);
}
sack_scoreboard_hole_t *left, *right;
u32 bytes = 0, blks = 0;
+ sb->last_lost_bytes = 0;
sb->lost_bytes = 0;
sb->sacked_bytes = 0;
left = scoreboard_last_hole (sb);
do
{
sb->lost_bytes += scoreboard_hole_bytes (right);
+ sb->last_lost_bytes += left->is_lost ? 0 : left->end - left->start;
left->is_lost = 1;
left = scoreboard_prev_hole (sb, right);
if (left)
sb->high_sacked = 0;
sb->high_rxt = 0;
sb->lost_bytes = 0;
+ sb->last_lost_bytes = 0;
sb->cur_rxt_hole = TCP_INVALID_SACK_HOLE_INDEX;
}
#endif /* CLIB_MARCH_VARIANT */
}
#ifndef CLIB_MARCH_VARIANT
+
void
tcp_rcv_sacks (tcp_connection_t * tc, u32 ack)
{
- sack_scoreboard_t *sb = &tc->sack_sb;
- sack_block_t *blk, tmp;
sack_scoreboard_hole_t *hole, *next_hole, *last_hole;
u32 blk_index = 0, old_sacked_bytes, hole_index;
+ sack_scoreboard_t *sb = &tc->sack_sb;
+ sack_block_t *blk, tmp;
int i, j;
sb->last_sacked_bytes = 0;
sb->last_bytes_delivered += sb->high_sacked - hole->end;
}
}
-
scoreboard_remove_hole (sb, hole);
hole = next_hole;
}
scoreboard_update_bytes (tc, sb);
sb->last_sacked_bytes = sb->sacked_bytes
- (old_sacked_bytes - sb->last_bytes_delivered);
+
ASSERT (sb->last_sacked_bytes <= sb->sacked_bytes || tcp_in_recovery (tc));
ASSERT (sb->sacked_bytes == 0 || tcp_in_recovery (tc)
|| sb->sacked_bytes < tc->snd_nxt - seq_max (tc->snd_una, ack));
- seq_max (tc->snd_una, ack) || tcp_in_recovery (tc));
ASSERT (sb->head == TCP_INVALID_SACK_HOLE_INDEX || tcp_in_recovery (tc)
|| sb->holes[sb->head].start == ack + sb->snd_una_adv);
+ ASSERT (sb->last_lost_bytes <= sb->lost_bytes);
+
TCP_EVT_DBG (TCP_EVT_CC_SCOREBOARD, tc);
}
#endif /* CLIB_MARCH_VARIANT */
#ifndef CLIB_MARCH_VARIANT
void
-tcp_cc_fastrecovery_exit (tcp_connection_t * tc)
+tcp_cc_fastrecovery_clear (tcp_connection_t * tc)
{
- tc->cc_algo->recovered (tc);
tc->snd_rxt_bytes = 0;
tc->rcv_dupacks = 0;
- tc->snd_rxt_bytes = 0;
tc->rtt_ts = 0;
tcp_fastrecovery_off (tc);
}
else if (tcp_in_fastrecovery (tc))
{
- tcp_cc_fastrecovery_exit (tc);
+ tcp_cc_fastrecovery_clear (tc);
}
+ tcp_cc_undo_recovery (tc);
ASSERT (tc->rto_boff == 0);
TCP_EVT_DBG (TCP_EVT_CC_EVT, tc, 5);
}
if (tcp_in_recovery (tc))
tcp_cc_recovery_exit (tc);
else if (tcp_in_fastrecovery (tc))
- tcp_cc_fastrecovery_exit (tc);
+ {
+ tcp_cc_recovered (tc);
+ tcp_cc_fastrecovery_clear (tc);
+ }
ASSERT (tc->rto_boff == 0);
ASSERT (!tcp_in_cong_recovery (tc));
tcp_rcv_fin (tcp_worker_ctx_t * wrk, tcp_connection_t * tc, vlib_buffer_t * b,
u32 * error)
{
+ /* Reject out-of-order fins */
+ if (vnet_buffer (b)->tcp.seq_end != tc->rcv_nxt)
+ return;
+
/* Account for the FIN and send ack */
tc->rcv_nxt += 1;
tcp_program_ack (wrk, tc);
break;
/* Still have outstanding tx data */
- if (transport_max_tx_dequeue (&tc0->connection))
+ max_dequeue = transport_max_tx_dequeue (&tc0->connection);
+ if (max_dequeue > tc0->burst_acked)
break;
tcp_send_fin (tc0);