#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. |
1.4.1