/*++ Copyright (c) 1997 Microsoft Corporation Module Name: ARPSTRUC.H Abstract: Structure definitions for the ARP protocol implementation Author: Aaron Ogus (aarono) Environment: Win32/COM Revision History: Date Author Description ======= ====== ============================================================ 1/27/97 aarono Original 2/18/98 aarono Added more fields to SEND for SendEx support 6/6/98 aarono Turn on throttling and windowing 2/12/00 aarono Concurrency issues, fix VOL usage and Refcount --*/ #ifndef _ARPSTRUC_H_ #define _ARPSTRUC_H_ #include #include #include #include "arpd.h" #include "bufpool.h" #include "bilink.h" #include "mydebug.h" //#include "threads.h" //#pragma warning( disable : 4090) #define VOL volatile // // Information about sent packets, tracked for operational statistics. // #define SENDSTAT_SIGN SIGNATURE('S','T','A','T') typedef struct PROTOCOL *PPROTOCOL; typedef struct _SENDSTAT { #ifdef SIGN UINT Signature; // Signature for SIGN #endif union { BILINK StatList; // linked on Send and later SESSION. struct _SENDSTAT *pNext; }; UINT messageid; UINT sequence; // sequence number UINT serial; // serial number UINT tSent; // tick time when this packet instance sent. UINT LocalBytesSent; // number of bytes sent on session at send time. UINT RemoteBytesReceived;// last remote byte report at send time. UINT tRemoteBytesReceived; // remote timestamp when received. UINT bResetBias; } SENDSTAT, *PSENDSTAT; #define SEND_SIGN SIGNATURE('S','E','N','D') typedef enum _TRANSMITSTATE { Start=0, // Never sent a packet. Sending=1, // Thread to send is running and xmitting. Throttled=2, // Waiting for send bandwidth. WaitingForAck=3, // Timer running, listening for ACKs. WaitingForId=4, // Waiting for a Send Id. ReadyToSend=5, // Have stuff to xmit, waiting for thread. TimedOut=6, // Retry timed out. Cancelled=7, // User cancelled send. UserTimeOut=8, // Didn't try to send until too late. Done=9 // Finished sending, singalled sender. } TRANSMITSTATE; struct _SESSION; // this Send is an ACK or NACK (OR'ed into SEND.dwFlags) #define ASEND_PROTOCOL 0x80000000 #pragma pack(push,1) typedef struct _SEND{ #ifdef SIGN UINT Signature; // Signature for SIGN #endif CRITICAL_SECTION SendLock; // Lock for Send Structure UINT RefCount; // @#$%! - not marked volatile since accessed only with Interlocked fns. VOL TRANSMITSTATE SendState; // State of this message's transmission. // Lists and Links... union { struct _SEND *pNext; // linking on free pool BILINK SendQ; // linking on session send queue }; BILINK m_GSendQ; // Global Priority Queue BILINK TimeoutList; // List of sends waiting for timeout (workaround MMTIMER cancel bug). struct _SESSION *pSession; // pointer to SESSIONion(gets a ref) PPROTOCOL pProtocol; // pointer to Protocol instance that created us. // Send Information DPID idFrom; DPID idTo; WORD wIdTo; // index in table WORD wIdFrom; // index in table UINT dwFlags; // Send Flags (include reliable) PBUFFER pMessage; // Buffer chain describing message. UINT MessageSize; // Total size of the message. UINT FrameDataLen; // Data area of each frame. UINT nFrames; // Number of frames for this message. UINT Priority; // Send Priority. // User cancel and complete info DWORD dwMsgID; // message id given to user, for use in cancel. LPVOID lpvUserMsgID; // user's own identifier for this send. BOOL bSendEx; // called through SendEx. // Vars for reliability BOOL fSendSmall; VOL BOOL fUpdate; // update to NS,NR NACKMask made by receive. UINT messageid; // Message ID number. UINT serial; // serial number. VOL UINT OpenWindow; // Number of sends we are trying to get outstanding VOL UINT NS; // Sequence Sent. VOL UINT NR; // Sequence ACKED. UINT SendSEQMSK; // Mask to use. VOL UINT NACKMask; // Bit pattern of NACKed frames. // These are the values at NR - updated by ACKs VOL UINT SendOffset; // Current offset we are sending. VOL PBUFFER pCurrentBuffer; // Current buffer being sent. VOL UINT CurrentBufferOffset; // Offset in the current buffer of next packet. // info to update link characteristics when ACKs come in. BILINK StatList; // Info for packets already sent. DWORD BytesThisSend; // number of bytes being sent in the current packet. // Operational Characteristics VOL UINT_PTR uRetryTimer; UINT TimerUnique; UINT RetryCount; // Number of times we retransmitted. UINT WindowSize; // Maximum Window Size. UINT SAKInterval; // interval (frames) at which a SAK is required. UINT SAKCountDown; // countdown to 0 from interval. UINT tLastACK; // Time we last got an ACK. UINT dwSendTime; // time we were called in send. UINT dwTimeOut; // timeout time. UINT PacketSize; // Size of packets to send. UINT FrameSize; // Size of Frames for this send. // Completion Vars HANDLE hEvent; // Event to wait on for internal send. UINT Status; // Send Completion Status. PASYNCSENDINFO pAsyncInfo; // ptr to Info for completing Async send(NULL=>internal send) ASYNCSENDINFO AsyncInfo; // actual info (copied at send call). DWORD tScheduled; // the time we scheduled the retry; DWORD tRetryScheduled; // expected retry timer run time. VOL BOOL bCleaningUp; // we are on the queue but don't take a ref pls. } SEND, *PSEND; #pragma pack(pop) #define RECEIVE_SIGN SIGNATURE('R','C','V','_') // Receive buffers are in reverse receive order. When they have all // been received, they are then put in proper order. typedef struct _RECEIVE { #ifdef SIGN UINT Signature; // Signature for SIGN #endif union { BILINK pReceiveQ; struct _RECEIVE * pNext; }; BILINK RcvBuffList; // List of receive buffers that make up the message. CRITICAL_SECTION ReceiveLock; struct _SESSION *pSession; VOL BOOL fBusy; // Someone is moving this receive. BOOL fReliable; // Whether this is a reliable receive. VOL BOOL fEOM; // Whether we received the EOM bit. UINT command; UINT messageid; VOL UINT MessageSize; VOL UINT iNR; // Absolute index of first receiving packet (reliable only). VOL UINT NR; // Last in sequence packet received. VOL UINT NS; // Highest packet number received. VOL UINT RCVMask; // bitmask of received packets (NR relative) PUCHAR pSPHeader; UCHAR SPHeader[0]; } RECEIVE, *PRECEIVE; #pragma pack(push,1) typedef struct _CMDINFO { WORD wIdTo; // index WORD wIdFrom; // index DPID idTo; // actual DPID DPID idFrom; // actual DPID UINT bytes; // read from ACK. DWORD tRemoteACK; // remote time remote ACKed/NACKed UINT tReceived; // timeGetTime() when received. UINT command; UINT IDMSK; USHORT SEQMSK; USHORT messageid; USHORT sequence; UCHAR serial; UCHAR flags; PVOID pSPHeader; // used to issue a reply. } CMDINFO, *PCMDINFO; #pragma pack(pop) #define SESSION_SIGN SIGNATURE('S','E','S','S') // since we now have a full byte for messagid and sequenne in the small headers, // we no longer have an advantage for full headers until we apply the new // bitmask package, then we must transit to large frame for windows > 127 messages. #define MAX_SMALL_CSENDS 29UL // Maximum Concurrent Sends when using small frame headers #define MAX_LARGE_CSENDS 29UL // Maxinum Concurrent Sends when using large frame headers (could make larger except for mask bits) #define MAX_SMALL_DG_CSENDS 16UL // Maximum concurrent datagrams when using small frame #define MAX_LARGE_DG_CSENDS 16UL // Maximum Concurrent datagrams when using large frames. #define MAX_SMALL_WINDOW 24UL #define MAX_LARGE_WINDOW 24UL typedef enum _SESSION_STATE { Open, // When created and Inited. Closing, // Don't accept new receives/sends. Closed // gone. } SESSION_STATE; #define SERVERPLAYER_INDEX 0xFFFE #define SESSION_THROTTLED 0x00000001 // session throttle is on. #define SESSION_UNTHROTTLED 0x00000002 // unthrottle is deffered to avoid confusing GetMessageQueue. ///////////////////////////////////////////////////////////////// // // Transition Matrix for Throttle Adjust // // Initial State Event: // No Drops 1 Drop >1 Drop // // Start + Start - Meta -- Start // // Meta + Meta - Stable -- Meta // // Stable + Stable - Stable -- Meta // // // Engagement of Backlog Throttle goes to MetaStable State. /////////////////////////////////////////////////////////////////// #define METASTABLE_GROWTH_RATE 4 #define METASTABLE_ADJUST_SMALL_ERR 12 #define METASTABLE_ADJUST_LARGE_ERR 25 #define START_GROWTH_RATE 50 #define START_ADJUST_SMALL_ERR 25 #define START_ADJUST_LARGE_ERR 50 #define STABLE_GROWTH_RATE 2 #define STABLE_ADJUST_SMALL_ERR 12 #define STABLE_ADJUST_LARGE_ERR 25 typedef enum _ThrottleAdjustState { Begin=0, // At start, double until drop or backlog MetaStable=1, // Meta stable, large deltas for drops Stable=2 // Stable, small deltas for drops } eThrottleAdjust; typedef struct _SESSION { PPROTOCOL pProtocol; // back ptr to object. #ifdef SIGN UINT Signature; // Signature for SIGN #endif // Identification CRITICAL_SECTION SessionLock; // Lock for the SESSIONion. UINT RefCount; // RefCount for the SESSION. - not vol, only accessed with Interlocked VOL SESSION_STATE eState; HANDLE hClosingEvent; // Delete waits on this during close. DPID dpid; // The remote direct play id for this session. UINT iSession; // index in the session table UINT iSysPlayer; // index in session table of sys player. // NOTE: if iSysPlayer != iSession, then rest of struct not req'd. BILINK SendQ; // Priority order sendQ; BOOL fFastLink; // set True when link > 50K/sec, set False when less than 10K/sec. BOOL fSendSmall; // Whether we are sending small reliable frames. BOOL fSendSmallDG; // Whether we are sending small datagram frames. BOOL fReceiveSmall; BOOL fReceiveSmallDG; UINT MaxPacketSize; // Largest packet allowed on the media. // Operating parameters -- Send // Common UINT MaxCSends; // maximum number of concurrent sends UINT MaxCDGSends; // maximum number of concurrent datagram sends // Reliable VOL UINT FirstMsg; // First message number being transmitted VOL UINT LastMsg; // Last message number being transmitted VOL UINT OutMsgMask; // relative to FirstMsg, unacked messages UINT nWaitingForMessageid; // number of sends on queue that can't start sending because they don't have an id. // DataGram VOL UINT DGFirstMsg; // First message number being transmitted VOL UINT DGLastMsg; // Last message number being transmitted VOL UINT DGOutMsgMask; // relative to FirstMsg, not-fully sent messages. UINT nWaitingForDGMessageid; // number of sends on queue that can't start sending because they don't have an id. // Send stats are tracked seperately since sends may // no longer be around when completions come in. //BILINK OldStatList; // Operating parameters -- Receive // DataGram Receive. BILINK pDGReceiveQ; // queue of ongoing datagram receives // Reliable Receive. BILINK pRlyReceiveQ; // queue of ongoing reliable receives BILINK pRlyWaitingQ; // Queue of out of order reliable receives waiting. // only used when PROTOCOL_NO_ORDER not set. VOL UINT FirstRlyReceive; VOL UINT LastRlyReceive; VOL UINT InMsgMask; // mask of fully received receives, relative to FirstRlyReceive // Operational characteristics - MUST BE DWORD ALIGNED!!! - this is because we read and write them // without a lock and assume the reads and writes are atomic (not in combination) UINT WindowSize; // Max outstanding packets on a send - reliable UINT DGWindowSize; // Max outstanding packets on a send - datagram UINT MaxRetry; // Usual max retries before dropping. UINT MinDropTime; // Min time to retry before dropping. UINT MaxDropTime; // After this time always drop. VOL UINT LocalBytesReceived; // Total Data Bytes received (including retries). VOL UINT RemoteBytesReceived; // Last value from remote. VOL DWORD tRemoteBytesReceived; // Remote time last value received. UINT LongestLatency; // longest observed latency (msec) UINT ShortestLatency; // shortest observed latency(msec) UINT LastLatency; // last observed latency (msec) UINT FpAverageLatency; // average latency (msec 24.8) (128 samples) UINT FpLocalAverageLatency; // Local average latency (msec 24.8) (16 samples) UINT FpAvgDeviation; // average deviation of latency. (msec 24.8) (128 samples) UINT FpLocalAvgDeviation; // average deviation of latency. (msec 24.8) (16 samples) UINT Bandwidth; // latest observed bandwidth (bps) UINT HighestBandwidth; // highest observed bandwidth (bps) // we will use changes in the remote ACK delta to isolate latency in the send direction. UINT RemAvgACKDelta; // average clock delta between our send time (local time) and remote ACK time (remote time). UINT RemAvgACKDeltaResidue; UINT RemAvgACKBias; // This value is used to pull the clock delta into a safe range (not near 0 or -1) // that won't risk hitting the wraparound when doing calculations // Throttle statistics DWORD dwFlags; // Session Flags - currently just "throttle on/off"(MUST STAY THIS WAY) UINT SendRateThrottle; // current rate (bps) at which we are throttling. DWORD bhitThrottle; // we hit a throttle DWORD tNextSend; // when we are allowed to send again. DWORD tNextSendResidue; // residual from calculating next send time DWORD_PTR uUnThrottle; DWORD UnThrottleUnique; DWORD FpAvgUnThrottleTime; // (24.8) how late Unthrottle usually called. (throttle when send is this far ahead) // last 16 samples, start at 5 ms. DWORD tLastSAK; // last time we asked for an ACK CRITICAL_SECTION SessionStatLock; // [locks this section ------------------------------------------- ] BILINK DGStatList; // [Send Statistics for Datagrams (for reliable they are on Sends) ] DWORD BytesSent; // [Total Bytes Sent to this target ] DWORD BytesLost; // [Total Bytes Lost on the link. ] DWORD bResetBias; // [Counts down to reset latency bias ] // [---------------------------------------------------------------] eThrottleAdjust ThrottleState; // ZEROINIT puts in Start DWORD GrowCount; // number of times we grew in this state DWORD ShrinkCount; // number of times we shrank in this state DWORD tLastThrottleAdjust; // remember when we last throttled to avoid overthrottling. } SESSION, *PSESSION; #endif