|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2005-2010 Irene Ruengeler 00003 // Copyright (C) 2009-2010 Thomas Dreibholz 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00017 // 00018 00019 #ifndef __SCTPASSOCIATION_H 00020 #define __SCTPASSOCIATION_H 00021 00022 #include <omnetpp.h> 00023 #include "IPvXAddress.h" 00024 #include "IPAddress.h" 00025 #include "SCTP.h" 00026 #include "RoutingTable.h" 00027 #include "RoutingTableAccess.h" 00028 #include "InterfaceTable.h" 00029 #include "InterfaceTableAccess.h" 00030 #include "SCTPQueue.h" 00031 #include "SCTPSendStream.h" 00032 #include "SCTPReceiveStream.h" 00033 #include "SCTPMessage.h" 00034 #include "IPControlInfo.h" 00035 #include <list> 00036 #include <iostream> 00037 #include <errno.h> 00038 #include <math.h> 00039 #include <platdep/intxtypes.h> 00040 #include "common.h" 00041 00042 00043 class SCTPMessage; 00044 class SCTPCommand; 00045 class SCTPOpenCommand; 00046 class SCTPReceiveStream; 00047 class SCTPSendStream; 00048 class SCTPAlgorithm; 00049 class SCTP; 00050 00051 typedef std::vector<IPvXAddress> AddressVector; 00052 00053 enum SctpState 00054 { 00055 SCTP_S_CLOSED = 0, 00056 SCTP_S_COOKIE_WAIT = FSM_Steady(1), 00057 SCTP_S_COOKIE_ECHOED = FSM_Steady(2), 00058 SCTP_S_ESTABLISHED = FSM_Steady(3), 00059 SCTP_S_SHUTDOWN_PENDING = FSM_Steady(4), 00060 SCTP_S_SHUTDOWN_SENT = FSM_Steady(5), 00061 SCTP_S_SHUTDOWN_RECEIVED = FSM_Steady(6), 00062 SCTP_S_SHUTDOWN_ACK_SENT = FSM_Steady(7) 00063 }; 00064 00065 00066 // 00067 // Event, strictly for the FSM state transition purposes. 00068 // DO NOT USE outside performStateTransition()! 00069 // 00070 enum SCTPEventCode 00071 { 00072 SCTP_E_ASSOCIATE, 00073 SCTP_E_OPEN_PASSIVE, 00074 SCTP_E_ABORT, 00075 SCTP_E_SHUTDOWN, 00076 SCTP_E_CLOSE, 00077 SCTP_E_SEND, 00078 SCTP_E_RCV_INIT, 00079 SCTP_E_RCV_ABORT, 00080 SCTP_E_RCV_VALID_COOKIE_ECHO, 00081 SCTP_E_RCV_INIT_ACK, 00082 SCTP_E_RCV_COOKIE_ACK, 00083 SCTP_E_RCV_SHUTDOWN, 00084 SCTP_E_RCV_SHUTDOWN_ACK, 00085 SCTP_E_RCV_SHUTDOWN_COMPLETE, 00086 SCTP_E_NO_MORE_OUTSTANDING, 00087 SCTP_E_TIMEOUT_INIT_TIMER, 00088 SCTP_E_TIMEOUT_SHUTDOWN_TIMER, 00089 SCTP_E_TIMEOUT_RTX_TIMER, 00090 SCTP_E_TIMEOUT_HEARTBEAT_TIMER, 00091 SCTP_E_IGNORE, 00092 SCTP_E_RECEIVE, 00093 SCTP_E_DUP_RECEIVED, 00094 SCTP_E_PRIMARY, 00095 SCTP_E_DELIVERED, 00096 SCTP_E_QUEUE_MSGS_LIMIT, 00097 SCTP_E_QUEUE_BYTES_LIMIT, 00098 SCTP_E_SEND_QUEUE_LIMIT, 00099 SCTP_E_SEND_SHUTDOWN_ACK, 00100 SCTP_E_STOP_SENDING 00101 }; 00102 00103 enum SCTPChunkTypes 00104 { 00105 DATA = 0, 00106 INIT = 1, 00107 INIT_ACK = 2, 00108 SACK = 3, 00109 HEARTBEAT = 4, 00110 HEARTBEAT_ACK = 5, 00111 ABORT = 6, 00112 SHUTDOWN = 7, 00113 SHUTDOWN_ACK = 8, 00114 ERRORTYPE = 9, 00115 COOKIE_ECHO = 10, 00116 COOKIE_ACK = 11, 00117 SHUTDOWN_COMPLETE = 14, 00118 00119 }; 00120 00121 00122 enum SCTPFlags 00123 { 00124 COMPLETE_MESG_UNORDERED = 1, 00125 COMPLETE_MESG_ORDERED = 0 00126 }; 00127 00128 00129 enum SCTPParameterTypes 00130 { 00131 UNRECOGNIZED_PARAMETER = 8, 00132 SUPPORTED_ADDRESS_TYPES = 12, 00133 }; 00134 00135 00136 00137 00138 enum SCTPCCModules 00139 { 00140 RFC4960 = 0 00141 }; 00142 00143 enum SCTPStreamSchedulers 00144 { 00145 ROUND_ROBIN = 0 00146 }; 00147 00148 00149 #define SCTP_COMMON_HEADER 12 // without options 00150 #define SCTP_INIT_CHUNK_LENGTH 20 00151 #define SCTP_DATA_CHUNK_LENGTH 16 00152 #define SCTP_SACK_CHUNK_LENGTH 16 00153 #define SCTP_HEARTBEAT_CHUNK_LENGTH 4 00154 #define SCTP_ABORT_CHUNK_LENGTH 4 00155 #define SCTP_COOKIE_ACK_LENGTH 4 00156 #define SCTP_FORWARD_TSN_CHUNK_LENGTH 8 00157 #define SCTP_SHUTDOWN_CHUNK_LENGTH 8 00158 #define SCTP_SHUTDOWN_ACK_LENGTH 4 00159 #define SCTP_ERROR_CHUNK_LENGTH 4 // without parameters 00160 #define IP_HEADER_LENGTH 20 00161 #define SCTP_DEFAULT_ARWND (1<<16) 00162 #define SCTP_DEFAULT_INBOUND_STREAMS 17 00163 #define SCTP_DEFAULT_OUTBOUND_STREAMS 17 00164 #define VALID_COOKIE_LIFE_TIME 10 00165 #define SCTP_COOKIE_LENGTH 76 00166 #define HB_INTERVAL 30 00167 #define PATH_MAX_RETRANS 5 00168 00169 #define SCTP_TIMEOUT_INIT_REXMIT 3 // initially 3 seconds 00170 #define SCTP_TIMEOUT_INIT_REXMIT_MAX 240 // 4 mins 00171 #define SACK_DELAY 0.2 00172 #define RTO_BETA 0.25 00173 #define RTO_ALPHA 0.125 00174 #define RTO_INITIAL 3 00175 #define IPTOS_DEFAULT 0x10 // IPTOS_LOWDELAY 00176 00177 #define DEFAULT_MAX_SENDQUEUE 0 /* unlimited send queue */ 00178 #define DEFAULT_MAX_RECVQUEUE 0 /* unlimited recv queue - unused really */ 00179 00180 #define MAX_ASSOCS 10 00181 00182 #define SCTP_MAX_PAYLOAD 1488 // 12 bytes for common header 00183 00184 #define MAX_GAP_COUNT 500 00185 #define MAX_GAP_REPORTS 4 00186 #define ADD_PADDING(x) ((((x) + 3) >> 2) << 2) 00187 00188 #define DEBUG 1 00189 00190 #define SHUTDOWN_GUARD_TIMEOUT 180 00191 00195 inline double min(const double a, const double b) { return (a < b) ? a : b; } 00196 00200 inline double max(const double a, const double b) { return (a < b) ? b : a; } 00201 00202 00203 class INET_API SCTPPathVariables : public cPolymorphic 00204 { 00205 public: 00206 SCTPPathVariables(const IPvXAddress& addr, SCTPAssociation* assoc); 00207 ~SCTPPathVariables(); 00208 00209 SCTPAssociation* association; 00210 IPvXAddress remoteAddress; 00211 00212 // ====== Path Management ============================================= 00213 bool activePath; 00214 bool confirmed; 00215 bool requiresRtx; 00216 bool primaryPathCandidate; 00217 bool forceHb; 00218 // ====== T3 Timer Handling =========================================== 00219 // Set to TRUE when CumAck has acknowledged TSNs on this path. 00220 // Needed to reset T3 timer. 00221 bool newCumAck; // T.D. 05.12.2009 00222 // ====== Path Status ================================================= 00223 uint32 pathErrorCount; 00224 uint32 pathErrorThreshold; 00225 uint32 pmtu; 00226 // ====== Congestion Control ========================================== 00227 uint32 cwnd; 00228 uint32 ssthresh; 00229 uint32 partialBytesAcked; 00230 uint32 queuedBytes; // T.D. 19.02.2010 00231 uint32 outstandingBytes; 00232 // ~~~~~~ Temporary storage for SACK handling ~~~~~~~ 00233 uint32 outstandingBytesBeforeUpdate; // T.D. 20.10.2009 00234 uint32 newlyAckedBytes; // T.D. 20.10.2009 00235 // ====== Fast Recovery =============================================== 00236 bool fastRecoveryActive; // T.D. 21.11.2009 00237 uint32 fastRecoveryExitPoint; // T.D. 21.11.2009 00238 simtime_t fastRecoveryEnteringTime; // T.D. 03.12.2009 00239 // ====== Lowest TSN (used for triggering T3 RTX Timer Restart) ======= 00240 bool findLowestTSN; // T.D. 08.12.2009 00241 bool lowestTSNRetransmitted; // T.D. 08.12.2009 00242 00243 // ====== Timers ====================================================== 00244 cMessage* HeartbeatTimer; 00245 cMessage* HeartbeatIntervalTimer; 00246 cMessage* CwndTimer; 00247 cMessage* T3_RtxTimer; 00248 00249 // ====== Path Status ================================================= 00250 simtime_t heartbeatTimeout; 00251 simtime_t heartbeatIntervalTimeout; 00252 simtime_t rtxTimeout; 00253 simtime_t cwndTimeout; 00254 simtime_t updateTime; 00255 simtime_t lastAckTime; 00256 simtime_t pathRto; 00257 simtime_t srtt; 00258 simtime_t rttvar; 00259 00260 // ====== Path Statistics ============================================= 00261 unsigned int gapAcksInLastSACK; 00262 unsigned int gapNAcksInLastSACK; 00263 unsigned int numberOfDuplicates; 00264 unsigned int numberOfFastRetransmissions; 00265 unsigned int numberOfTimerBasedRetransmissions; 00266 unsigned int numberOfHeartbeatsSent; 00267 unsigned int numberOfHeartbeatAcksSent; 00268 unsigned int numberOfHeartbeatsRcvd; 00269 unsigned int numberOfHeartbeatAcksRcvd; 00270 00271 // ====== Output Vectors ============================================== 00272 cOutVector* pathTSN; 00273 cOutVector* pathRcvdTSN; 00274 cOutVector* pathHb; 00275 cOutVector* pathRcvdHb; 00276 cOutVector* pathHbAck; 00277 cOutVector* pathRcvdHbAck; 00278 cOutVector* statisticsPathRTO; 00279 cOutVector* statisticsPathRTT; 00280 cOutVector* statisticsPathSSthresh; 00281 cOutVector* statisticsPathCwnd; 00282 }; 00283 00284 00285 00286 class INET_API SCTPDataVariables : public cPolymorphic 00287 { 00288 public: 00289 SCTPDataVariables(); 00290 ~SCTPDataVariables(); 00291 00292 inline void setInitialDestination(SCTPPathVariables* path) { 00293 initialDestination = path; 00294 } 00295 inline const IPvXAddress& getInitialDestination() const { 00296 if(initialDestination != NULL) { 00297 return(initialDestination->remoteAddress); 00298 } 00299 return(zeroAddress); 00300 } 00301 inline SCTPPathVariables* getInitialDestinationPath() const { 00302 return(initialDestination); 00303 } 00304 00305 inline void setLastDestination(SCTPPathVariables* path) { 00306 lastDestination = path; 00307 } 00308 inline const IPvXAddress& getLastDestination() const { 00309 if(lastDestination != NULL) { 00310 return(lastDestination->remoteAddress); 00311 } 00312 return(zeroAddress); 00313 } 00314 inline SCTPPathVariables* getLastDestinationPath() const { 00315 return(lastDestination); 00316 } 00317 00318 inline void setNextDestination(SCTPPathVariables* path) { 00319 nextDestination = path; 00320 } 00321 inline const IPvXAddress& getNextDestination() const { 00322 if(nextDestination != NULL) { 00323 return(nextDestination->remoteAddress); 00324 } 00325 return(zeroAddress); 00326 } 00327 inline SCTPPathVariables* getNextDestinationPath() const { 00328 return(nextDestination); 00329 } 00330 00331 cPacket* userData; 00332 uint32 len; // Different from wire 00333 uint32 booksize; 00334 uint32 tsn; 00335 uint16 sid; 00336 uint16 ssn; 00337 bool enqueuedInTransmissionQ; // In transmissionQ? Otherwise, it is just in retransmissionQ. 00338 bool countsAsOutstanding; // Is chunk outstanding? 00339 bool hasBeenFastRetransmitted; 00340 bool hasBeenAbandoned; 00341 bool hasBeenReneged; // Has chunk been reneged? 00342 bool hasBeenAcked; // Has chunk been SACK'ed? 00343 bool bbit; 00344 bool ebit; 00345 bool ordered; 00346 uint32 ppid; 00347 uint32 gapReports; 00348 simtime_t enqueuingTime; 00349 simtime_t sendTime; 00350 simtime_t ackTime; 00351 simtime_t expiryTime; 00352 uint32 numberOfRetransmissions; 00353 uint32 numberOfTransmissions; 00354 uint32 allowedNoRetransmissions; 00355 00356 public: 00357 static const IPvXAddress zeroAddress; 00358 00359 private: 00360 SCTPPathVariables* initialDestination; 00361 SCTPPathVariables* lastDestination; 00362 SCTPPathVariables* nextDestination; 00363 }; 00364 00365 00366 00367 class INET_API SCTPStateVariables : public cPolymorphic 00368 { 00369 public: 00370 SCTPStateVariables(); 00371 ~SCTPStateVariables(); 00372 public: 00373 inline void setPrimaryPath(SCTPPathVariables* path) { 00374 primaryPath = path; 00375 } 00376 inline const IPvXAddress& getPrimaryPathIndex() const { 00377 if(primaryPath != NULL) { 00378 return(primaryPath->remoteAddress); 00379 } 00380 return(SCTPDataVariables::zeroAddress); 00381 } 00382 inline SCTPPathVariables* getPrimaryPath() const { 00383 return(primaryPath); 00384 } 00385 00386 bool active; 00387 bool fork; 00388 bool ackPointAdvanced; 00389 bool dataChunkReceived; 00390 bool initReceived; 00391 bool cookieEchoReceived; 00392 bool newChunkReceived; 00393 bool firstChunkReceived; 00394 bool swsAvoidanceInvoked; 00395 bool probingIsAllowed; 00396 bool zeroWindowProbing; 00397 bool alwaysBundleSack; 00398 bool fastRecoverySupported; 00399 bool nagleEnabled; 00400 bool sackAllowed; 00401 bool reactivatePrimaryPath; 00402 bool resetPending; 00403 bool stopReceiving; // incoming data will be discarded 00404 bool stopOldData; // data with TSN<peerTsnAfterReset will be discarded 00405 bool queueUpdate; 00406 bool firstDataSent; 00407 bool peerWindowFull; 00408 bool zeroWindow; 00409 bool stopSending; // will be called when SCTP_E_SHUTDOWN arrived 00410 bool inOut; 00411 bool noMoreOutstanding; 00412 uint32 numGapReports; 00413 IPvXAddress initialPrimaryPath; 00414 IPvXAddress lastDataSourceAddress; 00415 AddressVector localAddresses; 00416 std::list<uint32> dupList; 00417 uint32 errorCount; // overall error counter 00418 uint64 peerRwnd; 00419 uint64 initialPeerRwnd; 00420 uint64 localRwnd; 00421 uint32 nextTSN; // TSN to be sent 00422 uint32 lastTsnAck; // stored at the sender side; cumTSNAck announced in a SACK 00423 uint32 cTsnAck; // will be put in the SACK chunk 00424 uint32 highestTsnReceived; // will be set when DATA chunk arrived 00425 uint32 highestTsnAcked; 00426 uint32 highestTsnStored; // used to compare Tsns in makeRoomForTsn 00427 uint32 lastTsnReceived; // SACK 00428 uint32 lastTSN; // my very last TSN to be sent 00429 uint32 ackState; // number of packets to be acknowledged 00430 uint32 numGaps; 00431 uint32 gapStartList[MAX_GAP_COUNT]; 00432 uint32 gapStopList[MAX_GAP_COUNT]; 00433 uint64 outstandingBytes; // Number of bytes outstanding 00434 uint64 queuedReceivedBytes; // Number of bytes in receiver queue 00435 uint32 lastStreamScheduled; 00436 uint32 assocPmtu; // smallest overall path mtu 00437 uint32 msgNum; // indicates the sequence number of the message 00438 uint64 bytesRcvd; 00439 uint32 numRequests; 00440 uint32 bytesToRetransmit; 00441 uint32 messagesToPush; 00442 int32 pushMessagesLeft; 00443 uint32 count; 00444 uint8 localTieTag[32]; 00445 uint8 peerTieTag[32]; 00446 uint64 queuedMessages; // Messages buffered at the sender side 00447 uint32 messageAcceptLimit; 00448 uint32 queueLimit; 00449 uint16 header; 00450 int32 probingTimeout; 00451 std::vector<int32> numMsgsReq; 00452 int32 cookieLifeTime; 00454 int16 initRetransCounter; 00455 simtime_t initRexmitTimeout; 00457 SCTPInitChunk* initChunk; 00459 SCTPCookieEchoChunk* cookieChunk; 00461 SCTPShutdownChunk* shutdownChunk; 00462 SCTPShutdownAckChunk* shutdownAckChunk; 00463 SCTPMessage* sctpmsg; 00464 uint64 sendQueueLimit; 00465 uint64 sendBuffer; 00466 bool appSendAllowed; 00467 simtime_t lastSendQueueAbated; 00468 uint32 nextRSid; 00469 uint32 swsLimit; 00470 bool lastMsgWasFragment; 00471 bool enableHeartbeats; 00472 SCTPMessage* sctpMsg; 00473 uint16 chunksAdded; 00474 uint16 dataChunksAdded; 00475 uint32 packetBytes; 00476 bool authAdded; 00477 // ====== Max Burst =================================================== 00478 uint32 maxBurst; 00479 bool ssNextStream; 00480 bool ssLastDataChunkSizeSet; 00481 00482 private: 00483 SCTPPathVariables* primaryPath; 00484 }; 00485 00486 00487 00488 class INET_API SCTPAssociation : public cObject 00489 { 00490 friend class SCTP; 00491 friend class SCTPPathVariables; 00492 00493 // map for storing the path parameters 00494 typedef std::map<IPvXAddress,SCTPPathVariables*> SCTPPathMap; 00495 // map for storing the queued bytes per path 00496 typedef std::map<IPvXAddress, uint32> CounterMap; 00497 typedef struct counter { 00498 uint64 roomSumSendStreams; 00499 uint64 bookedSumSendStreams; 00500 uint64 roomSumRcvStreams; 00501 CounterMap roomTransQ; 00502 CounterMap bookedTransQ; 00503 CounterMap roomRetransQ; 00504 } QueueCounter; 00505 typedef struct calcBytesToSend { 00506 bool chunk; 00507 bool packet; 00508 uint32 bytesToSend; 00509 } BytesToBeSent; 00510 typedef struct congestionControlFunctions { 00511 void (SCTPAssociation::*ccInitParams)(SCTPPathVariables* path); 00512 void (SCTPAssociation::*ccUpdateAfterSack)(); 00513 void (SCTPAssociation::*ccUpdateAfterCwndTimeout)(SCTPPathVariables* path); 00514 void (SCTPAssociation::*ccUpdateAfterRtxTimeout)(SCTPPathVariables* path); 00515 void (SCTPAssociation::*ccUpdateMaxBurst)(SCTPPathVariables* path); 00516 void (SCTPAssociation::*ccUpdateBytesAcked)(SCTPPathVariables* path, const uint32 ackedBytes, const bool ctsnaAdvanced); 00517 } CCFunctions; 00518 typedef std::map<uint32, SCTPSendStream*> SCTPSendStreamMap; 00519 typedef std::map<uint32, SCTPReceiveStream*> SCTPReceiveStreamMap; 00520 00521 public: 00522 // connection identification by apps: appgateIndex+assocId 00523 int32 appGateIndex; // Application gate index 00524 int32 assocId; // Identifies connection within the app 00525 IPvXAddress remoteAddr; // Remote address from last message 00526 IPvXAddress localAddr; // Local address from last message 00527 uint16 localPort; // Remote port from last message 00528 uint16 remotePort; // Local port from last message 00529 uint32 localVTag; // Local verification tag 00530 uint32 peerVTag; // Remote verification tag 00531 bool listen; 00532 00533 // Timers 00534 cMessage* T1_InitTimer; 00535 cMessage* T2_ShutdownTimer; 00536 cMessage* T5_ShutdownGuardTimer; 00537 cMessage* SackTimer; 00538 cMessage* StartTesting; 00539 00540 protected: 00541 AddressVector localAddressList; 00542 AddressVector remoteAddressList; 00543 uint32 numberOfRemoteAddresses; 00544 uint32 inboundStreams; 00545 uint32 outboundStreams; 00546 00547 int32 status; 00548 uint32 initTsn; 00549 uint32 initPeerTsn; 00550 uint32 sackFrequency; 00551 double sackPeriod; 00552 CCFunctions ccFunctions; 00553 uint16 ccModule; 00554 00555 cOutVector* advRwnd; 00556 cOutVector* cumTsnAck; 00557 cOutVector* sendQueue; 00558 cOutVector* numGapBlocks; 00559 00560 // Variables associated with the state of this association 00561 SCTPStateVariables* state; 00562 BytesToBeSent bytes; 00563 SCTP* sctpMain; // SCTP module 00564 cFSM* fsm; // SCTP state machine 00565 SCTPPathMap sctpPathMap; 00566 QueueCounter qCounter; 00567 SCTPQueue* transmissionQ; 00568 SCTPQueue* retransmissionQ; 00569 SCTPSendStreamMap sendStreams; 00570 SCTPReceiveStreamMap receiveStreams; 00571 SCTPAlgorithm* sctpAlgorithm; 00572 00573 public: 00577 SCTPAssociation(SCTP* mod, int32 appGateIndex, int32 assocId); 00581 ~SCTPAssociation(); 00585 void sendOnPath(SCTPPathVariables* pathId, const bool firstPass = true); 00586 void sendOnAllPaths(SCTPPathVariables* firstPath); 00587 00589 static const char* indicationName(const int32 code); 00590 00591 /* @name Various getters */ 00593 inline int32 getFsmState() const { return fsm->getState(); }; 00594 inline SCTPStateVariables* getState() const { return state; }; 00595 inline SCTPQueue* getTransmissionQueue() const { return transmissionQ; }; 00596 inline SCTPQueue* getRetransmissionQueue() const { return retransmissionQ; }; 00597 inline SCTPAlgorithm* getSctpAlgorithm() const { return sctpAlgorithm; }; 00598 inline SCTP* getSctpMain() const { return sctpMain; }; 00599 inline cFSM* getFsm() const { return fsm; }; 00600 inline cMessage* getInitTimer() const { return T1_InitTimer; }; 00601 inline cMessage* getShutdownTimer() const { return T2_ShutdownTimer; }; 00602 inline cMessage* getSackTimer() const { return SackTimer; }; 00603 00605 static const char* stateName(const int32 state); 00606 00607 static uint32 chunkToInt(const char* type); 00608 00609 /* Process self-messages (timers). 00610 * Normally returns true. A return value of false means that the 00611 * connection structure must be deleted by the caller (SCTPMain). 00612 */ 00613 bool processTimer(cMessage* msg); 00619 bool processSCTPMessage(SCTPMessage* sctpmsg, const IPvXAddress& srcAddr, const IPvXAddress& destAddr); 00625 bool processAppCommand(cPacket* msg); 00626 void removePath(); 00627 void removePath(const IPvXAddress& addr); 00628 void deleteStreams(); 00629 void stopTimer(cMessage* timer); 00630 void stopTimers(); 00631 inline SCTPPathVariables* getPath(const IPvXAddress& pathId) const { 00632 SCTPPathMap::const_iterator iterator = sctpPathMap.find(pathId); 00633 if (iterator !=sctpPathMap.end()) { 00634 return iterator->second; 00635 } 00636 return NULL; 00637 } 00638 void printSctpPathMap() const; 00639 00640 00641 protected: 00645 SCTPEventCode preanalyseAppCommandEvent(int32 commandCode); 00647 bool performStateTransition(const SCTPEventCode& event); 00648 void stateEntered(int32 state); 00650 00652 void process_ASSOCIATE(SCTPEventCode& event, SCTPCommand* sctpCommand, cPacket* msg); 00653 void process_OPEN_PASSIVE(SCTPEventCode& event, SCTPCommand* sctpCommand, cPacket* msg); 00654 void process_SEND(SCTPEventCode& event, SCTPCommand* sctpCommand, cPacket* msg); 00655 void process_CLOSE(SCTPEventCode& event); 00656 void process_ABORT(SCTPEventCode& event); 00657 void process_STATUS(SCTPEventCode& event, SCTPCommand* sctpCommand, cPacket* msg); 00658 void process_RECEIVE_REQUEST(SCTPEventCode& event, SCTPCommand* sctpCommand); 00659 void process_PRIMARY(SCTPEventCode& event, SCTPCommand* sctpCommand); 00661 00664 bool process_RCV_Message(SCTPMessage* sctpseg, const IPvXAddress& src, const IPvXAddress& dest); 00668 bool processInitArrived(SCTPInitChunk* initChunk, int32 sport, int32 dport); 00669 bool processInitAckArrived(SCTPInitAckChunk* initAckChunk); 00670 bool processCookieEchoArrived(SCTPCookieEchoChunk* cookieEcho, IPvXAddress addr); 00671 bool processCookieAckArrived(); 00672 SCTPEventCode processDataArrived(SCTPDataChunk* dataChunk); 00673 SCTPEventCode processSackArrived(SCTPSackChunk* sackChunk); 00674 SCTPEventCode processHeartbeatAckArrived(SCTPHeartbeatAckChunk* heartbeatack, SCTPPathVariables* path); 00676 00679 int32 process_TIMEOUT_RTX(SCTPPathVariables* path); 00680 void process_TIMEOUT_HEARTBEAT(SCTPPathVariables* path); 00681 void process_TIMEOUT_HEARTBEAT_INTERVAL(SCTPPathVariables* path, bool force); 00682 void process_TIMEOUT_INIT_REXMIT(SCTPEventCode& event); 00683 void process_TIMEOUT_PROBING(); 00684 void process_TIMEOUT_SHUTDOWN(SCTPEventCode& event); 00685 int32 updateCounters(SCTPPathVariables* path); 00687 00688 void startTimer(cMessage* timer, const simtime_t& timeout); 00689 00691 SCTPAssociation* cloneAssociation(); 00692 00694 void initAssociation(SCTPOpenCommand* openCmd); 00695 00697 bool tsnIsDuplicate(const uint32 tsn) const; 00698 bool advanceCtsna(); 00699 bool updateGapList(const uint32 tsn); 00700 void removeFromGapList(const uint32 removedTsn); 00701 bool makeRoomForTsn(const uint32 tsn, const uint32 length, const bool uBit); 00702 00704 void sendInit(); 00705 void sendInitAck(SCTPInitChunk* initchunk); 00706 void sendCookieEcho(SCTPInitAckChunk* initackchunk); 00707 void sendCookieAck(const IPvXAddress& dest); 00708 void sendAbort(); 00709 void sendHeartbeat(const SCTPPathVariables* path); 00710 void sendHeartbeatAck(const SCTPHeartbeatChunk* heartbeatChunk, 00711 const IPvXAddress& src, 00712 const IPvXAddress& dest); 00713 void sendSack(); 00714 void sendShutdown(); 00715 void sendShutdownAck(const IPvXAddress& dest); 00716 void sendShutdownComplete(); 00717 SCTPSackChunk* createSack(); 00719 void retransmitInit(); 00720 void retransmitCookieEcho(); 00721 void retransmitShutdown(); 00722 void retransmitShutdownAck(); 00723 00725 void sendToIP(SCTPMessage* sctpmsg, const IPvXAddress& dest, const bool qs = false); 00726 inline void sendToIP(SCTPMessage* sctpmsg, const bool qs = false) { 00727 sendToIP(sctpmsg, remoteAddr, qs); 00728 } 00729 void recordInPathVectors(SCTPMessage* pMsg, const IPvXAddress& rDest); 00730 void scheduleSack(); 00732 void signalConnectionTimeout(); 00733 00735 inline void scheduleTimeout(cMessage* msg, const simtime_t& timeout) { 00736 sctpMain->scheduleAt(simulation.getSimTime() + timeout, msg); 00737 } 00738 00740 inline cMessage* cancelEvent(cMessage* msg) { 00741 return sctpMain->cancelEvent(msg); 00742 } 00743 00745 void sendToApp(cPacket* msg); 00746 00748 void sendIndicationToApp(const int32 code, const int32 value = 0); 00749 00751 void sendEstabIndicationToApp(); 00752 void pushUlp(); 00753 void sendDataArrivedNotification(uint16 sid); 00754 void putInDeliveryQ(uint16 sid); 00756 void printConnBrief(); 00758 static void printSegmentBrief(SCTPMessage* sctpmsg); 00759 00760 00762 static const char* eventName(const int32 event); 00763 00764 void addPath(const IPvXAddress& addr); 00765 SCTPPathVariables* getNextPath(const SCTPPathVariables* oldPath) const; 00766 inline const IPvXAddress& getNextAddress(const SCTPPathVariables* oldPath) const { 00767 const SCTPPathVariables* nextPath = getNextPath(oldPath); 00768 if(nextPath != NULL) { 00769 return(nextPath->remoteAddress); 00770 } 00771 return(SCTPDataVariables::zeroAddress); 00772 } 00773 SCTPPathVariables* getNextDestination(SCTPDataVariables* chunk) const; 00774 00775 void bytesAllowedToSend(SCTPPathVariables* path, const bool firstPass); 00776 00777 void pathStatusIndication(const SCTPPathVariables* path, const bool status); 00778 00779 bool allPathsInactive() const; 00780 00784 SCTPDataChunk* transformDataChunk(SCTPDataVariables* chunk); 00785 SCTPDataVariables* makeVarFromMsg(SCTPDataChunk* datachunk); 00786 00791 int32 streamScheduler(bool peek); 00792 void initStreams(uint32 inStreams, uint32 outStreams); 00793 int32 numUsableStreams(); 00794 typedef struct streamSchedulingFunctions { 00795 void (SCTPAssociation::*ssInitStreams)(uint32 inStreams, uint32 outStreams); 00796 int32 (SCTPAssociation::*ssGetNextSid)(bool peek); 00797 int32 (SCTPAssociation::*ssUsableStreams)(); 00798 } SSFunctions; 00799 SSFunctions ssFunctions; 00800 uint16 ssModule; 00801 00805 void process_QUEUE_MSGS_LIMIT(const SCTPCommand* sctpCommand); 00806 void process_QUEUE_BYTES_LIMIT(const SCTPCommand* sctpCommand); 00807 int32 getOutstandingBytes() const; 00808 uint32 dequeueAckedChunks(const uint32 tsna, 00809 SCTPPathVariables* path, 00810 simtime_t& rttEstimation); 00811 SCTPDataMsg* peekOutboundDataMsg(); 00812 SCTPDataVariables* peekAbandonedChunk(const SCTPPathVariables* path); 00813 SCTPDataVariables* getOutboundDataChunk(const SCTPPathVariables* path, 00814 const int32 availableSpace, 00815 const int32 availableCwnd); 00816 SCTPDataMsg* dequeueOutboundDataMsg(const int32 availableSpace, 00817 const int32 availableCwnd); 00818 bool nextChunkFitsIntoPacket(int32 bytes); 00819 void putInTransmissionQ(uint32 tsn, SCTPDataVariables* chunk); 00823 void pmStartPathManagement(); 00824 void pmDataIsSentOn(SCTPPathVariables* path); 00825 void pmClearPathCounter(SCTPPathVariables* path); 00826 void pmRttMeasurement(SCTPPathVariables* path, 00827 const simtime_t& rttEstimation); 00831 inline static int32 tsnLt (const uint32 tsn1, const uint32 tsn2) { return ((int32)(tsn1-tsn2)<0); } 00832 inline static int32 tsnLe (const uint32 tsn1, const uint32 tsn2) { return ((int32)(tsn1-tsn2)<=0); } 00833 inline static int32 tsnGe (const uint32 tsn1, const uint32 tsn2) { return ((int32)(tsn1-tsn2)>=0); } 00834 inline static int32 tsnGt (const uint32 tsn1, const uint32 tsn2) { return ((int32)(tsn1-tsn2)>0); } 00835 inline static int32 tsnBetween (const uint32 tsn1, const uint32 midtsn, const uint32 tsn2) { return ((tsn2-tsn1)>=(midtsn-tsn1)); } 00836 00837 inline static int16 ssnGt (const uint16 ssn1, const uint16 ssn2) { return ((int16)(ssn1-ssn2)>0); } 00838 00839 void disposeOf(SCTPMessage* sctpmsg); 00840 void tsnWasReneged(SCTPDataVariables* chunk, 00841 const int type); 00842 void printOutstandingTsns(); 00843 00845 void initCCParameters(SCTPPathVariables* path); 00846 void updateFastRecoveryStatus(const uint32 lastTsnAck); 00847 void cwndUpdateAfterSack(); 00848 void cwndUpdateAfterCwndTimeout(SCTPPathVariables* path); 00849 void cwndUpdateAfterRtxTimeout(SCTPPathVariables* path); 00850 void cwndUpdateMaxBurst(SCTPPathVariables* path); 00851 void cwndUpdateBytesAcked(SCTPPathVariables* path, 00852 const uint32 ackedBytes, 00853 const bool ctsnaAdvanced); 00854 00855 private: 00856 SCTPDataVariables* makeDataVarFromDataMsg(SCTPDataMsg* datMsg, 00857 SCTPPathVariables* path); 00858 SCTPPathVariables* choosePathForRetransmission(); 00859 void timeForSack(bool& sackOnly, bool& sackWithData); 00860 void recordCwndUpdate(SCTPPathVariables* path); 00861 void handleChunkReportedAsAcked(uint32& highestNewAck, 00862 simtime_t& rttEstimation, 00863 SCTPDataVariables* myChunk, 00864 SCTPPathVariables* sackPath); 00865 void handleChunkReportedAsMissing(const SCTPSackChunk* sackChunk, 00866 const uint32 highestNewAck, 00867 SCTPDataVariables* myChunk, 00868 const SCTPPathVariables* sackPath); 00869 void moveChunkToOtherPath(SCTPDataVariables* chunk, 00870 SCTPPathVariables* newPath); 00871 void decreaseOutstandingBytes(SCTPDataVariables* chunk); 00872 void increaseOutstandingBytes(SCTPDataVariables* chunk, 00873 SCTPPathVariables* path); 00874 int32 calculateBytesToSendOnPath(const SCTPPathVariables* pathVar); 00875 void storePacket(SCTPPathVariables* pathVar, 00876 SCTPMessage* sctpMsg, 00877 const uint16 chunksAdded, 00878 const uint16 dataChunksAdded, 00879 const uint32 packetBytes, 00880 const bool authAdded); 00881 void loadPacket(SCTPPathVariables* pathVar, 00882 SCTPMessage** sctpMsg, 00883 uint16* chunksAdded, 00884 uint16* dataChunksAdded, 00885 uint32* packetBytes, 00886 bool* authAdded); 00887 inline void ackChunk(SCTPDataVariables* chunk) { 00888 chunk->hasBeenAcked = true; 00889 } 00890 inline void unackChunk(SCTPDataVariables* chunk) { 00891 chunk->hasBeenAcked = false; 00892 } 00893 inline bool chunkHasBeenAcked(const SCTPDataVariables* chunk) const { 00894 return(chunk->hasBeenAcked); 00895 } 00896 inline bool chunkHasBeenAcked(const uint32 tsn) const { 00897 const SCTPDataVariables* chunk = retransmissionQ->getChunk(tsn); 00898 if(chunk) { 00899 return(chunkHasBeenAcked(chunk)); 00900 } 00901 return(false); 00902 } 00903 }; 00904 00905 #endif