00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <string.h>
00021 #include <assert.h>
00022 #include "SCTP.h"
00023 #include "SCTPAssociation.h"
00024 #include "SCTPCommand_m.h"
00025 #include "IPControlInfo_m.h"
00026 #include "SCTPQueue.h"
00027 #include "SCTPAlgorithm.h"
00028 #include "IPv4InterfaceData.h"
00029
00030 #include <sstream>
00031
00032
00033 SCTPPathVariables::SCTPPathVariables(const IPvXAddress& addr, SCTPAssociation* assoc)
00034 {
00035 InterfaceTableAccess interfaceTableAccess;
00036
00037 association = assoc;
00038 remoteAddress = addr;
00039 activePath = true;
00040 confirmed = false;
00041 primaryPathCandidate = false;
00042 pathErrorCount = 0;
00043 pathErrorThreshold = assoc->getSctpMain()->par("pathMaxRetrans");
00044 if (!pathErrorThreshold) {
00045 pathErrorThreshold = PATH_MAX_RETRANS;
00046 }
00047 pathRto = assoc->getSctpMain()->par("rtoInitial");
00048 heartbeatTimeout = pathRto;
00049 double interval = (double)assoc->getSctpMain()->par("hbInterval");
00050 if (!interval) {
00051 interval = HB_INTERVAL;
00052 }
00053 heartbeatIntervalTimeout = pathRto+interval;
00054 srtt = pathRto;
00055 lastAckTime = 0;
00056 forceHb = false;
00057 partialBytesAcked = 0;
00058 queuedBytes = 0;
00059 outstandingBytes = 0;
00060
00061 RoutingTableAccess routingTableAccess;
00062 const InterfaceEntry* rtie = routingTableAccess.get()->getInterfaceForDestAddr(remoteAddress.get4());
00063 if(rtie == NULL) {
00064 opp_error("No interface for remote address %s found!", remoteAddress.get4().str().c_str());
00065 }
00066 pmtu = rtie->getMTU();
00067 rttvar = 0.0;
00068
00069 cwndTimeout = pathRto;
00070 cwnd = 0;
00071 ssthresh = 0;
00072 updateTime = 0.0;
00073 fastRecoveryExitPoint = 0;
00074 fastRecoveryActive = false;
00075
00076 numberOfFastRetransmissions = 0;
00077 numberOfTimerBasedRetransmissions = 0;
00078 numberOfHeartbeatsSent = 0;
00079 numberOfHeartbeatsRcvd = 0;
00080 numberOfHeartbeatAcksSent = 0;
00081 numberOfHeartbeatAcksRcvd = 0;
00082
00083 char str[128];
00084 snprintf(str, sizeof(str), "HB_TIMER %d:%s",assoc->assocId,addr.str().c_str());
00085 HeartbeatTimer = new cMessage(str);
00086 snprintf(str, sizeof(str), "HB_INT_TIMER %d:%s",assoc->assocId,addr.str().c_str());
00087 HeartbeatIntervalTimer = new cMessage(str);
00088 snprintf(str, sizeof(str), "CWND_TIMER %d:%s",assoc->assocId,addr.str().c_str());
00089 CwndTimer = new cMessage(str);
00090 snprintf(str, sizeof(str), "RTX_TIMER %d:%s",assoc->assocId,addr.str().c_str());
00091 T3_RtxTimer = new cMessage(str);
00092 HeartbeatTimer->setContextPointer(association);
00093 HeartbeatIntervalTimer->setContextPointer(association);
00094 CwndTimer->setContextPointer(association);
00095 T3_RtxTimer->setContextPointer(association);
00096
00097 snprintf(str, sizeof(str), "RTO %d:%s",assoc->assocId,addr.str().c_str());
00098 statisticsPathRTO = new cOutVector(str);
00099 snprintf(str, sizeof(str), "RTT %d:%s",assoc->assocId,addr.str().c_str());
00100 statisticsPathRTT = new cOutVector(str);
00101
00102 snprintf(str, sizeof(str), "Slow Start Threshold %d:%s",assoc->assocId,addr.str().c_str());
00103 statisticsPathSSthresh = new cOutVector(str);
00104 snprintf(str, sizeof(str), "Congestion Window %d:%s",assoc->assocId,addr.str().c_str());
00105 statisticsPathCwnd = new cOutVector(str);
00106
00107 snprintf(str, sizeof(str), "TSN Sent %d:%s",assoc->assocId,addr.str().c_str());
00108 pathTSN = new cOutVector(str);
00109 snprintf(str, sizeof(str), "TSN Received %d:%s",assoc->assocId,addr.str().c_str());
00110 pathRcvdTSN = new cOutVector(str);
00111
00112 snprintf(str, sizeof(str), "HB Sent %d:%s",assoc->assocId,addr.str().c_str());
00113 pathHb = new cOutVector(str);
00114 snprintf(str, sizeof(str), "HB ACK Sent %d:%s",assoc->assocId,addr.str().c_str());
00115 pathHbAck = new cOutVector(str);
00116 snprintf(str, sizeof(str), "HB Received %d:%s",assoc->assocId,addr.str().c_str());
00117 pathRcvdHb = new cOutVector(str);
00118 snprintf(str, sizeof(str), "HB ACK Received %d:%s",assoc->assocId,addr.str().c_str());
00119 pathRcvdHbAck = new cOutVector(str);
00120
00121
00122
00123 SCTPPathInfo* pinfo = new SCTPPathInfo("pinfo");
00124 pinfo->setRemoteAddress(addr);
00125 T3_RtxTimer->setControlInfo(pinfo);
00126 HeartbeatTimer->setControlInfo(pinfo->dup());
00127 HeartbeatIntervalTimer->setControlInfo(pinfo->dup());
00128 CwndTimer->setControlInfo(pinfo->dup());
00129
00130 }
00131
00132 SCTPPathVariables::~SCTPPathVariables()
00133 {
00134 statisticsPathSSthresh->record(0);
00135 statisticsPathCwnd->record(0);
00136 delete statisticsPathSSthresh;
00137 delete statisticsPathCwnd;
00138 statisticsPathRTO->record(0);
00139 statisticsPathRTT->record(0);
00140 delete statisticsPathRTO;
00141 delete statisticsPathRTT;
00142
00143 delete pathTSN;
00144 delete pathRcvdTSN;
00145 delete pathHb;
00146 delete pathRcvdHb;
00147 delete pathHbAck;
00148 delete pathRcvdHbAck;
00149
00150 }
00151
00152
00153 const IPvXAddress SCTPDataVariables::zeroAddress = IPvXAddress("0.0.0.0");
00154
00155 SCTPDataVariables::SCTPDataVariables()
00156 {
00157 userData = NULL;
00158 ordered = true;
00159 len = 0;
00160 tsn = 0;
00161 sid = 0;
00162 ssn = 0;
00163 ppid = 0;
00164 gapReports = 0;
00165 enqueuingTime = 0;
00166 sendTime = 0;
00167 ackTime = 0;
00168 expiryTime = 0;
00169 enqueuedInTransmissionQ = false;
00170 hasBeenAcked = false;
00171 hasBeenReneged = false;
00172 hasBeenAbandoned = false;
00173 hasBeenFastRetransmitted = false;
00174 countsAsOutstanding = false;
00175 lastDestination = NULL;
00176 nextDestination = NULL;
00177 initialDestination = NULL;
00178 numberOfTransmissions = 0;
00179 numberOfRetransmissions = 0;
00180 booksize = 0;
00181 }
00182
00183 SCTPDataVariables::~SCTPDataVariables()
00184 {
00185 }
00186
00187 SCTPStateVariables::SCTPStateVariables()
00188 {
00189 active = false;
00190 fork = false;
00191 initReceived = false;
00192 cookieEchoReceived = false;
00193 ackPointAdvanced = false;
00194 swsAvoidanceInvoked = false;
00195 firstChunkReceived = false;
00196 probingIsAllowed = false;
00197 zeroWindowProbing = true;
00198 alwaysBundleSack = true;
00199 fastRecoverySupported = true;
00200 reactivatePrimaryPath = false;
00201 newChunkReceived = false;
00202 dataChunkReceived = false;
00203 sackAllowed = false;
00204 resetPending = false;
00205 stopReceiving = false;
00206 stopOldData = false;
00207 stopSending = false;
00208 inOut = false;
00209 queueUpdate = false;
00210 firstDataSent = false;
00211 peerWindowFull = false;
00212 zeroWindow = false;
00213 appSendAllowed = true;
00214 noMoreOutstanding = false;
00215 primaryPath = NULL;
00216 lastDataSourceAddress = IPvXAddress("0.0.0.0");
00217 shutdownChunk = NULL;
00218 initChunk = NULL;
00219 cookieChunk = NULL;
00220 sctpmsg = NULL;
00221 sctpMsg = NULL;
00222 bytesToRetransmit = 0;
00223 initRexmitTimeout = SCTP_TIMEOUT_INIT_REXMIT;
00224 localRwnd = SCTP_DEFAULT_ARWND;
00225 errorCount = 0;
00226 initRetransCounter = 0;
00227 nextTSN = 0;
00228 cTsnAck = 0;
00229 lastTsnAck = 0;
00230 highestTsnReceived = 0;
00231 highestTsnAcked = 0;
00232 highestTsnStored = 0;
00233 nextRSid = 0;
00234 ackState = 0;
00235 lastStreamScheduled = 0;
00236 peerRwnd = 0;
00237 initialPeerRwnd = 0;
00238 assocPmtu = 0;
00239 outstandingBytes = 0;
00240 messagesToPush = 0;
00241 pushMessagesLeft = 0;
00242 numGaps = 0;
00243 msgNum = 0;
00244 bytesRcvd = 0;
00245 sendBuffer = 0;
00246 queuedReceivedBytes = 0;
00247 lastSendQueueAbated = simTime();
00248 queuedMessages = 0;
00249 queueLimit = 0;
00250 probingTimeout = 1;
00251 numRequests = 0;
00252 numMsgsReq.resize(65536);
00253 for (unsigned int i = 0; i < 65536; i++) {
00254 numMsgsReq[i] = 0;
00255 }
00256 for (unsigned int i = 0; i < MAX_GAP_COUNT; i++) {
00257 gapStartList[i] = 0;
00258 gapStopList[i] = 0;
00259 }
00260 for (unsigned int i = 0; i < 32; i++) {
00261 localTieTag[i] = 0;
00262 peerTieTag[i] = 0;
00263 }
00264 count = 0;
00265 }
00266
00267 SCTPStateVariables::~SCTPStateVariables()
00268 {
00269 }
00270
00271
00272
00273
00274
00275
00276 SCTPAssociation::SCTPAssociation(SCTP* _module, int32 _appGateIndex, int32 _assocId)
00277 {
00278
00279 sctpMain = _module;
00280 appGateIndex = _appGateIndex;
00281 assocId = _assocId;
00282 localPort = 0;
00283 remotePort = 0;
00284 localVTag = 0;
00285 peerVTag = 0;
00286 numberOfRemoteAddresses = 0;
00287 inboundStreams = SCTP_DEFAULT_INBOUND_STREAMS;
00288 outboundStreams = SCTP_DEFAULT_OUTBOUND_STREAMS;
00289
00290 transmissionQ = NULL;
00291 retransmissionQ = NULL;
00292 sctpAlgorithm = NULL;
00293 state = NULL;
00294 sackPeriod = SACK_DELAY;
00295
00296
00297
00298
00299
00300 cumTsnAck = NULL;
00301 sendQueue = NULL;
00302 numGapBlocks = NULL;
00303
00304 qCounter.roomSumSendStreams = 0;
00305 qCounter.bookedSumSendStreams = 0;
00306 qCounter.roomSumRcvStreams = 0;
00307 bytes.chunk = false;
00308 bytes.packet = false;
00309 bytes.bytesToSend = 0;
00310
00311 sctpEV3 << "SCTPAssociationBase::SCTPAssociation(): new assocId="
00312 << assocId << endl;
00313
00314
00315 char fsmName[64];
00316 snprintf(fsmName, sizeof(fsmName), "fsm-%d", assocId);
00317 fsm = new cFSM();
00318 fsm->setName(fsmName);
00319 fsm->setState(SCTP_S_CLOSED);
00320
00321
00322
00323 SCTPPathInfo* pinfo = new SCTPPathInfo("pathInfo");
00324 pinfo->setRemoteAddress(IPvXAddress("0.0.0.0"));
00325
00326
00327 char timerName[128];
00328 snprintf(timerName, sizeof(timerName), "T1_INIT of Association %d", assocId);
00329 T1_InitTimer = new cMessage(timerName);
00330 snprintf(timerName, sizeof(timerName), "T2_SHUTDOWN of Association %d", assocId);
00331 T2_ShutdownTimer = new cMessage(timerName);
00332 snprintf(timerName, sizeof(timerName), "T5_SHUTDOWN_GUARD of Association %d", assocId);
00333 T5_ShutdownGuardTimer = new cMessage(timerName);
00334 snprintf(timerName, sizeof(timerName), "SACK_TIMER of Association %d", assocId);
00335 SackTimer = new cMessage(timerName);
00336
00337 if (sctpMain->testTimeout > 0){
00338 StartTesting = new cMessage("StartTesting");
00339 StartTesting->setContextPointer(this);
00340 StartTesting->setControlInfo(pinfo->dup());
00341 scheduleTimeout(StartTesting, sctpMain->testTimeout);
00342 }
00343 T1_InitTimer->setContextPointer(this);
00344 T2_ShutdownTimer->setContextPointer(this);
00345 SackTimer->setContextPointer(this);
00346 T5_ShutdownGuardTimer->setContextPointer(this);
00347
00348 T1_InitTimer->setControlInfo(pinfo);
00349 T2_ShutdownTimer->setControlInfo(pinfo->dup());
00350 SackTimer->setControlInfo(pinfo->dup());
00351 T5_ShutdownGuardTimer->setControlInfo(pinfo->dup());
00352
00353
00354 char vectorName[128];
00355 snprintf(vectorName, sizeof(vectorName), "Advertised Receiver Window %d", assocId);
00356 advRwnd = new cOutVector(vectorName);
00357
00358
00359 ssModule = sctpMain->par("ssModule");
00360 switch (ssModule)
00361 {
00362 case ROUND_ROBIN:
00363 ssFunctions.ssInitStreams = &SCTPAssociation::initStreams;
00364 ssFunctions.ssGetNextSid = &SCTPAssociation::streamScheduler;
00365 ssFunctions.ssUsableStreams = &SCTPAssociation::numUsableStreams;
00366 break;
00367 }
00368 }
00369
00370 SCTPAssociation::~SCTPAssociation()
00371 {
00372 sctpEV3 << "Destructor SCTPAssociation" << endl;
00373
00374 delete T1_InitTimer;
00375 delete T2_ShutdownTimer;
00376 delete T5_ShutdownGuardTimer;
00377 delete SackTimer;
00378
00379 delete advRwnd;
00380 delete cumTsnAck;
00381 delete numGapBlocks;
00382 delete sendQueue;
00383
00384
00385 delete fsm;
00386 delete state;
00387 delete sctpAlgorithm;
00388 }
00389
00390 bool SCTPAssociation::processTimer(cMessage *msg)
00391 {
00392 SCTPPathVariables* path = NULL;
00393
00394 sctpEV3 << msg->getName() << " timer expired at "<<simulation.getSimTime()<<"\n";
00395
00396 SCTPPathInfo* pinfo = check_and_cast<SCTPPathInfo*>(msg->getControlInfo());
00397 IPvXAddress addr = pinfo->getRemoteAddress();
00398
00399 if (addr != IPvXAddress("0.0.0.0"))
00400 path = getPath(addr);
00401
00402 SCTPEventCode event;
00403 event = SCTP_E_IGNORE;
00404 if (msg==T1_InitTimer)
00405 {
00406 process_TIMEOUT_INIT_REXMIT(event);
00407 }
00408 else if (msg==SackTimer)
00409 {
00410 sctpEV3<<simulation.getSimTime()<<" delayed Sack: cTsnAck="<<state->cTsnAck<<" highestTsnReceived="<<state->highestTsnReceived<<" lastTsnReceived="<<state->lastTsnReceived<<" ackState="<<state->ackState<<" numGaps="<<state->numGaps<<"\n";
00411 sendSack();
00412 }
00413 else if (msg==T2_ShutdownTimer)
00414 {
00415 stopTimer(T2_ShutdownTimer);
00416 process_TIMEOUT_SHUTDOWN(event);
00417 }
00418 else if (msg==T5_ShutdownGuardTimer)
00419 {
00420 stopTimer(T5_ShutdownGuardTimer);
00421 delete state->shutdownChunk;
00422 sendIndicationToApp(SCTP_I_CONN_LOST);
00423 sendAbort();
00424 sctpMain->removeAssociation(this);
00425 }
00426 else if (path!=NULL && msg==path->HeartbeatIntervalTimer)
00427 {
00428 process_TIMEOUT_HEARTBEAT_INTERVAL(path, path->forceHb);
00429 }
00430 else if (path!=NULL && msg==path->HeartbeatTimer)
00431 {
00432 process_TIMEOUT_HEARTBEAT(path);
00433 }
00434 else if (path!=NULL && msg==path->T3_RtxTimer)
00435 {
00436 process_TIMEOUT_RTX(path);
00437 }
00438 else if (path!=NULL && msg==path->CwndTimer)
00439 {
00440 (this->*ccFunctions.ccUpdateAfterCwndTimeout)(path);
00441 }
00442 else if (strcmp(msg->getName(), "StartTesting")==0)
00443 {
00444 if (sctpMain->testing == false)
00445 {
00446 sctpMain->testing = true;
00447 sctpEV3<<"set testing to true\n";
00448 }
00449 }
00450 else
00451 {
00452 sctpAlgorithm->processTimer(msg, event);
00453 }
00454
00455 return performStateTransition(event);
00456 }
00457
00458 bool SCTPAssociation::processSCTPMessage(SCTPMessage* sctpmsg,
00459 const IPvXAddress& msgSrcAddr,
00460 const IPvXAddress& msgDestAddr)
00461 {
00462 printConnBrief();
00463
00464 localAddr = msgDestAddr;
00465 localPort = sctpmsg->getDestPort();
00466 remoteAddr = msgSrcAddr;
00467 remotePort = sctpmsg->getSrcPort();
00468
00469 return process_RCV_Message(sctpmsg, msgSrcAddr, msgDestAddr);
00470 }
00471
00472 SCTPEventCode SCTPAssociation::preanalyseAppCommandEvent(int32 commandCode)
00473 {
00474 switch (commandCode) {
00475 case SCTP_C_ASSOCIATE: return SCTP_E_ASSOCIATE;
00476 case SCTP_C_OPEN_PASSIVE: return SCTP_E_OPEN_PASSIVE;
00477 case SCTP_C_SEND: return SCTP_E_SEND;
00478 case SCTP_C_CLOSE: return SCTP_E_CLOSE;
00479 case SCTP_C_ABORT: return SCTP_E_ABORT;
00480 case SCTP_C_RECEIVE: return SCTP_E_RECEIVE;
00481 case SCTP_C_SEND_UNORDERED: return SCTP_E_SEND;
00482 case SCTP_C_SEND_ORDERED: return SCTP_E_SEND;
00483 case SCTP_C_PRIMARY: return SCTP_E_PRIMARY;
00484 case SCTP_C_QUEUE_MSGS_LIMIT: return SCTP_E_QUEUE_MSGS_LIMIT;
00485 case SCTP_C_QUEUE_BYTES_LIMIT: return SCTP_E_QUEUE_BYTES_LIMIT;
00486 case SCTP_C_SHUTDOWN: return SCTP_E_SHUTDOWN;
00487 case SCTP_C_NO_OUTSTANDING: return SCTP_E_SEND_SHUTDOWN_ACK;
00488 default:
00489 sctpEV3<<"commandCode="<<commandCode<<"\n";
00490 opp_error("Unknown message kind in app command");
00491 return (SCTPEventCode)0;
00492 }
00493 }
00494
00495 bool SCTPAssociation::processAppCommand(cPacket *msg)
00496 {
00497 printConnBrief();
00498
00499
00500 SCTPCommand *sctpCommand = (SCTPCommand *)(msg->removeControlInfo());
00501 SCTPEventCode event = preanalyseAppCommandEvent(msg->getKind());
00502
00503 sctpEV3 << "App command: " << eventName(event) << "\n";
00504 switch (event)
00505 {
00506 case SCTP_E_ASSOCIATE: process_ASSOCIATE(event, sctpCommand, msg); break;
00507 case SCTP_E_OPEN_PASSIVE: process_OPEN_PASSIVE(event, sctpCommand, msg); break;
00508 case SCTP_E_SEND: process_SEND(event, sctpCommand, msg); break;
00509 case SCTP_E_CLOSE: process_CLOSE(event); break;
00510 case SCTP_E_ABORT: process_ABORT(event); break;
00511 case SCTP_E_RECEIVE: process_RECEIVE_REQUEST(event, sctpCommand); break;
00512 case SCTP_E_PRIMARY: process_PRIMARY(event, sctpCommand); break;
00513 case SCTP_E_QUEUE_BYTES_LIMIT: process_QUEUE_BYTES_LIMIT(sctpCommand); break;
00514 case SCTP_E_QUEUE_MSGS_LIMIT: process_QUEUE_MSGS_LIMIT(sctpCommand); break;
00515 case SCTP_E_SHUTDOWN:
00516 sctpEV3<<"SCTP_E_SHUTDOWN in state "<<stateName(fsm->getState())<<"\n";
00517 if (fsm->getState()==SCTP_S_SHUTDOWN_RECEIVED) {
00518 sctpEV3<<"send shutdown ack\n";
00519 sendShutdownAck(remoteAddr);
00520 }
00521 break;
00522 case SCTP_E_STOP_SENDING: break;
00523 case SCTP_E_SEND_SHUTDOWN_ACK:
00524
00525
00526
00527
00528
00529 break;
00530 default: opp_error("wrong event code");
00531 }
00532 delete sctpCommand;
00533
00534 return performStateTransition(event);
00535 }
00536
00537
00538 bool SCTPAssociation::performStateTransition(const SCTPEventCode& event)
00539 {
00540 sctpEV3<<"performStateTransition\n";
00541 if (event==SCTP_E_IGNORE)
00542 {
00543 ev << "Staying in state: " << stateName(fsm->getState()) << " (no FSM event)\n";
00544 return true;
00545 }
00546
00547
00548 int32 oldState = fsm->getState();
00549 switch (fsm->getState())
00550 {
00551 case SCTP_S_CLOSED:
00552 switch (event)
00553 {
00554 case SCTP_E_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00555 case SCTP_E_OPEN_PASSIVE: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00556 case SCTP_E_ASSOCIATE: FSM_Goto((*fsm), SCTP_S_COOKIE_WAIT); break;
00557 case SCTP_E_RCV_INIT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00558 case SCTP_E_RCV_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00559 case SCTP_E_RCV_VALID_COOKIE_ECHO: FSM_Goto((*fsm), SCTP_S_ESTABLISHED); break;
00560 case SCTP_E_CLOSE: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00561 default:;
00562 }
00563 break;
00564
00565 case SCTP_S_COOKIE_WAIT:
00566 switch (event)
00567 {
00568 case SCTP_E_RCV_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00569 case SCTP_E_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00570 case SCTP_E_RCV_INIT_ACK: FSM_Goto((*fsm), SCTP_S_COOKIE_ECHOED); break;
00571 case SCTP_E_RCV_VALID_COOKIE_ECHO: FSM_Goto((*fsm), SCTP_S_ESTABLISHED); break;
00572 default:;
00573 }
00574 break;
00575
00576 case SCTP_S_COOKIE_ECHOED:
00577 switch (event)
00578 {
00579 case SCTP_E_RCV_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00580 case SCTP_E_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00581 case SCTP_E_RCV_COOKIE_ACK:FSM_Goto((*fsm), SCTP_S_ESTABLISHED); break;
00582 default:;
00583 }
00584 break;
00585 case SCTP_S_ESTABLISHED:
00586 switch (event)
00587 {
00588 case SCTP_E_SEND: FSM_Goto((*fsm), SCTP_S_ESTABLISHED); break;
00589 case SCTP_E_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00590 case SCTP_E_RCV_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00591 case SCTP_E_SHUTDOWN: FSM_Goto((*fsm), SCTP_S_SHUTDOWN_PENDING); break;
00592 case SCTP_E_STOP_SENDING: FSM_Goto((*fsm), SCTP_S_SHUTDOWN_PENDING); state->stopSending = true; state->lastTSN = state->nextTSN-1; break;
00593 case SCTP_E_RCV_SHUTDOWN: FSM_Goto((*fsm), SCTP_S_SHUTDOWN_RECEIVED); break;
00594 case SCTP_E_CLOSE: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00595 default:;
00596 }
00597 break;
00598
00599 case SCTP_S_SHUTDOWN_PENDING:
00600 switch (event)
00601 {
00602 case SCTP_E_RCV_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00603 case SCTP_E_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00604 case SCTP_E_NO_MORE_OUTSTANDING: FSM_Goto((*fsm), SCTP_S_SHUTDOWN_SENT); break;
00605 case SCTP_E_RCV_SHUTDOWN: FSM_Goto((*fsm), SCTP_S_SHUTDOWN_RECEIVED); break;
00606 case SCTP_E_RCV_SHUTDOWN_ACK: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00607 default:;
00608 }
00609 break;
00610
00611 case SCTP_S_SHUTDOWN_RECEIVED:
00612 switch (event)
00613 {
00614 case SCTP_E_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00615 case SCTP_E_RCV_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00616 case SCTP_E_NO_MORE_OUTSTANDING:
00617 FSM_Goto((*fsm), SCTP_S_SHUTDOWN_ACK_SENT);
00618 break;
00619 case SCTP_E_SHUTDOWN: sendShutdownAck(remoteAddr); break;
00620 default:;
00621 }
00622 break;
00623
00624 case SCTP_S_SHUTDOWN_SENT:
00625 switch (event)
00626 {
00627 case SCTP_E_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00628 case SCTP_E_RCV_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00629 case SCTP_E_RCV_SHUTDOWN_ACK: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00630 case SCTP_E_RCV_SHUTDOWN: sendShutdownAck(remoteAddr); FSM_Goto((*fsm), SCTP_S_SHUTDOWN_ACK_SENT); break;
00631 default:;
00632 }
00633 break;
00634
00635 case SCTP_S_SHUTDOWN_ACK_SENT:
00636 switch (event)
00637 {
00638 case SCTP_E_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00639 case SCTP_E_RCV_ABORT: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00640 case SCTP_E_RCV_SHUTDOWN_COMPLETE: FSM_Goto((*fsm), SCTP_S_CLOSED); break;
00641 default:;
00642 }
00643 break;
00644
00645 }
00646
00647 if (oldState!=fsm->getState())
00648 {
00649 ev << "Transition: " << stateName(oldState) << " --> " << stateName(fsm->getState()) << " (event was: " << eventName(event) << ")\n";
00650 sctpEV3 << sctpMain->getName() << ": " << stateName(oldState) << " --> " << stateName(fsm->getState()) << " (on " << eventName(event) << ")\n";
00651 stateEntered(fsm->getState());
00652 }
00653 else
00654 {
00655 ev<< "Staying in state: " << stateName(fsm->getState()) << " (event was: " << eventName(event) << ")\n";
00656 }
00657 if (event==SCTP_E_ABORT && oldState==fsm->getState() && fsm->getState()==SCTP_S_CLOSED)
00658 return true;
00659
00660 if (oldState!=fsm->getState() && fsm->getState()==SCTP_S_CLOSED)
00661 {
00662 sctpEV3<<"return false because oldState="<<oldState<<" and new state is closed\n";
00663 return false;
00664 }
00665 else
00666 return true;
00667 }
00668
00669 void SCTPAssociation::stateEntered(int32 status)
00670 {
00671 switch (status)
00672 {
00673 case SCTP_S_COOKIE_WAIT:
00674 break;
00675 case SCTP_S_ESTABLISHED:
00676 {
00677 sctpEV3 << "State ESTABLISHED entered" << endl;
00678 stopTimer(T1_InitTimer);
00679 if (state->initChunk) {
00680 delete state->initChunk;
00681 }
00682 state->nagleEnabled = (bool)sctpMain->par("nagleEnabled");
00683 state->enableHeartbeats = (bool)sctpMain->par("enableHeartbeats");
00684 state->numGapReports = sctpMain->par("numGapReports");
00685 state->maxBurst = (uint32)sctpMain->par("maxBurst");
00686 state->header = 0;
00687 state->swsLimit = (uint32)sctpMain->par("swsLimit");
00688 state->fastRecoverySupported = (bool)sctpMain->par("fastRecoverySupported");
00689 state->reactivatePrimaryPath = (bool)sctpMain->par("reactivatePrimaryPath");
00690 sackPeriod = (double)sctpMain->par("sackPeriod");
00691 sackFrequency = sctpMain->par("sackFrequency");
00692 SCTP::AssocStat stat;
00693 stat.assocId = assocId;
00694 stat.start = simulation.getSimTime();
00695 stat.stop = 0;
00696 stat.rcvdBytes = 0;
00697 stat.ackedBytes = 0;
00698 stat.sentBytes = 0;
00699 stat.transmittedBytes = 0;
00700 stat.numFastRtx = 0;
00701 stat.numT3Rtx = 0;
00702 stat.numDups = 0;
00703 stat.numPathFailures = 0;
00704 stat.numForwardTsn = 0;
00705 stat.lifeTime = 0;
00706 stat.throughput = 0;
00707 sctpMain->assocStatMap[stat.assocId] = stat;
00708 ccModule = sctpMain->par("ccModule");
00709 switch (ccModule)
00710 {
00711 case RFC4960:
00712 {
00713 ccFunctions.ccInitParams = &SCTPAssociation::initCCParameters;
00714 ccFunctions.ccUpdateAfterSack = &SCTPAssociation::cwndUpdateAfterSack;
00715 ccFunctions.ccUpdateAfterCwndTimeout = &SCTPAssociation::cwndUpdateAfterCwndTimeout;
00716 ccFunctions.ccUpdateAfterRtxTimeout = &SCTPAssociation::cwndUpdateAfterRtxTimeout;
00717 ccFunctions.ccUpdateMaxBurst = &SCTPAssociation::cwndUpdateMaxBurst;
00718 ccFunctions.ccUpdateBytesAcked = &SCTPAssociation::cwndUpdateBytesAcked;
00719 break;
00720 }
00721 }
00722 pmStartPathManagement();
00723 state->sendQueueLimit = (uint32)sctpMain->par("sendQueueLimit");
00724 sendEstabIndicationToApp();
00725 char str[128];
00726 snprintf(str, sizeof(str), "Cumulated TSN Ack of Association %d", assocId);
00727 cumTsnAck = new cOutVector(str);
00728 snprintf(str, sizeof(str), "Number of Gap Blocks in Last SACK of Association %d", assocId);
00729 numGapBlocks = new cOutVector(str);
00730 snprintf(str, sizeof(str), "SendQueue of Association %d", assocId);
00731 sendQueue = new cOutVector(str);
00732 state->sendQueueLimit = (uint32)sctpMain->par("sendQueueLimit");
00733 SCTP::VTagPair vtagPair;
00734 vtagPair.peerVTag = peerVTag;
00735 vtagPair.localVTag = localVTag;
00736 vtagPair.localPort = localPort;
00737 vtagPair.remotePort = remotePort;
00738 sctpMain->sctpVTagMap[assocId] = vtagPair;
00739 break;
00740 }
00741 case SCTP_S_CLOSED:
00742 {
00743 sendIndicationToApp(SCTP_I_CLOSED);
00744 break;
00745 }
00746 case SCTP_S_SHUTDOWN_PENDING:
00747 {
00748 if (getOutstandingBytes()==0 && transmissionQ->getQueueSize()==0 && qCounter.roomSumSendStreams==0)
00749 sendShutdown();
00750 break;
00751 }
00752 case SCTP_S_SHUTDOWN_RECEIVED:
00753 {
00754 sctpEV3 << "Entered state SHUTDOWN_RECEIVED, osb=" << getOutstandingBytes()
00755 << ", transQ=" << transmissionQ->getQueueSize()
00756 << ", scount=" << qCounter.roomSumSendStreams << endl;
00757 if (getOutstandingBytes()==0 && transmissionQ->getQueueSize()==0 && qCounter.roomSumSendStreams==0) {
00758 sendShutdownAck(remoteAddr);
00759 }
00760 else {
00761 sendOnAllPaths(state->getPrimaryPath());
00762 }
00763 break;
00764 }
00765 }
00766 }
00767
00768 void SCTPAssociation::removePath()
00769 {
00770 SCTPPathMap::iterator pathIterator;
00771 while((pathIterator = sctpPathMap.begin()) != sctpPathMap.end())
00772 {
00773 SCTPPathVariables* path = pathIterator->second;
00774 sctpEV3 << getFullPath() << " remove path " << path->remoteAddress << endl;
00775 stopTimer(path->HeartbeatTimer);
00776 delete path->HeartbeatTimer;
00777 stopTimer(path->HeartbeatIntervalTimer);
00778 sctpEV3 << "delete timer " << path->HeartbeatIntervalTimer->getName() << endl;
00779 delete path->HeartbeatIntervalTimer;
00780 stopTimer(path->T3_RtxTimer);
00781 delete path->T3_RtxTimer;
00782 stopTimer(path->CwndTimer);
00783 delete path->CwndTimer;
00784 delete path;
00785 sctpPathMap.erase(pathIterator);
00786 }
00787 }