summaryrefslogtreecommitdiffstats
path: root/src/vnet/tcp/tcp.c
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2017-05-03 21:09:42 -0700
committerDave Barach <openvpp@barachs.net>2017-05-07 12:38:12 +0000
commit3af90fceb61d0c236709c25df936bbbf304cbff5 (patch)
tree19b9166a401fd23fb9e58a9ceba48ca8452c50a4 /src/vnet/tcp/tcp.c
parent1989bce006a28781156a61ced693775a6f5aba95 (diff)
Fix TCP loss recovery, VPP-745
Allows pure loss recovery retransmits only on timeout. Change-Id: I563cdbf9e7b890a6569350bdbda4f746ace0544e Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vnet/tcp/tcp.c')
-rw-r--r--src/vnet/tcp/tcp.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c
index de4edfa6b22..e80e2ec9b7c 100644
--- a/src/vnet/tcp/tcp.c
+++ b/src/vnet/tcp/tcp.c
@@ -567,30 +567,49 @@ tcp_session_send_mss (transport_connection_t * trans_conn)
return tc->snd_mss;
}
+always_inline u32
+tcp_round_snd_space (tcp_connection_t * tc, u32 snd_space)
+{
+ if (tc->snd_wnd < tc->snd_mss)
+ {
+ return tc->snd_wnd < snd_space ? tc->snd_wnd : 0;
+ }
+
+ /* If we can't write at least a segment, don't try at all */
+ if (snd_space < tc->snd_mss)
+ return 0;
+
+ /* round down to mss multiple */
+ return snd_space - (snd_space % tc->snd_mss);
+}
+
/**
* Compute tx window session is allowed to fill.
*/
u32
tcp_session_send_space (transport_connection_t * trans_conn)
{
- u32 snd_space, chunk;
+ int snd_space;
tcp_connection_t *tc = (tcp_connection_t *) trans_conn;
/* If we haven't gotten dupacks or if we did and have gotten sacked bytes
* then we can still send */
- if (PREDICT_TRUE (tcp_in_fastrecovery (tc) == 0
+ if (PREDICT_TRUE (tcp_in_cong_recovery (tc) == 0
&& (tc->rcv_dupacks == 0
|| tc->sack_sb.last_sacked_bytes)))
{
- chunk = tc->snd_wnd > tc->snd_mss ? tc->snd_mss : tc->snd_wnd;
snd_space = tcp_available_snd_space (tc);
+ return tcp_round_snd_space (tc, snd_space);
+ }
- /* If we can't write at least a segment, don't try at all */
- if (chunk == 0 || snd_space < chunk)
+ if (tcp_in_recovery (tc))
+ {
+ tc->snd_nxt = tc->snd_una_max;
+ snd_space = tcp_available_wnd (tc) - tc->rtx_bytes
+ - (tc->snd_una_max - tc->snd_congestion);
+ if (snd_space <= 0)
return 0;
-
- /* round down to mss multiple */
- return snd_space - (snd_space % chunk);
+ return tcp_round_snd_space (tc, snd_space);
}
/* If in fast recovery, send 1 SMSS if wnd allows */