From ff674d3e0e6ef3abe6456ee2f489799bcd43679e Mon Sep 17 00:00:00 2001 From: Asias He Date: Fri, 7 Nov 2014 16:25:27 +0800 Subject: [PATCH] tcp: Avoid unnecessary ACK E.g. Avoid Dup ACK in packet #981 979 4.115432000 192.168.66.123 -> 192.168.66.100 TCP 20406 [TCP Window Full] 10000 > 50112 [ACK] Seq=10675905 Ack=801512443 Win=3737600 Len=20352 980 4.119002000 192.168.66.100 -> 192.168.66.123 TCP 54 [TCP ZeroWindow] 50112 > 10000 [ACK] Seq=801512443 Ack=10696257 Win=0 Len=0 981 4.119063000 192.168.66.123 -> 192.168.66.100 TCP 54 [TCP Dup ACK 979#1] 10000 > 50112 [ACK] Seq=10696257 Ack=801512443 Win=3737600 Len=0 982 4.137244000 192.168.66.100 -> 192.168.66.123 TCP 54 [TCP Window Update] 50112 > 10000 [ACK] Seq=801512443 Ack=10696257 Win=40704 Len=0 --- net/tcp.hh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/tcp.hh b/net/tcp.hh index f01b812c89..7d9f9c7a4f 100644 --- a/net/tcp.hh +++ b/net/tcp.hh @@ -470,6 +470,7 @@ void tcp::tcb::input(tcp_hdr* th, packet p) { p.trim_front(th->data_offset * 4); bool do_output = false; + bool do_output_data = false; tcp_seq seg_seq = th->seq; auto seg_len = p.len(); @@ -554,6 +555,7 @@ void tcp::tcb::input(tcp_hdr* th, packet p) { // If this packet contains data as well, we can ACK both data // and in a single packet, so canncel the previous ACK. clear_delayed_ack(); + do_output = false; output(); // FIXME: Implement TIME-WAIT state @@ -602,9 +604,7 @@ void tcp::tcb::input(tcp_hdr* th, packet p) { } // some data is acked, try send more data - if (can_send() > 0) { - do_output = true; - } + do_output_data = true; if (_snd.data.empty()) { // All outstanding segments are acked, turn off the timer. @@ -632,14 +632,14 @@ void tcp::tcb::input(tcp_hdr* th, packet p) { if (th->seq >= _snd.wl1 && th->ack >= _snd.wl2) { if (!_snd.window && th->window && _snd.unsent_len) { - do_output = true; + do_output_data = true; } _snd.window = th->window << _snd.window_scale; _snd.wl1 = th->seq; _snd.wl2 = th->ack; } // send some stuff - if (do_output) { + if (do_output || (do_output_data && can_send())) { output(); } }