#include <TCPReno.h>
Inheritance diagram for TCPReno:
Public Member Functions | |
TCPReno () | |
virtual void | receivedDataAck (uint32 firstSeqAcked) |
virtual void | receivedDuplicateAck () |
Protected Member Functions | |
virtual TCPStateVariables * | createStateVariables () |
void | recalculateSlowStartThreshold () |
virtual void | processRexmitTimer (TCPEventCode &event) |
Protected Attributes | |
TCPRenoStateVariables *& | state |
|
Ctor 00026 : TCPTahoeRenoFamily(), 00027 state((TCPRenoStateVariables *&)TCPAlgorithm::state) 00028 { 00029 }
|
|
Create and return a TCPRenoStateVariables object. Implements TCPAlgorithm. 00041 { 00042 return new TCPRenoStateVariables(); 00043 }
|
|
Redefine what should happen on retransmission Reimplemented from TCPBaseAlg. 00041 { 00042 TCPTahoeRenoFamily::processRexmitTimer(event); 00043 if (event==TCP_E_ABORT) 00044 return; 00045 00046 // begin Slow Start (RFC2001) 00047 recalculateSlowStartThreshold(); 00048 state->snd_cwnd = state->snd_mss; 00049 if (cwndVector) cwndVector->record(state->snd_cwnd); 00050 tcpEV << "Begin Slow Start: resetting cwnd to " << state->snd_cwnd 00051 << ", ssthresh=" << state->ssthresh << "\n"; 00052 00053 // Reno retransmits all data (unlike Tahoe which transmits only the segment) 00054 conn->retransmitData(); 00055 }
|
|
Utility function to recalculate ssthresh 00032 { 00033 // set ssthresh to flight size/2, but at least 2 MSS 00034 // (the formula below practically amounts to ssthresh=cwnd/2 most of the time) 00035 uint flight_size = Min(state->snd_cwnd, state->snd_wnd); 00036 state->ssthresh = Max(flight_size/2, 2*state->snd_mss); 00037 if (ssthreshVector) ssthreshVector->record(state->ssthresh); 00038 }
|
|
Redefine what should happen when data got acked, to add congestion window management Reimplemented from TCPBaseAlg. 00058 { 00059 TCPTahoeRenoFamily::receivedDataAck(firstSeqAcked); 00060 00061 if (state->dupacks>=3) 00062 { 00063 // 00064 // Perform Fast Recovery: set cwnd to ssthresh (deflating the window). 00065 // 00066 tcpEV << "Fast Recovery: setting cwnd to ssthresh=" << state->ssthresh << "\n"; 00067 state->snd_cwnd = state->ssthresh; 00068 if (cwndVector) cwndVector->record(state->snd_cwnd); 00069 } 00070 else 00071 { 00072 // 00073 // Perform slow start and congestion avoidance. 00074 // 00075 if (state->snd_cwnd < state->ssthresh) 00076 { 00077 tcpEV << "cwnd<=ssthresh: Slow Start: increasing cwnd by one segment, to "; 00078 00079 // perform Slow Start. rfc 2581: "During slow start, a TCP increments cwnd 00080 // by at most SMSS bytes for each ACK received that acknowledges new data." 00081 state->snd_cwnd += state->snd_mss; 00082 00083 // NOTE: we could increase cwnd based on the number of bytes being 00084 // acknowledged by each arriving ACK, rather than by the number of ACKs 00085 // that arrive. This is called "Appropriate Byte Counting" (ABC) and is 00086 // described in rfc 3465. This rfc is experimental and probably not 00087 // implemented in real-life TCPs, hence it's commented out. Also, the ABC 00088 // rfc would require other modifications as well in addition to the 00089 // two lines below. 00090 // 00091 // int bytesAcked = state->snd_una - firstSeqAcked; 00092 // state->snd_cwnd += bytesAcked*state->snd_mss; 00093 00094 if (cwndVector) cwndVector->record(state->snd_cwnd); 00095 00096 tcpEV << "cwnd=" << state->snd_cwnd << "\n"; 00097 } 00098 else 00099 { 00100 // perform Congestion Avoidance (rfc 2581) 00101 int incr = state->snd_mss * state->snd_mss / state->snd_cwnd; 00102 if (incr==0) 00103 incr = 1; 00104 state->snd_cwnd += incr; 00105 if (cwndVector) cwndVector->record(state->snd_cwnd); 00106 00107 // 00108 // NOTE: some implementations use extra additive constant mss/8 here 00109 // which is known to be incorrect (rfc 2581 p5) 00110 // 00111 // NOTE 2: rfc 3465 (experimental) "Appropriate Byte Counting" (ABC) 00112 // would require maintaining a bytes_acked variable here which we don't do 00113 // 00114 00115 tcpEV << "cwnd>ssthresh: Congestion Avoidance: increasing cwnd linearly, to " << state->snd_cwnd << "\n"; 00116 } 00117 } 00118 00119 // ack and/or cwnd increase may have freed up some room in the window, try sending 00120 sendData(); 00121 }
|
|
Redefine what should happen when dupAck was received, to add congestion window management Reimplemented from TCPBaseAlg. 00124 { 00125 TCPTahoeRenoFamily::receivedDuplicateAck(); 00126 00127 if (state->dupacks==3) 00128 { 00129 tcpEV << "Reno on dupAck=3: perform Fast Retransmit, and enter Fast Recovery:"; 00130 00131 // Fast Retransmission: retransmit missing segment without waiting 00132 // for the REXMIT timer to expire 00133 conn->retransmitOneSegment(); 00134 00135 // enter slow start 00136 // "set cwnd to ssthresh plus 3 times the segment size." (rfc 2001) 00137 recalculateSlowStartThreshold(); 00138 state->snd_cwnd = state->ssthresh + 3*state->snd_mss; // 20051129 (1) 00139 if (cwndVector) cwndVector->record(state->snd_cwnd); 00140 00141 tcpEV << "set cwnd=" << state->snd_cwnd << ", ssthresh=" << state->ssthresh << "\n"; 00142 00143 // restart retransmission timer (with rexmit_count=0), and cancel round-trip time measurement 00144 // (see p972 "29.4 Fast Retransmit and Fast Recovery Algorithms" of 00145 // TCP/IP Illustrated, Vol2) -- but that's probably New Reno 00146 cancelEvent(rexmitTimer); 00147 startRexmitTimer(); 00148 state->rtseq_sendtime = 0; 00149 } 00150 else if (state->dupacks > 3) 00151 { 00152 // 00153 // Reno: For each additional duplicate ACK received, increment cwnd by MSS. 00154 // This artificially inflates the congestion window in order to reflect the 00155 // additional segment that has left the network 00156 // 00157 state->snd_cwnd += state->snd_mss; 00158 tcpEV << "Reno on dupAck>3: Fast Recovery: inflating cwnd by MSS, new cwnd=" << state->snd_cwnd << "\n"; 00159 if (cwndVector) cwndVector->record(state->snd_cwnd); 00160 00161 // cwnd increased, try sending 00162 sendData(); // 20051129 (2) 00163 } 00164 }
|
|
Reimplemented from TCPTahoeRenoFamily. |