00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef ns_sctp_h
00040 #define ns_sctp_h
00041
00042 #include "agent.h"
00043 #include "node.h"
00044 #include "packet.h"
00045
00046
00047
00048 #define SCTP_HDR_SIZE 12
00049
00050 #define MAX_RWND_SIZE 0xffffffff
00051 #define MAX_DATA_CHUNK_SIZE 0xffffffff
00052 #define MIN_DATA_CHUNK_SIZE 16
00053 #define MAX_NUM_STREAMS 0x0000ffff
00054
00055 #define DELAYED_SACK_TRIGGER 2 // sack for every 2 data packets
00056
00057 #define RTO_ALPHA 0.125 // RTO.alpha is 1/8
00058 #define RTO_BETA 0.25 // RTO.Beta is 1/4
00059
00060 #define MAX_BURST 4
00061 typedef enum MaxBurstUsage_E
00062 {
00063 MAX_BURST_USAGE_OFF,
00064 MAX_BURST_USAGE_ON
00065 };
00066
00067
00068
00069
00070
00071
00072 #undef FALSE
00073 #undef TRUE
00074 typedef enum Boolean_E
00075 {
00076 FALSE,
00077 TRUE
00078 };
00079
00080 typedef enum RtxToAlt_E
00081 {
00082 RTX_TO_ALT_OFF,
00083 RTX_TO_ALT_ON,
00084 RTX_TO_ALT_TIMEOUTS_ONLY
00085 };
00086
00087
00088
00089
00090 typedef enum DormantAction_E
00091 {
00092 DORMANT_HOP,
00093 DORMANT_PRIMARY,
00094 DORMANT_LASTDEST
00095 };
00096
00097
00098
00099
00100 typedef enum DataSource_E
00101 {
00102 DATA_SOURCE_APPLICATION,
00103 DATA_SOURCE_INFINITE
00104 };
00105
00106
00107
00108 typedef enum SctpChunkType_E
00109 {
00110 SCTP_CHUNK_DATA,
00111 SCTP_CHUNK_INIT,
00112 SCTP_CHUNK_INIT_ACK,
00113 SCTP_CHUNK_SACK,
00114 SCTP_CHUNK_HB,
00115 SCTP_CHUNK_HB_ACK,
00116 SCTP_CHUNK_ABORT,
00117 SCTP_CHUNK_SHUTDOWN,
00118 SCTP_CHUNK_SHUTDOWN_ACK,
00119 SCTP_CHUNK_ERROR,
00120 SCTP_CHUNK_COOKIE_ECHO,
00121 SCTP_CHUNK_COOKIE_ACK,
00122 SCTP_CHUNK_ECNE,
00123 SCTP_CHUNK_CWR,
00124 SCTP_CHUNK_SHUTDOWN_COMPLETE,
00125
00126
00127
00128
00129
00130 SCTP_CHUNK_FORWARD_TSN,
00131
00132
00133
00134 SCTP_CHUNK_TIMESTAMP
00135 };
00136
00137 typedef struct AppData_S
00138 {
00139
00140
00141 u_short usNumStreams;
00142 u_short usNumUnreliable;
00143
00144
00145
00146 u_short usStreamId;
00147 u_short usReliability;
00148 Boolean_E eUnordered;
00149 u_int uiNumBytes;
00150 };
00151
00152
00153
00154
00155
00156 typedef struct SctpTrace_S
00157 {
00158 SctpChunkType_E eType;
00159 u_int uiTsn;
00160 u_short usStreamId;
00161 u_short usStreamSeqNum;
00162 };
00163
00164 struct hdr_sctp
00165 {
00166
00167
00168 static int offset_;
00169 inline static int& offset() { return offset_; }
00170 inline static hdr_sctp* access(Packet* p)
00171 {
00172 return (hdr_sctp*) p->access(offset_);
00173 }
00174
00175
00176
00177
00178
00179 u_int uiNumChunks;
00180 SctpTrace_S *spSctpTrace;
00181
00182 u_int& NumChunks() { return uiNumChunks; }
00183 SctpTrace_S*& SctpTrace() { return spSctpTrace; }
00184 };
00185
00186 typedef struct SctpChunkHdr_S
00187 {
00188 u_char ucType;
00189 u_char ucFlags;
00190 u_short usLength;
00191 };
00192
00193
00194
00195 #define SCTP_INIT_PARAM_UNREL 0xC000
00196 typedef struct SctpUnrelStreamsParam_S
00197 {
00198 u_short usType;
00199 u_short usLength;
00200
00201
00202
00203 };
00204
00205 typedef struct SctpUnrelStreamPair_S
00206 {
00207 u_short usStart;
00208 u_short usEnd;
00209 };
00210
00211 typedef struct SctpInitChunk_S
00212 {
00213 SctpChunkHdr_S sHdr;
00214 u_int uiInitTag;
00215 u_int uiArwnd;
00216 u_short usNumOutboundStreams;
00217 u_short usMaxInboundStreams;
00218 u_int uiInitialTsn;
00219
00220 SctpUnrelStreamsParam_S sUnrelStream;
00221 };
00222 typedef SctpInitChunk_S SctpInitAckChunk_S;
00223
00224 typedef struct SctpCookieEchoChunk_S
00225 {
00226 SctpChunkHdr_S sHdr;
00227
00228
00229 };
00230 typedef SctpCookieEchoChunk_S SctpCookieAckChunk_S;
00231
00232 typedef struct SctpDataChunkHdr_S
00233 {
00234 SctpChunkHdr_S sHdr;
00235 u_int uiTsn;
00236 u_short usStreamId;
00237 u_short usStreamSeqNum;
00238 u_int uiPayloadType;
00239
00240
00241 };
00242
00243
00244
00245 #define SCTP_DATA_FLAG_END 0x01 // indicates last fragment
00246 #define SCTP_DATA_FLAG_BEGINNING 0x02 // indicates first fragment
00247 #define SCTP_DATA_FLAG_UNORDERED 0x04 // indicates unordered DATA chunk
00248
00249
00250
00251
00252 typedef struct SctpSackChunk_S
00253 {
00254 SctpChunkHdr_S sHdr;
00255 u_int uiCumAck;
00256 u_int uiArwnd;
00257 u_short usNumGapAckBlocks;
00258 u_short usNumDupTsns;
00259
00260
00261
00262 };
00263
00264 typedef struct SctpGapAckBlock_S
00265 {
00266 u_short usStartOffset;
00267 u_short usEndOffset;
00268 };
00269
00270 typedef struct SctpDupTsn_S
00271 {
00272 u_int uiTsn;
00273 };
00274
00275 #define SCTP_CHUNK_FORWARD_TSN_LENGTH 8
00276 typedef struct SctpForwardTsnChunk_S
00277 {
00278 SctpChunkHdr_S sHdr;
00279 u_int uiNewCum;
00280 };
00281
00282 typedef struct SctpDest_S;
00283 #define SCTP_CHUNK_HEARTBEAT_LENGTH 24
00284 typedef struct SctpHeartbeatChunk_S
00285 {
00286 SctpChunkHdr_S sHdr;
00287 u_short usInfoType;
00288 u_short usInfoLength;
00289 double dTimestamp;
00290 SctpDest_S *spDest;
00291 };
00292 typedef SctpHeartbeatChunk_S SctpHeartbeatAckChunk_S;
00293
00294
00295 typedef enum SctpState_E
00296 {
00297 SCTP_STATE_UNINITIALIZED,
00298 SCTP_STATE_CLOSED,
00299 SCTP_STATE_ESTABLISHED,
00300 SCTP_STATE_COOKIE_WAIT,
00301 SCTP_STATE_COOKIE_ECHOED,
00302 SCTP_STATE_SHUTDOWN_SENT,
00303 SCTP_STATE_SHUTDOWN_RECEIVED,
00304 SCTP_STATE_SHUTDOWN_ACK_SENT,
00305 SCTP_STATE_SHUTDOWN_PENDING
00306 };
00307
00308 class SctpAgent;
00309
00310 class T1InitTimer : public TimerHandler
00311 {
00312 public:
00313 T1InitTimer(SctpAgent *a) : TimerHandler(), opAgent(a) { }
00314
00315 protected:
00316 virtual void expire(Event *);
00317 SctpAgent *opAgent;
00318 };
00319
00320 class T1CookieTimer : public TimerHandler
00321 {
00322 public:
00323 T1CookieTimer(SctpAgent *a) : TimerHandler(), opAgent(a) { }
00324
00325 protected:
00326 virtual void expire(Event *);
00327 SctpAgent *opAgent;
00328 };
00329
00330 class T3RtxTimer : public TimerHandler
00331 {
00332 public:
00333 T3RtxTimer(SctpAgent *a, SctpDest_S *d)
00334 : TimerHandler(), opAgent(a) {spDest = d;}
00335
00336 protected:
00337 virtual void expire(Event *);
00338 SctpAgent *opAgent;
00339 SctpDest_S *spDest;
00340 };
00341
00342 class CwndDegradeTimer : public TimerHandler
00343 {
00344 public:
00345 CwndDegradeTimer(SctpAgent *a, SctpDest_S *d)
00346 : TimerHandler(), opAgent(a) {spDest = d;}
00347
00348 protected:
00349 virtual void expire(Event *);
00350 SctpAgent *opAgent;
00351 SctpDest_S *spDest;
00352 };
00353
00354 class HeartbeatGenTimer : public TimerHandler
00355 {
00356 public:
00357 HeartbeatGenTimer(SctpAgent *a, SctpDest_S *d)
00358 : TimerHandler(), opAgent(a) {spDest = d;}
00359
00360 double dStartTime;
00361
00362 protected:
00363 virtual void expire(Event *);
00364 SctpAgent *opAgent;
00365 SctpDest_S *spDest;
00366 };
00367
00368 class HeartbeatTimeoutTimer : public TimerHandler
00369 {
00370 public:
00371 HeartbeatTimeoutTimer(SctpAgent *a, SctpDest_S *d)
00372 : TimerHandler(), opAgent(a) {spDest = d;}
00373
00374 SctpDest_S *spDest;
00375
00376 protected:
00377 virtual void expire(Event *);
00378 SctpAgent *opAgent;
00379 };
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 class RouteCacheFlushTimer : public TimerHandler
00390 {
00391 public:
00392 RouteCacheFlushTimer(SctpAgent *a, SctpDest_S *d)
00393 : TimerHandler(), opAgent(a) {spDest = d;}
00394
00395 protected:
00396 virtual void expire(Event *);
00397 SctpAgent *opAgent;
00398 SctpDest_S *spDest;
00399 };
00400
00401
00402
00403
00404
00405
00406
00407 class RouteCalcDelayTimer : public TimerHandler
00408 {
00409 public:
00410 RouteCalcDelayTimer(SctpAgent *a, SctpDest_S *d)
00411 : TimerHandler(), opAgent(a) {spDest = d;}
00412
00413 protected:
00414 virtual void expire(Event *);
00415 SctpAgent *opAgent;
00416 SctpDest_S *spDest;
00417 };
00418
00419 typedef struct SctpInterface_S
00420 {
00421 int iNsAddr;
00422 int iNsPort;
00423 NsObject *opTarget;
00424 NsObject *opLink;
00425 };
00426
00427 typedef enum SctpDestStatus_E
00428 {
00429 SCTP_DEST_STATUS_INACTIVE,
00430 SCTP_DEST_STATUS_ACTIVE
00431 };
00432
00433 typedef enum NodeType_E
00434 {
00435 NODE_TYPE_STREAM_BUFFER,
00436 NODE_TYPE_RECV_TSN_BLOCK,
00437 NODE_TYPE_DUP_TSN,
00438 NODE_TYPE_SEND_BUFFER,
00439 NODE_TYPE_APP_LAYER_BUFFER,
00440 NODE_TYPE_INTERFACE_LIST,
00441 NODE_TYPE_DESTINATION_LIST,
00442 NODE_TYPE_PACKET_BUFFER
00443 };
00444
00445 typedef struct Node_S
00446 {
00447 NodeType_E eType;
00448 void *vpData;
00449 Node_S *spNext;
00450 Node_S *spPrev;
00451 };
00452
00453 typedef struct List_S
00454 {
00455 u_int uiLength;
00456 Node_S *spHead;
00457 Node_S *spTail;
00458 };
00459
00460 typedef struct SctpSendBufferNode_S;
00461 typedef struct SctpDest_S
00462 {
00463 int iNsAddr;
00464 int iNsPort;
00465
00466
00467
00468
00469
00470
00471 Packet *opRoutingAssistPacket;
00472
00473 int iCwnd;
00474 int iSsthresh;
00475 Boolean_E eFirstRttMeasurement;
00476 double dRto;
00477 double dSrtt;
00478 double dRttVar;
00479 int iPmtu;
00480 Boolean_E eRtxTimerIsRunning;
00481 T3RtxTimer *opT3RtxTimer;
00482 Boolean_E eRtoPending;
00483
00484 int iPartialBytesAcked;
00485 int iOutstandingBytes;
00486
00487 int iTimeoutCount;
00488 int iErrorCount;
00489 SctpDestStatus_E eStatus;
00490 CwndDegradeTimer *opCwndDegradeTimer;
00491 double dIdleSince;
00492 HeartbeatGenTimer *opHeartbeatGenTimer;
00493 HeartbeatTimeoutTimer *opHeartbeatTimeoutTimer;
00494
00495
00496
00497
00498 Boolean_E eCcApplied;
00499 SctpSendBufferNode_S *spFirstOutstanding;
00500 int iNumNewlyAckedBytes;
00501
00502
00503
00504
00505 int iRcdCount;
00506 Boolean_E eRouteCached;
00507 RouteCacheFlushTimer *opRouteCacheFlushTimer;
00508 RouteCalcDelayTimer *opRouteCalcDelayTimer;
00509 List_S sBufferedPackets;
00510 };
00511
00512 typedef struct SctpRecvTsnBlock_S
00513 {
00514 u_int uiStartTsn;
00515 u_int uiEndTsn;
00516 };
00517
00518
00519
00520
00521
00522
00523 typedef enum SctpRtxLimit_E
00524 {
00525 RTX_LIMIT_ONE_PACKET,
00526 RTX_LIMIT_CWND
00527 };
00528
00529 typedef enum MarkedForRtx_E
00530 {
00531 NO_RTX,
00532 FAST_RTX,
00533 TIMEOUT_RTX
00534 };
00535
00536 typedef struct SctpSendBufferNode_S
00537 {
00538 SctpDataChunkHdr_S *spChunk;
00539 Boolean_E eAdvancedAcked;
00540 Boolean_E eGapAcked;
00541 Boolean_E eAddedToPartialBytesAcked;
00542 int iNumMissingReports;
00543 int iUnrelRtxLimit;
00544 MarkedForRtx_E eMarkedForRtx;
00545 Boolean_E eIneligibleForFastRtx;
00546 int iNumTxs;
00547 double dTxTimestamp;
00548 SctpDest_S *spDest;
00549
00550
00551
00552 u_int uiFastRtxRecover;
00553 };
00554
00555 typedef struct SctpStreamBufferNode_S
00556 {
00557 SctpDataChunkHdr_S *spChunk;
00558 };
00559
00560 typedef enum SctpStreamMode_E
00561 {
00562 SCTP_STREAM_RELIABLE,
00563 SCTP_STREAM_UNRELIABLE
00564 };
00565
00566 typedef struct SctpInStream_S
00567 {
00568 SctpStreamMode_E eMode;
00569 u_short usNextStreamSeqNum;
00570 List_S sBufferedChunkList;
00571 };
00572
00573 typedef struct SctpOutStream_S
00574 {
00575 SctpStreamMode_E eMode;
00576 u_short usNextStreamSeqNum;
00577 };
00578
00579 class SackGenTimer : public TimerHandler
00580 {
00581 public:
00582 SackGenTimer(SctpAgent *a) : TimerHandler(), opAgent(a) { }
00583
00584 protected:
00585 virtual void expire(Event *);
00586 SctpAgent *opAgent;
00587 };
00588
00589 class SctpAgent : public Agent
00590 {
00591 public:
00592 SctpAgent();
00593 ~SctpAgent();
00594
00595 virtual void recv(Packet *pkt, Handler*);
00596 virtual void sendmsg(int nbytes, const char *flags = 0);
00597 virtual int command(int argc, const char*const* argv);
00598
00599 void T1InitTimerExpiration();
00600 void T1CookieTimerExpiration();
00601 virtual void Timeout(SctpChunkType_E, SctpDest_S *);
00602 virtual void CwndDegradeTimerExpiration(SctpDest_S *);
00603 void HeartbeatGenTimerExpiration(double, SctpDest_S *);
00604 void SackGenTimerExpiration();
00605 void RouteCacheFlushTimerExpiration(SctpDest_S *);
00606 void RouteCalcDelayTimerExpiration(SctpDest_S *);
00607
00608 protected:
00609 virtual void delay_bind_init_all();
00610 virtual int delay_bind_dispatch(const char *varName, const char *localName,
00611 TclObject *tracer);
00612
00613
00614
00615 void SetDebugOutFile();
00616 virtual void Reset();
00617 virtual void OptionReset();
00618 virtual u_int ControlChunkReservation();
00619
00620
00621
00622 virtual void TraceVar(const char*);
00623 virtual void TraceAll();
00624 void trace(TracedVar*);
00625
00626
00627
00628 void InsertNode(List_S *, Node_S *, Node_S *, Node_S *);
00629 void DeleteNode(List_S *, Node_S *);
00630 void ClearList(List_S *);
00631
00632
00633
00634 void AddInterface(int, int, NsObject *, NsObject *);
00635 void AddDestination(int, int);
00636 int SetPrimary(int);
00637 int ForceSource(int);
00638
00639
00640
00641 int GenChunk(SctpChunkType_E, u_char *);
00642 u_int GetNextDataChunkSize();
00643 int GenOneDataChunk(u_char *);
00644 virtual int GenMultipleDataChunks(u_char *, int);
00645 virtual int BundleControlChunks(u_char *);
00646
00647
00648
00649 void StartT3RtxTimer(SctpDest_S *);
00650 void StopT3RtxTimer(SctpDest_S *);
00651 virtual void AddToSendBuffer(SctpDataChunkHdr_S *, int, u_int, SctpDest_S *);
00652 void RttUpdate(double, SctpDest_S *);
00653 virtual void SendBufferDequeueUpTo(u_int);
00654 virtual void AdjustCwnd(SctpDest_S *);
00655 void AdvancePeerAckPoint();
00656 u_int GetHighestOutstandingTsn();
00657 void FastRtx();
00658 void TimeoutRtx(SctpDest_S *);
00659 void MarkChunkForRtx(SctpSendBufferNode_S *, MarkedForRtx_E);
00660 Boolean_E AnyMarkedChunks();
00661 virtual void RtxMarkedChunks(SctpRtxLimit_E);
00662 void SendHeartbeat(SctpDest_S *);
00663 SctpDest_S *GetNextDest(SctpDest_S *);
00664 double CalcHeartbeatTime(double);
00665 void SetSource(SctpDest_S *);
00666 void SetDestination(SctpDest_S *);
00667 void SendPacket(u_char *, int, SctpDest_S *);
00668 SctpDest_S *GetReplyDestination(hdr_ip *);
00669 u_int TotalOutstanding();
00670 virtual void SendMuch();
00671
00672
00673
00674 Boolean_E UpdateHighestTsn(u_int);
00675 Boolean_E IsDuplicateChunk(u_int);
00676 void InsertDuplicateTsn(u_int);
00677 void UpdateCumAck();
00678 void UpdateRecvTsnBlocks(u_int);
00679 void PassToUpperLayer(SctpDataChunkHdr_S *);
00680 void InsertInStreamBuffer(List_S *, SctpDataChunkHdr_S *);
00681 void PassToStream(SctpDataChunkHdr_S *);
00682 void UpdateAllStreams();
00683
00684
00685
00686 void ProcessInitChunk(u_char *);
00687 void ProcessInitAckChunk(u_char *);
00688 void ProcessCookieEchoChunk(SctpCookieEchoChunk_S *);
00689 void ProcessCookieAckChunk(SctpCookieAckChunk_S *);
00690 void ProcessDataChunk(SctpDataChunkHdr_S *);
00691 virtual Boolean_E ProcessGapAckBlocks(u_char *, Boolean_E);
00692 void ProcessSackChunk(u_char *);
00693 void ProcessForwardTsnChunk(SctpForwardTsnChunk_S *);
00694 void ProcessHeartbeatAckChunk(SctpHeartbeatChunk_S *);
00695 virtual void ProcessOptionChunk(u_char *);
00696 int ProcessChunk(u_char *, u_char **);
00697 void NextChunk(u_char **, int *);
00698
00699
00700
00701 void Close();
00702
00703
00704
00705 void SctpAgent::DumpSendBuffer();
00706
00707
00708
00709 SctpState_E eState;
00710
00711
00712
00713 List_S sAppLayerBuffer;
00714
00715
00716
00717 Classifier *opCoreTarget;
00718 List_S sInterfaceList;
00719 List_S sDestList;
00720 SctpDest_S *spPrimaryDest;
00721 SctpDest_S *spNewTxDest;
00722 SctpDest_S *spReplyDest;
00723 Boolean_E eForceSource;
00724 int iAssocErrorCount;
00725
00726
00727
00728 HeartbeatGenTimer *opHeartbeatGenTimer;
00729 HeartbeatTimeoutTimer *opHeartbeatTimeoutTimer;
00730
00731
00732
00733 T1InitTimer *opT1InitTimer;
00734 T1CookieTimer *opT1CookieTimer;
00735 int iInitTryCount;
00736 u_int uiNextTsn;
00737 u_short usNextStreamId;
00738 SctpOutStream_S *spOutStreams;
00739 u_int uiPeerRwnd;
00740 u_int uiCumAckPoint;
00741 u_int uiAdvancedPeerAckPoint;
00742 u_int uiHighestTsnNewlyAcked;
00743 u_int uiRecover;
00744 List_S sSendBuffer;
00745 Boolean_E eForwardTsnNeeded;
00746 Boolean_E eSendNewDataChunks;
00747 Boolean_E eMarkedChunksPending;
00748 Boolean_E eApplyMaxBurst;
00749 DataSource_E eDataSource;
00750 u_int uiBurstLength;
00751
00752
00753
00754 u_int uiMyRwnd;
00755 u_int uiCumAck;
00756 u_int uiHighestRecvTsn;
00757 List_S sRecvTsnBlockList;
00758 List_S sDupTsnList;
00759 int iNumInStreams;
00760 SctpInStream_S *spInStreams;
00761 Boolean_E eStartOfPacket;
00762 int iDataPktCountSinceLastSack;
00763 Boolean_E eSackChunkNeeded;
00764 SackGenTimer *opSackGenTimer;
00765
00766
00767
00768 u_int uiDebugMask;
00769 int iDebugFileIndex;
00770 u_int uiPathMaxRetrans;
00771 u_int uiChangePrimaryThresh;
00772 u_int uiAssociationMaxRetrans;
00773 u_int uiMaxInitRetransmits;
00774 Boolean_E eOneHeartbeatTimer;
00775 u_int uiHeartbeatInterval;
00776 u_int uiMtu;
00777 u_int uiInitialRwnd;
00778 int iInitialSsthresh;
00779 u_int uiIpHeaderSize;
00780 u_int uiDataChunkSize;
00781 u_int uiNumOutStreams;
00782 Boolean_E eUseDelayedSacks;
00783 double dSackDelay;
00784 MaxBurstUsage_E eUseMaxBurst;
00785 int iInitialCwnd;
00786 double dInitialRto;
00787 double dMinRto;
00788 double dMaxRto;
00789 int iFastRtxTrigger;
00790 u_int uiNumUnrelStreams;
00791 u_int uiReliability;
00792 Boolean_E eUnordered;
00793 RtxToAlt_E eRtxToAlt;
00794 DormantAction_E eDormantAction;
00795 double dRouteCacheLifetime;
00796 double dRouteCalcDelay;
00797 Boolean_E eTraceAll;
00798 TracedInt tiCwnd;
00799 TracedDouble tdRto;
00800 TracedInt tiErrorCount;
00801 TracedInt tiFrCount;
00802 TracedInt tiTimeoutCount;
00803 TracedInt tiRcdCount;
00804
00805
00806
00807 u_int uiMaxPayloadSize;
00808 u_int uiMaxDataSize;
00809 FILE *fhpDebugFile;
00810
00811
00812
00813 u_int uiNumChunks;
00814 SctpTrace_S *spSctpTrace;
00815 };
00816
00817 #endif