00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #ifndef lint
00051 static const char rcsid[] =
00052 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/sctp/sctp-mfrHbAfterRto.cc,v 1.1 2005/10/07 06:14:37 tomh Exp $ (UD/PEL)";
00053 #endif
00054
00055 #include "ip.h"
00056 #include "sctp-mfrHbAfterRto.h"
00057 #include "flags.h"
00058 #include "random.h"
00059 #include "template.h"
00060
00061 #include "sctpDebug.h"
00062
00063 #ifdef DMALLOC
00064 #include "dmalloc.h"
00065 #endif
00066
00067 #define MIN(x,y) (((x)<(y))?(x):(y))
00068 #define MAX(x,y) (((x)>(y))?(x):(y))
00069
00070 static class MfrHbAfterRtoSctpClass : public TclClass
00071 {
00072 public:
00073 MfrHbAfterRtoSctpClass() : TclClass("Agent/SCTP/MfrHbAfterRto") {}
00074 TclObject* create(int, const char*const*)
00075 {
00076 return (new MfrHbAfterRtoSctpAgent());
00077 }
00078 } classSctpMfrHbAfterRto;
00079
00080 MfrHbAfterRtoSctpAgent::MfrHbAfterRtoSctpAgent() : MultipleFastRtxSctpAgent()
00081 {
00082 }
00083
00084 void MfrHbAfterRtoSctpAgent::delay_bind_init_all()
00085 {
00086 MultipleFastRtxSctpAgent::delay_bind_init_all();
00087 }
00088
00089 int MfrHbAfterRtoSctpAgent::delay_bind_dispatch(const char *cpVarName,
00090 const char *cpLocalName,
00091 TclObject *opTracer)
00092 {
00093 return MultipleFastRtxSctpAgent::delay_bind_dispatch(cpVarName,
00094 cpLocalName, opTracer);
00095 }
00096
00097 void MfrHbAfterRtoSctpAgent::Timeout(SctpChunkType_E eChunkType,
00098 SctpDest_S *spDest)
00099 {
00100 DBG_I(Timeout);
00101 DBG_PL(Timeout, "eChunkType=%s spDest=%p"),
00102 (eChunkType == SCTP_CHUNK_DATA) ? "DATA" : "HEARTBEAT",
00103 spDest
00104 DBG_PR;
00105
00106 double dCurrTime = Scheduler::instance().clock();
00107
00108 DBG_PL(Timeout, "dCurrTime=%f"), dCurrTime DBG_PR;
00109
00110 if(eChunkType == SCTP_CHUNK_DATA)
00111 {
00112 spDest->eRtxTimerIsRunning = FALSE;
00113
00114
00115
00116 if(spDest->iCwnd > 1 * (int) uiMaxDataSize)
00117 {
00118 spDest->iSsthresh = MAX(spDest->iCwnd/2,
00119 iInitialCwnd * (int) uiMaxDataSize);
00120 spDest->iCwnd = 1*uiMaxDataSize;
00121 spDest->iPartialBytesAcked = 0;
00122 tiCwnd++;
00123 }
00124
00125 spDest->opCwndDegradeTimer->force_cancel();
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 spDest->eRtoPending = FALSE;
00152 }
00153
00154 DBG_PL(Timeout, "was spDest->dRto=%f"), spDest->dRto DBG_PR;
00155 spDest->dRto *= 2;
00156 if(spDest->dRto > dMaxRto)
00157 spDest->dRto = dMaxRto;
00158 tdRto++;
00159 DBG_PL(Timeout, "now spDest->dRto=%f"), spDest->dRto DBG_PR;
00160
00161 spDest->iTimeoutCount++;
00162 spDest->iErrorCount++;
00163 DBG_PL(Timeout, "now spDest->iErrorCount=%d"), spDest->iErrorCount DBG_PR;
00164
00165 if(spDest->eStatus == SCTP_DEST_STATUS_ACTIVE)
00166 {
00167 iAssocErrorCount++;
00168 DBG_PL(Timeout, "now iAssocErrorCount=%d"), iAssocErrorCount DBG_PR;
00169
00170
00171 if(spDest->iErrorCount > (int) uiPathMaxRetrans)
00172 {
00173 spDest->eStatus = SCTP_DEST_STATUS_INACTIVE;
00174 if(spDest == spNewTxDest)
00175 {
00176 spNewTxDest = GetNextDest(spDest);
00177 DBG_PL(Timeout, "failing over from %p to %p"),
00178 spDest, spNewTxDest DBG_PR;
00179 }
00180 }
00181 if(iAssocErrorCount > (int) uiAssociationMaxRetrans)
00182 {
00183
00184
00185 DBG_PL(Timeout, "abruptly closing the association!") DBG_PR;
00186 Close();
00187 DBG_X(Timeout);
00188 return;
00189 }
00190 }
00191
00192
00193 tiTimeoutCount++;
00194 tiErrorCount++;
00195
00196 if(spDest->iErrorCount > (int) uiChangePrimaryThresh &&
00197 spDest == spPrimaryDest)
00198 {
00199 spPrimaryDest = spNewTxDest;
00200 DBG_PL(Timeout, "changing primary from %p to %p"),
00201 spDest, spNewTxDest DBG_PR;
00202 }
00203
00204 if(eChunkType == SCTP_CHUNK_DATA)
00205 {
00206 TimeoutRtx(spDest);
00207
00208
00209
00210
00211
00212
00213 if(GetNextDest(spDest) != spDest)
00214 SendHeartbeat(spDest);
00215
00216
00217 }
00218 else if(eChunkType == SCTP_CHUNK_HB)
00219 {
00220 if(uiHeartbeatInterval != 0)
00221 SendHeartbeat(spDest);
00222 }
00223
00224 DBG_X(Timeout);
00225 }