aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/tcp/tcp_input.c
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2018-11-02 12:52:10 -0700
committerMarco Varlese <marco.varlese@suse.de>2018-11-05 08:20:51 +0000
commit36ee9f1ca37daf277c2cd8d33bf16eabc15773e5 (patch)
tree14c53a845447cb77efeaea2a7dad79a3f2e6ca92 /src/vnet/tcp/tcp_input.c
parent40cca7585d969499e92b98c32956bbe3f2050e4e (diff)
tcp: send unsent data in fast recovery
Allows sending of unsent data in fast recovery and consolidates logic in tcp, instead of splitting it between tcp fast retransmit and tcp output path called by the session layer. Change-Id: I9b12cdf2aa2ac50b9f25e46856fed037163501fe Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vnet/tcp/tcp_input.c')
-rw-r--r--src/vnet/tcp/tcp_input.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c
index 21e5f3cdaba..0b79a6699d7 100644
--- a/src/vnet/tcp/tcp_input.c
+++ b/src/vnet/tcp/tcp_input.c
@@ -719,8 +719,7 @@ scoreboard_update_bytes (tcp_connection_t * tc, sack_scoreboard_t * sb)
sack_scoreboard_hole_t *
scoreboard_next_rxt_hole (sack_scoreboard_t * sb,
sack_scoreboard_hole_t * start,
- u8 have_sent_1_smss,
- u8 * can_rescue, u8 * snd_limited)
+ u8 have_unsent, u8 * can_rescue, u8 * snd_limited)
{
sack_scoreboard_hole_t *hole = 0;
@@ -742,11 +741,11 @@ scoreboard_next_rxt_hole (sack_scoreboard_t * sb,
}
else
{
- /* Rule (2): output takes care of transmitting new data */
- if (!have_sent_1_smss)
+ /* Rule (2): available unsent data */
+ if (have_unsent)
{
- hole = 0;
sb->cur_rxt_hole = TCP_INVALID_SACK_HOLE_INDEX;
+ return 0;
}
/* Rule (3): if hole not lost */
else if (seq_lt (hole->start, sb->high_sacked))
@@ -772,16 +771,17 @@ scoreboard_next_rxt_hole (sack_scoreboard_t * sb,
}
static void
-scoreboard_init_high_rxt (sack_scoreboard_t * sb, u32 seq)
+scoreboard_init_high_rxt (sack_scoreboard_t * sb, u32 snd_una)
{
sack_scoreboard_hole_t *hole;
hole = scoreboard_first_hole (sb);
if (hole)
{
- seq = seq_gt (seq, hole->start) ? seq : hole->start;
+ snd_una = seq_gt (snd_una, hole->start) ? snd_una : hole->start;
sb->cur_rxt_hole = sb->head;
}
- sb->high_rxt = seq;
+ sb->high_rxt = snd_una;
+ sb->rescue_rxt = snd_una - 1;
}
void
@@ -1306,7 +1306,6 @@ tcp_cc_handle_event (tcp_connection_t * tc, u32 is_dack)
{
tc->cwnd = tc->ssthresh;
scoreboard_init_high_rxt (&tc->sack_sb, tc->snd_una);
- tc->sack_sb.rescue_rxt = tc->snd_una - 1;
}
else
{
@@ -1316,6 +1315,7 @@ tcp_cc_handle_event (tcp_connection_t * tc, u32 is_dack)
tc->cwnd = tc->ssthresh + 3 * tc->snd_mss;
}
+ /* Constrain rate until we get a partial ack */
pacer_wnd = clib_max (0.1 * tc->cwnd, 2 * tc->snd_mss);
tcp_connection_tx_pacer_reset (tc, pacer_wnd,
0 /* start bucket */ );
@@ -1387,6 +1387,10 @@ partial_ack:
* Legitimate ACK. 2) If PARTIAL ACK try to retransmit
*/
+ /* Update the pacing rate. For the first partial ack we move from
+ * the artificially constrained rate to the one after congestion */
+ tcp_connection_tx_pacer_update (tc);
+
/* XXX limit this only to first partial ack? */
tcp_retransmit_timer_force_update (tc);
@@ -1422,10 +1426,14 @@ partial_ack:
{
/* Apparently all retransmitted holes have been acked */
tc->snd_rxt_bytes = 0;
+ tc->sack_sb.high_rxt = tc->snd_una;
}
}
else
{
+ tcp_fastrecovery_first_on (tc);
+ /* Reuse last bytes delivered to track total bytes acked */
+ tc->sack_sb.last_bytes_delivered += tc->bytes_acked;
if (tc->snd_rxt_bytes > tc->bytes_acked)
tc->snd_rxt_bytes -= tc->bytes_acked;
else
@@ -1473,7 +1481,7 @@ tcp_rcv_ack (tcp_connection_t * tc, vlib_buffer_t * b,
{
tcp_make_ack (tc, b);
*next = tcp_next_output (tc->c_is_ip4);
- *error = TCP_ERROR_ACK_INVALID;
+ *error = TCP_ERROR_ACK_FUTURE;
TCP_EVT_DBG (TCP_EVT_ACK_RCV_ERR, tc, 0,
vnet_buffer (b)->tcp.ack_number);
return -1;
@@ -1483,7 +1491,6 @@ tcp_rcv_ack (tcp_connection_t * tc, vlib_buffer_t * b,
vnet_buffer (b)->tcp.ack_number);
tc->snd_nxt = vnet_buffer (b)->tcp.ack_number;
- *error = TCP_ERROR_ACK_FUTURE;
}
/* If old ACK, probably it's an old dupack */