Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "SCTPAssociation.h"
00020
00021 #ifdef _MSC_VER
00022 inline double rint(double x) {return floor(x+.5);}
00023 #endif
00024
00025
00026
00027
00028
00029
00030 void SCTPAssociation::recordCwndUpdate(SCTPPathVariables* path)
00031 {
00032 path->statisticsPathSSthresh->record(path->ssthresh);
00033 path->statisticsPathCwnd->record(path->cwnd);
00034 }
00035
00036
00037
00038
00039 void SCTPAssociation::initCCParameters(SCTPPathVariables* path)
00040 {
00041 path->cwnd = (int32)min(4 * path->pmtu, max(2 * path->pmtu, 4380));
00042 path->ssthresh = state->peerRwnd;
00043 recordCwndUpdate(path);
00044
00045 sctpEV3 << simTime() << ":\tCC [initCCParameters]\t" << path->remoteAddress
00046 << "\tsst=" << path->ssthresh << " cwnd=" << path->cwnd << endl;
00047 }
00048
00049
00050 void SCTPAssociation::cwndUpdateAfterSack()
00051 {
00052 for (SCTPPathMap::iterator iter = sctpPathMap.begin(); iter != sctpPathMap.end(); iter++) {
00053 SCTPPathVariables* path = iter->second;
00054 if(path->fastRecoveryActive == false) {
00055
00056
00057 if(path->requiresRtx) {
00058 double decreaseFactor = 0.5;
00059
00060 sctpEV3 << simTime() << ":\tCC [cwndUpdateAfterSack]\t" << path->remoteAddress
00061 << "\tsst=" << path->ssthresh << " cwnd=" << path->cwnd;
00062
00063 path->ssthresh = max((int32)path->cwnd - (int32)rint(decreaseFactor * (double)path->cwnd),
00064 4 * (int32)path->pmtu);
00065 path->cwnd = path->ssthresh;
00066
00067 sctpEV3 << "\t=>\tsst=" << path->ssthresh << " cwnd=" << path->cwnd << endl;
00068 recordCwndUpdate(path);
00069 path->partialBytesAcked = 0;
00070
00071
00072
00073 if(state->fastRecoverySupported) {
00074 uint32 highestAckOnPath = state->lastTsnAck;
00075 for(SCTPQueue::PayloadQueue::iterator pq = retransmissionQ->payloadQueue.begin();
00076 pq != retransmissionQ->payloadQueue.end(); pq++) {
00077 if( (chunkHasBeenAcked(pq->second) == true) &&
00078 (tsnGt(pq->second->tsn, highestAckOnPath)) &&
00079 (pq->second->getLastDestinationPath() == path) ) {
00080
00081 highestAckOnPath = pq->second->tsn;
00082 }
00083 }
00084
00085 path->fastRecoveryActive = true;
00086 path->fastRecoveryExitPoint = highestAckOnPath;
00087 path->fastRecoveryEnteringTime = simTime();
00088
00089 sctpEV3 << simTime() << ":\tCC [cwndUpdateAfterSack] Entering Fast Recovery on path "
00090 << path->remoteAddress
00091 << ", exit point is " << path->fastRecoveryExitPoint << endl;
00092 }
00093 }
00094 }
00095 else {
00096 for (SCTPPathMap::iterator iter = sctpPathMap.begin(); iter != sctpPathMap.end(); iter++) {
00097 SCTPPathVariables* path = iter->second;
00098 if(path->fastRecoveryActive) {
00099 sctpEV3 << simTime() << ":\tCC [cwndUpdateAfterSack] Still in Fast Recovery on path "
00100 << path->remoteAddress
00101 << ", exit point is " << path->fastRecoveryExitPoint << endl;
00102 }
00103 }
00104 }
00105 }
00106 }
00107
00108
00109 void SCTPAssociation::updateFastRecoveryStatus(const uint32 lastTsnAck)
00110 {
00111 for (SCTPPathMap::iterator iter = sctpPathMap.begin(); iter != sctpPathMap.end(); iter++) {
00112 SCTPPathVariables* path = iter->second;
00113
00114 if (path->fastRecoveryActive) {
00115 if ( (tsnGt(lastTsnAck, path->fastRecoveryExitPoint)) ||
00116 (lastTsnAck == path->fastRecoveryExitPoint)
00117 ) {
00118 path->fastRecoveryActive = false;
00119 path->fastRecoveryExitPoint = 0;
00120
00121 sctpEV3 << simTime() << ":\tCC [cwndUpdateAfterSack] Leaving Fast Recovery on path "
00122 << path->remoteAddress
00123 << ", lastTsnAck=" << lastTsnAck << endl;
00124 }
00125 }
00126 }
00127 }
00128
00129
00130 void SCTPAssociation::cwndUpdateBytesAcked(SCTPPathVariables* path,
00131 const uint32 ackedBytes,
00132 const bool ctsnaAdvanced)
00133 {
00134 sctpEV3 << simulation.getSimTime() << "====> cwndUpdateBytesAcked:"
00135 << " path=" << path->remoteAddress
00136 << " ackedBytes=" << ackedBytes
00137 << " ctsnaAdvanced=" << ((ctsnaAdvanced == true) ? "yes" : "no")
00138 << " cwnd=" << path->cwnd
00139 << " ssthresh=" << path->ssthresh
00140 << " ackedBytes=" << ackedBytes
00141 << " pathOsbBeforeUpdate=" << path->outstandingBytesBeforeUpdate
00142 << " pathOsb=" << path->outstandingBytes
00143 << endl;
00144
00145 if (path->fastRecoveryActive == false) {
00146
00147
00148
00149
00150 if (path->cwnd <= path->ssthresh) {
00151
00152 path->partialBytesAcked = 0;
00153
00154
00155 if ((ctsnaAdvanced == true) &&
00156 (path->outstandingBytesBeforeUpdate >= path->cwnd)) {
00157 sctpEV3 << simTime() << ":\tCC [cwndUpdateBytesAcked-SlowStart]\t" << path->remoteAddress
00158 << "\tsst=" << path->ssthresh << " cwnd=" << path->cwnd << " acked=" << ackedBytes;
00159
00160 path->cwnd += (int32)min(path->pmtu, ackedBytes);
00161
00162 sctpEV3 << "\t=>\tsst=" << path->ssthresh << " cwnd=" << path->cwnd << endl;
00163 recordCwndUpdate(path);
00164 }
00165
00166
00167 else {
00168 sctpEV3 << simTime() << ":\tCC "
00169 << "Not increasing cwnd of path " << path->remoteAddress << " in slow start:\t"
00170 << "ctsnaAdvanced=" << ((ctsnaAdvanced == true) ? "yes" : "no") << "\t"
00171 << "cwnd=" << path->cwnd << "\t"
00172 << "ssthresh=" << path->ssthresh << "\t"
00173 << "ackedBytes=" << ackedBytes << "\t"
00174 << "pathOsbBeforeUpdate=" << path->outstandingBytesBeforeUpdate << "\t"
00175 << "pathOsb=" << path->outstandingBytes << "\t"
00176 << "(pathOsbBeforeUpdate >= path->cwnd)="
00177 << (path->outstandingBytesBeforeUpdate >= path->cwnd) << endl;
00178 }
00179 }
00180
00181
00182 else
00183 {
00184
00185 path->partialBytesAcked += ackedBytes;
00186
00187 double increaseFactor = 1.0;
00188
00189
00190 if ( (path->partialBytesAcked >= path->cwnd) &&
00191 (ctsnaAdvanced == true) &&
00192 (path->outstandingBytesBeforeUpdate >= path->cwnd) ) {
00193 sctpEV3 << simTime() << ":\tCC [cwndUpdateBytesAcked-CgAvoidance]\t" << path->remoteAddress
00194 << "\tsst=" << path->ssthresh << " cwnd=" << path->cwnd << " acked=" << ackedBytes;
00195
00196 path->cwnd += (int32)rint(increaseFactor * path->pmtu);
00197
00198 sctpEV3 << "\t=>\tsst=" << path->ssthresh << " cwnd=" << path->cwnd << endl;
00199 recordCwndUpdate(path);
00200 path->partialBytesAcked =
00201 ((path->cwnd < path->partialBytesAcked) ?
00202 (path->partialBytesAcked - path->cwnd) : 0);
00203 }
00204
00205
00206 else {
00207 sctpEV3 << simTime() << ":\tCC "
00208 << "Not increasing cwnd of path " << path->remoteAddress << " in congestion avoidance: "
00209 << "ctsnaAdvanced=" << ((ctsnaAdvanced == true) ? "yes" : "no") << "\t"
00210 << "cwnd=" << path->cwnd << "\t"
00211 << "ssthresh=" << path->ssthresh << "\t"
00212 << "ackedBytes=" << ackedBytes << "\t"
00213 << "pathOsbBeforeUpdate=" << path->outstandingBytesBeforeUpdate << "\t"
00214 << "pathOsb=" << path->outstandingBytes << "\t"
00215 << "(pathOsbBeforeUpdate >= path->cwnd)="
00216 << (path->outstandingBytesBeforeUpdate >= path->cwnd) << "\t"
00217 << "partialBytesAcked=" << path->partialBytesAcked << "\t"
00218 << "(path->partialBytesAcked >= path->cwnd)="
00219 << (path->partialBytesAcked >= path->cwnd) << endl;
00220 }
00221 }
00222
00223
00224 if(path->outstandingBytes == 0) {
00225 path->partialBytesAcked = 0;
00226 }
00227 }
00228 else {
00229 sctpEV3 << simTime() << ":\tCC "
00230 << "Not increasing cwnd of path " << path->remoteAddress
00231 << " during Fast Recovery" << endl;
00232 }
00233 }
00234
00235
00236 void SCTPAssociation::cwndUpdateAfterRtxTimeout(SCTPPathVariables* path)
00237 {
00238 sctpEV3 << simTime() << ":\tCC [cwndUpdateAfterRtxTimeout]\t" << path->remoteAddress
00239 << "\tsst=" << path->ssthresh << " cwnd=" << path->cwnd;
00240
00241 path->ssthresh = (int32)max(path->cwnd / 2, 4 * path->pmtu);
00242 path->cwnd = path->pmtu;
00243
00244 sctpEV3 << "\t=>\tsst=" << path->ssthresh << " cwnd=" << path->cwnd << endl;
00245 path->partialBytesAcked = 0;
00246 recordCwndUpdate(path);
00247
00248
00249 if (path->fastRecoveryActive == true) {
00250 path->fastRecoveryActive = false;
00251 path->fastRecoveryExitPoint = 0;
00252 }
00253 }
00254
00255
00256 void SCTPAssociation::cwndUpdateMaxBurst(SCTPPathVariables* path)
00257 {
00258 if(path->cwnd > ((path->outstandingBytes + state->maxBurst * path->pmtu))) {
00259 sctpEV3 << simTime() << ":\tCC [cwndUpdateMaxBurst]\t" << path->remoteAddress
00260 << "\tsst=" << path->ssthresh << " cwnd=" << path->cwnd
00261 << "\tosb=" << path->outstandingBytes
00262 << "\tmaxBurst=" << state->maxBurst * path->pmtu << endl;
00263
00264 path->cwnd = path->outstandingBytes + (state->maxBurst * path->pmtu);
00265 recordCwndUpdate(path);
00266
00267 sctpEV3 << "\t=>\tsst=" << path->ssthresh << " cwnd=" << path->cwnd << endl;
00268 }
00269 }
00270
00271
00272 void SCTPAssociation::cwndUpdateAfterCwndTimeout(SCTPPathVariables* path)
00273 {
00274
00275
00276
00277 sctpEV3 << simTime() << ":\tCC [cwndUpdateAfterCwndTimeout]\t" << path->remoteAddress
00278 << "\tsst=" << path->ssthresh << " cwnd=" << path->cwnd;
00279 path->cwnd = (int32)min(4 * path->pmtu, max(2 * path->pmtu, 4380));
00280 sctpEV3 << "\t=>\tsst=" << path->ssthresh << " cwnd=" << path->cwnd << endl;
00281 recordCwndUpdate(path);
00282 }