SCTPAssociation.h

Go to the documentation of this file.
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