github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/transport/tcp/reno_recovery.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tcp 16 17 // renoRecovery stores the variables related to TCP Reno loss recovery 18 // algorithm. 19 // 20 // +stateify savable 21 type renoRecovery struct { 22 s *sender 23 } 24 25 func newRenoRecovery(s *sender) *renoRecovery { 26 return &renoRecovery{s: s} 27 } 28 29 func (rr *renoRecovery) DoRecovery(rcvdSeg *segment, fastRetransmit bool) { 30 ack := rcvdSeg.ackNumber 31 snd := rr.s 32 33 // We are in fast recovery mode. Ignore the ack if it's out of range. 34 if !ack.InRange(snd.SndUna, snd.SndNxt+1) { 35 return 36 } 37 38 // Don't count this as a duplicate if it is carrying data or 39 // updating the window. 40 if rcvdSeg.logicalLen() != 0 || snd.SndWnd != rcvdSeg.window { 41 return 42 } 43 44 // Inflate the congestion window if we're getting duplicate acks 45 // for the packet we retransmitted. 46 if !fastRetransmit && ack == snd.FastRecovery.First { 47 // We received a dup, inflate the congestion window by 1 packet 48 // if we're not at the max yet. Only inflate the window if 49 // regular FastRecovery is in use, RFC6675 does not require 50 // inflating cwnd on duplicate ACKs. 51 if snd.SndCwnd < snd.FastRecovery.MaxCwnd { 52 snd.SndCwnd++ 53 } 54 return 55 } 56 57 // A partial ack was received. Retransmit this packet and remember it 58 // so that we don't retransmit it again. 59 // 60 // We don't inflate the window because we're putting the same packet 61 // back onto the wire. 62 // 63 // N.B. The retransmit timer will be reset by the caller. 64 snd.FastRecovery.First = ack 65 snd.DupAckCount = 0 66 snd.resendSegment() 67 }