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 #ifndef lint
00038 static const char rcsid[] =
00039 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/sctp/sctp.cc,v 1.8 2005/10/07 05:58:29 tomh Exp $ (UD/PEL)";
00040 #endif
00041
00042 #include "ip.h"
00043 #include "sctp.h"
00044 #include "flags.h"
00045 #include "random.h"
00046 #include "template.h"
00047
00048 #include "sctpDebug.h"
00049
00050 #ifdef DMALLOC
00051 #include "dmalloc.h"
00052 #endif
00053
00054 #define MIN(x,y) (((x)<(y))?(x):(y))
00055 #define MAX(x,y) (((x)>(y))?(x):(y))
00056
00057 int hdr_sctp::offset_;
00058
00059 static class SCTPHeaderClass : public PacketHeaderClass
00060 {
00061 public:
00062 SCTPHeaderClass() : PacketHeaderClass("PacketHeader/SCTP",
00063 sizeof(hdr_sctp))
00064 {
00065 bind_offset(&hdr_sctp::offset_);
00066 }
00067 } class_sctphdr;
00068
00069 static class SctpClass : public TclClass
00070 {
00071 public:
00072 SctpClass() : TclClass("Agent/SCTP") {}
00073 TclObject* create(int, const char*const*)
00074 {
00075 return (new SctpAgent());
00076 }
00077 } classSctp;
00078
00079 SctpAgent::SctpAgent() : Agent(PT_SCTP)
00080 {
00081 fhpDebugFile = NULL;
00082 opCoreTarget = NULL;
00083 memset(&sInterfaceList, 0, sizeof(List_S) );
00084 memset(&sDestList, 0, sizeof(List_S) );
00085 memset(&sAppLayerBuffer, 0, sizeof(List_S) );
00086 memset(&sSendBuffer, 0, sizeof(List_S) );
00087 memset(&sRecvTsnBlockList, 0, sizeof(List_S) );
00088 memset(&sDupTsnList, 0, sizeof(List_S) );
00089 spOutStreams = NULL;
00090 opSackGenTimer = new SackGenTimer(this);
00091 spSctpTrace = NULL;
00092 opHeartbeatGenTimer = new HeartbeatGenTimer(this, NULL);
00093 opHeartbeatTimeoutTimer = new HeartbeatTimeoutTimer(this, NULL);
00094 opT1InitTimer = new T1InitTimer(this);
00095 opT1CookieTimer = new T1CookieTimer(this);
00096 eState = SCTP_STATE_UNINITIALIZED;
00097 }
00098
00099 SctpAgent::~SctpAgent()
00100 {
00101 Node_S *spCurrNode = NULL;
00102 Node_S *spPrevNode = NULL;
00103 SctpDest_S *spDest = NULL;
00104
00105 delete opSackGenTimer;
00106 opSackGenTimer = NULL;
00107 delete opHeartbeatGenTimer;
00108 opHeartbeatGenTimer = NULL;
00109 delete opHeartbeatTimeoutTimer;
00110 opHeartbeatTimeoutTimer = NULL;
00111 delete opT1InitTimer;
00112 opT1InitTimer = NULL;
00113 delete opT1CookieTimer;
00114 opT1CookieTimer = NULL;
00115
00116 if(spOutStreams != NULL)
00117 delete spOutStreams;
00118
00119 for(spCurrNode = sInterfaceList.spHead;
00120 spCurrNode != NULL;
00121 spPrevNode = spCurrNode, spCurrNode=spCurrNode->spNext, delete spPrevNode)
00122 {
00123 delete (SctpInterface_S *) spCurrNode->vpData;
00124 spCurrNode->vpData = NULL;
00125 }
00126
00127 for(spCurrNode = sDestList.spHead;
00128 spCurrNode != NULL;
00129 spPrevNode = spCurrNode, spCurrNode=spCurrNode->spNext, delete spPrevNode)
00130 {
00131 spDest = (SctpDest_S *) spCurrNode->vpData;
00132 if(spDest->opT3RtxTimer != NULL)
00133 {
00134 delete spDest->opT3RtxTimer;
00135 spDest->opT3RtxTimer = NULL;
00136 }
00137 if(spDest->opCwndDegradeTimer != NULL)
00138 {
00139 delete spDest->opCwndDegradeTimer;
00140 spDest->opCwndDegradeTimer = NULL;
00141 }
00142 if(spDest->opHeartbeatGenTimer != NULL)
00143 {
00144 delete spDest->opHeartbeatGenTimer;
00145 spDest->opHeartbeatGenTimer = NULL;
00146 }
00147 if(spDest->opHeartbeatTimeoutTimer != NULL)
00148 {
00149 delete spDest->opHeartbeatTimeoutTimer;
00150 spDest->opHeartbeatTimeoutTimer = NULL;
00151 }
00152 if(spDest->opRouteCacheFlushTimer != NULL)
00153 {
00154 delete spDest->opRouteCacheFlushTimer;
00155 spDest->opRouteCacheFlushTimer = NULL;
00156 }
00157 if(spDest->opRouteCalcDelayTimer != NULL)
00158 {
00159 delete spDest->opRouteCalcDelayTimer;
00160 spDest->opRouteCalcDelayTimer = NULL;
00161 }
00162 Packet::free(spDest->opRoutingAssistPacket);
00163 spDest->opRoutingAssistPacket = NULL;
00164 delete (SctpDest_S *) spCurrNode->vpData;
00165 spCurrNode->vpData = NULL;
00166 }
00167
00168 if(spSctpTrace != NULL)
00169 {
00170 delete spSctpTrace;
00171 spSctpTrace = NULL;
00172 }
00173 }
00174
00175 void SctpAgent::delay_bind_init_all()
00176 {
00177 delay_bind_init_one("debugMask_");
00178 delay_bind_init_one("debugFileIndex_");
00179 delay_bind_init_one("associationMaxRetrans_");
00180 delay_bind_init_one("pathMaxRetrans_");
00181 delay_bind_init_one("changePrimaryThresh_");
00182 delay_bind_init_one("maxInitRetransmits_");
00183 delay_bind_init_one("oneHeartbeatTimer_");
00184 delay_bind_init_one("heartbeatInterval_");
00185 delay_bind_init_one("mtu_");
00186 delay_bind_init_one("initialRwnd_");
00187 delay_bind_init_one("initialSsthresh_");
00188 delay_bind_init_one("ipHeaderSize_");
00189 delay_bind_init_one("dataChunkSize_");
00190 delay_bind_init_one("numOutStreams_");
00191 delay_bind_init_one("useDelayedSacks_");
00192 delay_bind_init_one("sackDelay_");
00193 delay_bind_init_one("useMaxBurst_");
00194 delay_bind_init_one("initialCwnd_");
00195 delay_bind_init_one("initialRto_");
00196 delay_bind_init_one("minRto_");
00197 delay_bind_init_one("maxRto_");
00198 delay_bind_init_one("fastRtxTrigger_");
00199 delay_bind_init_one("numUnrelStreams_");
00200 delay_bind_init_one("reliability_");
00201 delay_bind_init_one("unordered_");
00202 delay_bind_init_one("rtxToAlt_");
00203 delay_bind_init_one("dormantAction_");
00204 delay_bind_init_one("routeCacheLifetime_");
00205 delay_bind_init_one("routeCalcDelay_");
00206
00207 delay_bind_init_one("trace_all_");
00208 delay_bind_init_one("cwnd_");
00209 delay_bind_init_one("rto_");
00210 delay_bind_init_one("errorCount_");
00211 delay_bind_init_one("frCount_");
00212 delay_bind_init_one("timeoutCount_");
00213 delay_bind_init_one("rcdCount_");
00214
00215 Agent::delay_bind_init_all();
00216 }
00217
00218 int SctpAgent::delay_bind_dispatch(const char *cpVarName,
00219 const char *cpLocalName,
00220 TclObject *opTracer)
00221 {
00222 if(delay_bind(cpVarName, cpLocalName, "debugMask_", &uiDebugMask, opTracer))
00223 return TCL_OK;
00224
00225 if(delay_bind(cpVarName, cpLocalName,
00226 "debugFileIndex_", &iDebugFileIndex, opTracer))
00227 return TCL_OK;
00228
00229 if(delay_bind(cpVarName, cpLocalName,
00230 "associationMaxRetrans_", &uiAssociationMaxRetrans, opTracer))
00231 return TCL_OK;
00232
00233 if(delay_bind(cpVarName, cpLocalName,
00234 "pathMaxRetrans_", &uiPathMaxRetrans, opTracer))
00235 return TCL_OK;
00236
00237 if(delay_bind(cpVarName, cpLocalName,
00238 "changePrimaryThresh_", &uiChangePrimaryThresh, opTracer))
00239 return TCL_OK;
00240
00241 if(delay_bind(cpVarName, cpLocalName,
00242 "maxInitRetransmits_", &uiMaxInitRetransmits, opTracer))
00243 return TCL_OK;
00244
00245 if(delay_bind(cpVarName, cpLocalName,
00246 "oneHeartbeatTimer_", (int *) &eOneHeartbeatTimer, opTracer))
00247 return TCL_OK;
00248
00249 if(delay_bind(cpVarName, cpLocalName,
00250 "heartbeatInterval_", &uiHeartbeatInterval, opTracer))
00251 return TCL_OK;
00252
00253 if(delay_bind(cpVarName, cpLocalName, "mtu_", &uiMtu, opTracer))
00254 return TCL_OK;
00255
00256 if(delay_bind(cpVarName, cpLocalName,
00257 "initialRwnd_", &uiInitialRwnd, opTracer))
00258 return TCL_OK;
00259
00260 if(delay_bind(cpVarName, cpLocalName,
00261 "initialSsthresh_", &iInitialSsthresh, opTracer))
00262 return TCL_OK;
00263
00264 if(delay_bind(cpVarName, cpLocalName,
00265 "ipHeaderSize_", &uiIpHeaderSize, opTracer))
00266 return TCL_OK;
00267
00268 if(delay_bind(cpVarName, cpLocalName,
00269 "dataChunkSize_", &uiDataChunkSize, opTracer))
00270 return TCL_OK;
00271
00272 if(delay_bind(cpVarName, cpLocalName,
00273 "numOutStreams_", &uiNumOutStreams, opTracer))
00274 return TCL_OK;
00275
00276 if(delay_bind(cpVarName, cpLocalName,
00277 "useDelayedSacks_", (int *) &eUseDelayedSacks, opTracer))
00278 return TCL_OK;
00279
00280 if(delay_bind(cpVarName, cpLocalName,
00281 "sackDelay_", &dSackDelay, opTracer))
00282 return TCL_OK;
00283
00284 if(delay_bind(cpVarName, cpLocalName,
00285 "useMaxBurst_", (int *) &eUseMaxBurst, opTracer))
00286 return TCL_OK;
00287
00288 if(delay_bind(cpVarName, cpLocalName,
00289 "initialCwnd_", &iInitialCwnd, opTracer))
00290 return TCL_OK;
00291
00292 if(delay_bind(cpVarName, cpLocalName,
00293 "initialRto_", &dInitialRto, opTracer))
00294 return TCL_OK;
00295
00296 if(delay_bind(cpVarName, cpLocalName,
00297 "minRto_", &dMinRto, opTracer))
00298 return TCL_OK;
00299
00300 if(delay_bind(cpVarName, cpLocalName,
00301 "maxRto_", &dMaxRto, opTracer))
00302 return TCL_OK;
00303
00304 if(delay_bind(cpVarName, cpLocalName,
00305 "fastRtxTrigger_", &iFastRtxTrigger, opTracer))
00306 return TCL_OK;
00307
00308 if(delay_bind(cpVarName, cpLocalName,
00309 "numUnrelStreams_", &uiNumUnrelStreams, opTracer))
00310 return TCL_OK;
00311
00312 if(delay_bind(cpVarName, cpLocalName,
00313 "reliability_", &uiReliability, opTracer))
00314 return TCL_OK;
00315
00316 if(delay_bind(cpVarName, cpLocalName,
00317 "unordered_", (int *) &eUnordered, opTracer))
00318 return TCL_OK;
00319
00320 if(delay_bind(cpVarName, cpLocalName,
00321 "rtxToAlt_", (int *) &eRtxToAlt, opTracer))
00322 return TCL_OK;
00323
00324 if(delay_bind(cpVarName, cpLocalName,
00325 "dormantAction_", (int *) &eDormantAction, opTracer))
00326 return TCL_OK;
00327
00328 if(delay_bind(cpVarName, cpLocalName,
00329 "routeCacheLifetime_", &dRouteCacheLifetime, opTracer))
00330 return TCL_OK;
00331
00332 if(delay_bind(cpVarName, cpLocalName,
00333 "routeCalcDelay_", &dRouteCalcDelay, opTracer))
00334 return TCL_OK;
00335
00336 if(delay_bind(cpVarName, cpLocalName, "cwnd_", &tiCwnd, opTracer))
00337 return TCL_OK;
00338
00339 if(delay_bind(cpVarName, cpLocalName, "rto_", &tdRto, opTracer))
00340 return TCL_OK;
00341
00342 if(delay_bind(cpVarName, cpLocalName, "errorCount_", &tiErrorCount, opTracer))
00343 return TCL_OK;
00344
00345 if(delay_bind(cpVarName, cpLocalName, "frCount_", &tiFrCount, opTracer))
00346 return TCL_OK;
00347
00348 if(delay_bind(cpVarName, cpLocalName,
00349 "timeoutCount_", &tiTimeoutCount, opTracer))
00350 return TCL_OK;
00351
00352 if(delay_bind(cpVarName, cpLocalName, "rcdCount_", &tiRcdCount, opTracer))
00353 return TCL_OK;
00354
00355 if(delay_bind(cpVarName, cpLocalName,
00356 "trace_all_", (int *) &eTraceAll, opTracer))
00357 return TCL_OK;
00358
00359 return Agent::delay_bind_dispatch(cpVarName, cpLocalName, opTracer);
00360 }
00361
00362 void SctpAgent::TraceAll()
00363 {
00364 char cpOutString[500];
00365 Node_S *spCurrNode = NULL;
00366 SctpDest_S *spCurrDest = NULL;
00367 double dCurrTime = Scheduler::instance().clock();
00368
00369 for(spCurrNode = sDestList.spHead;
00370 spCurrNode != NULL;
00371 spCurrNode = spCurrNode->spNext)
00372 {
00373 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
00374 SetSource(spCurrDest);
00375 sprintf(cpOutString,
00376 "time: %-8.5f "
00377 "saddr: %-2d sport: %-2d daddr: %-2d dport: %-2d "
00378 "cwnd: %d pba: %d out: %d ssthresh: %d peerRwnd: %d "
00379 "rto: %-6.3f srtt: %-6.3f rttvar: %-6.3f "
00380 "assocErrors: %d pathErrors: %d dstatus: %s isPrimary: %s "
00381 "frCount: %d timeoutCount: %d rcdCount: %d\n",
00382 dCurrTime,
00383 addr(), port(), spCurrDest->iNsAddr, spCurrDest->iNsPort,
00384 spCurrDest->iCwnd, spCurrDest->iPartialBytesAcked,
00385 spCurrDest->iOutstandingBytes, spCurrDest->iSsthresh,
00386 uiPeerRwnd,
00387 spCurrDest->dRto, spCurrDest->dSrtt,
00388 spCurrDest->dRttVar,
00389 iAssocErrorCount,
00390 spCurrDest->iErrorCount,
00391 spCurrDest->eStatus ? "ACTIVE" : "INACTIVE",
00392 (spCurrDest == spPrimaryDest) ? "TRUE" : "FALSE",
00393 int(tiFrCount),
00394 spCurrDest->iTimeoutCount,
00395 spCurrDest->iRcdCount);
00396 if(channel_)
00397 (void)Tcl_Write(channel_, cpOutString, strlen(cpOutString));
00398 }
00399
00400 sprintf(cpOutString, "\n");
00401 if(channel_)
00402 (void)Tcl_Write(channel_, cpOutString, strlen(cpOutString));
00403 }
00404
00405 void SctpAgent::TraceVar(const char* cpVar)
00406 {
00407 char cpOutString[500];
00408 Node_S *spCurrNode = NULL;
00409 SctpDest_S *spCurrDest = NULL;
00410 double dCurrTime = Scheduler::instance().clock();
00411
00412 if(!strcmp(cpVar, "cwnd_"))
00413 for(spCurrNode = sDestList.spHead;
00414 spCurrNode != NULL;
00415 spCurrNode = spCurrNode->spNext)
00416 {
00417 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
00418 SetSource(spCurrDest);
00419 sprintf(cpOutString,
00420 "time: %-8.5f "
00421 "saddr: %-2d sport: %-2d daddr: %-2d dport: %-2d "
00422 "cwnd: %d pba: %d out: %d ssthresh: %d peerRwnd: %d\n",
00423 dCurrTime,
00424 addr(), port(),
00425 spCurrDest->iNsAddr, spCurrDest->iNsPort,
00426 spCurrDest->iCwnd, spCurrDest->iPartialBytesAcked,
00427 spCurrDest->iOutstandingBytes, spCurrDest->iSsthresh,
00428 uiPeerRwnd);
00429 if(channel_)
00430 (void)Tcl_Write(channel_, cpOutString, strlen(cpOutString));
00431 }
00432
00433 else if(!strcmp(cpVar, "rto_"))
00434 for(spCurrNode = sDestList.spHead;
00435 spCurrNode != NULL;
00436 spCurrNode = spCurrNode->spNext)
00437 {
00438 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
00439 SetSource(spCurrDest);
00440 sprintf(cpOutString,
00441 "time: %-8.5f "
00442 "saddr: %-2d sport: %-2d daddr: %-2d dport: %-2d "
00443 "rto: %-6.3f srtt: %-6.3f rttvar: %-6.3f\n",
00444 dCurrTime,
00445 addr(), port(),
00446 spCurrDest->iNsAddr, spCurrDest->iNsPort,
00447 spCurrDest->dRto, spCurrDest->dSrtt,
00448 spCurrDest->dRttVar);
00449 if(channel_)
00450 (void)Tcl_Write(channel_, cpOutString, strlen(cpOutString));
00451 }
00452
00453 else if(!strcmp(cpVar, "errorCount_"))
00454 for(spCurrNode = sDestList.spHead;
00455 spCurrNode != NULL;
00456 spCurrNode = spCurrNode->spNext)
00457 {
00458 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
00459 SetSource(spCurrDest);
00460 sprintf(cpOutString,
00461 "time: %-8.5f "
00462 "saddr: %-2d sport: %-2d daddr: %-2d dport: %-2d "
00463 "assocErrors: %d pathErrors: %d dstatus: %s isPrimary: %s\n",
00464 dCurrTime,
00465 addr(), port(),
00466 spCurrDest->iNsAddr, spCurrDest->iNsPort,
00467 iAssocErrorCount,
00468 spCurrDest->iErrorCount,
00469 spCurrDest->eStatus ? "ACTIVE" : "INACTIVE",
00470 (spCurrDest == spPrimaryDest) ? "TRUE" : "FALSE");
00471 if(channel_)
00472 (void)Tcl_Write(channel_, cpOutString, strlen(cpOutString));
00473 }
00474
00475 else if(!strcmp(cpVar, "frCount_"))
00476 {
00477 sprintf(cpOutString,
00478 "time: %-8.5f "
00479 "frCount: %d\n",
00480 dCurrTime,
00481 int(*((TracedInt*) cpVar)) );
00482 if(channel_)
00483 (void)Tcl_Write(channel_, cpOutString, strlen(cpOutString));
00484 }
00485
00486 else if(!strcmp(cpVar, "timeoutCount_"))
00487 {
00488 for(spCurrNode = sDestList.spHead;
00489 spCurrNode != NULL;
00490 spCurrNode = spCurrNode->spNext)
00491 {
00492 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
00493 SetSource(spCurrDest);
00494 sprintf(cpOutString,
00495 "time: %-8.5f "
00496 "saddr: %-2d sport: %-2d daddr: %-2d dport: %-2d "
00497 "timeoutCount: %d\n",
00498 dCurrTime,
00499 addr(), port(),
00500 spCurrDest->iNsAddr, spCurrDest->iNsPort,
00501 spCurrDest->iTimeoutCount);
00502 if(channel_)
00503 (void)Tcl_Write(channel_, cpOutString, strlen(cpOutString));
00504 }
00505 }
00506
00507 else if(!strcmp(cpVar, "rcdCount_"))
00508 {
00509 for(spCurrNode = sDestList.spHead;
00510 spCurrNode != NULL;
00511 spCurrNode = spCurrNode->spNext)
00512 {
00513 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
00514 SetSource(spCurrDest);
00515 sprintf(cpOutString,
00516 "time: %-8.5f "
00517 "saddr: %-2d sport: %-2d daddr: %-2d dport: %-2d "
00518 "rcdCount: %d\n",
00519 dCurrTime,
00520 addr(), port(),
00521 spCurrDest->iNsAddr, spCurrDest->iNsPort,
00522 spCurrDest->iRcdCount);
00523 if(channel_)
00524 (void)Tcl_Write(channel_, cpOutString, strlen(cpOutString));
00525 }
00526 }
00527
00528 else
00529 {
00530 sprintf(cpOutString,
00531 "time: %-8.5f "
00532 "saddr: %-2d sport: %-2d daddr: %-2d dport: %-2d %s: %s\n",
00533 dCurrTime, addr(), port(), daddr(), dport(),
00534 cpVar, "ERROR (unepected trace variable)");
00535 if(channel_)
00536 (void)Tcl_Write(channel_, cpOutString, strlen(cpOutString));
00537 }
00538
00539 sprintf(cpOutString, "\n");
00540 if(channel_)
00541 (void)Tcl_Write(channel_, cpOutString, strlen(cpOutString));
00542 }
00543
00544
00545 void SctpAgent::trace(TracedVar* v)
00546 {
00547 if(eTraceAll == TRUE)
00548 TraceAll();
00549 else
00550 TraceVar(v->name());
00551 }
00552
00553
00554
00555
00556
00557
00558 void SctpAgent::Reset()
00559 {
00560
00561
00562
00563
00564
00565 if(debug_ == TRUE && uiDebugMask == 0)
00566 uiDebugMask = 0xffffffff;
00567
00568
00569
00570
00571
00572 DBG_FOPEN();
00573 DBG_I(Reset);
00574
00575 if(eState != SCTP_STATE_UNINITIALIZED && eState != SCTP_STATE_CLOSED)
00576 Close();
00577
00578 DBG_PL(Reset, "uiDebugMask=%u"), uiDebugMask DBG_PR;
00579 DBG_PL(Reset, "iDebugFileIndex=%d"), iDebugFileIndex DBG_PR;
00580 DBG_PL(Reset, "uiAssociationMaxRetrans=%ld"), uiAssociationMaxRetrans DBG_PR;
00581 DBG_PL(Reset, "uiPathMaxRetrans=%ld"), uiPathMaxRetrans DBG_PR;
00582 DBG_PL(Reset, "uiChangePrimaryThresh=%d"), uiChangePrimaryThresh DBG_PR;
00583 DBG_PL(Reset, "eOneHeartbeatTimer=%s"),
00584 eOneHeartbeatTimer ? "TRUE" : "FALSE" DBG_PR;
00585 DBG_PL(Reset, "uiHeartbeatInterval=%ld"), uiHeartbeatInterval DBG_PR;
00586 DBG_PL(Reset, "uiMtu=%ld"), uiMtu DBG_PR;
00587 DBG_PL(Reset, "uiInitialRwnd=%ld"), uiInitialRwnd DBG_PR;
00588 DBG_PL(Reset, "iInitialSsthresh=%ld"), iInitialSsthresh DBG_PR;
00589 DBG_PL(Reset, "uiIpHeaderSize=%ld"), uiIpHeaderSize DBG_PR;
00590 DBG_PL(Reset, "uiDataChunkSize=%ld"), uiDataChunkSize DBG_PR;
00591 DBG_PL(Reset, "uiNumOutStreams=%ld"), uiNumOutStreams DBG_PR;
00592 DBG_PL(Reset, "eUseDelayedSacks=%s"),
00593 eUseDelayedSacks ? "TRUE" : "FALSE" DBG_PR;
00594 DBG_PL(Reset, "dSackDelay=%f"), dSackDelay DBG_PR;
00595 DBG_PL(Reset, "eUseMaxBurst=%s"), eUseMaxBurst ? "TRUE" : "FALSE" DBG_PR;
00596 DBG_PL(Reset, "iInitialCwnd=%ld"), iInitialCwnd DBG_PR;
00597 DBG_PL(Reset, "dInitialRto=%f"), dInitialRto DBG_PR;
00598 DBG_PL(Reset, "dMinRto=%f"), dMinRto DBG_PR;
00599 DBG_PL(Reset, "dMaxRto=%f"), dMaxRto DBG_PR;
00600 DBG_PL(Reset, "iFastRtxTrigger=%ld"), iFastRtxTrigger DBG_PR;
00601 DBG_PL(Reset, "uiNumUnrelStreams=%ld"), uiNumUnrelStreams DBG_PR;
00602 DBG_PL(Reset, "uiReliability=%ld"), uiReliability DBG_PR;
00603 DBG_PL(Reset, "eUnordered=%s"), eUnordered ? "TRUE" : "FALSE" DBG_PR;
00604
00605 switch(eRtxToAlt)
00606 {
00607 case RTX_TO_ALT_OFF:
00608 DBG_PL(Reset, "eRtxToAlt=RTX_TO_ALT_OFF") DBG_PR;
00609 break;
00610
00611 case RTX_TO_ALT_ON:
00612 DBG_PL(Reset, "eRtxToAlt=RTX_TO_ALT_ON") DBG_PR;
00613 break;
00614
00615 case RTX_TO_ALT_TIMEOUTS_ONLY:
00616 DBG_PL(Reset, "eRtxToAlt=RTX_TO_ALT_TIMEOUTS_ONLY") DBG_PR;
00617 break;
00618 }
00619
00620 switch(eDormantAction)
00621 {
00622 case DORMANT_HOP:
00623 DBG_PL(Reset, "eDormantAction=DORMANT_HOP") DBG_PR;
00624 break;
00625
00626 case DORMANT_PRIMARY:
00627 DBG_PL(Reset, "eDormantAction=DORMANT_PRIMARY") DBG_PR;
00628 break;
00629
00630 case DORMANT_LASTDEST:
00631 DBG_PL(Reset, "eDormantAction=DORMANT_LASTDEST") DBG_PR;
00632 break;
00633 }
00634
00635 DBG_PL(Reset, "eTraceAll=%s"), eTraceAll ? "TRUE" : "FALSE" DBG_PR;
00636
00637 Node_S *spCurrNode = NULL;
00638 SctpDest_S *spCurrDest = NULL;
00639 int i;
00640
00641 if(uiInitialRwnd > MAX_RWND_SIZE)
00642 {
00643 fprintf(stderr, "SCTP ERROR: initial rwnd (%d) > max (%d)\n",
00644 uiInitialRwnd, MAX_RWND_SIZE);
00645 DBG_PL(Reset, "ERROR: initial rwnd (%d) > max (%d)"),
00646 uiInitialRwnd, MAX_RWND_SIZE DBG_PR;
00647 DBG_PL(Reset, "exiting...") DBG_PR;
00648 exit(-1);
00649 }
00650
00651 if(uiNumOutStreams > MAX_NUM_STREAMS)
00652 {
00653 fprintf(stderr, "%s number of streams (%d) > max (%d)\n",
00654 "SCTP ERROR:",
00655 uiNumOutStreams, MAX_NUM_STREAMS);
00656 DBG_PL(Reset, "ERROR: number of streams (%d) > max (%d)"),
00657 uiNumOutStreams, MAX_NUM_STREAMS DBG_PR;
00658 DBG_PL(Reset, "exiting...") DBG_PR;
00659 exit(-1);
00660 }
00661 else if(uiNumUnrelStreams > uiNumOutStreams)
00662 {
00663 fprintf(stderr, "%s number of unreliable streams (%d) > total (%d)\n",
00664 "SCTP ERROR:",
00665 uiNumUnrelStreams, uiNumOutStreams);
00666 DBG_PL(Reset, "ERROR: number of unreliable streams (%d) > total (%d)"),
00667 uiNumUnrelStreams, uiNumOutStreams DBG_PR;
00668 DBG_PL(Reset, "exiting...") DBG_PR;
00669 exit(-1);
00670 }
00671
00672 uiMaxPayloadSize = uiMtu - SCTP_HDR_SIZE - uiIpHeaderSize;
00673 uiMaxDataSize = uiMaxPayloadSize - ControlChunkReservation();
00674
00675 if(uiDataChunkSize > MAX_DATA_CHUNK_SIZE)
00676 {
00677 fprintf(stderr, "%s data chunk size (%d) > max (%d)\n",
00678 "SCTP ERROR:",
00679 uiDataChunkSize, MAX_DATA_CHUNK_SIZE);
00680 DBG_PL(Reset, "ERROR: data chunk size (%d) > max (%d)"),
00681 uiDataChunkSize, MAX_DATA_CHUNK_SIZE DBG_PR;
00682 DBG_PL(Reset, "exiting...") DBG_PR;
00683 exit(-1);
00684 }
00685 else if(uiDataChunkSize > uiMaxDataSize)
00686 {
00687 fprintf(stderr, "SCTP ERROR: DATA chunk size (%d) too big!\n",
00688 uiDataChunkSize);
00689 fprintf(stderr, " SCTP/IP header = %d\n",
00690 SCTP_HDR_SIZE + uiIpHeaderSize);
00691 fprintf(stderr, " Control chunk reservation = %d\n",
00692 ControlChunkReservation());
00693 fprintf(stderr, " MTU = %d\n", uiMtu);
00694 fprintf(stderr, "\n");
00695
00696 DBG_PL(Reset,
00697 "ERROR: data chunk size (%d) + SCTP/IP header(%d) + Reserved (%d) > MTU (%d)"),
00698 uiDataChunkSize, SCTP_HDR_SIZE + uiIpHeaderSize,
00699 ControlChunkReservation(), uiMtu DBG_PR;
00700 DBG_PL(Reset, "exiting...") DBG_PR;
00701 exit(-1);
00702 }
00703 else if(uiDataChunkSize < MIN_DATA_CHUNK_SIZE)
00704 {
00705 fprintf(stderr, "%s data chunk size (%d) < min (%d)\n",
00706 "SCTP ERROR:",
00707 uiDataChunkSize, MIN_DATA_CHUNK_SIZE);
00708 DBG_PL(Reset, "ERROR: data chunk size (%d) < min (%d)"),
00709 uiDataChunkSize, MIN_DATA_CHUNK_SIZE DBG_PR;
00710 DBG_PL(Reset, "exiting...") DBG_PR;
00711 exit(-1);
00712 }
00713
00714
00715
00716
00717
00718
00719
00720 size_ = uiMtu - SCTP_HDR_SIZE - uiIpHeaderSize - sizeof(SctpDataChunkHdr_S);
00721
00722 eState = SCTP_STATE_CLOSED;
00723 eForceSource = FALSE;
00724 iAssocErrorCount = 0;
00725
00726 if(eOneHeartbeatTimer == TRUE && uiHeartbeatInterval != 0)
00727 {
00728 opHeartbeatGenTimer->force_cancel();
00729 opHeartbeatTimeoutTimer->force_cancel();
00730 }
00731
00732 opT1InitTimer->force_cancel();
00733 opT1CookieTimer->force_cancel();
00734 iInitTryCount = 0;
00735 uiNextTsn = 0;
00736 usNextStreamId = 0;
00737
00738
00739
00740
00741 if(spOutStreams != NULL)
00742 delete spOutStreams;
00743 spOutStreams = new SctpOutStream_S [uiNumOutStreams];
00744 memset(spOutStreams, 0, (uiNumOutStreams * sizeof(SctpOutStream_S)) );
00745
00746 for(i = 0; i < (int) uiNumUnrelStreams; i++)
00747 {
00748 DBG_PL(Reset, "setting outStream %d to UNRELIABLE"), i DBG_PR;
00749 spOutStreams[i].eMode = SCTP_STREAM_UNRELIABLE;
00750 }
00751 for(; i < (int) uiNumOutStreams; i++)
00752 {
00753 DBG_PL(Reset, "setting outStream %d to RELIABLE"), i DBG_PR;
00754 spOutStreams[i].eMode = SCTP_STREAM_RELIABLE;
00755 }
00756
00757 uiPeerRwnd = 0;
00758 uiCumAckPoint = 0;
00759 uiAdvancedPeerAckPoint = 0;
00760 uiHighestTsnNewlyAcked = 0;
00761 uiRecover = 0;
00762 memset(&sAppLayerBuffer, 0, sizeof(List_S) );
00763 memset(&sSendBuffer, 0, sizeof(List_S) );
00764
00765 if(uiAssociationMaxRetrans > (sDestList.uiLength * uiPathMaxRetrans))
00766 {
00767 DBG_PL(Reset,
00768 "WARNING: Association.Max.Retrans > "
00769 "summation of all destinations' Path.Max.Retrans "
00770 "(rfc2960 section 8.1)") DBG_PR;
00771 }
00772
00773 for(spCurrNode = sDestList.spHead;
00774 spCurrNode != NULL;
00775 spCurrNode = spCurrNode->spNext)
00776 {
00777 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
00778
00779 spCurrDest->iCwnd = iInitialCwnd * uiMaxDataSize;
00780 spCurrDest->iSsthresh = iInitialSsthresh;
00781 spCurrDest->eFirstRttMeasurement = TRUE;
00782 spCurrDest->dRto = dInitialRto;
00783
00784 if(spCurrDest->opT3RtxTimer == NULL)
00785 spCurrDest->opT3RtxTimer = new T3RtxTimer(this, spCurrDest);
00786 else
00787 spCurrDest->opT3RtxTimer->force_cancel();
00788
00789 spCurrDest->iOutstandingBytes = 0;
00790 spCurrDest->iPartialBytesAcked = 0;
00791
00792 spCurrDest->iErrorCount = 0;
00793 spCurrDest->iTimeoutCount = 0;
00794 spCurrDest->eStatus = SCTP_DEST_STATUS_ACTIVE;
00795
00796 if(spCurrDest->opCwndDegradeTimer == NULL)
00797 {
00798 spCurrDest->opCwndDegradeTimer =
00799 new CwndDegradeTimer(this, spCurrDest);
00800 }
00801 else
00802 {
00803 spCurrDest->opCwndDegradeTimer->force_cancel();
00804 }
00805
00806 if(eOneHeartbeatTimer == TRUE && uiHeartbeatInterval != 0)
00807 {
00808 spCurrDest->dIdleSince = 0;
00809 }
00810 else if(uiHeartbeatInterval != 0)
00811 {
00812 if(spCurrDest->opHeartbeatGenTimer == NULL)
00813 {
00814 spCurrDest->opHeartbeatGenTimer =
00815 new HeartbeatGenTimer(this, spCurrDest);
00816 }
00817 else
00818 {
00819 spCurrDest->opHeartbeatGenTimer->force_cancel();
00820 }
00821
00822 if(spCurrDest->opHeartbeatTimeoutTimer == NULL)
00823 {
00824 spCurrDest->opHeartbeatTimeoutTimer =
00825 new HeartbeatTimeoutTimer(this, spCurrDest);
00826 }
00827 else
00828 {
00829 spCurrDest->opHeartbeatTimeoutTimer->force_cancel();
00830 }
00831 }
00832
00833 spCurrDest->eCcApplied = FALSE;
00834 spCurrDest->spFirstOutstanding = NULL;
00835
00836 spCurrDest->iRcdCount = 0;
00837 spCurrDest->eRouteCached = FALSE;
00838
00839 if(spCurrDest->opRouteCacheFlushTimer == NULL)
00840 {
00841 spCurrDest->opRouteCacheFlushTimer =
00842 new RouteCacheFlushTimer(this, spCurrDest);
00843 }
00844 else
00845 {
00846 spCurrDest->opRouteCacheFlushTimer->force_cancel();
00847 }
00848
00849 if(spCurrDest->opRouteCalcDelayTimer == NULL)
00850 {
00851 spCurrDest->opRouteCalcDelayTimer =
00852 new RouteCalcDelayTimer(this, spCurrDest);
00853 }
00854 else
00855 {
00856 spCurrDest->opRouteCalcDelayTimer->force_cancel();
00857 }
00858
00859 memset(&spCurrDest->sBufferedPackets, 0, sizeof(List_S) );
00860 }
00861
00862 eForwardTsnNeeded = FALSE;
00863 eSendNewDataChunks = FALSE;
00864 eMarkedChunksPending = FALSE;
00865 eApplyMaxBurst = FALSE;
00866 eDataSource = DATA_SOURCE_APPLICATION;
00867 uiBurstLength = 0;
00868
00869 uiMyRwnd = uiInitialRwnd;
00870 uiCumAck = 0;
00871 uiHighestRecvTsn = 0;
00872 memset(&sRecvTsnBlockList, 0, sizeof(List_S) );
00873 memset(&sDupTsnList, 0, sizeof(List_S) );
00874 eStartOfPacket = FALSE;
00875 iDataPktCountSinceLastSack = 0;
00876 eSackChunkNeeded = FALSE;
00877
00878 opSackGenTimer->force_cancel();
00879
00880
00881
00882
00883 if(spSctpTrace != NULL)
00884 delete spSctpTrace;
00885
00886
00887
00888
00889 spSctpTrace = new SctpTrace_S[uiMaxPayloadSize / sizeof(SctpChunkHdr_S)];
00890
00891 uiNumChunks = 0;
00892
00893
00894
00895 tiCwnd++;
00896 tdRto++;
00897 tiErrorCount++;
00898 tiFrCount = 0;
00899 tiTimeoutCount++;
00900 tiRcdCount++;
00901
00902 OptionReset();
00903
00904 DBG_PL(Reset, "spSctpTrace=%p"), spSctpTrace DBG_PR;
00905 DBG_X(Reset);
00906 }
00907
00908
00909
00910
00911 void SctpAgent::OptionReset()
00912 {
00913 return;
00914 }
00915
00916
00917
00918
00919
00920
00921
00922
00923 u_int SctpAgent::ControlChunkReservation()
00924 {
00925 DBG_I(ControlChunkReservation);
00926 DBG_PL(ControlChunkReservation, "returning 0") DBG_PR;
00927 DBG_X(ControlChunkReservation);
00928 return 0;
00929 }
00930
00931 int SctpAgent::command(int argc, const char*const* argv)
00932 {
00933 DBG_I(command);
00934
00935 double dCurrTime = Scheduler::instance().clock();
00936 DBG_PL(command, "<time:%f> argc=%d argv[1]=%s"),
00937 dCurrTime, argc, argv[1] DBG_PR;
00938
00939 Tcl& oTcl = Tcl::instance();
00940 Node *opNode = NULL;
00941 int iNsAddr;
00942 int iNsPort;
00943 NsObject *opTarget = NULL;
00944 NsObject *opLink = NULL;
00945 int iRetVal;
00946
00947 if(argc == 2)
00948 {
00949 if (strcmp(argv[1], "reset") == 0)
00950 {
00951 Reset();
00952 DBG_X(command);
00953 return (TCL_OK);
00954 }
00955 else if (strcmp(argv[1], "close") == 0)
00956 {
00957 Close();
00958 DBG_X(command);
00959 return (TCL_OK);
00960 }
00961 }
00962 else if(argc == 3)
00963 {
00964 if (strcmp(argv[1], "advance") == 0)
00965 {
00966 DBG_X(command);
00967 return (TCL_OK);
00968 }
00969 else if (strcmp(argv[1], "set-multihome-core") == 0)
00970 {
00971 opCoreTarget = (Classifier *) TclObject::lookup(argv[2]);
00972 if(opCoreTarget == NULL)
00973 {
00974 oTcl.resultf("no such object %s", argv[4]);
00975 return (TCL_ERROR);
00976 }
00977 DBG_X(command);
00978 return (TCL_OK);
00979 }
00980 else if (strcmp(argv[1], "set-primary-destination") == 0)
00981 {
00982 opNode = (Node *) TclObject::lookup(argv[2]);
00983 if(opNode == NULL)
00984 {
00985 oTcl.resultf("no such object %s", argv[2]);
00986 return (TCL_ERROR);
00987 }
00988 iRetVal = SetPrimary( opNode->address() );
00989
00990 if(iRetVal == TCL_ERROR)
00991 {
00992 fprintf(stderr, "[SctpAgent::command] ERROR:"
00993 "%s is not a valid destination\n", argv[2]);
00994 DBG_X(command);
00995 return (TCL_ERROR);
00996 }
00997 DBG_X(command);
00998 return (TCL_OK);
00999 }
01000 else if (strcmp(argv[1], "force-source") == 0)
01001 {
01002 opNode = (Node *) TclObject::lookup(argv[2]);
01003 if(opNode == NULL)
01004 {
01005 oTcl.resultf("no such object %s", argv[2]);
01006 return (TCL_ERROR);
01007 }
01008 iRetVal = ForceSource( opNode->address() );
01009
01010 if(iRetVal == TCL_ERROR)
01011 {
01012 fprintf(stderr, "[SctpAgent::command] ERROR:"
01013 "%s is not a valid source\n", argv[2]);
01014 DBG_X(command);
01015 return (TCL_ERROR);
01016 }
01017 DBG_X(command);
01018 return (TCL_OK);
01019 }
01020 else if (strcmp(argv[1], "print") == 0)
01021 {
01022 if(eTraceAll == TRUE)
01023 TraceAll();
01024 else
01025 TraceVar(argv[2]);
01026 DBG_X(command);
01027 return (TCL_OK);
01028 }
01029 }
01030 else if(argc == 4)
01031 {
01032 if (strcmp(argv[1], "add-multihome-destination") == 0)
01033 {
01034 iNsAddr = atoi(argv[2]);
01035 iNsPort = atoi(argv[3]);
01036 AddDestination(iNsAddr, iNsPort);
01037 DBG_X(command);
01038 return (TCL_OK);
01039 }
01040 }
01041 else if(argc == 6)
01042 {
01043 if (strcmp(argv[1], "add-multihome-interface") == 0)
01044 {
01045 iNsAddr = atoi(argv[2]);
01046 iNsPort = atoi(argv[3]);
01047 opTarget = (NsObject *) TclObject::lookup(argv[4]);
01048 if(opTarget == NULL)
01049 {
01050 oTcl.resultf("no such object %s", argv[4]);
01051 return (TCL_ERROR);
01052 }
01053 opLink = (NsObject *) TclObject::lookup(argv[5]);
01054 if(opLink == NULL)
01055 {
01056 oTcl.resultf("no such object %s", argv[5]);
01057 return (TCL_ERROR);
01058 }
01059 AddInterface(iNsAddr, iNsPort, opTarget, opLink);
01060 DBG_X(command);
01061 return (TCL_OK);
01062 }
01063 }
01064
01065 DBG_X(command);
01066 return (Agent::command(argc, argv));
01067 }
01068
01069
01070
01071
01072 void SctpAgent::InsertNode(List_S *spList, Node_S *spPrevNode,
01073 Node_S *spNewNode, Node_S *spNextNode)
01074 {
01075 if(spPrevNode == NULL)
01076 spList->spHead = spNewNode;
01077 else
01078 spPrevNode->spNext = spNewNode;
01079
01080 spNewNode->spPrev = spPrevNode;
01081 spNewNode->spNext = spNextNode;
01082
01083 if(spNextNode == NULL)
01084 spList->spTail = spNewNode;
01085 else
01086 spNextNode->spPrev = spNewNode;
01087
01088 spList->uiLength++;
01089 }
01090
01091 void SctpAgent::DeleteNode(List_S *spList, Node_S *spNode)
01092 {
01093 if(spNode->spPrev == NULL)
01094 spList->spHead = spNode->spNext;
01095 else
01096 spNode->spPrev->spNext = spNode->spNext;
01097
01098 if(spNode->spNext == NULL)
01099 spList->spTail = spNode->spPrev;
01100 else
01101 spNode->spNext->spPrev = spNode->spPrev;
01102
01103
01104
01105 switch(spNode->eType)
01106 {
01107 case NODE_TYPE_STREAM_BUFFER:
01108 delete[] (u_char *) ((SctpStreamBufferNode_S *) spNode->vpData)->spChunk;
01109 ((SctpStreamBufferNode_S *) spNode->vpData)->spChunk = NULL;
01110 delete (SctpStreamBufferNode_S *) spNode->vpData;
01111 spNode->vpData = NULL;
01112 break;
01113
01114 case NODE_TYPE_RECV_TSN_BLOCK:
01115 delete (SctpRecvTsnBlock_S *) spNode->vpData;
01116 spNode->vpData = NULL;
01117 break;
01118
01119 case NODE_TYPE_DUP_TSN:
01120 delete (SctpDupTsn_S *) spNode->vpData;
01121 spNode->vpData = NULL;
01122 break;
01123
01124 case NODE_TYPE_SEND_BUFFER:
01125 delete[] (u_char *) ((SctpSendBufferNode_S *) spNode->vpData)->spChunk;
01126 ((SctpSendBufferNode_S *) spNode->vpData)->spChunk = NULL;
01127 delete (SctpSendBufferNode_S *) spNode->vpData;
01128 spNode->vpData = NULL;
01129 break;
01130
01131 case NODE_TYPE_APP_LAYER_BUFFER:
01132 delete (AppData_S *) spNode->vpData;
01133 spNode->vpData = NULL;
01134 break;
01135
01136 case NODE_TYPE_INTERFACE_LIST:
01137 delete (SctpInterface_S *) spNode->vpData;
01138 spNode->vpData = NULL;
01139 break;
01140
01141 case NODE_TYPE_DESTINATION_LIST:
01142 delete (SctpDest_S *) spNode->vpData;
01143 spNode->vpData = NULL;
01144 break;
01145
01146 case NODE_TYPE_PACKET_BUFFER:
01147
01148
01149
01150 spNode->vpData = NULL;
01151 break;
01152 }
01153
01154 delete spNode;
01155 spList->uiLength--;
01156 }
01157
01158 void SctpAgent::ClearList(List_S *spList)
01159 {
01160 Node_S *spCurrNode = spList->spHead;
01161 Node_S *spDeleteNode = NULL;
01162
01163 while(spCurrNode != NULL)
01164 {
01165 spDeleteNode = spCurrNode;
01166 spCurrNode = spCurrNode->spNext;
01167 DeleteNode(spList, spDeleteNode);
01168 }
01169 }
01170
01171 void SctpAgent::AddInterface(int iNsAddr, int iNsPort,
01172 NsObject *opTarget, NsObject *opLink)
01173 {
01174 DBG_I(AddInterface);
01175
01176 Node_S *spNewNode = new Node_S;
01177 spNewNode->eType = NODE_TYPE_INTERFACE_LIST;
01178 spNewNode->vpData = new SctpInterface_S;
01179
01180 SctpInterface_S *spNewInterface = (SctpInterface_S *) spNewNode->vpData;
01181 spNewInterface->iNsAddr = iNsAddr;
01182 spNewInterface->iNsPort = iNsPort;
01183 spNewInterface->opTarget = opTarget;
01184 spNewInterface->opLink = opLink;
01185
01186 InsertNode(&sInterfaceList, sInterfaceList.spTail, spNewNode, NULL);
01187
01188 DBG_X(AddInterface);
01189 }
01190
01191 void SctpAgent::AddDestination(int iNsAddr, int iNsPort)
01192 {
01193 DBG_I(AddDestination);
01194
01195 Node_S *spNewNode = new Node_S;
01196 spNewNode->eType = NODE_TYPE_DESTINATION_LIST;
01197 spNewNode->vpData = new SctpDest_S;
01198
01199 SctpDest_S *spNewDest = (SctpDest_S *) spNewNode->vpData;
01200 memset(spNewDest, 0, sizeof(SctpDest_S));
01201 spNewDest->iNsAddr = iNsAddr;
01202 spNewDest->iNsPort = iNsPort;
01203
01204
01205
01206
01207 spPrimaryDest = spNewDest;
01208 spNewTxDest = spPrimaryDest;
01209
01210
01211
01212 daddr() = spNewDest->iNsAddr;
01213 dport() = spNewDest->iNsPort;
01214 spNewDest->opRoutingAssistPacket = allocpkt();
01215
01216 InsertNode(&sDestList, sDestList.spTail, spNewNode, NULL);
01217
01218 DBG_X(AddDestination);
01219 }
01220
01221 int SctpAgent::SetPrimary(int iNsAddr)
01222 {
01223 DBG_I(SetPrimary);
01224
01225 Node_S *spCurrNode = NULL;
01226 SctpDest_S *spCurrDest = NULL;
01227
01228 for(spCurrNode = sDestList.spHead;
01229 spCurrNode != NULL;
01230 spCurrNode = spCurrNode->spNext)
01231 {
01232 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
01233
01234 if(spCurrDest->iNsAddr == iNsAddr)
01235 {
01236 spPrimaryDest = spCurrDest;
01237 spNewTxDest = spPrimaryDest;
01238 DBG_PL(SetPrimary, "returning TCL_OK") DBG_PR;
01239 DBG_X(SetPrimary);
01240 return (TCL_OK);
01241 }
01242 }
01243
01244 DBG_PL(SetPrimary, "returning TCL_ERROR") DBG_PR;
01245 DBG_X(SetPrimary);
01246 return (TCL_ERROR);
01247 }
01248
01249 int SctpAgent::ForceSource(int iNsAddr)
01250 {
01251 DBG_I(ForceSource);
01252
01253 Node_S *spCurrNode = sInterfaceList.spHead;
01254 SctpInterface_S *spCurrInterface = NULL;
01255
01256 while(spCurrNode != NULL)
01257 {
01258 spCurrInterface = (SctpInterface_S *) spCurrNode->vpData;
01259
01260 if(spCurrInterface->iNsAddr == iNsAddr)
01261 {
01262 addr() = spCurrInterface->iNsAddr;
01263 port() = spCurrInterface->iNsPort;
01264 target_ = spCurrInterface->opTarget;
01265 eForceSource = TRUE;
01266 DBG_PL(ForceSource, "returning TCL_OK") DBG_PR;
01267 DBG_X(ForceSource);
01268 return (TCL_OK);
01269 }
01270 else
01271 spCurrNode = spCurrNode->spNext;
01272 }
01273
01274 DBG_PL(ForceSource, "returning TCL_ERROR") DBG_PR;
01275 DBG_X(ForceSource);
01276 return (TCL_ERROR);
01277 }
01278
01279
01280
01281 int SctpAgent::GenChunk(SctpChunkType_E eType, u_char *ucpChunk)
01282 {
01283 DBG_I(GenChunk);
01284
01285 double dCurrTime = Scheduler::instance().clock();
01286 AppData_S *spAppMessage = NULL;
01287 int iSize = 0;
01288
01289 DBG_PL(GenChunk, "spSctpTrace=%p"), spSctpTrace DBG_PR;
01290
01291 switch(eType)
01292 {
01293 case SCTP_CHUNK_INIT:
01294 iSize = sizeof(SctpInitChunk_S);
01295 ((SctpInitChunk_S *) ucpChunk)->sHdr.ucType = eType;
01296 ((SctpInitChunk_S *) ucpChunk)->uiArwnd = uiInitialRwnd;
01297 ((SctpInitChunk_S *) ucpChunk)->usNumOutboundStreams = uiNumOutStreams;
01298 ((SctpInitChunk_S *) ucpChunk)->uiInitialTsn = 0;
01299
01300 ((SctpInitChunk_S *) ucpChunk)->sUnrelStream.usType
01301 = SCTP_INIT_PARAM_UNREL;
01302
01303 ((SctpInitChunk_S *) ucpChunk)->sUnrelStream.usLength
01304 = sizeof(SctpUnrelStreamsParam_S);
01305
01306 if(uiNumUnrelStreams > 0)
01307 {
01308 ((SctpInitChunk_S *) ucpChunk)->sUnrelStream.usLength
01309 += sizeof(SctpUnrelStreamPair_S);
01310
01311 SctpUnrelStreamPair_S *spUnrelStreamPair
01312 = (SctpUnrelStreamPair_S *) (ucpChunk+iSize);
01313 spUnrelStreamPair->usStart = 0;
01314 spUnrelStreamPair->usEnd = uiNumUnrelStreams - 1;
01315
01316 iSize += sizeof(SctpUnrelStreamPair_S);
01317 }
01318
01319 ((SctpInitChunk_S *) ucpChunk)->sHdr.usLength = iSize;
01320
01321
01322
01323 spSctpTrace[uiNumChunks].eType = eType;
01324 spSctpTrace[uiNumChunks].uiTsn = (u_int) -1;
01325 spSctpTrace[uiNumChunks].usStreamId = (u_short) -1;
01326 spSctpTrace[uiNumChunks].usStreamSeqNum = (u_short) -1;
01327 break;
01328
01329 case SCTP_CHUNK_INIT_ACK:
01330 iSize = sizeof(SctpInitAckChunk_S);
01331 ((SctpInitAckChunk_S *) ucpChunk)->sHdr.ucType = eType;
01332 ((SctpInitAckChunk_S *) ucpChunk)->uiArwnd = uiInitialRwnd;
01333 ((SctpInitChunk_S *) ucpChunk)->usNumOutboundStreams = uiNumOutStreams;
01334 ((SctpInitAckChunk_S *) ucpChunk)->uiInitialTsn = 0;
01335
01336 ((SctpInitAckChunk_S *) ucpChunk)->sUnrelStream.usType
01337 = SCTP_INIT_PARAM_UNREL;
01338
01339 ((SctpInitAckChunk_S *) ucpChunk)->sUnrelStream.usLength
01340 = sizeof(SctpUnrelStreamsParam_S);
01341
01342 if(uiNumUnrelStreams > 0)
01343 {
01344 ((SctpInitAckChunk_S *) ucpChunk)->sUnrelStream.usLength
01345 += sizeof(SctpUnrelStreamPair_S);
01346
01347 SctpUnrelStreamPair_S *spUnrelStreamPair
01348 = (SctpUnrelStreamPair_S *) (ucpChunk+iSize);
01349 spUnrelStreamPair->usStart = 0;
01350 spUnrelStreamPair->usEnd = uiNumUnrelStreams - 1;
01351
01352 iSize += sizeof(SctpUnrelStreamPair_S);
01353 }
01354
01355 ((SctpInitAckChunk_S *) ucpChunk)->sHdr.usLength = iSize;
01356
01357
01358
01359 spSctpTrace[uiNumChunks].eType = eType;
01360 spSctpTrace[uiNumChunks].uiTsn = (u_int) -1;
01361 spSctpTrace[uiNumChunks].usStreamId = (u_short) -1;
01362 spSctpTrace[uiNumChunks].usStreamSeqNum = (u_short) -1;
01363 break;
01364
01365 case SCTP_CHUNK_COOKIE_ECHO:
01366 iSize = sizeof(SctpCookieEchoChunk_S);
01367 ((SctpCookieEchoChunk_S *) ucpChunk)->sHdr.ucType = eType;
01368 ((SctpCookieEchoChunk_S *) ucpChunk)->sHdr.usLength = iSize;
01369
01370
01371
01372 spSctpTrace[uiNumChunks].eType = eType;
01373 spSctpTrace[uiNumChunks].uiTsn = (u_int) -1;
01374 spSctpTrace[uiNumChunks].usStreamId = (u_short) -1;
01375 spSctpTrace[uiNumChunks].usStreamSeqNum = (u_short) -1;
01376 break;
01377
01378 case SCTP_CHUNK_COOKIE_ACK:
01379 iSize = sizeof(SctpCookieAckChunk_S);
01380 ((SctpCookieAckChunk_S *) ucpChunk)->sHdr.ucType = eType;
01381 ((SctpCookieAckChunk_S *) ucpChunk)->sHdr.usLength = iSize;
01382
01383
01384
01385 spSctpTrace[uiNumChunks].eType = eType;
01386 spSctpTrace[uiNumChunks].uiTsn = (u_int) -1;
01387 spSctpTrace[uiNumChunks].usStreamId = (u_short) -1;
01388 spSctpTrace[uiNumChunks].usStreamSeqNum = (u_short) -1;
01389 break;
01390
01391 case SCTP_CHUNK_DATA:
01392
01393
01394
01395
01396 if(eDataSource == DATA_SOURCE_APPLICATION)
01397 {
01398
01399
01400
01401 DBG_PL (GenChunk, "eDataSource=DATA_SOURCE_APPLICATION") DBG_PR;
01402 spAppMessage = (AppData_S *) (sAppLayerBuffer.spHead->vpData);
01403
01404 DBG_PL (GenChunk, "App Message ---------------->") DBG_PR;
01405 DBG_PL (GenChunk, "usNumStreams: %d"),
01406 spAppMessage->usNumStreams DBG_PR;
01407 DBG_PL (GenChunk, "usNumUnreliable: %d"),
01408 spAppMessage->usNumUnreliable DBG_PR;
01409 DBG_PL (GenChunk, "uiNumBytes: %d"),
01410 spAppMessage->uiNumBytes DBG_PR;
01411 DBG_PL (GenChunk, "usStreamId: %d"),
01412 spAppMessage->usStreamId DBG_PR;
01413 DBG_PL (GenChunk, "eUnordered: %s"),
01414 spAppMessage->eUnordered ? "TRUE" : "FALSE" DBG_PR;
01415 DBG_PL (GenChunk, "usReliability: %d"),
01416 spAppMessage->usReliability DBG_PR;
01417 DBG_PL (GenChunk, "App Message <----------------") DBG_PR;
01418
01419 iSize = spAppMessage->uiNumBytes + sizeof(SctpDataChunkHdr_S);
01420 ((SctpDataChunkHdr_S *) ucpChunk)->sHdr.ucType = SCTP_CHUNK_DATA;
01421 ((SctpDataChunkHdr_S *) ucpChunk)->sHdr.usLength = iSize;
01422
01423
01424
01425
01426
01427 if( (iSize % 4) != 0)
01428 iSize += 4 - (iSize % 4);
01429
01430 ((SctpDataChunkHdr_S *) ucpChunk)->uiTsn = ++uiNextTsn;
01431
01432 ((SctpDataChunkHdr_S *) ucpChunk)->usStreamId
01433 = spAppMessage->usStreamId;
01434
01435 if(spAppMessage->eUnordered == TRUE)
01436 {
01437 ((SctpDataChunkHdr_S *) ucpChunk)->sHdr.ucFlags
01438 |= SCTP_DATA_FLAG_UNORDERED;
01439
01440
01441
01442 }
01443 else
01444 {
01445 ((SctpDataChunkHdr_S *) ucpChunk)->sHdr.ucFlags = 0;
01446 ((SctpDataChunkHdr_S *) ucpChunk)->usStreamSeqNum
01447 = spOutStreams[spAppMessage->usStreamId].usNextStreamSeqNum++;
01448 }
01449 }
01450 else
01451 {
01452 DBG_PL (GenChunk, "eDataSource=DATA_SOURCE_INFINITE") DBG_PR;
01453
01454 iSize = uiDataChunkSize;
01455 ((SctpDataChunkHdr_S *) ucpChunk)->sHdr.ucType = SCTP_CHUNK_DATA;
01456
01457 if(eUnordered == TRUE)
01458 {
01459 ((SctpDataChunkHdr_S *) ucpChunk)->sHdr.ucFlags
01460 |= SCTP_DATA_FLAG_UNORDERED;
01461 }
01462 else
01463 {
01464 ((SctpDataChunkHdr_S *) ucpChunk)->sHdr.ucFlags = 0;
01465 }
01466
01467 ((SctpDataChunkHdr_S *) ucpChunk)->sHdr.usLength = iSize;
01468
01469
01470
01471
01472
01473 if( (uiDataChunkSize % 4) != 0)
01474 iSize += 4 - (uiDataChunkSize % 4);
01475
01476 ((SctpDataChunkHdr_S *) ucpChunk)->uiTsn = ++uiNextTsn;
01477
01478 ((SctpDataChunkHdr_S *) ucpChunk)->usStreamId
01479 = (usNextStreamId % uiNumOutStreams);
01480
01481 if(eUnordered == TRUE)
01482 {
01483 ((SctpDataChunkHdr_S *) ucpChunk)->sHdr.ucFlags
01484 |= SCTP_DATA_FLAG_UNORDERED;
01485
01486
01487
01488 }
01489 else
01490 {
01491 ((SctpDataChunkHdr_S *) ucpChunk)->sHdr.ucFlags = 0;
01492 ((SctpDataChunkHdr_S *) ucpChunk)->usStreamSeqNum
01493 = spOutStreams[usNextStreamId%uiNumOutStreams].usNextStreamSeqNum++;
01494 }
01495
01496 usNextStreamId++;
01497 }
01498
01499
01500
01501 spSctpTrace[uiNumChunks].eType = eType;
01502 spSctpTrace[uiNumChunks].uiTsn = ((SctpDataChunkHdr_S *) ucpChunk)->uiTsn;
01503 spSctpTrace[uiNumChunks].usStreamId
01504 = ((SctpDataChunkHdr_S *) ucpChunk)->usStreamId;
01505 spSctpTrace[uiNumChunks].usStreamSeqNum
01506 = ((SctpDataChunkHdr_S *) ucpChunk)->usStreamSeqNum;
01507
01508 DBG_PL(GenChunk, "DataTsn=%d at dCurrTime=%f"),
01509 uiNextTsn, dCurrTime DBG_PR;
01510 break;
01511
01512 case SCTP_CHUNK_SACK:
01513 iSize = sizeof(SctpSackChunk_S);
01514 ((SctpSackChunk_S *) ucpChunk)->sHdr.ucType = eType;
01515 ((SctpSackChunk_S *) ucpChunk)->uiCumAck = uiCumAck;
01516 ((SctpSackChunk_S *) ucpChunk)->uiArwnd = uiMyRwnd;
01517 ((SctpSackChunk_S *) ucpChunk)->usNumGapAckBlocks
01518 = sRecvTsnBlockList.uiLength;
01519 ((SctpSackChunk_S *) ucpChunk)->usNumDupTsns = sDupTsnList.uiLength;
01520
01521 DBG_PL(GenChunk, "SACK CumAck=%d arwnd=%d"), uiCumAck, uiMyRwnd DBG_PR;
01522
01523
01524
01525 for(Node_S *spCurrFrag = sRecvTsnBlockList.spHead;
01526 (spCurrFrag != NULL) &&
01527 (iSize + sizeof(SctpGapAckBlock_S) < uiMaxDataSize);
01528 spCurrFrag = spCurrFrag->spNext, iSize += sizeof(SctpGapAckBlock_S) )
01529 {
01530 SctpGapAckBlock_S *spGapAckBlock
01531 = (SctpGapAckBlock_S *) (ucpChunk+iSize);
01532
01533 spGapAckBlock->usStartOffset
01534 = ((SctpRecvTsnBlock_S *)spCurrFrag->vpData)->uiStartTsn - uiCumAck;
01535
01536 spGapAckBlock->usEndOffset
01537 = ((SctpRecvTsnBlock_S *)spCurrFrag->vpData)->uiEndTsn - uiCumAck;
01538
01539 DBG_PL(GenChunk, "GapAckBlock StartOffset=%d EndOffset=%d"),
01540 spGapAckBlock->usStartOffset, spGapAckBlock->usEndOffset DBG_PR;
01541 }
01542
01543
01544
01545 for(Node_S *spPrevDup = NULL, *spCurrDup = sDupTsnList.spHead;
01546 (spCurrDup != NULL) &&
01547 (iSize + sizeof(SctpDupTsn_S) < uiMaxDataSize);
01548 spPrevDup = spCurrDup, spCurrDup = spCurrDup->spNext,
01549 DeleteNode(&sDupTsnList, spPrevDup), iSize += sizeof(SctpDupTsn_S) )
01550 {
01551 SctpDupTsn_S *spDupTsn = (SctpDupTsn_S *) (ucpChunk+iSize);
01552
01553 spDupTsn->uiTsn = ((SctpDupTsn_S *) spCurrDup->vpData)->uiTsn;
01554
01555 DBG_PL(GenChunk, "DupTsn=%d"), spDupTsn->uiTsn DBG_PR;
01556 }
01557
01558
01559
01560 ((SctpSackChunk_S *) ucpChunk)->sHdr.usLength = iSize;
01561
01562
01563
01564 spSctpTrace[uiNumChunks].eType = eType;
01565 spSctpTrace[uiNumChunks].uiTsn = ((SctpSackChunk_S *) ucpChunk)->uiCumAck;
01566 spSctpTrace[uiNumChunks].usStreamId = (u_short) -1;
01567 spSctpTrace[uiNumChunks].usStreamSeqNum = (u_short) -1;
01568 break;
01569
01570 case SCTP_CHUNK_FORWARD_TSN:
01571 iSize = SCTP_CHUNK_FORWARD_TSN_LENGTH;
01572 ((SctpForwardTsnChunk_S *) ucpChunk)->sHdr.ucType = eType;
01573 ((SctpForwardTsnChunk_S *) ucpChunk)->sHdr.ucFlags = 0;
01574 ((SctpForwardTsnChunk_S *) ucpChunk)->sHdr.usLength = iSize;
01575 ((SctpForwardTsnChunk_S *) ucpChunk)->uiNewCum = uiAdvancedPeerAckPoint;
01576
01577
01578
01579 spSctpTrace[uiNumChunks].eType = eType;
01580 spSctpTrace[uiNumChunks].uiTsn = uiAdvancedPeerAckPoint;
01581 spSctpTrace[uiNumChunks].usStreamId = (u_short) -1;
01582 spSctpTrace[uiNumChunks].usStreamSeqNum = (u_short) -1;
01583 break;
01584
01585 case SCTP_CHUNK_HB:
01586 case SCTP_CHUNK_HB_ACK:
01587 iSize = SCTP_CHUNK_HEARTBEAT_LENGTH;
01588 ((SctpHeartbeatChunk_S *) ucpChunk)->sHdr.ucType = eType;
01589 ((SctpHeartbeatChunk_S *) ucpChunk)->sHdr.ucFlags = 0;
01590 ((SctpHeartbeatChunk_S *) ucpChunk)->sHdr.usLength = iSize;
01591 ((SctpHeartbeatChunk_S *) ucpChunk)->usInfoType = 1;
01592 ((SctpHeartbeatChunk_S *) ucpChunk)->usInfoLength
01593 = iSize - sizeof(SctpChunkHdr_S);
01594 ((SctpHeartbeatChunk_S *) ucpChunk)->dTimestamp = dCurrTime;
01595 ((SctpHeartbeatChunk_S *) ucpChunk)->spDest = NULL;
01596
01597
01598
01599 spSctpTrace[uiNumChunks].eType = eType;
01600 spSctpTrace[uiNumChunks].uiTsn = (u_int) -1;
01601 spSctpTrace[uiNumChunks].usStreamId = (u_short) -1;
01602 spSctpTrace[uiNumChunks].usStreamSeqNum = (u_short) -1;
01603 break;
01604
01605 case SCTP_CHUNK_SHUTDOWN:
01606 break;
01607
01608 case SCTP_CHUNK_SHUTDOWN_ACK:
01609 break;
01610
01611 case SCTP_CHUNK_SHUTDOWN_COMPLETE:
01612 break;
01613
01614 default:
01615 fprintf(stderr, "[GenChunk] ERROR: bad chunk type!\n");
01616 DBG_PL(GenChunk, "ERROR: bad chunk type!") DBG_PR;
01617 DBG_PL(GenChunk, "exiting...") DBG_PR;
01618 exit(-1);
01619 }
01620
01621 uiNumChunks++;
01622
01623 DBG_X(GenChunk);
01624 return iSize;
01625 }
01626
01627 u_int SctpAgent::GetNextDataChunkSize()
01628 {
01629 DBG_I(GetNextDataChunkSize);
01630
01631 AppData_S *spAppMessage = NULL;
01632 u_int uiChunkSize = 0;
01633
01634 if(eDataSource == DATA_SOURCE_APPLICATION)
01635 {
01636 if(sAppLayerBuffer.uiLength == 0)
01637 {
01638 uiChunkSize = 0;
01639 }
01640 else
01641 {
01642 spAppMessage = (AppData_S *) (sAppLayerBuffer.spHead->vpData);
01643 uiChunkSize = spAppMessage->uiNumBytes + sizeof(SctpDataChunkHdr_S);
01644 }
01645 }
01646 else
01647 {
01648 uiChunkSize = uiDataChunkSize;
01649 }
01650
01651
01652
01653 if( (uiChunkSize % 4) != 0)
01654 uiChunkSize += 4 - (uiChunkSize % 4);
01655
01656 DBG_PL(GetNextDataChunkSize, "returning %d"), uiChunkSize DBG_PR;
01657 DBG_X(GetNextDataChunkSize);
01658 return uiChunkSize;
01659 }
01660
01661
01662
01663
01664
01665
01666 int SctpAgent::GenOneDataChunk(u_char *ucpOutData)
01667 {
01668 DBG_I(GenOneDataChunk);
01669
01670 AppData_S *spAppData = NULL;
01671 int iChunkSize = GenChunk(SCTP_CHUNK_DATA, ucpOutData);
01672
01673 if(eDataSource == DATA_SOURCE_APPLICATION)
01674 {
01675 spAppData = (AppData_S *) sAppLayerBuffer.spHead->vpData;
01676 AddToSendBuffer( (SctpDataChunkHdr_S *) ucpOutData, iChunkSize,
01677 spAppData->usReliability, spNewTxDest);
01678 DeleteNode(&sAppLayerBuffer, sAppLayerBuffer.spHead);
01679 }
01680 else
01681 {
01682 AddToSendBuffer( (SctpDataChunkHdr_S *) ucpOutData, iChunkSize,
01683 uiReliability, spNewTxDest);
01684 }
01685
01686 DBG_PL(GenOneDataChunk, "dest=%p"), spNewTxDest DBG_PR;
01687 spNewTxDest->iOutstandingBytes
01688 += ((SctpDataChunkHdr_S *) ucpOutData)->sHdr.usLength;
01689
01690
01691
01692 if(iChunkSize <= (int) uiPeerRwnd)
01693 uiPeerRwnd -= iChunkSize;
01694 else
01695 uiPeerRwnd = 0;
01696
01697 if(spNewTxDest->eRtxTimerIsRunning == FALSE)
01698 StartT3RtxTimer(spNewTxDest);
01699
01700 DBG_X(GenOneDataChunk);
01701 return iChunkSize;
01702 }
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712 int SctpAgent::GenMultipleDataChunks(u_char *ucpOutData, int iTotalOutDataSize)
01713 {
01714 DBG_I(GenMultipleDataChunks);
01715
01716 int iChunkSize = 0;
01717 int iStartingTotalSize = iTotalOutDataSize;
01718
01719 while((iTotalOutDataSize + GetNextDataChunkSize() <= uiMaxDataSize) &&
01720 (GetNextDataChunkSize() <= uiPeerRwnd) &&
01721 (eDataSource == DATA_SOURCE_INFINITE || sAppLayerBuffer.uiLength != 0))
01722 {
01723 iChunkSize = GenOneDataChunk(ucpOutData);
01724 ucpOutData += iChunkSize;
01725 iTotalOutDataSize += iChunkSize;
01726 }
01727
01728 DBG_X(GenMultipleDataChunks);
01729 return iTotalOutDataSize - iStartingTotalSize;
01730 }
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740 int SctpAgent::BundleControlChunks(u_char *ucpOutData)
01741 {
01742 DBG_I(BundleControlChunks);
01743 DBG_PL(BundleControlChunks, "None... returning 0") DBG_PR;
01744 DBG_X(BundleControlChunks);
01745 return 0;
01746 }
01747
01748 void SctpAgent::StartT3RtxTimer(SctpDest_S *spDest)
01749 {
01750 DBG_I(StartT3RtxTimer);
01751 double dCurrTime = Scheduler::instance().clock();
01752 DBG_PL(StartT3RtxTimer, "spDest=%p dCurrTime=%f expires at %f "),
01753 spDest, dCurrTime, dCurrTime+spDest->dRto DBG_PR;
01754 spDest->opT3RtxTimer->resched(spDest->dRto);
01755 spDest->eRtxTimerIsRunning = TRUE;
01756 DBG_X(StartT3RtxTimer);
01757 }
01758
01759 void SctpAgent::StopT3RtxTimer(SctpDest_S *spDest)
01760 {
01761 DBG_I(StopT3RtxTimer);
01762 double dCurrTime = Scheduler::instance().clock();
01763 DBG_PL(StopT3RtxTimer, "spDest=%p dCurrTime=%f"), spDest, dCurrTime DBG_PR;
01764 spDest->opT3RtxTimer->force_cancel();
01765 spDest->eRtxTimerIsRunning = FALSE;
01766 DBG_X(StopT3RtxTimer);
01767 }
01768
01769 void SctpAgent::AddToSendBuffer(SctpDataChunkHdr_S *spChunk,
01770 int iChunkSize,
01771 u_int uiReliability,
01772 SctpDest_S *spDest)
01773 {
01774 DBG_I(AddToSendBuffer);
01775 DBG_PL(AddToSendBuffer, "spDest=%p iChunkSize=%d"),
01776 spDest, iChunkSize DBG_PR;
01777
01778 Node_S *spNewNode = new Node_S;
01779 spNewNode->eType = NODE_TYPE_SEND_BUFFER;
01780 spNewNode->vpData = new SctpSendBufferNode_S;
01781
01782 SctpSendBufferNode_S * spNewNodeData
01783 = (SctpSendBufferNode_S *) spNewNode->vpData;
01784
01785
01786
01787
01788
01789 spNewNodeData->spChunk = (SctpDataChunkHdr_S *) new u_char[iChunkSize];
01790 memcpy(spNewNodeData->spChunk, spChunk, iChunkSize);
01791
01792 spNewNodeData->eAdvancedAcked = FALSE;
01793 spNewNodeData->eGapAcked = FALSE;
01794 spNewNodeData->eAddedToPartialBytesAcked = FALSE;
01795 spNewNodeData->iNumMissingReports = 0;
01796 spNewNodeData->iUnrelRtxLimit = uiReliability;
01797 spNewNodeData->eMarkedForRtx = NO_RTX;
01798 spNewNodeData->eIneligibleForFastRtx = FALSE;
01799 spNewNodeData->iNumTxs = 1;
01800 spNewNodeData->spDest = spDest;
01801
01802
01803
01804
01805 if(spDest->eRtoPending == FALSE)
01806 {
01807 spNewNodeData->dTxTimestamp = Scheduler::instance().clock();
01808 spDest->eRtoPending = TRUE;
01809 }
01810 else
01811 spNewNodeData->dTxTimestamp = 0;
01812
01813 InsertNode(&sSendBuffer, sSendBuffer.spTail, spNewNode, NULL);
01814
01815 DBG_X(AddToSendBuffer);
01816 }
01817
01818 void SctpAgent::RttUpdate(double dTxTime, SctpDest_S *spDest)
01819 {
01820 DBG_I(RttUpdate);
01821
01822 double dNewRtt;
01823 double dCurrTime = Scheduler::instance().clock();
01824
01825 dNewRtt = dCurrTime - dTxTime;
01826
01827 if(spDest->eFirstRttMeasurement == TRUE)
01828 {
01829
01830
01831
01832 spDest->eFirstRttMeasurement = FALSE;
01833 spDest->dSrtt = dNewRtt;
01834 spDest->dRttVar = dNewRtt/2;
01835 spDest->dRto = spDest->dSrtt + 4 * spDest->dRttVar;
01836 }
01837 else
01838 {
01839 spDest->dRttVar
01840 = ( (1 - RTO_BETA) * spDest->dRttVar
01841 + RTO_BETA * abs(spDest->dSrtt - dNewRtt) );
01842
01843 spDest->dSrtt
01844 = (1 - RTO_ALPHA) * spDest->dSrtt + RTO_ALPHA * dNewRtt;
01845
01846 spDest->dRto = spDest->dSrtt + 4 * spDest->dRttVar;
01847 }
01848
01849 if(spDest->dRto < dMinRto)
01850 spDest->dRto = dMinRto;
01851 else if(spDest->dRto > dMaxRto)
01852 spDest->dRto = dMaxRto;
01853 tdRto++;
01854
01855 DBG_PL(RttUpdate, "spDest->dRto=%f"), spDest->dRto DBG_PR;
01856 DBG_X(RttUpdate);
01857 }
01858
01859
01860
01861
01862
01863
01864
01865
01866 void SctpAgent::SendBufferDequeueUpTo(u_int uiTsn)
01867 {
01868 DBG_I(SendBufferDequeueUpTo);
01869
01870 Node_S *spDeleteNode = NULL;
01871 Node_S *spCurrNode = sSendBuffer.spHead;
01872 SctpSendBufferNode_S *spCurrNodeData = NULL;
01873
01874 iAssocErrorCount = 0;
01875
01876 while(spCurrNode != NULL &&
01877 ((SctpSendBufferNode_S*)spCurrNode->vpData)->spChunk->uiTsn <= uiTsn)
01878 {
01879 spCurrNodeData = (SctpSendBufferNode_S *) spCurrNode->vpData;
01880
01881
01882
01883
01884
01885 if((spCurrNodeData->eGapAcked == FALSE) &&
01886 (spCurrNodeData->eAdvancedAcked == FALSE) )
01887 {
01888 uiHighestTsnNewlyAcked = spCurrNodeData->spChunk->uiTsn;
01889
01890 spCurrNodeData->spDest->iNumNewlyAckedBytes
01891 += spCurrNodeData->spChunk->sHdr.usLength;
01892
01893
01894
01895
01896
01897 if(spCurrNodeData->spDest->iCwnd >spCurrNodeData->spDest->iSsthresh &&
01898 ( spCurrNodeData->spDest->iOutstandingBytes
01899 >= spCurrNodeData->spDest->iCwnd) )
01900 {
01901 spCurrNodeData->spDest->iPartialBytesAcked
01902 += spCurrNodeData->spChunk->sHdr.usLength;
01903 }
01904 }
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915 if(spCurrNodeData->eIneligibleForFastRtx == TRUE)
01916 eApplyMaxBurst = TRUE;
01917
01918
01919
01920
01921
01922
01923
01924
01925 if(spCurrNodeData->spDest->eRtoPending == TRUE &&
01926 spCurrNodeData->dTxTimestamp > 0 &&
01927 spCurrNodeData->iNumTxs == 1 &&
01928 spCurrNodeData->eGapAcked == FALSE &&
01929 spCurrNodeData->eAdvancedAcked == FALSE)
01930 {
01931
01932
01933
01934
01935
01936 if(spCurrNodeData->eMarkedForRtx != TIMEOUT_RTX)
01937 RttUpdate(spCurrNodeData->dTxTimestamp, spCurrNodeData->spDest);
01938 spCurrNodeData->spDest->eRtoPending = FALSE;
01939 }
01940
01941
01942
01943 if(spCurrNodeData->spDest->eRtxTimerIsRunning == TRUE)
01944 StopT3RtxTimer(spCurrNodeData->spDest);
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959 if(spCurrNodeData->spDest->iErrorCount != 0 &&
01960 spCurrNodeData->eMarkedForRtx != TIMEOUT_RTX &&
01961 spCurrNodeData->eGapAcked == FALSE)
01962 {
01963 DBG_PL(SendBufferDequeueUpTo,
01964 "clearing error counter for %p with tsn=%lu"),
01965 spCurrNodeData->spDest, spCurrNodeData->spChunk->uiTsn DBG_PR;
01966
01967 spCurrNodeData->spDest->iErrorCount = 0;
01968 tiErrorCount++;
01969 spCurrNodeData->spDest->eStatus = SCTP_DEST_STATUS_ACTIVE;
01970 if(spCurrNodeData->spDest == spPrimaryDest &&
01971 spNewTxDest != spPrimaryDest)
01972 {
01973 DBG_PL(SendBufferDequeueUpTo,
01974 "primary recovered... migrating back from %p to %p"),
01975 spNewTxDest, spPrimaryDest DBG_PR;
01976 spNewTxDest = spPrimaryDest;
01977 }
01978 }
01979
01980 spDeleteNode = spCurrNode;
01981 spCurrNode = spCurrNode->spNext;
01982 DeleteNode(&sSendBuffer, spDeleteNode);
01983 spDeleteNode = NULL;
01984 }
01985
01986 DBG_X(SendBufferDequeueUpTo);
01987 }
01988
01989
01990
01991
01992
01993 void SctpAgent::AdjustCwnd(SctpDest_S *spDest)
01994 {
01995 DBG_I(AdjustCwnd);
01996
01997 if(spDest->iCwnd <= spDest->iSsthresh)
01998 {
01999 DBG_PL(AdjustCwnd, "slow start mode") DBG_PR;
02000 DBG_PL(AdjustCwnd, "iSsthresh=%d"), spDest->iSsthresh DBG_PR;
02001
02002
02003
02004 if(spDest->iOutstandingBytes >= spDest->iCwnd)
02005 {
02006 spDest->iCwnd += MIN(spDest->iNumNewlyAckedBytes, (int)uiMaxDataSize);
02007 tiCwnd++;
02008 }
02009 }
02010 else
02011 {
02012 DBG_PL(AdjustCwnd,"congestion avoidance mode") DBG_PR;
02013 DBG_PL(AdjustCwnd,"iPartialBytesAcked=%d iCwnd=%d iOutStandingBytes=%d"),
02014 spDest->iPartialBytesAcked,
02015 spDest->iCwnd,
02016 spDest->iOutstandingBytes
02017 DBG_PR;
02018
02019
02020
02021 if(spDest->iPartialBytesAcked >= spDest->iCwnd &&
02022 spDest->iOutstandingBytes >= spDest->iCwnd )
02023 {
02024 DBG_PL(AdjustCwnd, "adjusting cwnd") DBG_PR;
02025 if(spDest->iCwnd <= spDest->iPartialBytesAcked)
02026 spDest->iPartialBytesAcked -= spDest->iCwnd;
02027 else
02028 spDest->iPartialBytesAcked = 0;
02029 spDest->iCwnd += uiMaxDataSize;
02030 tiCwnd++;
02031 }
02032 }
02033
02034 DBG_PL(AdjustCwnd, "pba=%d cwnd=%d out=%d PeerRwnd=%d"),
02035 spDest->iPartialBytesAcked,
02036 spDest->iCwnd,
02037 spDest->iOutstandingBytes,
02038 uiPeerRwnd
02039 DBG_PR;
02040 DBG_X(AdjustCwnd);
02041 }
02042
02043 void SctpAgent::AdvancePeerAckPoint()
02044 {
02045 DBG_I(AdvancePeerAckPoint);
02046
02047 Node_S *spCurrNode = NULL;
02048 SctpSendBufferNode_S *spCurrNodeData = NULL;
02049
02050 if(uiAdvancedPeerAckPoint < uiCumAckPoint)
02051 uiAdvancedPeerAckPoint = uiCumAckPoint;
02052
02053 for(spCurrNode = sSendBuffer.spHead;
02054 spCurrNode != NULL;
02055 spCurrNode = spCurrNode->spNext)
02056 {
02057 spCurrNodeData = (SctpSendBufferNode_S *) spCurrNode->vpData;
02058
02059
02060
02061
02062
02063 if(spCurrNodeData->eAdvancedAcked == FALSE &&
02064 spCurrNodeData->eGapAcked == FALSE)
02065 break;
02066
02067 uiAdvancedPeerAckPoint = spCurrNodeData->spChunk->uiTsn;
02068 }
02069
02070 DBG_PL(AdvancePeerAckPoint, "uiAdvancedPeerAckPoint=%d"),
02071 uiAdvancedPeerAckPoint DBG_PR;
02072 DBG_X(AdvancePeerAckPoint);
02073 }
02074
02075 u_int SctpAgent::GetHighestOutstandingTsn()
02076 {
02077 DBG_I(GetHighestOutstandingTsn);
02078
02079 u_int uiHighestOutstandingTsn = 0;
02080 Node_S *spCurrBuffNode = NULL;
02081 SctpSendBufferNode_S *spCurrBuffData = NULL;
02082
02083
02084
02085
02086 for(spCurrBuffNode = sSendBuffer.spTail;
02087 spCurrBuffNode != NULL;
02088 spCurrBuffNode = spCurrBuffNode->spPrev)
02089 {
02090 spCurrBuffData = (SctpSendBufferNode_S *) spCurrBuffNode->vpData;
02091
02092 if(spCurrBuffData->eMarkedForRtx == NO_RTX)
02093 {
02094 uiHighestOutstandingTsn = spCurrBuffData->spChunk->uiTsn;
02095 break;
02096 }
02097 }
02098
02099 DBG_PL(GetHighestOutstandingTsn, "uiHighestOutstandingTsn=%d"),
02100 uiHighestOutstandingTsn DBG_PR;
02101 DBG_X(GetHighestOutstandingTsn);
02102
02103 return uiHighestOutstandingTsn;
02104 }
02105
02106
02107
02108
02109
02110
02111 void SctpAgent::FastRtx()
02112 {
02113 DBG_I(FastRtx);
02114
02115 Node_S *spCurrDestNode = NULL;
02116 SctpDest_S *spCurrDestData = NULL;
02117 Node_S *spCurrBuffNode = NULL;
02118 SctpSendBufferNode_S *spCurrBuffData = NULL;
02119
02120
02121
02122 for(spCurrDestNode = sDestList.spHead;
02123 spCurrDestNode != NULL;
02124 spCurrDestNode = spCurrDestNode->spNext)
02125 {
02126 spCurrDestData = (SctpDest_S *) spCurrDestNode->vpData;
02127 spCurrDestData->eCcApplied = FALSE;
02128 }
02129
02130
02131
02132
02133
02134 for(spCurrBuffNode = sSendBuffer.spHead;
02135 spCurrBuffNode != NULL;
02136 spCurrBuffNode = spCurrBuffNode->spNext)
02137 {
02138 spCurrBuffData = (SctpSendBufferNode_S *) spCurrBuffNode->vpData;
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149 if( (spCurrBuffData->eMarkedForRtx != NO_RTX ||
02150 spCurrBuffData->eAdvancedAcked == TRUE) &&
02151 spCurrBuffData->spDest->eCcApplied == FALSE &&
02152 spCurrBuffData->spChunk->uiTsn > uiRecover)
02153
02154 {
02155
02156
02157 spCurrBuffData->spDest->iSsthresh
02158 = MAX(spCurrBuffData->spDest->iCwnd/2,
02159 iInitialCwnd * (int) uiMaxDataSize);
02160 spCurrBuffData->spDest->iCwnd = spCurrBuffData->spDest->iSsthresh;
02161 spCurrBuffData->spDest->iPartialBytesAcked = 0;
02162 tiCwnd++;
02163 spCurrBuffData->spDest->eCcApplied = TRUE;
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189 spCurrBuffData->spDest->eRtoPending = FALSE;
02190
02191
02192
02193
02194 uiRecover = GetHighestOutstandingTsn();
02195 }
02196 }
02197
02198
02199
02200
02201 if(eMarkedChunksPending == TRUE)
02202 RtxMarkedChunks(RTX_LIMIT_ONE_PACKET);
02203
02204 DBG_X(FastRtx);
02205 }
02206
02207 void SctpAgent::TimeoutRtx(SctpDest_S *spDest)
02208 {
02209 DBG_I(TimeoutRtx);
02210
02211 Node_S *spCurrNode = NULL;
02212 SctpSendBufferNode_S *spCurrNodeData = NULL;
02213
02214 DBG_PL(TimeoutRtx, "spDest=%p"), spDest DBG_PR;
02215
02216 for(spCurrNode = sSendBuffer.spHead;
02217 spCurrNode != NULL;
02218 spCurrNode = spCurrNode->spNext)
02219 {
02220 spCurrNodeData = (SctpSendBufferNode_S *) spCurrNode->vpData;
02221
02222
02223
02224
02225 if(spCurrNodeData->spDest == spDest &&
02226 spCurrNodeData->eGapAcked == FALSE &&
02227 spCurrNodeData->eAdvancedAcked == FALSE)
02228 {
02229 MarkChunkForRtx(spCurrNodeData, TIMEOUT_RTX);
02230 spCurrNodeData->iNumMissingReports = 0;
02231 }
02232 }
02233
02234 if(eMarkedChunksPending == TRUE)
02235 RtxMarkedChunks(RTX_LIMIT_ONE_PACKET);
02236
02237 DBG_X(TimeoutRtx);
02238 }
02239
02240 void SctpAgent::MarkChunkForRtx(SctpSendBufferNode_S *spNodeData,
02241 MarkedForRtx_E eMarkedForRtx)
02242 {
02243 DBG_I(MarkChunkForRtx);
02244
02245 SctpDataChunkHdr_S *spChunk = spNodeData->spChunk;
02246 SctpOutStream_S *spStream = &(spOutStreams[spChunk->usStreamId]);
02247
02248 DBG_PL(MarkChunkForRtx, "tsn=%lu eMarkedForRtx=%s"),
02249 spChunk->uiTsn,
02250 !eMarkedForRtx ? "NO_RTX"
02251 : (eMarkedForRtx==FAST_RTX ? "FAST_RTX": "TIMEOUT_RTX") DBG_PR;
02252
02253 spNodeData->eMarkedForRtx = eMarkedForRtx;
02254 uiPeerRwnd += spChunk->sHdr.usLength;
02255
02256
02257
02258
02259 if(spStream->eMode == SCTP_STREAM_UNRELIABLE)
02260 {
02261
02262
02263 if(spNodeData->iNumTxs > spNodeData->iUnrelRtxLimit)
02264 {
02265 DBG_PL(MarkChunkForRtx, "giving up on tsn %lu..."),
02266 spChunk->uiTsn DBG_PR;
02267
02268 spNodeData->eAdvancedAcked = TRUE;
02269 spNodeData->eMarkedForRtx = NO_RTX;
02270 spNodeData->spDest->iOutstandingBytes -= spChunk->sHdr.usLength;
02271 }
02272 }
02273
02274 if(spNodeData->eMarkedForRtx != NO_RTX)
02275 eMarkedChunksPending = TRUE;
02276
02277 DBG_PL(MarkChunkForRtx, "uiPeerRwnd=%lu"), uiPeerRwnd DBG_PR;
02278 DBG_X(MarkChunkForRtx);
02279 }
02280
02281 Boolean_E SctpAgent::AnyMarkedChunks()
02282 {
02283 DBG_I(AnyMarkedChunks);
02284
02285 Node_S *spCurrBuffNode = NULL;
02286 SctpSendBufferNode_S *spCurrBuffNodeData = NULL;
02287
02288 for(spCurrBuffNode = sSendBuffer.spHead;
02289 spCurrBuffNode != NULL;
02290 spCurrBuffNode = spCurrBuffNode->spNext)
02291 {
02292 spCurrBuffNodeData = (SctpSendBufferNode_S *) spCurrBuffNode->vpData;
02293 if(spCurrBuffNodeData->eMarkedForRtx != NO_RTX)
02294 {
02295 DBG_PL(AnyMarkedChunks, "TRUE") DBG_PR;
02296 DBG_X(AnyMarkedChunks);
02297 return TRUE;
02298 }
02299 }
02300
02301 DBG_PL(AnyMarkedChunks, "FALSE") DBG_PR;
02302 DBG_X(AnyMarkedChunks);
02303 return FALSE;
02304 }
02305
02306
02307
02308
02309
02310
02311
02312 void SctpAgent::RtxMarkedChunks(SctpRtxLimit_E eLimit)
02313 {
02314 DBG_I(RtxMarkedChunks);
02315
02316 u_char ucpOutData[uiMaxPayloadSize];
02317 u_char *ucpCurrOutData = ucpOutData;
02318 int iBundledControlChunkSize = 0;
02319 int iCurrSize = 0;
02320 int iOutDataSize = 0;
02321 Node_S *spCurrBuffNode = NULL;
02322 SctpSendBufferNode_S *spCurrBuffNodeData = NULL;
02323 SctpDataChunkHdr_S *spCurrChunk;
02324 SctpDest_S *spRtxDest = NULL;
02325 Node_S *spCurrDestNode = NULL;
02326 SctpDest_S *spCurrDestNodeData = NULL;
02327 Boolean_E eControlChunkBundled = FALSE;
02328 int iNumPacketsSent = 0;
02329
02330 memset(ucpOutData, 0, uiMaxPayloadSize);
02331
02332 uiBurstLength = 0;
02333
02334
02335
02336 for(spCurrDestNode = sDestList.spHead;
02337 spCurrDestNode != NULL;
02338 spCurrDestNode = spCurrDestNode->spNext)
02339 {
02340 spCurrDestNodeData = (SctpDest_S *) spCurrDestNode->vpData;
02341 spCurrDestNodeData->spFirstOutstanding = NULL;
02342 }
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356 for(spCurrBuffNode = sSendBuffer.spHead;
02357 spCurrBuffNode != NULL;
02358 spCurrBuffNode = spCurrBuffNode->spNext)
02359 {
02360 spCurrBuffNodeData = (SctpSendBufferNode_S *) spCurrBuffNode->vpData;
02361
02362 if(spCurrBuffNodeData->eMarkedForRtx != NO_RTX)
02363 {
02364 spCurrChunk = spCurrBuffNodeData->spChunk;
02365
02366 if(spRtxDest == NULL)
02367 {
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380 switch(eRtxToAlt)
02381 {
02382 case RTX_TO_ALT_OFF:
02383 if(spCurrBuffNodeData->spDest->eStatus
02384 == SCTP_DEST_STATUS_ACTIVE)
02385 {
02386 spRtxDest = spCurrBuffNodeData->spDest;
02387 }
02388 else
02389 {
02390 spRtxDest = GetNextDest(spCurrBuffNodeData->spDest);
02391 }
02392 break;
02393
02394 case RTX_TO_ALT_ON:
02395 spRtxDest = GetNextDest(spCurrBuffNodeData->spDest);
02396 break;
02397
02398 case RTX_TO_ALT_TIMEOUTS_ONLY:
02399 if(spCurrBuffNodeData->eMarkedForRtx == FAST_RTX &&
02400 spCurrBuffNodeData->spDest->eStatus
02401 == SCTP_DEST_STATUS_ACTIVE)
02402 {
02403 spRtxDest = spCurrBuffNodeData->spDest;
02404 }
02405 else
02406 {
02407 spRtxDest = GetNextDest(spCurrBuffNodeData->spDest);
02408 }
02409 break;
02410 }
02411 }
02412
02413 spCurrBuffNodeData->spDest->iOutstandingBytes
02414 -= spCurrChunk->sHdr.usLength;
02415 }
02416 }
02417
02418 spCurrBuffNode = sSendBuffer.spHead;
02419
02420 while( (eLimit == RTX_LIMIT_ONE_PACKET &&
02421 iNumPacketsSent < 1 &&
02422 spCurrBuffNode != NULL) ||
02423 (eLimit == RTX_LIMIT_CWND &&
02424 spRtxDest->iOutstandingBytes < spRtxDest->iCwnd &&
02425 spCurrBuffNode != NULL) )
02426 {
02427 DBG_PL(RtxMarkedChunks,
02428 "eLimit=%s pktsSent=%d out=%d cwnd=%d spCurrBuffNode=%p"),
02429 (eLimit == RTX_LIMIT_ONE_PACKET) ? "ONE_PACKET" : "CWND",
02430 iNumPacketsSent, spRtxDest->iOutstandingBytes, spRtxDest->iCwnd,
02431 spCurrBuffNode
02432 DBG_PR;
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442 for(eControlChunkBundled = FALSE;
02443 spCurrBuffNode != NULL;
02444 spCurrBuffNode = spCurrBuffNode->spNext)
02445 {
02446 spCurrBuffNodeData = (SctpSendBufferNode_S *) spCurrBuffNode->vpData;
02447
02448
02449
02450 if(spCurrBuffNodeData->spDest->spFirstOutstanding == NULL &&
02451 spCurrBuffNodeData->eGapAcked == FALSE &&
02452 spCurrBuffNodeData->eAdvancedAcked == FALSE)
02453 {
02454
02455
02456 spCurrBuffNodeData->spDest->spFirstOutstanding
02457 = spCurrBuffNodeData;
02458 }
02459
02460
02461
02462 if(spCurrBuffNodeData->eMarkedForRtx != NO_RTX)
02463 {
02464 spCurrChunk = spCurrBuffNodeData->spChunk;
02465
02466
02467
02468
02469 if(eControlChunkBundled == FALSE)
02470 {
02471 eControlChunkBundled = TRUE;
02472 iBundledControlChunkSize =BundleControlChunks(ucpCurrOutData);
02473 ucpCurrOutData += iBundledControlChunkSize;
02474 iOutDataSize += iBundledControlChunkSize;
02475 }
02476
02477
02478
02479 if((iOutDataSize + spCurrChunk->sHdr.usLength)
02480 > (int) uiMaxPayloadSize)
02481 break;
02482
02483
02484
02485 if(spCurrBuffNodeData->spDest->eRtoPending == TRUE &&
02486 spCurrBuffNodeData->dTxTimestamp > 0)
02487 {
02488 spCurrBuffNodeData->dTxTimestamp = 0;
02489 spCurrBuffNodeData->spDest->eRtoPending = FALSE;
02490 }
02491
02492
02493
02494
02495
02496
02497 if(spCurrBuffNodeData->spDest->spFirstOutstanding
02498 == spCurrBuffNodeData)
02499 {
02500 if(spCurrBuffNodeData->spDest->iOutstandingBytes > 0)
02501 StartT3RtxTimer(spCurrBuffNodeData->spDest);
02502 }
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514 if(spRtxDest->spFirstOutstanding == NULL ||
02515 spCurrChunk->uiTsn <
02516 spRtxDest->spFirstOutstanding->spChunk->uiTsn)
02517 {
02518
02519
02520 spRtxDest->spFirstOutstanding = spCurrBuffNodeData;
02521 StartT3RtxTimer(spRtxDest);
02522 }
02523
02524 memcpy(ucpCurrOutData, spCurrChunk, spCurrChunk->sHdr.usLength);
02525 iCurrSize = spCurrChunk->sHdr.usLength;
02526
02527
02528
02529
02530 if( (iCurrSize % 4) != 0 )
02531 iCurrSize += 4 - (iCurrSize % 4);
02532
02533 ucpCurrOutData += iCurrSize;
02534 iOutDataSize += iCurrSize;
02535 spCurrBuffNodeData->spDest = spRtxDest;
02536 spCurrBuffNodeData->iNumTxs++;
02537 spCurrBuffNodeData->eMarkedForRtx = NO_RTX;
02538
02539
02540
02541 spSctpTrace[uiNumChunks].eType = SCTP_CHUNK_DATA;
02542 spSctpTrace[uiNumChunks].uiTsn = spCurrChunk->uiTsn;
02543 spSctpTrace[uiNumChunks].usStreamId = spCurrChunk->usStreamId;
02544 spSctpTrace[uiNumChunks].usStreamSeqNum
02545 = spCurrChunk->usStreamSeqNum;
02546 uiNumChunks++;
02547
02548
02549
02550 spCurrBuffNodeData->spDest->iOutstandingBytes
02551 += spCurrChunk->sHdr.usLength;
02552 uiPeerRwnd -= spCurrChunk->sHdr.usLength;
02553 DBG_PL(RtxMarkedChunks, "spDest->iOutstandingBytes=%d"),
02554 spCurrBuffNodeData->spDest->iOutstandingBytes DBG_PR;
02555
02556 DBG_PL(RtxMarkedChunks, "TSN=%d"), spCurrChunk->uiTsn DBG_PR;
02557 }
02558 else if(spCurrBuffNodeData->eAdvancedAcked == TRUE)
02559 {
02560 if(spCurrBuffNodeData->spDest->spFirstOutstanding
02561 == spCurrBuffNodeData)
02562 {
02563
02564
02565
02566
02567
02568
02569
02570 if(spCurrBuffNodeData->spDest->iOutstandingBytes > 0)
02571 StartT3RtxTimer(spCurrBuffNodeData->spDest);
02572 else
02573 StopT3RtxTimer(spCurrBuffNodeData->spDest);
02574 }
02575 }
02576 }
02577
02578
02579
02580 if(iOutDataSize > 0)
02581 {
02582 SendPacket(ucpOutData, iOutDataSize, spRtxDest);
02583 if(spRtxDest->eRtxTimerIsRunning == FALSE)
02584 StartT3RtxTimer(spRtxDest);
02585 iNumPacketsSent++;
02586 iOutDataSize = 0;
02587 ucpCurrOutData = ucpOutData;
02588 memset(ucpOutData, 0, uiMaxPayloadSize);
02589
02590 spRtxDest->opCwndDegradeTimer->resched(spRtxDest->dRto);
02591
02592
02593
02594
02595
02596 if(eUseMaxBurst == MAX_BURST_USAGE_ON)
02597 if( (eApplyMaxBurst == TRUE) && (uiBurstLength++ >= MAX_BURST) )
02598 {
02599
02600
02601 eApplyMaxBurst = FALSE;
02602 break;
02603 }
02604 }
02605 }
02606
02607
02608
02609
02610 for(spCurrBuffNode = sSendBuffer.spHead;
02611 spCurrBuffNode != NULL;
02612 spCurrBuffNode = spCurrBuffNode->spNext)
02613 {
02614 spCurrBuffNodeData = (SctpSendBufferNode_S *) spCurrBuffNode->vpData;
02615
02616 if(spCurrBuffNodeData->eMarkedForRtx != NO_RTX)
02617 {
02618 spCurrChunk = spCurrBuffNodeData->spChunk;
02619 spCurrBuffNodeData->spDest->iOutstandingBytes
02620 += spCurrChunk->sHdr.usLength;
02621 }
02622 }
02623
02624
02625
02626
02627
02628
02629 eMarkedChunksPending = AnyMarkedChunks();
02630
02631 DBG_X(RtxMarkedChunks);
02632 }
02633
02634
02635
02636 Boolean_E SctpAgent::UpdateHighestTsn(u_int uiTsn)
02637 {
02638 DBG_I(UpdateHighestTsn);
02639
02640 if(uiTsn > uiHighestRecvTsn)
02641 {
02642 uiHighestRecvTsn = uiTsn;
02643 DBG_PL(UpdateHighestTsn, "returning TRUE") DBG_PR;
02644 DBG_X(UpdateHighestTsn);
02645 return TRUE;
02646 }
02647 else
02648 {
02649 DBG_PL(UpdateHighestTsn, "returning FALSE") DBG_PR;
02650 DBG_X(UpdateHighestTsn);
02651 return FALSE;
02652 }
02653 }
02654
02655
02656
02657 Boolean_E SctpAgent::IsDuplicateChunk(u_int uiTsn)
02658 {
02659 DBG_I(IsDuplicateChunk);
02660
02661 Node_S *spCurrNode = NULL;
02662
02663
02664
02665 if(uiTsn <= uiCumAck)
02666 {
02667 DBG_PL(IsDuplicateChunk, "returning TRUE") DBG_PR;
02668 DBG_X(IsDuplicateChunk);
02669 return TRUE;
02670 }
02671 if( !((uiCumAck < uiTsn) && (uiTsn <= uiHighestRecvTsn)) )
02672 {
02673 DBG_PL(IsDuplicateChunk, "returning FALSE") DBG_PR;
02674 DBG_X(IsDuplicateChunk);
02675 return FALSE;
02676 }
02677
02678
02679
02680 if(sRecvTsnBlockList.uiLength == 0)
02681 {
02682 DBG_PL(IsDuplicateChunk, "returning FALSE") DBG_PR;
02683 DBG_X(IsDuplicateChunk);
02684 return FALSE;
02685 }
02686
02687
02688
02689
02690 for(spCurrNode = sRecvTsnBlockList.spHead;
02691 spCurrNode != NULL;
02692 spCurrNode = spCurrNode->spNext)
02693 {
02694 if(((SctpRecvTsnBlock_S *)spCurrNode->vpData)->uiStartTsn <= uiTsn &&
02695 uiTsn <= ((SctpRecvTsnBlock_S *)spCurrNode->vpData)->uiEndTsn )
02696 {
02697 DBG_PL(IsDuplicateChunk, "returning TRUE") DBG_PR;
02698 DBG_X(IsDuplicateChunk);
02699 return TRUE;
02700 }
02701
02702
02703
02704
02705 if( ((SctpRecvTsnBlock_S *)spCurrNode->vpData)->uiEndTsn > uiTsn )
02706 {
02707 DBG_PL(IsDuplicateChunk, "returning FALSE") DBG_PR;
02708 DBG_X(IsDuplicateChunk);
02709 return FALSE;
02710 }
02711 }
02712
02713 DBG_PL(IsDuplicateChunk, "returning FALSE") DBG_PR;
02714 DBG_X(IsDuplicateChunk);
02715 return FALSE;
02716 }
02717
02718
02719
02720
02721 void SctpAgent::InsertDuplicateTsn(u_int uiTsn)
02722 {
02723 DBG_I(InsertDuplicateTsn);
02724 Node_S *spCurrNode = NULL;
02725 Node_S *spPrevNode = NULL;
02726 Node_S *spNewNode = NULL;
02727 u_int uiCurrTsn;
02728
02729
02730
02731 for(spPrevNode = NULL, spCurrNode = sDupTsnList.spHead;
02732 spCurrNode != NULL;
02733 spPrevNode = spCurrNode, spCurrNode = spCurrNode->spNext)
02734 {
02735 uiCurrTsn = ((SctpDupTsn_S *) spCurrNode->vpData)->uiTsn;
02736 if(uiTsn <= uiCurrTsn)
02737 break;
02738 }
02739
02740
02741
02742
02743
02744 if( (spCurrNode == NULL) || (uiTsn != uiCurrTsn) )
02745 {
02746 spNewNode = new Node_S;
02747 spNewNode->eType = NODE_TYPE_DUP_TSN;
02748 spNewNode->vpData = new SctpDupTsn_S;
02749 ((SctpDupTsn_S *) spNewNode->vpData)->uiTsn = uiTsn;
02750 InsertNode(&sDupTsnList, spPrevNode, spNewNode, spCurrNode);
02751 }
02752
02753 DBG_X(InsertDuplicateTsn);
02754 }
02755
02756
02757
02758
02759 void SctpAgent::UpdateCumAck()
02760 {
02761 DBG_I(UpdateCumAck);
02762 Node_S *spCurrNode = NULL;
02763
02764 if(sRecvTsnBlockList.uiLength == 0)
02765 {
02766 DBG_X(UpdateCumAck);
02767 return;
02768 }
02769
02770 for(spCurrNode = sRecvTsnBlockList.spHead;
02771 spCurrNode != NULL;
02772 spCurrNode = spCurrNode->spNext)
02773 {
02774 if( uiCumAck+1 == ((SctpRecvTsnBlock_S *)spCurrNode->vpData)->uiStartTsn )
02775 {
02776 uiCumAck = ((SctpRecvTsnBlock_S *)spCurrNode->vpData)->uiEndTsn;
02777 }
02778 else
02779 {
02780 DBG_X(UpdateCumAck);
02781 return;
02782 }
02783 }
02784
02785 DBG_X(UpdateCumAck);
02786 }
02787
02792 void SctpAgent::UpdateRecvTsnBlocks(u_int uiTsn)
02793 {
02794 DBG_I(UpdateRecvTsnBlocks);
02795
02796 u_int uiLow;
02797 u_int uiHigh;
02798 u_int uiGapSize;
02799
02800 Node_S *spCurrNode = NULL;
02801 Node_S *spPrevNode = NULL;
02802 Node_S *spNewNode = NULL;
02803
02804 uiLow = uiCumAck + 1;
02805
02806 for(spCurrNode = sRecvTsnBlockList.spHead;
02807 spCurrNode != NULL;
02808 spPrevNode = spCurrNode, spCurrNode = spCurrNode->spNext)
02809 {
02810 uiHigh = ((SctpRecvTsnBlock_S *)spCurrNode->vpData)->uiStartTsn - 1;
02811
02812
02813
02814 if( uiLow <= uiTsn && uiTsn <= uiHigh )
02815 {
02816 uiGapSize = uiHigh - uiLow + 1;
02817
02818 if(uiGapSize > 1)
02819 {
02820
02821
02822 if(uiTsn == uiHigh)
02823 {
02824 ((SctpRecvTsnBlock_S *)spCurrNode->vpData)->uiStartTsn
02825 = uiTsn;
02826
02827 UpdateCumAck();
02828 DBG_X(UpdateRecvTsnBlocks);
02829 return;
02830 }
02831
02832
02833
02834 else if(uiTsn == uiLow)
02835 {
02836 if(uiTsn == uiCumAck+1)
02837 {
02838 uiCumAck++;
02839 UpdateCumAck();
02840 DBG_X(UpdateRecvTsnBlocks);
02841 return;
02842 }
02843 else
02844 {
02845 ((SctpRecvTsnBlock_S *)spPrevNode->vpData)->uiEndTsn
02846 = uiTsn;
02847
02848 UpdateCumAck();
02849 DBG_X(UpdateRecvTsnBlocks);
02850 return;
02851 }
02852 }
02853
02854
02855
02856 else
02857 {
02858 spNewNode = new Node_S;
02859 spNewNode->eType = NODE_TYPE_RECV_TSN_BLOCK;
02860 spNewNode->vpData = new SctpRecvTsnBlock_S;
02861 ((SctpRecvTsnBlock_S *)spNewNode->vpData)->uiStartTsn = uiTsn;
02862 ((SctpRecvTsnBlock_S *)spNewNode->vpData)->uiEndTsn = uiTsn;
02863
02864 InsertNode(&sRecvTsnBlockList,
02865 spPrevNode, spNewNode, spCurrNode);
02866
02867 DBG_X(UpdateRecvTsnBlocks);
02868 return;
02869 }
02870 }
02871
02872 else
02873 {
02874 if(uiLow == uiCumAck+1)
02875 {
02876
02877
02878 uiCumAck
02879 = ((SctpRecvTsnBlock_S *)spCurrNode->vpData)->uiEndTsn;
02880
02881 DeleteNode(&sRecvTsnBlockList, spCurrNode);
02882 spCurrNode = NULL;
02883 UpdateCumAck();
02884 DBG_X(UpdateRecvTsnBlocks);
02885 return;
02886 }
02887 else
02888 {
02889 ((SctpRecvTsnBlock_S *)spPrevNode->vpData)->uiEndTsn
02890 = ((SctpRecvTsnBlock_S *)spCurrNode->vpData)->uiEndTsn;
02891
02892 DeleteNode(&sRecvTsnBlockList, spCurrNode);
02893 spCurrNode = NULL;
02894 UpdateCumAck();
02895 DBG_X(UpdateRecvTsnBlocks);
02896 return;
02897 }
02898 }
02899 }
02900
02901
02902
02903
02904 else
02905 {
02906 uiLow = ((SctpRecvTsnBlock_S *)spCurrNode->vpData)->uiEndTsn + 1;
02907 }
02908 }
02909
02910
02911
02912
02913 if(uiTsn == uiLow)
02914 {
02915 if(uiTsn == uiCumAck+1)
02916 {
02917 uiCumAck = uiTsn;
02918 UpdateCumAck();
02919 DBG_X(UpdateRecvTsnBlocks);
02920 return;
02921 }
02922
02923
02924
02925 if(spPrevNode != NULL)
02926 {
02927 ((SctpRecvTsnBlock_S *) spPrevNode->vpData)->uiEndTsn++;
02928 }
02929 DBG_X(UpdateRecvTsnBlocks);
02930 return;
02931 }
02932
02933
02934
02935 else
02936 {
02937 spNewNode = new Node_S;
02938 spNewNode->eType = NODE_TYPE_RECV_TSN_BLOCK;
02939 spNewNode->vpData = new SctpRecvTsnBlock_S;
02940 ((SctpRecvTsnBlock_S *) spNewNode->vpData)->uiStartTsn = uiTsn;
02941 ((SctpRecvTsnBlock_S *) spNewNode->vpData)->uiEndTsn = uiTsn;
02942 InsertNode(&sRecvTsnBlockList, spPrevNode, spNewNode, spCurrNode);
02943 DBG_X(UpdateRecvTsnBlocks);
02944 return;
02945 }
02946 }
02947
02948
02949
02950
02951 void SctpAgent::PassToUpperLayer(SctpDataChunkHdr_S *spDataChunkHdr)
02952 {
02953 DBG_I(PassToUpperLayer);
02954 DBG_PL(PassToUpperLayer, "tsn=%d"), spDataChunkHdr->uiTsn DBG_PR;
02955
02956
02957
02958
02959
02960 uiMyRwnd += spDataChunkHdr->sHdr.usLength;
02961
02962 DBG_PL(PassToUpperLayer, "uiMyRwnd=%d"), uiMyRwnd DBG_PR;
02963 DBG_X(PassToUpperLayer);
02964 }
02965
02966 void SctpAgent::InsertInStreamBuffer(List_S *spBufferedChunkList,
02967 SctpDataChunkHdr_S *spChunk)
02968 {
02969 DBG_I(InsertInStreamBuffer);
02970
02971 Node_S *spPrevNode;
02972 Node_S *spCurrNode;
02973 Node_S *spNewNode;
02974 SctpStreamBufferNode_S *spCurrNodeData;
02975 SctpStreamBufferNode_S *spNewNodeData;
02976 u_short usCurrStreamSeqNum;
02977
02978 spPrevNode = NULL;
02979 spCurrNode = spBufferedChunkList->spHead;
02980
02981
02982
02983 for(spPrevNode = NULL, spCurrNode = spBufferedChunkList->spHead;
02984 spCurrNode != NULL;
02985 spPrevNode = spCurrNode, spCurrNode = spCurrNode->spNext)
02986 {
02987 spCurrNodeData = (SctpStreamBufferNode_S *) spCurrNode->vpData;
02988 usCurrStreamSeqNum = spCurrNodeData->spChunk->usStreamSeqNum;
02989
02990
02991
02992 if(spChunk->usStreamSeqNum <= usCurrStreamSeqNum)
02993 break;
02994 }
02995
02996
02997
02998
02999 if( (spCurrNode == NULL) || (usCurrStreamSeqNum != spChunk->usStreamSeqNum) )
03000 {
03001 spNewNode = new Node_S;
03002 spNewNode->eType = NODE_TYPE_STREAM_BUFFER;
03003 spNewNode->vpData = new SctpStreamBufferNode_S;
03004 spNewNodeData = (SctpStreamBufferNode_S *) spNewNode->vpData;
03005
03006
03007
03008
03009
03010 spNewNodeData->spChunk
03011 = (SctpDataChunkHdr_S *) new u_char[spChunk->sHdr.usLength];
03012 memcpy(spNewNodeData->spChunk, spChunk, spChunk->sHdr.usLength);
03013
03014 DBG_PL(InsertInStreamBuffer, "vpData=%p spChunk=%p"),
03015 spNewNodeData, spNewNodeData->spChunk DBG_PR;
03016
03017 InsertNode(spBufferedChunkList, spPrevNode, spNewNode, spCurrNode);
03018 }
03019
03020 DBG_X(InsertInStreamBuffer);
03021 }
03022
03023
03024
03025
03026 void SctpAgent::PassToStream(SctpDataChunkHdr_S *spChunk)
03027 {
03028 DBG_I(PassToStream);
03029 DBG_PL(PassToStream, "uiMyRwnd=%d"), uiMyRwnd DBG_PR;
03030
03031 SctpInStream_S *spStream = &(spInStreams[spChunk->usStreamId]);
03032
03033 if(spChunk->sHdr.ucFlags & SCTP_DATA_FLAG_UNORDERED)
03034 {
03035 PassToUpperLayer(spChunk);
03036 }
03037 else
03038 {
03039
03040
03041
03042
03043
03044 DBG_PL(PassToStream, "streamId=%d streamSeqNum=%d"),
03045 spChunk->usStreamId, spChunk->usStreamSeqNum DBG_PR;
03046
03047 InsertInStreamBuffer( &(spStream->sBufferedChunkList), spChunk);
03048 }
03049
03050 DBG_PL(PassToStream, "uiMyRwnd=%d"), uiMyRwnd DBG_PR;
03051 DBG_X(PassToStream);
03052 }
03053
03054 void SctpAgent::UpdateAllStreams()
03055 {
03056 DBG_I(UpdateAllStreams);
03057 DBG_PL(UpdateAllStreams, "uiMyRwnd=%d"), uiMyRwnd DBG_PR;
03058
03059 Node_S *spCurrNode = NULL;
03060 Node_S *spDeleteNode = NULL;
03061 SctpDataChunkHdr_S *spBufferedChunk = NULL;
03062 int i;
03063
03064 for(i = 0; i < iNumInStreams; i++)
03065 {
03066 DBG_PL(UpdateAllStreams, "examining stream %d"), i DBG_PR;
03067 SctpInStream_S *spStream = &(spInStreams[i]);
03068
03069
03070
03071
03072 spCurrNode = spStream->sBufferedChunkList.spHead;
03073 while(spCurrNode != NULL)
03074 {
03075 spBufferedChunk
03076 = ((SctpStreamBufferNode_S *)spCurrNode->vpData)->spChunk;
03077
03078
03079
03080
03081
03082
03083
03084 if((spStream->eMode == SCTP_STREAM_UNRELIABLE) &&
03085 (spBufferedChunk->uiTsn <= uiCumAck) )
03086 {
03087 spStream->usNextStreamSeqNum = spBufferedChunk->usStreamSeqNum+1;
03088 PassToUpperLayer(spBufferedChunk);
03089 spDeleteNode = spCurrNode;
03090 spCurrNode = spCurrNode->spNext;
03091 DeleteNode( &(spStream->sBufferedChunkList), spDeleteNode );
03092 spDeleteNode = NULL;
03093 }
03094
03095
03096
03097 else if(spBufferedChunk->usStreamSeqNum==spStream->usNextStreamSeqNum)
03098 {
03099 spStream->usNextStreamSeqNum++;
03100 PassToUpperLayer(spBufferedChunk);
03101 spDeleteNode = spCurrNode;
03102 spCurrNode = spCurrNode->spNext;
03103 DeleteNode( &(spStream->sBufferedChunkList), spDeleteNode );
03104 spDeleteNode = NULL;
03105 }
03106
03107
03108
03109 else
03110 break;
03111 }
03112 }
03113
03114 DBG_PL(UpdateAllStreams, "uiMyRwnd=%d"), uiMyRwnd DBG_PR;
03115 DBG_X(UpdateAllStreams);
03116 }
03117
03118 void SctpAgent::ProcessInitChunk(u_char *ucpInitChunk)
03119 {
03120 DBG_I(ProcessInitChunk);
03121
03122 SctpInitChunk_S *spInitChunk = (SctpInitChunk_S *) ucpInitChunk;
03123 SctpUnrelStreamPair_S *spUnrelStreamPair
03124 = (SctpUnrelStreamPair_S *) (ucpInitChunk + sizeof(SctpInitChunk_S));
03125 int i = 0;
03126
03127 uiPeerRwnd = spInitChunk->uiArwnd;
03128 iNumInStreams = spInitChunk->usNumOutboundStreams;
03129 spInStreams = new SctpInStream_S[iNumInStreams];
03130 memset(spInStreams, 0, (iNumInStreams * sizeof(SctpInStream_S)) );
03131
03132 if(spInitChunk->sHdr.usLength > sizeof(SctpInitChunk_S) )
03133 {
03134 for(i = spUnrelStreamPair->usStart; i <= spUnrelStreamPair->usEnd; i++)
03135 {
03136 DBG_PL(ProcessInitChunk, "setting inStream %d to UNRELIABLE"), i DBG_PR;
03137 spInStreams[i].eMode = SCTP_STREAM_UNRELIABLE;
03138 }
03139 }
03140
03141 for(; i < iNumInStreams; i++)
03142 {
03143 DBG_PL(ProcessInitChunk, "setting inStream %d to RELIABLE"), i DBG_PR;
03144 spInStreams[i].eMode = SCTP_STREAM_RELIABLE;
03145 }
03146
03147 DBG_X(ProcessInitChunk);
03148 }
03149
03150 void SctpAgent::ProcessInitAckChunk(u_char *ucpInitAckChunk)
03151 {
03152 DBG_I(ProcessInitAckChunk);
03153
03154 SctpInitAckChunk_S *spInitAckChunk = (SctpInitAckChunk_S *) ucpInitAckChunk;
03155 SctpUnrelStreamPair_S *spUnrelStreamPair
03156 = (SctpUnrelStreamPair_S *) (ucpInitAckChunk + sizeof(SctpInitAckChunk_S) );
03157 int i = 0;
03158
03159 opT1InitTimer->force_cancel();
03160 uiPeerRwnd = spInitAckChunk->uiArwnd;
03161 iNumInStreams = spInitAckChunk->usNumOutboundStreams;
03162 spInStreams = new SctpInStream_S[iNumInStreams];
03163 memset(spInStreams, 0, (iNumInStreams * sizeof(SctpInStream_S)) );
03164
03165 if(spInitAckChunk->sHdr.usLength > sizeof(SctpInitAckChunk_S) )
03166 {
03167 for(i = spUnrelStreamPair->usStart; i <= spUnrelStreamPair->usEnd; i++)
03168 {
03169 DBG_PL(ProcessInitAckChunk, "setting inStream %d to UNRELIABLE"),
03170 i DBG_PR;
03171 spInStreams[i].eMode = SCTP_STREAM_UNRELIABLE;
03172 }
03173 }
03174
03175 for(; i < iNumInStreams; i++)
03176 {
03177 DBG_PL(ProcessInitAckChunk, "setting inStream %d to RELIABLE"), i DBG_PR;
03178 spInStreams[i].eMode = SCTP_STREAM_RELIABLE;
03179 }
03180
03181 DBG_X(ProcessInitAckChunk);
03182 }
03183
03184 void SctpAgent::ProcessCookieEchoChunk(SctpCookieEchoChunk_S *spCookieEchoChunk)
03185 {
03186
03187 }
03188
03189 void SctpAgent::ProcessCookieAckChunk(SctpCookieAckChunk_S *spCookieAckChunk)
03190 {
03191 opT1CookieTimer->force_cancel();
03192 }
03193
03194
03195
03196 void SctpAgent::ProcessDataChunk(SctpDataChunkHdr_S *spChunk)
03197 {
03198 DBG_I(ProcessDataChunk);
03199
03200
03201
03202
03203 if(spChunk->sHdr.usLength <= uiMyRwnd)
03204 {
03205 if((UpdateHighestTsn(spChunk->uiTsn) != TRUE) &&
03206 (IsDuplicateChunk(spChunk->uiTsn) == TRUE) )
03207 {
03208 InsertDuplicateTsn(spChunk->uiTsn);
03209 eSackChunkNeeded = TRUE;
03210 DBG_PL(ProcessDataChunk, "duplicate tsn=%d"), spChunk->uiTsn DBG_PR;
03211 }
03212 else
03213 {
03214
03215
03216
03217 uiMyRwnd -= spChunk->sHdr.usLength;
03218 UpdateRecvTsnBlocks(spChunk->uiTsn);
03219 PassToStream(spChunk);
03220 UpdateAllStreams();
03221 DBG_PL(ProcessDataChunk, "uiMyRwnd=%d"), uiMyRwnd DBG_PR;
03222 }
03223 }
03224 else
03225 {
03226
03227
03228 eSackChunkNeeded = FALSE;
03229 DBG_PL(ProcessDataChunk, "rwnd full... dropping tsn=%d"),
03230 spChunk->uiTsn DBG_PR;
03231 }
03232
03233 DBG_X(ProcessDataChunk);
03234 }
03235
03236
03237
03238 Boolean_E SctpAgent::ProcessGapAckBlocks(u_char *ucpSackChunk,
03239 Boolean_E eNewCumAck)
03240 {
03241 DBG_I(ProcessGapAckBlocks);
03242
03243 Boolean_E eFastRtxNeeded = FALSE;
03244 u_int uiHighestTsnSacked = uiHighestTsnNewlyAcked;
03245 u_int uiStartTsn;
03246 u_int uiEndTsn;
03247 Node_S *spCurrNode = NULL;
03248 SctpSendBufferNode_S *spCurrNodeData = NULL;
03249 Node_S *spCurrDestNode = NULL;
03250 SctpDest_S *spCurrDestNodeData = NULL;
03251
03252 SctpSackChunk_S *spSackChunk = (SctpSackChunk_S *) ucpSackChunk;
03253
03254 u_short usNumGapAcksProcessed = 0;
03255 SctpGapAckBlock_S *spCurrGapAck
03256 = (SctpGapAckBlock_S *) (ucpSackChunk + sizeof(SctpSackChunk_S));
03257
03258 DBG_PL(ProcessGapAckBlocks,"CumAck=%d"), spSackChunk->uiCumAck DBG_PR;
03259
03260 if(sSendBuffer.spHead == NULL)
03261 {
03262
03263
03264
03265 }
03266
03267 else
03268 {
03269
03270
03271
03272 for(spCurrDestNode = sDestList.spHead;
03273 spCurrDestNode != NULL;
03274 spCurrDestNode = spCurrDestNode->spNext)
03275 {
03276 spCurrDestNodeData = (SctpDest_S *) spCurrDestNode->vpData;
03277 spCurrDestNodeData->spFirstOutstanding = NULL;
03278 }
03279
03280 for(spCurrNode = sSendBuffer.spHead;
03281 (spCurrNode != NULL) &&
03282 (usNumGapAcksProcessed != spSackChunk->usNumGapAckBlocks);
03283 spCurrNode = spCurrNode->spNext)
03284 {
03285 spCurrNodeData = (SctpSendBufferNode_S *) spCurrNode->vpData;
03286
03287
03288
03289 if(spCurrNodeData->spDest->spFirstOutstanding == NULL &&
03290 spCurrNodeData->eGapAcked == FALSE &&
03291 spCurrNodeData->eAdvancedAcked == FALSE)
03292 {
03293
03294
03295 spCurrNodeData->spDest->spFirstOutstanding = spCurrNodeData;
03296 }
03297
03298 DBG_PL(ProcessGapAckBlocks, "--> rtx list chunk begin") DBG_PR;
03299
03300 DBG_PL(ProcessGapAckBlocks, " TSN=%d"),
03301 spCurrNodeData->spChunk->uiTsn
03302 DBG_PR;
03303
03304 DBG_PL(ProcessGapAckBlocks, " %s=%s %s=%s"),
03305 "eGapAcked",
03306 spCurrNodeData->eGapAcked ? "TRUE" : "FALSE",
03307 "eAddedToPartialBytesAcked",
03308 spCurrNodeData->eAddedToPartialBytesAcked ? "TRUE" : "FALSE"
03309 DBG_PR;
03310
03311 DBG_PL(ProcessGapAckBlocks, " NumMissingReports=%d NumTxs=%d"),
03312 spCurrNodeData->iNumMissingReports,
03313 spCurrNodeData->iNumTxs
03314 DBG_PR;
03315
03316 DBG_PL(ProcessGapAckBlocks, "<-- rtx list chunk end") DBG_PR;
03317
03318 DBG_PL(ProcessGapAckBlocks,"GapAckBlock StartOffset=%d EndOffset=%d"),
03319 spCurrGapAck->usStartOffset, spCurrGapAck->usEndOffset DBG_PR;
03320
03321 uiStartTsn = spSackChunk->uiCumAck + spCurrGapAck->usStartOffset;
03322 uiEndTsn = spSackChunk->uiCumAck + spCurrGapAck->usEndOffset;
03323
03324 DBG_PL(ProcessGapAckBlocks, "GapAckBlock StartTsn=%d EndTsn=%d"),
03325 uiStartTsn, uiEndTsn DBG_PR;
03326
03327 if(spCurrNodeData->spChunk->uiTsn < uiStartTsn)
03328 {
03329
03330
03331
03332
03333
03334
03335
03336 if(spCurrNodeData->eGapAcked == TRUE)
03337 {
03338 DBG_PL(ProcessGapAckBlocks,
03339 "out of order SACK? setting TSN=%d eGapAcked=FALSE"),
03340 spCurrNodeData->spChunk->uiTsn DBG_PR;
03341 spCurrNodeData->eGapAcked = FALSE;
03342 spCurrNodeData->spDest->iOutstandingBytes
03343 += spCurrNodeData->spChunk->sHdr.usLength;
03344
03345
03346
03347
03348
03349
03350
03351
03352 }
03353 }
03354 else if((uiStartTsn <= spCurrNodeData->spChunk->uiTsn) &&
03355 (spCurrNodeData->spChunk->uiTsn <= uiEndTsn) )
03356 {
03357
03358
03359 DBG_PL(ProcessGapAckBlocks, "gap ack acks this chunk: %s%s"),
03360 "eGapAcked=",
03361 spCurrNodeData->eGapAcked ? "TRUE" : "FALSE"
03362 DBG_PR;
03363
03364
03365
03366
03367
03368
03369 if(uiHighestTsnSacked < spCurrNodeData->spChunk->uiTsn)
03370 uiHighestTsnSacked = spCurrNodeData->spChunk->uiTsn;
03371
03372 if(spCurrNodeData->eGapAcked == FALSE)
03373 {
03374 DBG_PL(ProcessGapAckBlocks, "setting eGapAcked=TRUE") DBG_PR;
03375 spCurrNodeData->eGapAcked = TRUE;
03376
03377
03378
03379
03380 if(uiHighestTsnNewlyAcked < spCurrNodeData->spChunk->uiTsn)
03381 uiHighestTsnNewlyAcked = spCurrNodeData->spChunk->uiTsn;
03382
03383 if(spCurrNodeData->eAdvancedAcked == FALSE)
03384 {
03385 spCurrNodeData->spDest->iNumNewlyAckedBytes
03386 += spCurrNodeData->spChunk->sHdr.usLength;
03387 }
03388
03389
03390
03391
03392
03393 if(( spCurrNodeData->spDest->iCwnd
03394 > spCurrNodeData->spDest->iSsthresh) &&
03395 eNewCumAck == TRUE &&
03396 spCurrNodeData->eAddedToPartialBytesAcked == FALSE)
03397 {
03398 DBG_PL(ProcessGapAckBlocks,
03399 "setting eAddedToPartiallyBytesAcked=TRUE") DBG_PR;
03400
03401 spCurrNodeData->eAddedToPartialBytesAcked = TRUE;
03402
03403 spCurrNodeData->spDest->iPartialBytesAcked
03404 += spCurrNodeData->spChunk->sHdr.usLength;
03405 }
03406
03407
03408
03409
03410
03411
03412
03413
03414 if(spCurrNodeData->spDest->eRtoPending == TRUE &&
03415 spCurrNodeData->dTxTimestamp > 0 &&
03416 spCurrNodeData->iNumTxs == 1 &&
03417 spCurrNodeData->eAdvancedAcked == FALSE)
03418 {
03419
03420
03421
03422
03423
03424
03425
03426 if(spCurrNodeData->eMarkedForRtx != TIMEOUT_RTX)
03427 RttUpdate(spCurrNodeData->dTxTimestamp,
03428 spCurrNodeData->spDest);
03429 spCurrNodeData->spDest->eRtoPending = FALSE;
03430 }
03431
03432
03433
03434
03435
03436
03437
03438
03439 if(spCurrNodeData->spDest->spFirstOutstanding
03440 == spCurrNodeData)
03441
03442 {
03443 if(spCurrNodeData->spDest->eRtxTimerIsRunning == TRUE)
03444 StopT3RtxTimer(spCurrNodeData->spDest);
03445 }
03446
03447 iAssocErrorCount = 0;
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465 if(spCurrNodeData->spDest->iErrorCount != 0 &&
03466 spCurrNodeData->eMarkedForRtx != TIMEOUT_RTX)
03467 {
03468 DBG_PL(ProcessGapAckBlocks,
03469 "clearing error counter for %p with tsn=%lu"),
03470 spCurrNodeData->spDest,
03471 spCurrNodeData->spChunk->uiTsn DBG_PR;
03472
03473 spCurrNodeData->spDest->iErrorCount = 0;
03474 tiErrorCount++;
03475 spCurrNodeData->spDest->eStatus = SCTP_DEST_STATUS_ACTIVE;
03476 if(spCurrNodeData->spDest == spPrimaryDest &&
03477 spNewTxDest != spPrimaryDest)
03478 {
03479 DBG_PL(ProcessGapAckBlocks,
03480 "primary recovered... "
03481 "migrating back from %p to %p"),
03482 spNewTxDest, spPrimaryDest DBG_PR;
03483 spNewTxDest = spPrimaryDest;
03484 }
03485 }
03486
03487 spCurrNodeData->eMarkedForRtx = NO_RTX;
03488 }
03489 }
03490 else if(spCurrNodeData->spChunk->uiTsn > uiEndTsn)
03491 {
03492
03493
03494
03495 usNumGapAcksProcessed++;
03496
03497
03498
03499 if(usNumGapAcksProcessed != spSackChunk->usNumGapAckBlocks)
03500 {
03501 DBG_PL(ProcessGapAckBlocks, "jump to next gap ack block")
03502 DBG_PR;
03503
03504 spCurrGapAck
03505 = ((SctpGapAckBlock_S *)
03506 (ucpSackChunk + sizeof(SctpSackChunk_S)
03507 + (usNumGapAcksProcessed * sizeof(SctpGapAckBlock_S))));
03508 }
03509
03510
03511
03512
03513
03514 if(spCurrNodeData->eGapAcked == TRUE)
03515 {
03516 DBG_PL(ProcessGapAckBlocks,
03517 "out of order SACK? setting TSN=%d eGapAcked=FALSE"),
03518 spCurrNodeData->spChunk->uiTsn DBG_PR;
03519 spCurrNodeData->eGapAcked = FALSE;
03520 spCurrNodeData->spDest->iOutstandingBytes
03521 += spCurrNodeData->spChunk->sHdr.usLength;
03522
03523
03524
03525
03526
03527
03528
03529
03530 }
03531 }
03532 }
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542 for(; spCurrNode != NULL; spCurrNode = spCurrNode->spNext)
03543 {
03544
03545
03546 spCurrNodeData = (SctpSendBufferNode_S *) spCurrNode->vpData;
03547
03548
03549
03550
03551
03552 if(spCurrNodeData->eGapAcked == TRUE)
03553 {
03554 DBG_PL(ProcessGapAckBlocks,
03555 "out of order SACK? setting TSN=%d eGapAcked=FALSE"),
03556 spCurrNodeData->spChunk->uiTsn DBG_PR;
03557 spCurrNodeData->eGapAcked = FALSE;
03558 spCurrNodeData->spDest->iOutstandingBytes
03559 += spCurrNodeData->spChunk->sHdr.usLength;
03560
03561
03562
03563
03564
03565
03566
03567 }
03568 }
03569
03570 DBG_PL(ProcessGapAckBlocks, "now incrementing missing reports...") DBG_PR;
03571 DBG_PL(ProcessGapAckBlocks, "uiHighestTsnNewlyAcked=%d"),
03572 uiHighestTsnNewlyAcked DBG_PR;
03573
03574 for(spCurrNode = sSendBuffer.spHead;
03575 spCurrNode != NULL;
03576 spCurrNode = spCurrNode->spNext)
03577 {
03578 spCurrNodeData = (SctpSendBufferNode_S *) spCurrNode->vpData;
03579
03580 DBG_PL(ProcessGapAckBlocks, "TSN=%d eGapAcked=%s"),
03581 spCurrNodeData->spChunk->uiTsn,
03582 spCurrNodeData->eGapAcked ? "TRUE" : "FALSE"
03583 DBG_PR;
03584
03585 if(spCurrNodeData->eGapAcked == FALSE)
03586 {
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599 if( (spCurrNodeData->spChunk->uiTsn < uiHighestTsnNewlyAcked) ||
03600 (eNewCumAck == TRUE &&
03601 uiHighestTsnNewlyAcked <= uiRecover &&
03602 spCurrNodeData->spChunk->uiTsn < uiHighestTsnSacked))
03603 {
03604 spCurrNodeData->iNumMissingReports++;
03605 DBG_PL(ProcessGapAckBlocks,
03606 "incrementing missing report for TSN=%d to %d"),
03607 spCurrNodeData->spChunk->uiTsn,
03608 spCurrNodeData->iNumMissingReports
03609 DBG_PR;
03610
03611 if(spCurrNodeData->iNumMissingReports >= iFastRtxTrigger &&
03612 spCurrNodeData->eIneligibleForFastRtx == FALSE &&
03613 spCurrNodeData->eAdvancedAcked == FALSE)
03614 {
03615 MarkChunkForRtx(spCurrNodeData, FAST_RTX);
03616 eFastRtxNeeded = TRUE;
03617 spCurrNodeData->eIneligibleForFastRtx = TRUE;
03618 DBG_PL(ProcessGapAckBlocks,
03619 "setting eFastRtxNeeded = TRUE") DBG_PR;
03620 }
03621 }
03622 }
03623 }
03624 }
03625
03626 if(eFastRtxNeeded == TRUE)
03627 tiFrCount++;
03628
03629 DBG_PL(ProcessGapAckBlocks, "eFastRtxNeeded=%s"),
03630 eFastRtxNeeded ? "TRUE" : "FALSE" DBG_PR;
03631 DBG_X(ProcessGapAckBlocks);
03632 return eFastRtxNeeded;
03633 }
03634
03635 void SctpAgent::ProcessSackChunk(u_char *ucpSackChunk)
03636 {
03637 DBG_I(ProcessSackChunk);
03638
03639 SctpSackChunk_S *spSackChunk = (SctpSackChunk_S *) ucpSackChunk;
03640
03641 DBG_PL(ProcessSackChunk, "cum=%d arwnd=%d #gapacks=%d #duptsns=%d"),
03642 spSackChunk->uiCumAck, spSackChunk->uiArwnd,
03643 spSackChunk->usNumGapAckBlocks, spSackChunk->usNumDupTsns
03644 DBG_PR;
03645
03646 Boolean_E eFastRtxNeeded = FALSE;
03647 Boolean_E eNewCumAck = FALSE;
03648 Node_S *spCurrDestNode = NULL;
03649 SctpDest_S *spCurrDestNodeData = NULL;
03650 u_int uiTotalOutstanding = 0;
03651 int i = 0;
03652
03653
03654
03655 for(spCurrDestNode = sDestList.spHead;
03656 spCurrDestNode != NULL;
03657 spCurrDestNode = spCurrDestNode->spNext)
03658 {
03659 spCurrDestNodeData = (SctpDest_S *) spCurrDestNode->vpData;
03660 spCurrDestNodeData->iNumNewlyAckedBytes = 0;
03661 spCurrDestNodeData->spFirstOutstanding = NULL;
03662 }
03663
03664 if(spSackChunk->uiCumAck < uiCumAckPoint)
03665 {
03666
03667
03668
03669 DBG_PL(ProcessSackChunk, "ignoring out of order sack!") DBG_PR;
03670 DBG_X(ProcessSackChunk);
03671 return;
03672 }
03673 else if(spSackChunk->uiCumAck > uiCumAckPoint)
03674 {
03675 eNewCumAck = TRUE;
03676 SendBufferDequeueUpTo(spSackChunk->uiCumAck);
03677 uiCumAckPoint = spSackChunk->uiCumAck;
03678 }
03679
03680 if(spSackChunk->usNumGapAckBlocks != 0)
03681 {
03682 eFastRtxNeeded = ProcessGapAckBlocks(ucpSackChunk, eNewCumAck);
03683 }
03684
03685 for(spCurrDestNode = sDestList.spHead;
03686 spCurrDestNode != NULL;
03687 spCurrDestNode = spCurrDestNode->spNext)
03688 {
03689 spCurrDestNodeData = (SctpDest_S *) spCurrDestNode->vpData;
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700 if(eNewCumAck == TRUE &&
03701 spCurrDestNodeData->iNumNewlyAckedBytes > 0 &&
03702 spSackChunk->uiCumAck >= uiRecover)
03703 {
03704 AdjustCwnd(spCurrDestNodeData);
03705 }
03706
03707
03708
03709
03710 if(spCurrDestNodeData->iNumNewlyAckedBytes <=
03711 spCurrDestNodeData->iOutstandingBytes)
03712 {
03713 spCurrDestNodeData->iOutstandingBytes
03714 -= spCurrDestNodeData->iNumNewlyAckedBytes;
03715 }
03716 else
03717 spCurrDestNodeData->iOutstandingBytes = 0;
03718
03719 DBG_PL(ProcessSackChunk,"Dest #%d (%d:%d) (%p): outstanding=%d, cwnd=%d"),
03720 ++i, spCurrDestNodeData->iNsAddr, spCurrDestNodeData->iNsPort,
03721 spCurrDestNodeData, spCurrDestNodeData->iOutstandingBytes,
03722 spCurrDestNodeData->iCwnd DBG_PR;
03723
03724 if(spCurrDestNodeData->iOutstandingBytes == 0)
03725 {
03726
03727
03728 spCurrDestNodeData->iPartialBytesAcked = 0;
03729
03730
03731
03732 if(spCurrDestNodeData->eRtxTimerIsRunning == TRUE)
03733 {
03734 DBG_PL(ProcessSackChunk, "Dest #%d (%p): stopping timer"),
03735 i, spCurrDestNodeData DBG_PR;
03736 StopT3RtxTimer(spCurrDestNodeData);
03737 }
03738 }
03739
03740
03741
03742
03743
03744 if(spCurrDestNodeData->iOutstandingBytes > 0 &&
03745 spCurrDestNodeData->eRtxTimerIsRunning == FALSE)
03746 {
03747 StartT3RtxTimer(spCurrDestNodeData);
03748 }
03749 }
03750
03751 DBG_F(ProcessSackChunk, DumpSendBuffer());
03752
03753 AdvancePeerAckPoint();
03754
03755 if(eFastRtxNeeded == TRUE)
03756 FastRtx();
03757
03758
03759
03760
03761 else if( (eMarkedChunksPending = AnyMarkedChunks()) == TRUE)
03762 {
03763
03764
03765
03766
03767
03768 RtxMarkedChunks(RTX_LIMIT_CWND);
03769 }
03770
03771
03772
03773
03774
03775
03776
03777 uiTotalOutstanding = TotalOutstanding();
03778 if(uiTotalOutstanding <= spSackChunk->uiArwnd)
03779 uiPeerRwnd = (spSackChunk->uiArwnd - uiTotalOutstanding);
03780 else
03781 uiPeerRwnd = 0;
03782
03783 DBG_PL(ProcessSackChunk, "uiPeerRwnd=%d, uiArwnd=%d"), uiPeerRwnd,
03784 spSackChunk->uiArwnd DBG_PR;
03785 DBG_X(ProcessSackChunk);
03786 }
03787
03788 void SctpAgent::ProcessForwardTsnChunk(SctpForwardTsnChunk_S *spForwardTsnChunk)
03789 {
03790 DBG_I(ProcessForwardTsnChunk);
03791
03792 int i;
03793 u_int uiNewCum = spForwardTsnChunk->uiNewCum;
03794
03795
03796
03797
03798
03799
03800
03801 for(i = uiCumAck+1; i <= (int) uiNewCum; i++)
03802 {
03803 if( IsDuplicateChunk(i) == FALSE )
03804 UpdateRecvTsnBlocks(i);
03805 }
03806
03807 UpdateAllStreams();
03808
03809 DBG_PL(ProcessForwardTsnChunk, "uiCumAck=%d"), uiCumAck DBG_PR;
03810 DBG_X(ProcessForwardTsnChunk);
03811 }
03812
03813 void SctpAgent::ProcessHeartbeatAckChunk(SctpHeartbeatAckChunk_S
03814 *spHeartbeatAckChunk)
03815 {
03816 DBG_I(ProcessHeartbeatAckChunk);
03817
03818 double dTime = 0;
03819
03820 iAssocErrorCount = 0;
03821
03822
03823
03824 if(spHeartbeatAckChunk->spDest->iErrorCount != 0)
03825 {
03826 spHeartbeatAckChunk->spDest->iErrorCount = 0;
03827 tiErrorCount++;
03828 spHeartbeatAckChunk->spDest->eStatus = SCTP_DEST_STATUS_ACTIVE;
03829 if(spHeartbeatAckChunk->spDest == spPrimaryDest &&
03830 spNewTxDest != spPrimaryDest)
03831 {
03832 DBG_PL(ProcessHeartbeatAckChunk,
03833 "primary recovered... migrating back from %p to %p"),
03834 spNewTxDest, spPrimaryDest DBG_PR;
03835 spNewTxDest = spPrimaryDest;
03836 }
03837 }
03838
03839 RttUpdate(spHeartbeatAckChunk->dTimestamp, spHeartbeatAckChunk->spDest);
03840
03841 DBG_PL(ProcessHeartbeatAckChunk, "set rto of dest=%p to %f"),
03842 spHeartbeatAckChunk->spDest, spHeartbeatAckChunk->spDest->dRto DBG_PR;
03843
03844 if(eOneHeartbeatTimer == TRUE && uiHeartbeatInterval != 0)
03845 {
03846 opHeartbeatTimeoutTimer->force_cancel();
03847 }
03848 else if(uiHeartbeatInterval != 0)
03849 {
03850 spHeartbeatAckChunk->spDest->opHeartbeatTimeoutTimer->force_cancel();
03851 DBG_PL(ProcessHeartbeatAckChunk,
03852 "about to calculate heartbeat time for dest=%p"),
03853 spHeartbeatAckChunk->spDest DBG_PR;
03854 dTime = CalcHeartbeatTime(spHeartbeatAckChunk->spDest->dRto);
03855 spHeartbeatAckChunk->spDest->opHeartbeatGenTimer->resched(dTime);
03856 }
03857
03858 DBG_X(ProcessHeartbeatAckChunk);
03859 }
03860
03861
03862
03863
03864
03865 void SctpAgent::ProcessOptionChunk(u_char *ucpInChunk)
03866 {
03867 DBG_I(ProcessOptionChunk);
03868 double dCurrTime = Scheduler::instance().clock();
03869
03870 DBG_PL(ProcessOptionChunk, "unexpected chunk type (unknown: %d) at %f"),
03871 ((SctpChunkHdr_S *)ucpInChunk)->ucType, dCurrTime DBG_PR;
03872 printf("[ProcessOptionChunk] unexpected chunk type (unknown: %d) at %f\n",
03873 ((SctpChunkHdr_S *)ucpInChunk)->ucType, dCurrTime);
03874
03875 DBG_X(ProcessOptionChunk);
03876 }
03877
03878 int SctpAgent::ProcessChunk(u_char *ucpInChunk, u_char **ucppOutData)
03879 {
03880 DBG_I(ProcessChunk);
03881 int iThisOutDataSize = 0;
03882 Node_S *spCurrNode = NULL;
03883 SctpDest_S *spCurrDest = NULL;
03884 double dCurrTime = Scheduler::instance().clock();
03885 double dTime;
03886 SctpHeartbeatAckChunk_S *spHeartbeatChunk = NULL;
03887 SctpHeartbeatAckChunk_S *spHeartbeatAckChunk = NULL;
03888
03889 switch(eState)
03890 {
03891 case SCTP_STATE_CLOSED:
03892 switch( ((SctpChunkHdr_S *)ucpInChunk)->ucType)
03893 {
03894 case SCTP_CHUNK_INIT:
03895 DBG_PL(ProcessChunk, "got INIT!! ...sending INIT_ACK") DBG_PR;
03896 ProcessInitChunk(ucpInChunk);
03897 iThisOutDataSize = GenChunk(SCTP_CHUNK_INIT_ACK, *ucppOutData);
03898 *ucppOutData += iThisOutDataSize;
03899
03900 break;
03901
03902 case SCTP_CHUNK_COOKIE_ECHO:
03903 DBG_PL(ProcessChunk,
03904 "got COOKIE_ECHO!! (established!) ...sending COOKIE_ACK")
03905 DBG_PR;
03906 ProcessCookieEchoChunk( (SctpCookieEchoChunk_S *) ucpInChunk );
03907 iThisOutDataSize = GenChunk(SCTP_CHUNK_COOKIE_ACK, *ucppOutData);
03908 *ucppOutData += iThisOutDataSize;
03909 eState = SCTP_STATE_ESTABLISHED;
03910 if(eOneHeartbeatTimer == TRUE && uiHeartbeatInterval != 0)
03911 {
03912 dTime = CalcHeartbeatTime(spPrimaryDest->dRto);
03913 opHeartbeatGenTimer->force_cancel();
03914 opHeartbeatGenTimer->resched(dTime);
03915 opHeartbeatGenTimer->dStartTime = dCurrTime;
03916
03917 for(spCurrNode = sDestList.spHead;
03918 spCurrNode != NULL;
03919 spCurrNode = spCurrNode->spNext)
03920 {
03921 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
03922 spCurrDest->dIdleSince = dCurrTime;
03923 }
03924 }
03925 else if(uiHeartbeatInterval != 0)
03926 {
03927 for(spCurrNode = sDestList.spHead;
03928 spCurrNode != NULL;
03929 spCurrNode = spCurrNode->spNext)
03930 {
03931 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
03932 DBG_PL(Reset, "about to calculate HB time for dest=%p"),
03933 spCurrDest DBG_PR;
03934 dTime = CalcHeartbeatTime(spCurrDest->dRto);
03935 spCurrDest->opHeartbeatGenTimer->resched(dTime);
03936 }
03937 }
03938 break;
03939
03940 default:
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954 DBG_PL(ProcessChunk, "association closed... ignoring chunk %s"),
03955 "(not COOKIE_ECHO or INIT)" DBG_PR;
03956 break;
03957 }
03958 break;
03959
03960 case SCTP_STATE_COOKIE_WAIT:
03961 DBG_PL(ProcessChunk, "got INIT_ACK!! ...sending COOKIE_ECHO") DBG_PR;
03962 ProcessInitAckChunk(ucpInChunk);
03963 iThisOutDataSize = GenChunk(SCTP_CHUNK_COOKIE_ECHO, *ucppOutData);
03964 *ucppOutData += iThisOutDataSize;
03965 opT1CookieTimer->resched(spPrimaryDest->dRto);
03966 eState = SCTP_STATE_COOKIE_ECHOED;
03967 break;
03968
03969 case SCTP_STATE_COOKIE_ECHOED:
03970 DBG_PL(ProcessChunk, "got COOKIE_ACK!! (established!) ...sending DATA")
03971 DBG_PR;
03972 ProcessCookieAckChunk( (SctpCookieAckChunk_S *) ucpInChunk );
03973 eSendNewDataChunks = TRUE;
03974 eState = SCTP_STATE_ESTABLISHED;
03975 if(eOneHeartbeatTimer == TRUE && uiHeartbeatInterval != 0)
03976 {
03977 dTime = CalcHeartbeatTime(spPrimaryDest->dRto);
03978 opHeartbeatGenTimer->force_cancel();
03979 opHeartbeatGenTimer->resched(dTime);
03980 opHeartbeatGenTimer->dStartTime = dCurrTime;
03981
03982 for(spCurrNode = sDestList.spHead;
03983 spCurrNode != NULL;
03984 spCurrNode = spCurrNode->spNext)
03985 {
03986 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
03987 spCurrDest->dIdleSince = dCurrTime;
03988 }
03989 }
03990 else if(uiHeartbeatInterval != 0)
03991 {
03992 for(spCurrNode = sDestList.spHead;
03993 spCurrNode != NULL;
03994 spCurrNode = spCurrNode->spNext)
03995 {
03996 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
03997 DBG_PL(Reset, "about to calculate HB time for dest=%p"),
03998 spCurrDest DBG_PR;
03999 dTime = CalcHeartbeatTime(spCurrDest->dRto);
04000 spCurrDest->opHeartbeatGenTimer->resched(dTime);
04001 }
04002 }
04003 break;
04004
04005 case SCTP_STATE_ESTABLISHED:
04006 switch( ((SctpChunkHdr_S *)ucpInChunk)->ucType)
04007 {
04008 case SCTP_CHUNK_DATA:
04009 DBG_PL(ProcessChunk, "got DATA (TSN=%d)!!"),
04010 ((SctpDataChunkHdr_S *)ucpInChunk)->uiTsn DBG_PR;
04011
04012 if(eUseDelayedSacks == FALSE)
04013 {
04014
04015
04016 eSackChunkNeeded = TRUE;
04017 }
04018 else
04019 {
04020
04021
04022 if(eStartOfPacket == TRUE)
04023 {
04024 eStartOfPacket = FALSE;
04025 iDataPktCountSinceLastSack++;
04026
04027 if(iDataPktCountSinceLastSack == 1)
04028 {
04029 opSackGenTimer->resched(dSackDelay);
04030 }
04031 else if(iDataPktCountSinceLastSack == DELAYED_SACK_TRIGGER)
04032 {
04033 iDataPktCountSinceLastSack = 0;
04034 opSackGenTimer->force_cancel();
04035 eSackChunkNeeded = TRUE;
04036 }
04037 }
04038 }
04039
04040 ProcessDataChunk( (SctpDataChunkHdr_S *) ucpInChunk );
04041
04042
04043
04044
04045 if(sRecvTsnBlockList.uiLength > 0)
04046 {
04047 iDataPktCountSinceLastSack = 0;
04048 opSackGenTimer->force_cancel();
04049 eSackChunkNeeded = TRUE;
04050 }
04051
04052
04053
04054 break;
04055
04056 case SCTP_CHUNK_SACK:
04057 DBG_PL(ProcessChunk, "got SACK (CumAck=%d)!!"),
04058 ((SctpSackChunk_S *)ucpInChunk)->uiCumAck DBG_PR;
04059
04060 ProcessSackChunk(ucpInChunk);
04061
04062
04063
04064 if(uiAdvancedPeerAckPoint > uiCumAckPoint)
04065 eForwardTsnNeeded = TRUE;
04066
04067 eSendNewDataChunks = TRUE;
04068 break;
04069
04070 case SCTP_CHUNK_FORWARD_TSN:
04071 DBG_PL(ProcessChunk, "got FORWARD TSN (tsn=%d)!!"),
04072 ((SctpForwardTsnChunk_S *) ucpInChunk)->uiNewCum DBG_PR;
04073
04074 ProcessForwardTsnChunk( (SctpForwardTsnChunk_S *) ucpInChunk );
04075 break;
04076
04077 case SCTP_CHUNK_HB:
04078 DBG_PL(ProcessChunk, "got HEARTBEAT!!") DBG_PR;
04079
04080
04081
04082 iThisOutDataSize = GenChunk(SCTP_CHUNK_HB_ACK, *ucppOutData);
04083
04084
04085
04086 spHeartbeatChunk = (SctpHeartbeatAckChunk_S *) ucpInChunk;
04087 spHeartbeatAckChunk = (SctpHeartbeatAckChunk_S *) *ucppOutData;
04088 spHeartbeatAckChunk->dTimestamp = spHeartbeatChunk->dTimestamp;
04089 spHeartbeatAckChunk->spDest = spHeartbeatChunk->spDest;
04090 *ucppOutData += iThisOutDataSize;
04091 break;
04092
04093 case SCTP_CHUNK_HB_ACK:
04094 DBG_PL(ProcessChunk, "got HEARTBEAT ACK!!") DBG_PR;
04095 ProcessHeartbeatAckChunk( (SctpHeartbeatAckChunk_S *) ucpInChunk);
04096 break;
04097
04098 case SCTP_CHUNK_INIT:
04099 DBG_PL(ProcessChunk, "unexpected chunk type (INIT) at %f"),
04100 dCurrTime DBG_PR;
04101 printf("[ProcessChunk] unexpected chunk type (INIT) at %f\n",
04102 dCurrTime);
04103 break;
04104
04105 case SCTP_CHUNK_INIT_ACK:
04106 DBG_PL(ProcessChunk, "unexpected chunk type (INIT_ACK) at %f"),
04107 dCurrTime DBG_PR;
04108 printf("[ProcessChunk] unexpected chunk type (INIT_ACK) at %f\n",
04109 dCurrTime);
04110 break;
04111
04112
04113
04114
04115
04116
04117
04118 case SCTP_CHUNK_COOKIE_ECHO:
04119 DBG_PL(ProcessChunk,
04120 "got COOKIE_ECHO!! (established!) ...sending COOKIE_ACK")
04121 DBG_PR;
04122 ProcessCookieEchoChunk( (SctpCookieEchoChunk_S *) ucpInChunk);
04123 iThisOutDataSize = GenChunk(SCTP_CHUNK_COOKIE_ACK, *ucppOutData);
04124 *ucppOutData += iThisOutDataSize;
04125 break;
04126
04127 case SCTP_CHUNK_COOKIE_ACK:
04128 DBG_PL(ProcessChunk, "unexpected chunk type (COOKIE_ACK) at %f"),
04129 dCurrTime DBG_PR;
04130 printf("[ProcessChunk] unexpected chunk type (COOKIE_ACK) at %f\n",
04131 dCurrTime);
04132 break;
04133
04134 default:
04135 ProcessOptionChunk(ucpInChunk);
04136 break;
04137 }
04138 break;
04139
04140 case SCTP_STATE_UNINITIALIZED:
04141 case SCTP_STATE_SHUTDOWN_SENT:
04142 case SCTP_STATE_SHUTDOWN_RECEIVED:
04143 case SCTP_STATE_SHUTDOWN_ACK_SENT:
04144 case SCTP_STATE_SHUTDOWN_PENDING:
04145 break;
04146 }
04147
04148 DBG_X(ProcessChunk);
04149 return iThisOutDataSize;
04150 }
04151
04152
04153
04154
04155 void SctpAgent::NextChunk(u_char **ucpChunk, int *ipRemainingDataLen)
04156 {
04157 DBG_I(NextChunk);
04158 unsigned long ulSize = ((SctpChunkHdr_S *) *ucpChunk)->usLength;
04159
04160
04161
04162
04163 if( (ulSize % 4) != 0 )
04164 ulSize += 4 - (ulSize % 4);
04165
04166 *ipRemainingDataLen -= ulSize;
04167
04168 if(*ipRemainingDataLen > 0)
04169 *ucpChunk += ulSize;
04170 else
04171 *ucpChunk = NULL;
04172
04173 DBG_X(NextChunk);
04174 }
04175
04176
04177
04178
04179
04180
04181 SctpDest_S *SctpAgent::GetNextDest(SctpDest_S *spDest)
04182 {
04183 DBG_I(GetNextDest);
04184 DBG_PL(GetNextDest, "previously dest = %p"), spDest DBG_PR;
04185
04186 Node_S *spCurrDestNode = NULL;
04187 Node_S *spNextDestNode = NULL;
04188 SctpDest_S *spNextDestNodeData = NULL;
04189
04190
04191
04192 for(spCurrDestNode = sDestList.spHead;
04193 spCurrDestNode != NULL;
04194 spCurrDestNode = spCurrDestNode->spNext)
04195 {
04196 if(spCurrDestNode->vpData == spDest)
04197 break;
04198 }
04199
04200 assert(spCurrDestNode != NULL);
04201
04202
04203
04204
04205 spNextDestNode = spCurrDestNode;
04206 do
04207 {
04208 spNextDestNode = spNextDestNode->spNext;
04209 if(spNextDestNode == NULL)
04210 spNextDestNode = sDestList.spHead;
04211 spNextDestNodeData = (SctpDest_S *) spNextDestNode->vpData;
04212 } while(spNextDestNodeData->eStatus == SCTP_DEST_STATUS_INACTIVE &&
04213 spNextDestNode != spCurrDestNode);
04214
04215
04216
04217 if(spNextDestNode == spCurrDestNode &&
04218 spNextDestNodeData->eStatus == SCTP_DEST_STATUS_INACTIVE)
04219 {
04220 switch(eDormantAction)
04221 {
04222 case DORMANT_HOP:
04223
04224
04225
04226
04227 spNextDestNode = spNextDestNode->spNext;
04228 if(spNextDestNode == NULL)
04229 spNextDestNode = sDestList.spHead;
04230 spNextDestNodeData = (SctpDest_S *) spNextDestNode->vpData;
04231 break;
04232
04233 case DORMANT_PRIMARY:
04234 spNextDestNodeData = spPrimaryDest;
04235 break;
04236
04237 case DORMANT_LASTDEST:
04238
04239
04240
04241
04242
04243 break;
04244 }
04245 }
04246
04247 DBG_PL(GetNextDest, "next dest = %p"), spNextDestNodeData DBG_PR;
04248 DBG_X(GetNextDest);
04249 return spNextDestNodeData;
04250 }
04251
04252
04253
04254
04255
04256
04257 double SctpAgent::CalcHeartbeatTime(double dRto)
04258 {
04259 DBG_I(CalcHeartbeatTime);
04260
04261 double dRetVal = 0;
04262 double dCurrTime = Scheduler::instance().clock();
04263
04264 dRetVal = dRto + uiHeartbeatInterval;
04265 dRetVal += Random::uniform(dRto);
04266 dRetVal -= dRto/2;
04267
04268 DBG_PL(CalcHeartbeatTime, "next HEARTBEAT interval in %f secs"), dRetVal
04269 DBG_PR;
04270 DBG_PL(CalcHeartbeatTime, "next HEARTBEAT interval at %f"),
04271 dRetVal+dCurrTime DBG_PR;
04272
04273 DBG_X(CalcHeartbeatTime);
04274 return dRetVal;
04275 }
04276
04277
04278
04279
04280
04281 void SctpAgent::SetSource(SctpDest_S *spDest)
04282 {
04283 DBG_I(SetSource);
04284
04285
04286
04287
04288
04289
04290
04291 if(eForceSource == FALSE && opCoreTarget != NULL)
04292 {
04293 Node_S *spCurrNode = sInterfaceList.spHead;
04294 SctpInterface_S *spCurrInterface = NULL;
04295
04296
04297
04298 Connector *connector
04299 = (Connector *) opCoreTarget->find(spDest->opRoutingAssistPacket);
04300
04301 while(spCurrNode != NULL)
04302 {
04303 spCurrInterface = (SctpInterface_S *) spCurrNode->vpData;
04304
04305 if(spCurrInterface->opLink == connector)
04306 {
04307 addr() = spCurrInterface->iNsAddr;
04308 port() = spCurrInterface->iNsPort;
04309 target_ = spCurrInterface->opTarget;
04310 break;
04311 }
04312 else
04313 spCurrNode = spCurrNode->spNext;
04314 }
04315 }
04316
04317 DBG_PL(SetSource, "(%d:%d)"), addr(), port() DBG_PR;
04318 DBG_X(SetSource);
04319 }
04320
04321 void SctpAgent::SetDestination(SctpDest_S *spDest)
04322 {
04323 DBG_I(SetDestination);
04324
04325 daddr() = spDest->iNsAddr;
04326 dport() = spDest->iNsPort;
04327
04328 DBG_PL(SetDestination, "(%d:%d)"), daddr(), dport() DBG_PR;
04329 DBG_X(SetDestination);
04330 }
04331
04332 void SctpAgent::SendPacket(u_char *ucpData, int iDataSize, SctpDest_S *spDest)
04333 {
04334 DBG_I(SendPacket);
04335 DBG_PL(SendPacket, "spDest=%p (%d:%d)"),
04336 spDest, spDest->iNsAddr, spDest->iNsPort DBG_PR;
04337 DBG_PL(SendPacket, "iDataSize=%d uiNumChunks=%d"),
04338 iDataSize, uiNumChunks DBG_PR;
04339
04340 Node_S *spNewNode = NULL;
04341 Packet *opPacket = NULL;
04342 PacketData *opPacketData = NULL;
04343
04344 SetSource(spDest);
04345 SetDestination(spDest);
04346
04347 opPacket = allocpkt();
04348 opPacketData = new PacketData(iDataSize);
04349 memcpy(opPacketData->data(), ucpData, iDataSize);
04350 opPacket->setdata(opPacketData);
04351 hdr_cmn::access(opPacket)->size() = iDataSize + SCTP_HDR_SIZE+uiIpHeaderSize;
04352
04353 hdr_sctp::access(opPacket)->NumChunks() = uiNumChunks;
04354 hdr_sctp::access(opPacket)->SctpTrace() = new SctpTrace_S[uiNumChunks];
04355 memcpy(hdr_sctp::access(opPacket)->SctpTrace(), spSctpTrace,
04356 (uiNumChunks * sizeof(SctpTrace_S)) );
04357
04358 uiNumChunks = 0;
04359
04360 if(dRouteCalcDelay == 0)
04361 {
04362 send(opPacket, 0);
04363 }
04364 else
04365 {
04366 if(spDest->eRouteCached == TRUE)
04367 {
04368
04369
04370
04371 spDest->opRouteCacheFlushTimer->resched(dRouteCacheLifetime);
04372 send(opPacket, 0);
04373 }
04374 else
04375 {
04376
04377
04378
04379 spNewNode = new Node_S;
04380 spNewNode->eType = NODE_TYPE_PACKET_BUFFER;
04381 spNewNode->vpData = opPacket;
04382 InsertNode(&spDest->sBufferedPackets, spDest->sBufferedPackets.spTail,
04383 spNewNode, NULL);
04384
04385 if(spDest->opRouteCalcDelayTimer->status() != TIMER_PENDING)
04386 spDest->opRouteCalcDelayTimer->sched(dRouteCalcDelay);
04387 }
04388 }
04389
04390 DBG_X(SendPacket);
04391 }
04392
04393 SctpDest_S *SctpAgent::GetReplyDestination(hdr_ip *spIpHdr)
04394 {
04395 Node_S *spCurrNode = NULL;
04396 SctpDest_S *spDest = NULL;
04397 int iAddr = spIpHdr->saddr();
04398 int iPort = spIpHdr->sport();
04399
04400 for(spCurrNode = sDestList.spHead;
04401 spCurrNode != NULL;
04402 spCurrNode = spCurrNode->spNext)
04403 {
04404 spDest = (SctpDest_S *) spCurrNode->vpData;
04405
04406 if(spDest->iNsAddr == iAddr && spDest->iNsPort == iPort)
04407 return spDest;
04408 }
04409
04410 return NULL;
04411 }
04412
04413 void SctpAgent::recv(Packet *opInPkt, Handler*)
04414 {
04415
04416
04417
04418
04419 if(eState == SCTP_STATE_UNINITIALIZED)
04420 Reset();
04421
04422 DBG_I(recv);
04423
04424 hdr_ip *spIpHdr = hdr_ip::access(opInPkt);
04425 PacketData *opInPacketData = (PacketData *) opInPkt->userdata();
04426 u_char *ucpInData = opInPacketData->data();
04427 u_char *ucpCurrInChunk = ucpInData;
04428 int iRemainingDataLen = opInPacketData->size();
04429
04430 u_char ucpOutData[uiMaxPayloadSize];
04431 u_char *ucpCurrOutData = ucpOutData;
04432
04433
04434
04435
04436 int iOutDataSize = 0;
04437
04438 memset(ucpOutData, 0, uiMaxPayloadSize);
04439 memset(spSctpTrace, 0,
04440 (uiMaxPayloadSize / sizeof(SctpChunkHdr_S)) * sizeof(SctpTrace_S) );
04441
04442 spReplyDest = GetReplyDestination(spIpHdr);
04443
04444 eStartOfPacket = TRUE;
04445
04446 do
04447 {
04448 DBG_PL(recv, "iRemainingDataLen=%d"), iRemainingDataLen DBG_PR;
04449
04450
04451
04452
04453
04454 iOutDataSize += ProcessChunk(ucpCurrInChunk, &ucpCurrOutData);
04455 NextChunk(&ucpCurrInChunk, &iRemainingDataLen);
04456 }
04457 while(ucpCurrInChunk != NULL);
04458
04459
04460
04461
04462
04463
04464 if(iOutDataSize > 0)
04465 {
04466 SendPacket(ucpOutData, iOutDataSize, spReplyDest);
04467 DBG_PL(recv, "responded with control chunk(s)") DBG_PR;
04468 }
04469
04470
04471
04472
04473
04474
04475
04476 if(eSackChunkNeeded == TRUE)
04477 {
04478 memset(ucpOutData, 0, uiMaxPayloadSize);
04479 iOutDataSize = BundleControlChunks(ucpOutData);
04480 iOutDataSize += GenChunk(SCTP_CHUNK_SACK, ucpOutData+iOutDataSize);
04481 SendPacket(ucpOutData, iOutDataSize, spReplyDest);
04482 DBG_PL(recv, "SACK sent (%d bytes)"), iOutDataSize DBG_PR;
04483 eSackChunkNeeded = FALSE;
04484 }
04485
04486
04487
04488 if(eForwardTsnNeeded == TRUE)
04489 {
04490 memset(ucpOutData, 0, uiMaxPayloadSize);
04491 iOutDataSize = BundleControlChunks(ucpOutData);
04492 iOutDataSize += GenChunk(SCTP_CHUNK_FORWARD_TSN, ucpOutData+iOutDataSize);
04493 SendPacket(ucpOutData, iOutDataSize, spNewTxDest);
04494 DBG_PL(recv, "FORWARD TSN chunk sent") DBG_PR;
04495 eForwardTsnNeeded = FALSE;
04496 }
04497
04498
04499
04500
04501
04502
04503
04504
04505 if(eSendNewDataChunks == TRUE && eMarkedChunksPending == FALSE)
04506 {
04507 SendMuch();
04508 eSendNewDataChunks = FALSE;
04509 }
04510
04511 delete hdr_sctp::access(opInPkt)->SctpTrace();
04512 hdr_sctp::access(opInPkt)->SctpTrace() = NULL;
04513 Packet::free(opInPkt);
04514 opInPkt = NULL;
04515 DBG_X(recv);
04516 }
04517
04518 u_int SctpAgent::TotalOutstanding()
04519 {
04520 DBG_I(TotalOutstanding);
04521
04522 Node_S *spCurrNode = NULL;
04523 SctpDest_S *spCurrDest = NULL;
04524 u_int uiTotalOutstanding = 0;
04525
04526 for(spCurrNode = sDestList.spHead;
04527 spCurrNode != NULL;
04528 spCurrNode = spCurrNode->spNext)
04529 {
04530 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
04531 uiTotalOutstanding += spCurrDest->iOutstandingBytes;
04532 DBG_PL(TotalOutstanding, "spCurrDest->iOutstandingBytes=%lu"),
04533 spCurrDest->iOutstandingBytes DBG_PR;
04534 }
04535
04536 DBG_PL(TotalOutstanding, "%lu"), uiTotalOutstanding DBG_PR;
04537 DBG_X(TotalOutstanding);
04538 return uiTotalOutstanding;
04539 }
04540
04541 void SctpAgent::SendMuch()
04542 {
04543 DBG_I(SendMuch);
04544 DBG_PL(SendMuch, "eDataSource=%s"),
04545 ( (eDataSource == DATA_SOURCE_APPLICATION)
04546 ? "DATA_SOURCE_APPLICATION"
04547 : "DATA_SOURCE_INFINITE" )
04548 DBG_PR;
04549
04550 u_char ucpOutData[uiMaxPayloadSize];
04551 int iOutDataSize = 0;
04552 double dTime = 0;
04553 double dCurrTime = Scheduler::instance().clock();
04554
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565 while((spNewTxDest->iOutstandingBytes < spNewTxDest->iCwnd) &&
04566 (eDataSource == DATA_SOURCE_INFINITE || sAppLayerBuffer.uiLength != 0))
04567 {
04568 DBG_PL(SendMuch, "uiAdvancedPeerAckPoint=%d uiCumAckPoint=%d"),
04569 uiAdvancedPeerAckPoint, uiCumAckPoint DBG_PR;
04570 DBG_PL(SendMuch, "uiPeerRwnd=%d"), uiPeerRwnd DBG_PR;
04571 DBG_PL(SendMuch, "spNewTxDest->iCwnd=%d"), spNewTxDest->iCwnd DBG_PR;
04572 DBG_PL(SendMuch, "spNewTxDest->iPartialBytesAcked=%d"),
04573 spNewTxDest->iPartialBytesAcked DBG_PR;
04574 DBG_PL(SendMuch, "spNewTxDest->iOutstandingBytes=%d"),
04575 spNewTxDest->iOutstandingBytes DBG_PR;
04576 DBG_PL(SendMuch, "TotalOutstanding=%lu"),
04577 TotalOutstanding() DBG_PR;
04578 DBG_PL(SendMuch, "eApplyMaxBurst=%s uiBurstLength=%d"),
04579 eApplyMaxBurst ? "TRUE" : "FALSE", uiBurstLength DBG_PR;
04580
04581 if(GetNextDataChunkSize() <= uiPeerRwnd)
04582 {
04583
04584
04585
04586
04587 if(eUseMaxBurst == MAX_BURST_USAGE_ON)
04588 if( (eApplyMaxBurst == TRUE) && (uiBurstLength++ >= MAX_BURST) )
04589 {
04590
04591
04592 eApplyMaxBurst = FALSE;
04593 break;
04594 }
04595
04596 memset(ucpOutData, 0, uiMaxPayloadSize);
04597 iOutDataSize = BundleControlChunks(ucpOutData);
04598 iOutDataSize += GenMultipleDataChunks(ucpOutData+iOutDataSize, 0);
04599 SendPacket(ucpOutData, iOutDataSize, spNewTxDest);
04600 DBG_PL(SendMuch, "DATA chunk(s) sent") DBG_PR;
04601 }
04602 else if(TotalOutstanding() == 0)
04603 {
04604
04605
04606 memset(ucpOutData, 0, uiMaxPayloadSize);
04607 iOutDataSize = BundleControlChunks(ucpOutData);
04608 iOutDataSize += GenOneDataChunk(ucpOutData+iOutDataSize);
04609 SendPacket(ucpOutData, iOutDataSize, spNewTxDest);
04610 DBG_PL(SendMuch, "DATA chunk probe sent") DBG_PR;
04611 }
04612 else
04613 {
04614 break;
04615 }
04616 }
04617
04618 if(iOutDataSize > 0)
04619 {
04620 spNewTxDest->opCwndDegradeTimer->resched(spNewTxDest->dRto);
04621 if(eOneHeartbeatTimer == TRUE && uiHeartbeatInterval != 0)
04622 {
04623 spNewTxDest->dIdleSince = dCurrTime;
04624 }
04625 else if(uiHeartbeatInterval != 0)
04626 {
04627 DBG_PL(SendMuch, "about to calculate heartbeat time for dest=%p"),
04628 spNewTxDest DBG_PR;
04629 dTime = CalcHeartbeatTime(spNewTxDest->dRto);
04630 spNewTxDest->opHeartbeatGenTimer->resched(dTime);
04631 }
04632 }
04633
04634
04635
04636
04637 uiBurstLength = 0;
04638
04639 DBG_X(SendMuch);
04640 }
04641
04642 void SctpAgent::sendmsg(int iNumBytes, const char *cpFlags)
04643 {
04644
04645
04646
04647
04648 if(eState == SCTP_STATE_UNINITIALIZED)
04649 Reset();
04650
04651 DBG_I(sendmsg);
04652
04653 u_char ucpOutData[uiMaxPayloadSize];
04654 int iOutDataSize = 0;
04655 AppData_S *spAppData = (AppData_S *) cpFlags;
04656 Node_S *spNewNode = NULL;
04657 int iMsgSize = 0;
04658 u_int uiMaxFragSize = uiMaxDataSize - sizeof(SctpDataChunkHdr_S);
04659
04660 if(iNumBytes == -1)
04661 eDataSource = DATA_SOURCE_INFINITE;
04662 else
04663 eDataSource = DATA_SOURCE_APPLICATION;
04664
04665 if(eDataSource == DATA_SOURCE_APPLICATION)
04666 {
04667 if(spAppData != NULL)
04668 {
04669
04670
04671
04672 DBG_PL (sendmsg, "sctp-aware app: iNumBytes=%d"), iNumBytes DBG_PR;
04673 spNewNode = new Node_S;
04674 uiNumOutStreams = spAppData->usNumStreams;
04675 uiNumUnrelStreams = spAppData->usNumUnreliable;
04676 spNewNode->eType = NODE_TYPE_APP_LAYER_BUFFER;
04677 spNewNode->vpData = spAppData;
04678 InsertNode(&sAppLayerBuffer, sAppLayerBuffer.spTail, spNewNode, NULL);
04679 }
04680 else
04681 {
04682
04683
04684 DBG_PL (sendmsg, "non-sctp-aware app: iNumBytes=%d"),iNumBytes DBG_PR;
04685 uiNumOutStreams = 1;
04686 uiNumUnrelStreams = (uiNumUnrelStreams > 0) ? 1 : 0;
04687
04688
04689
04690
04691
04692
04693
04694 for(iMsgSize = iNumBytes;
04695 iMsgSize > 0;
04696 iMsgSize -= MIN(iMsgSize, (int) uiMaxFragSize) )
04697 {
04698 spNewNode = new Node_S;
04699 spNewNode->eType = NODE_TYPE_APP_LAYER_BUFFER;
04700 spAppData = new AppData_S;
04701 spAppData->usNumStreams = uiNumOutStreams;
04702 spAppData->usNumUnreliable = uiNumUnrelStreams;
04703 spAppData->usStreamId = 0;
04704 spAppData->usReliability = uiReliability;
04705 spAppData->eUnordered = eUnordered;
04706 spAppData->uiNumBytes = MIN(iMsgSize, (int) uiMaxFragSize);
04707 spNewNode->vpData = spAppData;
04708 InsertNode(&sAppLayerBuffer, sAppLayerBuffer.spTail,
04709 spNewNode, NULL);
04710 }
04711 }
04712
04713 if(uiNumOutStreams > MAX_NUM_STREAMS)
04714 {
04715 fprintf(stderr, "%s number of streams (%d) > max (%d)\n",
04716 "SCTP ERROR:",
04717 uiNumOutStreams, MAX_NUM_STREAMS);
04718 DBG_PL(sendmsg, "ERROR: number of streams (%d) > max (%d)"),
04719 uiNumOutStreams, MAX_NUM_STREAMS DBG_PR;
04720 DBG_PL(sendmsg, "exiting...") DBG_PR;
04721 exit(-1);
04722 }
04723 else if(uiNumUnrelStreams > uiNumOutStreams)
04724 {
04725 fprintf(stderr, "%s number of unreliable streams (%d) > total (%d)\n",
04726 "SCTP ERROR:",
04727 uiNumUnrelStreams, uiNumOutStreams);
04728 DBG_PL(sendmsg,
04729 "ERROR: number of unreliable streams (%d) > total (%d)"),
04730 uiNumUnrelStreams, uiNumOutStreams DBG_PR;
04731 DBG_PL(sendmsg, "exiting...") DBG_PR;
04732 exit(-1);
04733 }
04734
04735 if(spAppData->uiNumBytes + sizeof(SctpDataChunkHdr_S)
04736 > MAX_DATA_CHUNK_SIZE)
04737 {
04738 fprintf(stderr, "SCTP ERROR: message size (%d) too big\n",
04739 spAppData->uiNumBytes);
04740 fprintf(stderr, "%s data chunk size (%d) > max (%d)\n",
04741 "SCTP ERROR:",
04742 spAppData->uiNumBytes + sizeof(SctpDataChunkHdr_S),
04743 MAX_DATA_CHUNK_SIZE);
04744 DBG_PL(sendmsg, "ERROR: message size (%d) too big"),
04745 spAppData->uiNumBytes DBG_PR;
04746 DBG_PL(sendmsg, "ERROR: data chunk size (%d) > max (%d)"),
04747 spAppData->uiNumBytes + sizeof(SctpDataChunkHdr_S),
04748 MAX_DATA_CHUNK_SIZE
04749 DBG_PR;
04750 DBG_PL(sendmsg, "exiting...") DBG_PR;
04751 exit(-1);
04752 }
04753 else if(spAppData->uiNumBytes + sizeof(SctpDataChunkHdr_S)
04754 > uiMaxDataSize)
04755 {
04756 fprintf(stderr, "SCTP ERROR: message size (%d) too big\n",
04757 spAppData->uiNumBytes);
04758 fprintf(stderr,
04759 "%s data chunk size (%d) + SCTP/IP header(%d) > MTU (%d)\n",
04760 "SCTP ERROR:",
04761 spAppData->uiNumBytes + sizeof(SctpDataChunkHdr_S),
04762 SCTP_HDR_SIZE + uiIpHeaderSize, uiMtu);
04763 fprintf(stderr, " %s\n",
04764 "...chunk fragmentation is not yet supported!");
04765 DBG_PL(sendmsg, "ERROR: message size (%d) too big"),
04766 spAppData->uiNumBytes DBG_PR;
04767 DBG_PL(sendmsg, "exiting...") DBG_PR;
04768 exit(-1);
04769 }
04770 }
04771
04772 switch(eState)
04773 {
04774 case SCTP_STATE_CLOSED:
04775 DBG_PL(sendmsg, "sending INIT") DBG_PR;
04776
04777
04778
04779
04780
04781 set_pkttype(PT_SCTP);
04782 iOutDataSize = GenChunk(SCTP_CHUNK_INIT, ucpOutData);
04783 opT1InitTimer->resched(spPrimaryDest->dRto);
04784 eState = SCTP_STATE_COOKIE_WAIT;
04785 SendPacket(ucpOutData, iOutDataSize, spPrimaryDest);
04786 break;
04787
04788 case SCTP_STATE_ESTABLISHED:
04789 if(eDataSource == DATA_SOURCE_APPLICATION)
04790 {
04791 SendMuch();
04792 }
04793 else if(eDataSource == DATA_SOURCE_INFINITE)
04794 {
04795 fprintf(stderr, "[sendmsg] ERROR: unexpected state... %s\n",
04796 "sendmsg called more than once for infinite data");
04797 DBG_PL(sendmsg,
04798 "ERROR: unexpected state... %s"),
04799 "sendmsg called more than once for infinite data" DBG_PR;
04800 DBG_PL(sendmsg, "exiting...") DBG_PR;
04801 exit(-1);
04802 }
04803 break;
04804
04805 default:
04806
04807
04808
04809
04810 break;
04811 }
04812
04813 DBG_X(sendmsg);
04814 }
04815
04816 void SctpAgent::T1InitTimerExpiration()
04817 {
04818 DBG_I(T1InitTimerExpiration);
04819
04820 u_char ucpOutData[uiMaxPayloadSize];
04821 int iOutDataSize = 0;
04822
04823 iInitTryCount++;
04824 if(iInitTryCount > (int) uiMaxInitRetransmits)
04825 {
04826 Close();
04827 }
04828 else
04829 {
04830 spPrimaryDest->dRto *= 2;
04831 if(spPrimaryDest->dRto > dMaxRto)
04832 spPrimaryDest->dRto = dMaxRto;
04833 tdRto++;
04834
04835 iOutDataSize = GenChunk(SCTP_CHUNK_INIT, ucpOutData);
04836 SendPacket(ucpOutData, iOutDataSize, spPrimaryDest);
04837 opT1InitTimer->resched(spPrimaryDest->dRto);
04838 }
04839
04840 DBG_X(T1InitTimerExpiration);
04841 }
04842
04843 void T1InitTimer::expire(Event*)
04844 {
04845 opAgent->T1InitTimerExpiration();
04846 }
04847
04848 void SctpAgent::T1CookieTimerExpiration()
04849 {
04850 DBG_I(T1CookieTimerExpiration);
04851
04852 u_char ucpOutData[uiMaxPayloadSize];
04853 int iOutDataSize = 0;
04854
04855 iInitTryCount++;
04856 if(iInitTryCount > (int) uiMaxInitRetransmits)
04857 Close();
04858 else
04859 {
04860 spPrimaryDest->dRto *= 2;
04861 if(spPrimaryDest->dRto > dMaxRto)
04862 spPrimaryDest->dRto = dMaxRto;
04863 tdRto++;
04864
04865 iOutDataSize = GenChunk(SCTP_CHUNK_COOKIE_ECHO, ucpOutData);
04866 SendPacket(ucpOutData, iOutDataSize, spPrimaryDest);
04867 opT1CookieTimer->resched(spPrimaryDest->dRto);
04868 }
04869
04870 DBG_X(T1CookieTimerExpiration);
04871 }
04872
04873 void T1CookieTimer::expire(Event*)
04874 {
04875 opAgent->T1CookieTimerExpiration();
04876 }
04877
04878 void SctpAgent::Close()
04879 {
04880 DBG_I(Close);
04881
04882 Node_S *spCurrNode = NULL;
04883 SctpDest_S *spCurrDest = NULL;
04884
04885 eState = SCTP_STATE_CLOSED;
04886
04887
04888
04889 opT1InitTimer->force_cancel();
04890 opT1CookieTimer->force_cancel();
04891 opSackGenTimer->force_cancel();
04892 if(eOneHeartbeatTimer == TRUE && uiHeartbeatInterval != 0)
04893 {
04894 opHeartbeatGenTimer->force_cancel();
04895 opHeartbeatTimeoutTimer->force_cancel();
04896 }
04897
04898 for(spCurrNode = sDestList.spHead;
04899 spCurrNode != NULL;
04900 spCurrNode = spCurrNode->spNext)
04901 {
04902 spCurrDest = (SctpDest_S *) spCurrNode->vpData;
04903 spCurrDest->opT3RtxTimer->force_cancel();
04904 spCurrDest->opCwndDegradeTimer->force_cancel();
04905 if(eOneHeartbeatTimer == FALSE && uiHeartbeatInterval != 0)
04906 {
04907 spCurrDest->opHeartbeatGenTimer->force_cancel();
04908 spCurrDest->opHeartbeatTimeoutTimer->force_cancel();
04909 }
04910 }
04911
04912 ClearList(&sSendBuffer);
04913 ClearList(&sAppLayerBuffer);
04914 ClearList(&sRecvTsnBlockList);
04915 ClearList(&sDupTsnList);
04916
04917 DBG_X(Close);
04918 }
04919
04920
04921
04922
04923 void SctpAgent::Timeout(SctpChunkType_E eChunkType, SctpDest_S *spDest)
04924 {
04925 DBG_I(Timeout);
04926 DBG_PL(Timeout, "eChunkType=%s spDest=%p"),
04927 (eChunkType == SCTP_CHUNK_DATA) ? "DATA" : "HEARTBEAT",
04928 spDest
04929 DBG_PR;
04930
04931 double dCurrTime = Scheduler::instance().clock();
04932
04933 DBG_PL(Timeout, "dCurrTime=%f"), dCurrTime DBG_PR;
04934
04935 if(eChunkType == SCTP_CHUNK_DATA)
04936 {
04937 spDest->eRtxTimerIsRunning = FALSE;
04938
04939
04940
04941 if(spDest->iCwnd > 1 * (int) uiMaxDataSize)
04942 {
04943 spDest->iSsthresh
04944 = MAX(spDest->iCwnd/2, iInitialCwnd * (int) uiMaxDataSize);
04945 spDest->iCwnd = 1*uiMaxDataSize;
04946 spDest->iPartialBytesAcked = 0;
04947 tiCwnd++;
04948 }
04949
04950 spDest->opCwndDegradeTimer->force_cancel();
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976 spDest->eRtoPending = FALSE;
04977 }
04978
04979 DBG_PL(Timeout, "was spDest->dRto=%f"), spDest->dRto DBG_PR;
04980 spDest->dRto *= 2;
04981 if(spDest->dRto > dMaxRto)
04982 spDest->dRto = dMaxRto;
04983 tdRto++;
04984 DBG_PL(Timeout, "now spDest->dRto=%f"), spDest->dRto DBG_PR;
04985
04986 spDest->iTimeoutCount++;
04987 spDest->iErrorCount++;
04988 DBG_PL(Timeout, "now spDest->iErrorCount=%d"), spDest->iErrorCount DBG_PR;
04989
04990 if(spDest->eStatus == SCTP_DEST_STATUS_ACTIVE)
04991 {
04992 iAssocErrorCount++;
04993 DBG_PL(Timeout, "now iAssocErrorCount=%d"), iAssocErrorCount DBG_PR;
04994
04995
04996 if(spDest->iErrorCount > (int) uiPathMaxRetrans)
04997 {
04998 spDest->eStatus = SCTP_DEST_STATUS_INACTIVE;
04999 if(spDest == spNewTxDest)
05000 {
05001 spNewTxDest = GetNextDest(spDest);
05002 DBG_PL(Timeout, "failing over from %p to %p"),
05003 spDest, spNewTxDest DBG_PR;
05004 }
05005 }
05006 if(iAssocErrorCount > (int) uiAssociationMaxRetrans)
05007 {
05008
05009
05010 DBG_PL(Timeout, "abruptly closing the association!") DBG_PR;
05011 Close();
05012 DBG_X(Timeout);
05013 return;
05014 }
05015 }
05016
05017
05018 tiTimeoutCount++;
05019 tiErrorCount++;
05020
05021 if(spDest->iErrorCount > (int) uiChangePrimaryThresh &&
05022 spDest == spPrimaryDest)
05023 {
05024 spPrimaryDest = spNewTxDest;
05025 DBG_PL(Timeout, "changing primary from %p to %p"),
05026 spDest, spNewTxDest DBG_PR;
05027 }
05028
05029 if(eChunkType == SCTP_CHUNK_DATA)
05030 {
05031 TimeoutRtx(spDest);
05032 if(spDest->eStatus == SCTP_DEST_STATUS_INACTIVE && uiHeartbeatInterval!=0)
05033 SendHeartbeat(spDest);
05034 }
05035 else if(eChunkType == SCTP_CHUNK_HB)
05036 {
05037 if(uiHeartbeatInterval != 0)
05038 SendHeartbeat(spDest);
05039 }
05040
05041 DBG_X(Timeout);
05042 }
05043
05044 void T3RtxTimer::expire(Event*)
05045 {
05046 opAgent->Timeout(SCTP_CHUNK_DATA, spDest);
05047 }
05048
05049 void HeartbeatTimeoutTimer::expire(Event*)
05050 {
05051 opAgent->Timeout(SCTP_CHUNK_HB, spDest);
05052 }
05053
05054 void SctpAgent::CwndDegradeTimerExpiration(SctpDest_S *spDest)
05055 {
05056 DBG_I(CwndDegradeTimerExpiration);
05057 DBG_PL(CwndDegradeTimerExpiration, "spDest=%p"), spDest DBG_PR;
05058 if(spDest->iCwnd > iInitialCwnd * (int) uiMaxDataSize)
05059 {
05060 spDest->iCwnd = MAX(spDest->iCwnd/2, iInitialCwnd * (int) uiMaxDataSize);
05061 tiCwnd++;
05062 }
05063 spDest->opCwndDegradeTimer->resched(spDest->dRto);
05064 DBG_X(CwndDegradeTimerExpiration);
05065 }
05066
05067 void CwndDegradeTimer::expire(Event*)
05068 {
05069 opAgent->CwndDegradeTimerExpiration(spDest);
05070 }
05071
05072 void SctpAgent::SendHeartbeat(SctpDest_S *spDest)
05073 {
05074 DBG_I(SendHeartbeat);
05075 DBG_PL(SendHeartbeat, "spDest=%p"), spDest DBG_PR;
05076
05077 SctpHeartbeatChunk_S sHeartbeatChunk;
05078 double dCurrTime = Scheduler::instance().clock();
05079
05080 GenChunk(SCTP_CHUNK_HB, (u_char *) &sHeartbeatChunk);
05081 sHeartbeatChunk.spDest = spDest;
05082 SendPacket((u_char *) &sHeartbeatChunk, SCTP_CHUNK_HEARTBEAT_LENGTH, spDest);
05083 if(eOneHeartbeatTimer == TRUE)
05084 {
05085 spDest->dIdleSince = dCurrTime;
05086 opHeartbeatTimeoutTimer->resched(spDest->dRto);
05087 opHeartbeatTimeoutTimer->spDest = spDest;
05088 }
05089 else
05090 {
05091 spDest->opHeartbeatTimeoutTimer->resched(spDest->dRto);
05092 }
05093 DBG_PL(SendHeartbeat, "HEARTBEAT times out at %f"),
05094 spDest->dRto+dCurrTime DBG_PR;
05095
05096 DBG_X(SendHeartbeat);
05097 }
05098
05099 void SctpAgent::HeartbeatGenTimerExpiration(double dTimerStartTime,
05100 SctpDest_S *spDest)
05101 {
05102 DBG_I(HeartbeatGenTimerExpiration);
05103
05104 Node_S *spCurrNode = NULL;
05105 SctpDest_S *spCurrNodeData = NULL;
05106 Node_S *spLongestIdleNode = NULL;
05107 SctpDest_S *spLongestIdleNodeData = NULL;
05108 double dCurrTime = Scheduler::instance().clock();
05109 double dTime;
05110
05111 if(eOneHeartbeatTimer == FALSE)
05112 SendHeartbeat(spDest);
05113 else
05114 {
05115 DBG_PL(HeartbeatGenTimerExpiration, "finding the longest idle dest...")
05116 DBG_PR;
05117
05118
05119
05120 for(spCurrNode = spLongestIdleNode = sDestList.spHead;
05121 spCurrNode != NULL;
05122 spCurrNode = spCurrNode->spNext)
05123 {
05124 spCurrNodeData = (SctpDest_S *) spCurrNode->vpData;
05125 spLongestIdleNodeData = (SctpDest_S *) spLongestIdleNode->vpData;
05126
05127 DBG_PL(HeartbeatGenTimerExpiration, "spDest=%p idle since %f"),
05128 spCurrNodeData, spCurrNodeData->dIdleSince DBG_PR;
05129
05130 if(spCurrNodeData->dIdleSince < spLongestIdleNodeData->dIdleSince)
05131 spLongestIdleNode = spCurrNode;
05132 }
05133
05134
05135
05136 spLongestIdleNodeData = (SctpDest_S *) spLongestIdleNode->vpData;
05137 DBG_PL(HeartbeatGenTimerExpiration, "longest idle dest since %f"),
05138 spLongestIdleNodeData->dIdleSince DBG_PR;
05139 DBG_PL(HeartbeatGenTimerExpiration, "timer start time %f"),
05140 dTimerStartTime DBG_PR;
05141 if(spLongestIdleNodeData->dIdleSince <= dTimerStartTime)
05142 SendHeartbeat(spLongestIdleNodeData);
05143 else
05144 DBG_PL(HeartbeatGenTimerExpiration,
05145 "longest idle dest not idle long enough!") DBG_PR;
05146
05147
05148
05149 dTime = CalcHeartbeatTime(spLongestIdleNodeData->dRto);
05150 opHeartbeatGenTimer->resched(dTime);
05151 opHeartbeatGenTimer->dStartTime = dCurrTime;
05152 }
05153
05154 DBG_X(HeartbeatGenTimerExpiration);
05155 }
05156
05157 void HeartbeatGenTimer::expire(Event*)
05158 {
05159 opAgent->HeartbeatGenTimerExpiration(dStartTime, spDest);
05160 }
05161
05162 void SctpAgent::SackGenTimerExpiration()
05163 {
05164 DBG_I(SackGenTimerExpiration);
05165
05166 u_char ucpOutData[uiMaxPayloadSize];
05167 int iOutDataSize = 0;
05168 memset(ucpOutData, 0, uiMaxPayloadSize);
05169
05170 iDataPktCountSinceLastSack = 0;
05171
05172 iOutDataSize = BundleControlChunks(ucpOutData);
05173 iOutDataSize += GenChunk(SCTP_CHUNK_SACK, ucpOutData+iOutDataSize);
05174 SendPacket(ucpOutData, iOutDataSize, spReplyDest);
05175 DBG_PL(SackGenTimerExpiration, "SACK sent (%d bytes)"), iOutDataSize DBG_PR;
05176
05177 DBG_X(SackGenTimerExpiration);
05178 }
05179
05180 void SackGenTimer::expire(Event*)
05181 {
05182 opAgent->SackGenTimerExpiration();
05183 }
05184
05185 void SctpAgent::RouteCacheFlushTimerExpiration(SctpDest_S *spDest)
05186 {
05187 DBG_I(RouteCacheFlushTimerExpiration);
05188 DBG_PL(RouteCacheFlushTimerExpiration, "spDest=%p"), spDest DBG_PR;
05189 double dCurrTime = Scheduler::instance().clock();
05190 DBG_PL(RouteCacheFlushTimerExpiration, "dCurrTime=%f"), dCurrTime DBG_PR;
05191
05192 spDest->eRouteCached = FALSE;
05193
05194 DBG_X(RouteCacheFlushTimerExpiration);
05195 }
05196
05197 void RouteCacheFlushTimer::expire(Event*)
05198 {
05199 opAgent->RouteCacheFlushTimerExpiration(spDest);
05200 }
05201
05202 void SctpAgent::RouteCalcDelayTimerExpiration(SctpDest_S *spDest)
05203 {
05204 DBG_I(RouteCalcDelayTimerExpiration);
05205 DBG_PL(RouteCalcDelayTimerExpiration, "spDest=%p"), spDest DBG_PR;
05206 double dCurrTime = Scheduler::instance().clock();
05207 DBG_PL(RouteCalcDelayTimerExpiration, "dCurrTime=%f"), dCurrTime DBG_PR;
05208
05209 Node_S *spCurrNode = spDest->sBufferedPackets.spHead;
05210 Node_S *spDeleteNode = NULL;
05211
05212 spDest->iRcdCount++;
05213 tiRcdCount++;
05214 spDest->eRouteCached = TRUE;
05215 SetSource(spDest);
05216 SetDestination(spDest);
05217
05218
05219
05220 while(spCurrNode != NULL)
05221 {
05222 send( (Packet *) spCurrNode->vpData, 0);
05223 spDeleteNode = spCurrNode;
05224 spCurrNode = spCurrNode->spNext;
05225 DeleteNode(&spDest->sBufferedPackets, spDeleteNode);
05226 }
05227
05228 DBG_X(RouteCalcDelayTimerExpiration);
05229 }
05230
05231 void RouteCalcDelayTimer::expire(Event*)
05232 {
05233 opAgent->RouteCalcDelayTimerExpiration(spDest);
05234 }
05235
05236
05237
05238
05239
05240 void SctpAgent::DumpSendBuffer()
05241 {
05242 DBG_IF(DumpSendBuffer)
05243 {
05244 DBG_I(DumpSendBuffer);
05245
05246 Node_S *spCurrNode = NULL;
05247 SctpSendBufferNode_S *spCurrNodeData = NULL;
05248 SctpDataChunkHdr_S *spChunk = NULL;
05249
05250 for(spCurrNode = sSendBuffer.spHead;
05251 spCurrNode != NULL;
05252 spCurrNode = spCurrNode->spNext)
05253 {
05254 spCurrNodeData = (SctpSendBufferNode_S *) spCurrNode->vpData;
05255 spChunk = spCurrNodeData->spChunk;
05256 DBG_PL(DumpSendBuffer,
05257 "tsn=%d spDest=%p eMarkedForRtx=%s %s %s"),
05258 spChunk->uiTsn,
05259 spCurrNodeData->spDest,
05260 (!spCurrNodeData->eMarkedForRtx ? "NO_RTX"
05261 : (spCurrNodeData->eMarkedForRtx==FAST_RTX ? "FAST_RTX"
05262 : "TIMEOUT_RTX")),
05263 spCurrNodeData->eMarkedForRtx ? "MarkedForRtx" : "",
05264 spCurrNodeData->eGapAcked ? "GapAcked" : "",
05265 spCurrNodeData->eAdvancedAcked ? "AdvancedAcked" : ""
05266 DBG_PR;
05267 DBG_PL(DumpSendBuffer,
05268 " spCurrNodeData->spDest->iOutstandingBytes=%lu"),
05269 spCurrNodeData->spDest->iOutstandingBytes DBG_PR;
05270 }
05271
05272 DBG_X(DumpSendBuffer);
05273 }
05274 }