summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/testprot/tpdrvr/packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/testprot/tpdrvr/packet.c')
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/packet.c2164
1 files changed, 2164 insertions, 0 deletions
diff --git a/private/ntos/ndis/testprot/tpdrvr/packet.c b/private/ntos/ndis/testprot/tpdrvr/packet.c
new file mode 100644
index 000000000..72a27edef
--- /dev/null
+++ b/private/ntos/ndis/testprot/tpdrvr/packet.c
@@ -0,0 +1,2164 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ packet.c
+
+Abstract:
+
+ simple protocol to test the NDIS wrapper.
+
+Author:
+
+ Tom Adams (tomad) 14-Jul-1990
+
+Environment:
+
+ Kernel mode, FSD
+
+Revision History:
+
+ Sanjeev Katariya (sanjeevk) 3-24-1993
+ 1. Corrected TpStressCreatePacket() to allocate the first buffer in a packet of correct
+ size. Added functionality to work with discontiguous physical data(Buffer chains)
+ 2. Changed functions to reflect the data structure change in
+ STRESS_BLOCK
+ a. TpStressCreateTruncatedPacket()
+ b. TpStressSetTruncatedPacketInfo()
+
+--*/
+
+#include <ndis.h>
+#include <stdlib.h>
+
+#include "tpdefs.h"
+#include "media.h"
+#include "tpprocs.h"
+
+
+
+VOID
+TpSetRandom(
+ VOID
+ )
+{
+ LARGE_INTEGER TmpTime;
+
+ //
+ // Uses the system clock to return a random number.
+ // The randomness of the number is subject to some debate.
+ // The time increments in exact intervals; for example on
+ // a 386 it is 300000. We want to shift over enough that
+ // the LSB changes rapidly, but not too much so that we
+ // can only handle a small Range.
+ //
+
+ KeQuerySystemTime( &TmpTime );
+ srand( TmpTime.LowTime >> 10 );
+}
+
+
+UINT
+TpGetRandom(
+ IN UINT Low,
+ IN UINT High
+ )
+{
+ UINT Range = High - Low + 1;
+
+ return (UINT)(( rand() % Range ) + Low );
+}
+
+
+PTP_PACKET
+TpStressInitPacketHeader(
+ IN POPEN_BLOCK OpenP,
+ IN INT TmpBufSize,
+ IN INT PacketSize,
+ IN PUCHAR DestAddr,
+ IN PUCHAR SrcAddr,
+ IN UCHAR DestInstance,
+ IN UCHAR SrcInstance,
+ IN UCHAR PacketProtocol,
+ IN UCHAR ResponseType,
+ IN ULONG DataBufOffset,
+ IN ULONG SequenceNumber,
+ IN ULONG MaxSequenceNumber,
+ IN UCHAR ClientReference,
+ IN UCHAR ServerReference,
+ IN BOOLEAN DataChecking
+ )
+{
+ NDIS_STATUS Status;
+ PTP_PACKET TmpBuffer;
+
+ //
+ // Allocate a buffer to hold the packet header information.
+ //
+
+ Status = NdisAllocateMemory(
+ (PVOID *)&TmpBuffer,
+ TmpBufSize,
+ 0,
+ HighestAddress
+ );
+
+ if ( Status != NDIS_STATUS_SUCCESS ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressInitPacketHeader: failed to allocate TmpBuffer\n");
+ }
+ return NULL;
+ } else {
+ NdisZeroMemory( (PVOID)TmpBuffer,TmpBufSize );
+ }
+
+ //
+ // and stuff the packet header info into it.
+ //
+
+ if ( !TpInitMediaHeader(
+ &TmpBuffer->u.S.hdr,
+ OpenP->Media,
+ DestAddr,
+ SrcAddr,
+ PacketSize
+ )) {
+ NdisFreeMemory( TmpBuffer,0,0 );
+ return NULL;
+ }
+
+ //
+ // initialize the Stress header information.
+ //
+
+ TmpBuffer->u.S.hdr.info.Signature = STRESS_PACKET_SIGNATURE;
+ TmpBuffer->u.S.hdr.info.PacketSize = PacketSize;
+ TmpBuffer->u.S.hdr.info.DestInstance = DestInstance;
+ TmpBuffer->u.S.hdr.info.SrcInstance = SrcInstance;
+ TmpBuffer->u.S.hdr.info.PacketType = STRESS_PACKET_TYPE;
+ TmpBuffer->u.S.hdr.info.u.PacketProtocol = PacketProtocol;
+ TmpBuffer->u.S.hdr.info.CheckSum = 0xFFFFFFFF;
+
+ TmpBuffer->u.S.sc.DataBufOffset = DataBufOffset;
+ TmpBuffer->u.S.sc.SequenceNumber = SequenceNumber;
+ TmpBuffer->u.S.sc.MaxSequenceNumber = MaxSequenceNumber;
+ TmpBuffer->u.S.sc.ResponseType = ResponseType;
+ TmpBuffer->u.S.sc.ClientReference = ClientReference;
+ TmpBuffer->u.S.sc.ServerReference = ServerReference;
+ TmpBuffer->u.S.sc.DataChecking = DataChecking;
+
+ return TmpBuffer;
+}
+
+
+PNDIS_PACKET
+TpStressCreatePacket(
+ IN POPEN_BLOCK OpenP,
+ IN NDIS_HANDLE PacketHandle,
+ IN PACKET_MAKEUP PacketMakeUp,
+ IN UCHAR DestInstance,
+ IN UCHAR SrcInstance,
+ IN UCHAR PacketProtocol,
+ IN UCHAR ResponseType,
+ IN PUCHAR DestAddr,
+ IN INT PacketSize,
+ IN INT BufferSize,
+ IN ULONG SequenceNumber,
+ IN ULONG MaxSequenceNumber,
+ IN UCHAR ClientReference,
+ IN UCHAR ServerReference,
+ IN BOOLEAN DataChecking
+ )
+
+{
+ NDIS_STATUS Status ;
+ PNDIS_PACKET Packet ;
+ PNDIS_BUFFER Buffer ;
+ PPROTOCOL_RESERVED ProtRes ;
+ PUCHAR DataBufOffset1 ;
+ PUCHAR DataBufOffset2 ;
+ PUCHAR TmpBuf ;
+ PUCHAR TmpBufDataOffset ;
+ ULONG RandomOffset ;
+ INT TmpBufSize ;
+ INT TmpBufDataSize ;
+ INT MdlSize ;
+ INT NumBuffers ;
+ INT i ;
+ INT RemainingHdr ;
+ INT RemainingPkt ;
+ BOOLEAN FirstBuffer = TRUE ;
+ BOOLEAN Pulse = TRUE ;
+
+ //
+ // Using a DISCONTIGUOUS allocation scheme in the CLIENT pool case
+ //
+
+ //
+ // Comments : SanjeevK
+ //
+ // BRIEF WORKING
+ //
+ // This function simply allocates a packet from the packet pool and
+ // is reponsible for putting the packet together. The data portion of the
+ // packet is directly used from the the DataBuffers associated with the
+ // stress block. The packet creation is given the option of using
+ // a known buffer size mapping(which generates a definite number of buffers
+ // since the packet size is known) or can simply randomly choose how big
+ // or small it would like to make the buffer sizes. This option is characterized
+ // by the parameter KNOWN.
+ // The packet is created by created an initial header, setting the appropriate fields
+ // and then linking in the data buffers. The total length of the created packet is
+ // controlled by the PacketSize
+ //
+ // The variables and their boundary sizes are given below:
+ //
+ // <-------------------- PacketSize ------------------->[STRESS_PACKET,MAX_PACKET_LENGTH]
+ //
+ // <------ TmpBufSize ---->[STRESS_PACKET,max(2*STRESS_PACKET,PacketSize)]
+ // for PacketMakeUp != KNOWN
+ //
+ // MEDIA_FRAME,PacketSize]
+ //
+ // ----------------------------------------------------
+ // | STRESS_PACKET+ | Additional DATA |
+ // | Random Data Size | |
+ // ----------------------- ----------------------------
+ //
+ // ---.....-----....----....---
+ // | |
+ // |
+ // ---.....-----....----....---
+ //
+ // <-------- BufferSize -------->[MediaHeaderSize, max(STRESS_PACKET,PacketSize)]
+ //
+ //
+
+
+
+ //
+ // Make sure that this is a legal packetsize, and buffersize if
+ // PacketMakeUp = KNOWN, if not use a default smallest or largest
+ // size allowable.
+ //
+ if ( PacketSize < sizeof( STRESS_PACKET )) {
+ PacketSize = sizeof( STRESS_PACKET );
+ } else if ( PacketSize > (INT)OpenP->Media->MaxPacketLen ) {
+ PacketSize = OpenP->Media->MaxPacketLen;
+ }
+
+
+ //
+ // Check the condition for KNOWN packet type.
+ // If TRUE ensure that the BufferSize is between
+ // MediaHeaderSize and max(STRESS_PACKET,PacketSize).
+ //
+ if ( PacketMakeUp == KNOWN ) {
+ if ( BufferSize < OpenP->Media->HeaderSize ) {
+ BufferSize = OpenP->Media->HeaderSize ;
+ } else if ( BufferSize > PacketSize ) {
+ BufferSize = PacketSize;
+ }
+ }
+
+
+
+
+ //
+ // Allocate a PACKET out of the packet pool
+ //
+ NdisAllocatePacket( &Status,&Packet,PacketHandle );
+
+ if ( Status != NDIS_STATUS_SUCCESS ) {
+
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+
+ if( OpenP->Stress->Arguments != NULL ) {
+
+ //
+ // This is the special case where we realize that we will run out
+ // of packets very quickly since the packet pool is 200 only. ONLY
+ // in this case will we not issue a debug message to the screen
+ //
+ if ( (OpenP->Stress->Arguments->WindowEnabled == FALSE ) &&
+ (OpenP->Stress->Arguments->ResponseType == ACK_10_TIMES )
+ ) return NULL;
+
+ }
+
+ TpPrint1("TpStressCreatePacket: NdisAllocatePacket failed %s\n",
+ TpGetStatus( Status ));
+
+ }
+
+ return NULL;
+
+ }
+
+
+ //
+ // Mark the Packet's protocol reserved section to NULL to indicate
+ // that this packet was not allocated from a TP_TRANSMIT_POOL, and set
+ // the InstanceCounters to NULL. TpStressCreateTransmitPool and the
+ // Packet Set Info routines will set them if applicable.
+ //
+
+ ProtRes = PROT_RES( Packet );
+ ProtRes->Pool.TransmitPool = NULL;
+ ProtRes->InstanceCounters = NULL;
+
+ //
+ // Now select the random size of the header buffer which will be used to
+ // hold the Frame Header, the Test Protocol Packet Header, and a random
+ // chunk of the actual frame data.
+ //
+ // TmpBufSize = The random size of the header buffer
+ // where
+ // Header buffer = Frame Header +
+ // Test Protocol Packet Header +
+ // A random chunk of the actual frame data.
+ //
+ //
+ if ( PacketMakeUp != KNOWN ) { // ( PacketMakeUp == RAND|ONES|ZEROS|SMALL )
+
+ //
+ // Sanjeevk : Comment
+ //
+ // The TmpBufSize being within the bounds, STRESS_PACKET and 2*STRESS_PACKET
+ // will quite comfortably accomodate the MEDIA_HEADER. This restriction must
+ // be followed closely since this is the first buffer in the packet chain
+ //
+
+ TmpBufSize = TpGetRandom(
+ sizeof( STRESS_PACKET ),
+ ( 2 * sizeof( STRESS_PACKET ))
+ );
+
+ if ( TmpBufSize > PacketSize ) {
+ TmpBufSize = PacketSize;
+ }
+
+
+ } else {
+
+ //
+ // Packet_MakeUp is KNOWN, i.e. we can calculate the number of buffers
+ // from the size of the packet and the given buffersize
+ // We must however determine the number of buffers that
+ // will fit in the TP_PACKET_HEADER section of the packet, and how
+ // large that header will actually be.
+ //
+ // At this point BufferSize is between MediaHeaderSize
+ // and max(PacketSize,STRESS_PACKET)
+ //
+ if ( BufferSize >= sizeof( STRESS_PACKET ) ) {
+
+ //
+ // If the BufferSize is greater than the size needed to fit the
+ // packet header then we will just allocate one chunk of memory
+ // of that size, and tack on some additional data at the the end.
+ //
+
+ TmpBufSize = BufferSize;
+ RemainingPkt = PacketSize % BufferSize;
+ RemainingHdr = 0;
+ NumBuffers = 1;
+
+ } else {
+
+ //
+ // The BufferSize is smaller that then packet header, so we must
+ // determine the number of buffers that will fit in the header,
+ // and, if there is any remainder, how big it is.
+ //
+
+ NumBuffers = sizeof( STRESS_PACKET ) / BufferSize;
+ RemainingHdr = sizeof( STRESS_PACKET ) % BufferSize;
+ RemainingPkt = PacketSize % BufferSize;
+
+ //
+ // There are three possible cases here that must be handled.
+ //
+ // 1) only X buffers are needed to create the packet header
+ //
+ // 2) X buffers, and a remainder buffer are needed to create the
+ // packet header.
+ // a) the remainder is the rest of the actual packet.
+ //
+ // b) the remainder is the rest of the header. (and the
+ // packet)
+ //
+ // [-------------------------------------]
+ // packet header
+ //
+ // 1) [---------][---------][- -][---------]
+ // buf_1 buf_2 ... buf_X
+ //
+ // 2a) [-------][-------][- -][-------][--------------]
+ // buf_1 buf_2 ... buf_X remaining packet
+ //
+ // 2b) [-------][-------][- -][-------][---]
+ // buf_1 buf_2 ... buf_X remaining header
+ //
+
+ if (((NumBuffers+1) * BufferSize) <= PacketSize ) {
+
+ //
+ // The packet header can fit in NumBuffers+1 buffers.
+ //
+
+ TmpBufSize = (( NumBuffers + 1 ) * BufferSize );
+ NumBuffers++;
+ RemainingHdr = 0;
+
+ } else if ((( NumBuffers * BufferSize ) + RemainingPkt ) == PacketSize ) {
+
+ //
+ // The packet header can fit in a NumBuffers buffers plus the
+ // remainder of the packet. This is the entire packet.
+ //
+
+ TmpBufSize = ( NumBuffers * BufferSize ) + RemainingPkt ;
+ RemainingHdr = RemainingPkt;
+ RemainingPkt = 0;
+
+ } else {
+
+ //
+ // The packet header can fit in a NumBuffers buffers plus the
+ // remainder of the header. This is the entire packet.
+ //
+
+ TmpBufSize = (( NumBuffers * BufferSize ) + RemainingHdr );
+ TP_ASSERT( RemainingHdr != RemainingPkt );
+ RemainingPkt = 0;
+ }
+ }
+ }
+
+ RandomOffset = TpGetRandom( 0,OpenP->Media->MaxPacketLen );
+
+ TmpBuf = (PUCHAR)TpStressInitPacketHeader(
+ OpenP,
+ TmpBufSize,
+ PacketSize,
+ DestAddr,
+ OpenP->StationAddress,
+ DestInstance,
+ SrcInstance,
+ PacketProtocol,
+ ResponseType,
+ RandomOffset,
+ SequenceNumber,
+ MaxSequenceNumber,
+ ClientReference,
+ ServerReference,
+ DataChecking
+ );
+
+ if ( TmpBuf == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to initialize Packet Header\n");
+ }
+ return NULL;
+ }
+
+ ((PTP_PACKET)TmpBuf)->u.S.sc.CheckSum =
+
+ TpSetCheckSum(
+ (PUCHAR)&((PTP_PACKET)TmpBuf)->u.S.hdr.info,
+ sizeof( STRESS_PACKET ) -
+// ( sizeof( ULONG ) + OpenP->Media->HeaderSize )
+ ( sizeof(ULONG) + sizeof(MEDIA_HEADER))
+ );
+
+ //
+ // Now setup the remainder of TmpBuf with a random amount of data
+ // from the data buffer.
+ //
+ // DataBufOffset1,2 is the random offset into the data buffer that will be
+ // used to fill the packet.
+ //
+
+ DataBufOffset1 = OpenP->Stress->DataBuffer[0] + RandomOffset;
+ DataBufOffset2 = OpenP->Stress->DataBuffer[1] + RandomOffset;
+
+ //
+ // TmpBufDataSize is the remainder of the TmpBuf that will be filled with
+ // data from the DataBuf
+ //
+
+ TmpBufDataSize = TmpBufSize - sizeof( STRESS_PACKET );
+
+ if ( TmpBufDataSize > 0 ) {
+
+ TmpBufDataOffset = TmpBuf + sizeof( STRESS_PACKET );
+
+ RtlMoveMemory(
+ TmpBufDataOffset,
+ DataBufOffset1,
+ TmpBufDataSize
+ );
+
+ DataBufOffset1 += TmpBufDataSize;
+ DataBufOffset2 += TmpBufDataSize;
+
+ } else {
+ TP_ASSERT( TmpBufDataSize >= 0 );
+ }
+
+
+ //
+ // Sanjeevk : Comment
+ //
+ // We now simply proceed to create the packet. We start of by using the TmpBuf we created
+ // and forming the header and then tack on the data buffer we allocated. MDL's are allocated
+ // as we go thru the data portions
+ //
+ // NOTE: To make the data discontiguous, we are using the following sheme
+ //
+ // We have allocated two data buffers and filled them in with identical contents
+ //
+ // LOC.A
+ // --------------------------------
+ // BUFFER 1 | 00 01 02 03 .....FF 00 01 ..... |
+ // --------------------------------
+ // LOC.B
+ // ---------------------------------
+ // BUFFER 2 | 00 01 02 03 .....FF 00 01 ..... |
+ // ---------------------------------
+ // ^
+ // |
+ // COMMON OFFSET
+ // We now maintain a common offset into both buffers and simply switch between the two
+ // locations.
+ //
+ // LOGIC
+ // 1. Get location A at COMMON OFFSET from buffer 1. Take length Y. Obtain a MDL
+ // and chain than buffer onto the packet
+ // 2. Increment the COMMON OFFSET by length Y
+ // 3. Get location B at COMMON OFFSET from buffer 2. Take length X. Obtain a MDL
+ // and chain than buffer onto the packet
+ // 4. Increment the COMMON OFFSET by length X
+ // 5. Repeat steps 1,2,3 and 4 till you have reached the end of the total packet
+ // length to be mapped(ie. incremental length = 0 )
+ //
+ // This makes the data verification an easy process since the sequence of data bytes
+ // stays the same although now the data areas are no longer contiguous.
+ //
+ switch( PacketMakeUp ) {
+
+ case RAND:
+
+ //
+ // Slice up the TmpBuf containing the Frame Header and the
+ // TP_PACKET_HEADER, and create the beginning of the PACKET.
+ //
+
+ while ( TmpBufSize > 0 ) {
+
+ MdlSize = TpGetRandom(
+ 0,
+ OpenP->Media->MaxPacketLen /
+ ( 2 * OpenP->Environment->RandomBufferNumber )
+ );
+
+ if ( MdlSize > TmpBufSize ) {
+ MdlSize = TmpBufSize;
+ }
+
+
+ //
+ // STARTCHANGE
+ //
+ //
+ // Ensure that the first buffer in the packet has length >= size
+ // of the media header. This is an NDIS 3.0 requirement for
+ // the sake of maintaining performance
+ //
+ if ( FirstBuffer ) {
+ if ( MdlSize < OpenP->Media->HeaderSize ) {
+ MdlSize = OpenP->Media->HeaderSize;
+ }
+ FirstBuffer = FALSE;
+ }
+ //
+ // STOPCHANGE
+ //
+
+ Buffer = TpAllocateBuffer( TmpBuf,MdlSize );
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ TmpBuf += MdlSize;
+ TmpBufSize -= MdlSize;
+ PacketSize -= MdlSize;
+ }
+
+ //
+ // Now convert the data section of the into NDIS_BUFFERs and add to the
+ // end of the PACKET.
+ //
+
+ while ( PacketSize > 0 ) {
+
+ MdlSize = TpGetRandom(
+ 0,
+ OpenP->Media->MaxPacketLen /
+ ( 2 * OpenP->Environment->RandomBufferNumber )
+ );
+
+ if ( MdlSize > PacketSize ) {
+ MdlSize = PacketSize;
+ }
+
+ //
+ // Using DISCONTIGUITY
+ //
+ if ( Pulse ) {
+ Buffer = TpAllocateBuffer( DataBufOffset1,MdlSize );
+ Pulse = FALSE;
+ } else {
+ Buffer = TpAllocateBuffer( DataBufOffset2,MdlSize );
+ Pulse = TRUE;
+ }
+
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ PacketSize -= MdlSize;
+ DataBufOffset1 += (ULONG)MdlSize;
+ DataBufOffset2 += (ULONG)MdlSize;
+ }
+ break;
+
+ case ZEROS:
+
+ //
+ // Slice up the TmpBuf containing the Frame Header and the
+ // TP_PACKET_HEADER, and create the beginning of the PACKET.
+ //
+
+ while (TmpBufSize > 0) {
+
+ if ( ( MdlSize = TpGetRandom( 0,3 ) ) != 0 ) {
+ MdlSize = TpGetRandom(
+ 0,
+ OpenP->Media->MaxPacketLen /
+ ( 2 * OpenP->Environment->RandomBufferNumber )
+ );
+ }
+ if ( MdlSize > TmpBufSize ) {
+ MdlSize = TmpBufSize;
+ }
+ //
+ // STARTCHANGE
+ //
+ //
+ // Ensure that the first buffer in the pakcet has length >= size
+ // of the media header. This is an NDIS 3.0 requirement for
+ // the sake of maintaining performance
+ //
+ if ( FirstBuffer ) {
+ if ( MdlSize < OpenP->Media->HeaderSize ) {
+ MdlSize = OpenP->Media->HeaderSize;
+ }
+ FirstBuffer = FALSE;
+ }
+ //
+ // STOPCHANGE
+ //
+ Buffer = TpAllocateBuffer( TmpBuf,MdlSize );
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ TmpBuf += MdlSize;
+ TmpBufSize -= MdlSize;
+ PacketSize -= MdlSize;
+ }
+
+ //
+ // Now convert the data section of the into NDIS_BUFFERs and add to the
+ // end of the PACKET.
+ //
+
+ while ( PacketSize > 0 ) {
+
+ if ( ( MdlSize = TpGetRandom( 0,3 ) ) != 0 ) {
+ MdlSize = TpGetRandom(
+ 0,
+ OpenP->Media->MaxPacketLen /
+ ( 2 * OpenP->Environment->RandomBufferNumber )
+ );
+ }
+
+ if ( MdlSize > PacketSize ) {
+ MdlSize = PacketSize;
+ }
+
+
+ //
+ // Using DISCONTIGUITY
+ //
+ if ( Pulse ) {
+ Buffer = TpAllocateBuffer( DataBufOffset1,MdlSize );
+ Pulse = FALSE;
+ } else {
+ Buffer = TpAllocateBuffer( DataBufOffset2,MdlSize );
+ Pulse = TRUE;
+ }
+
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ PacketSize -= MdlSize;
+ DataBufOffset1 += (ULONG)MdlSize;
+ DataBufOffset2 += (ULONG)MdlSize;
+ }
+ break;
+
+ case ONES:
+
+ //
+ // Slice up the TmpBuf containing the Frame Header and the
+ // TP_PACKET_HEADER, and create the beginning of the PACKET.
+ //
+
+ while ( TmpBufSize > 0 ) {
+
+ if ( ( MdlSize = TpGetRandom( 0,3 ) ) != 1 ) {
+ MdlSize = TpGetRandom(
+ 0,
+ OpenP->Media->MaxPacketLen /
+ ( 2 * OpenP->Environment->RandomBufferNumber )
+ );
+ }
+ if ( MdlSize > TmpBufSize ) {
+ MdlSize = TmpBufSize;
+ }
+
+ //
+ // STARTCHANGE
+ //
+ //
+ // Ensure that the first buffer in the pakcet has length >= size
+ // of the media header. This is an NDIS 3.0 requirement for
+ // the sake of maintaining performance
+ //
+ if ( FirstBuffer ) {
+ if ( MdlSize < OpenP->Media->HeaderSize ) {
+ MdlSize = OpenP->Media->HeaderSize;
+ }
+ FirstBuffer = FALSE;
+ }
+ //
+ // STOPCHANGE
+ //
+
+ Buffer = TpAllocateBuffer( TmpBuf,MdlSize );
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ TmpBuf += MdlSize;
+ TmpBufSize -= MdlSize;
+ PacketSize -= MdlSize;
+ }
+
+ //
+ // Now convert the data section of the into NDIS_BUFFERs and add to the
+ // end of the PACKET.
+ //
+
+ while ( PacketSize > 0 ) {
+
+ if ( ( MdlSize = TpGetRandom( 0,3 ) ) != 1 ) {
+ MdlSize = TpGetRandom(
+ 0,
+ OpenP->Media->MaxPacketLen /
+ ( 2 * OpenP->Environment->RandomBufferNumber )
+ );
+ }
+
+ if ( MdlSize > PacketSize ) {
+ MdlSize = PacketSize;
+ }
+
+ //
+ // Using DISCONTIGUITY
+ //
+ if ( Pulse ) {
+ Buffer = TpAllocateBuffer( DataBufOffset1,MdlSize );
+ Pulse = FALSE;
+ } else {
+ Buffer = TpAllocateBuffer( DataBufOffset2,MdlSize );
+ Pulse = TRUE;
+ }
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ PacketSize -= MdlSize;
+ DataBufOffset1 += (ULONG)MdlSize;
+ DataBufOffset2 += (ULONG)MdlSize;
+
+ }
+ break;
+
+ case SMALL:
+
+ //
+ // Slice up the TmpBuf containing the Frame Header and the
+ // TP_PACKET_HEADER, and create the beginning of the PACKET.
+ //
+
+ while ( TmpBufSize > 0 ) {
+
+ MdlSize = TpGetRandom( 0,OpenP->Media->MaxPacketLen/50 );
+
+ if ( MdlSize > TmpBufSize ) {
+ MdlSize = TmpBufSize;
+ }
+
+ //
+ // STARTCHANGE
+ //
+ //
+ // Ensure that the first buffer in the pakcet has length >= size
+ // of the media header. This is an NDIS 3.0 requirement for
+ // the sake of maintaining performance
+ //
+ if ( FirstBuffer ) {
+ if ( MdlSize < OpenP->Media->HeaderSize ) {
+ MdlSize = OpenP->Media->HeaderSize;
+ }
+ FirstBuffer = FALSE;
+ }
+ //
+ // STOPCHANGE
+ //
+
+ Buffer = TpAllocateBuffer( TmpBuf,MdlSize );
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ TmpBuf += MdlSize;
+ TmpBufSize -= MdlSize;
+ PacketSize -= MdlSize;
+ }
+
+ //
+ // Now convert the data section of the into NDIS_BUFFERs and add to the
+ // end of the PACKET.
+ //
+
+ while ( PacketSize > 0 ) {
+
+ MdlSize = TpGetRandom( 0,OpenP->Media->MaxPacketLen/50 );
+
+ if ( MdlSize > PacketSize ) {
+ MdlSize = PacketSize;
+ }
+
+ //
+ // Using DISCONTIGUITY
+ //
+ if ( Pulse ) {
+ Buffer = TpAllocateBuffer( DataBufOffset1,MdlSize );
+ Pulse = FALSE;
+ } else {
+ Buffer = TpAllocateBuffer( DataBufOffset2,MdlSize );
+ Pulse = TRUE;
+ }
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ PacketSize -= MdlSize;
+ DataBufOffset1 += (ULONG)MdlSize;
+ DataBufOffset2 += (ULONG)MdlSize;
+ }
+ break;
+
+ case KNOWN:
+
+
+ for ( i=0;i<NumBuffers;i++ ) {
+
+ Buffer = TpAllocateBuffer( TmpBuf,BufferSize );
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ TmpBuf += BufferSize;
+ PacketSize -= BufferSize;
+ }
+
+ if ( RemainingHdr > 0 ) {
+
+ Buffer = TpAllocateBuffer( TmpBuf,RemainingHdr );
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ PacketSize -= RemainingHdr;
+ }
+
+ if ( PacketSize > 0 ) {
+
+ //
+ // Determine the number of remaining buffers, and if it exists,
+ // the size of the last buffer.
+ //
+
+ NumBuffers = PacketSize / BufferSize;
+
+ for (i=0;i<NumBuffers;i++ ) {
+
+ //
+ // Using DISCONTIGUITY
+ //
+ if ( Pulse ) {
+ Buffer = TpAllocateBuffer( DataBufOffset1,BufferSize );
+ Pulse = FALSE;
+ } else {
+ Buffer = TpAllocateBuffer( DataBufOffset2,BufferSize );
+ Pulse = TRUE;
+ }
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ DataBufOffset1 += (ULONG)BufferSize;
+ DataBufOffset2 += (ULONG)BufferSize;
+ }
+
+ if ( RemainingPkt > 0 ) {
+
+ //
+ // Using DISCONTIGUITY
+ //
+ if ( Pulse ) {
+ Buffer = TpAllocateBuffer( DataBufOffset1,RemainingPkt );
+ Pulse = FALSE;
+ } else {
+ Buffer = TpAllocateBuffer( DataBufOffset2,RemainingPkt );
+ Pulse = TRUE;
+ }
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+ }
+ }
+ break;
+
+ default:
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: unknown packet makeup\n");
+ }
+ return NULL;
+ }
+ return Packet;
+}
+
+
+PNDIS_PACKET
+TpStressCreateTruncatedPacket(
+ IN POPEN_BLOCK OpenP,
+ IN NDIS_HANDLE PacketHandle,
+ IN UCHAR PacketProtocol,
+ IN UCHAR ResponseType
+ )
+{
+ NDIS_STATUS Status;
+ PNDIS_PACKET Packet;
+ PNDIS_BUFFER Buffer;
+ PUCHAR TmpBuf;
+ PPROTOCOL_RESERVED ProtRes;
+
+ //
+ // Using a CONTIGUOUS allocation scheme in the SERVER pool
+ //
+ NdisAllocatePacket( &Status,&Packet,PacketHandle );
+
+ if ( Status != NDIS_STATUS_SUCCESS ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint1("TpStressCreatePacket: NdisAllocatePacket failed %s\n",
+ TpGetStatus( Status ));
+ }
+ return NULL;
+ }
+
+ //
+ // Mark the Protocol's reserved section to NULL to indicate that
+ // this packet was not allocated from a TP_TRANSMIT_POOL, and set
+ // the InstanceCounters to NULL. TpStressCreateTransmitPool and the
+ // Packet Set Info routines will set them if applicable.
+ //
+
+ ProtRes = PROT_RES( Packet );
+ ProtRes->Pool.TransmitPool = NULL;
+ ProtRes->InstanceCounters = NULL;
+
+ TmpBuf = (PUCHAR)TpStressInitPacketHeader(
+ OpenP,
+ ( 2 * sizeof( STRESS_PACKET ) ),
+ sizeof( STRESS_PACKET ),
+ NULL_ADDRESS,
+ OpenP->StationAddress,
+ 0, //DestInstance
+ 0, //SrcInstance
+ PacketProtocol,
+ ResponseType,
+ 0, //RandomOffset
+ 0L, //SequenceNumber
+ 0L, //MaxSequenceNumber
+ 0, //ClientReference
+ 0, //ServerReference
+ FALSE // DataChecking
+ );
+
+ if ( TmpBuf == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreateTruncatedPacket: failed to initialize Packet Header\n");
+ }
+ return NULL;
+ }
+
+ Buffer = TpAllocateBuffer( TmpBuf,sizeof( STRESS_PACKET ) );
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ Buffer = TpAllocateBuffer(
+ OpenP->Stress->DataBuffer[0],
+ OpenP->Media->MaxPacketLen*2
+ );
+
+ if ( Buffer == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreatePacket: failed to create the MDL\n");
+ }
+ TpStressFreePacket( Packet );
+ return NULL;
+ }
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ //
+ // STOPCHANGE
+ //
+
+ return Packet;
+}
+
+
+ULONG
+TpGetPacketSignature(
+ IN PNDIS_PACKET Packet
+ )
+
+{
+ NDIS_STATUS Status;
+ PUCHAR TmpBuf;
+ PUCHAR TmpBuf1;
+ UINT TmpBufSize = sizeof( STRESS_PACKET );
+ PNDIS_BUFFER Buffer;
+ PUCHAR Memory;
+ UINT MemoryLength;
+ ULONG Signature;
+ BOOLEAN GotWholeTpPacket;
+
+ if ( Packet == NULL ) {
+ return 0xffffffff;
+ }
+
+ Status = NdisAllocateMemory(
+ (PVOID *)&TmpBuf,
+ TmpBufSize,
+ 0,
+ HighestAddress
+ );
+
+ if ( Status != NDIS_STATUS_SUCCESS ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpGetPacketSignature: unable to allocate tmp buffer\n");
+ }
+ return 0xffffffff;
+ } else {
+ NdisZeroMemory( TmpBuf,TmpBufSize );
+ }
+
+ TmpBuf1 = TmpBuf;
+
+ NdisQueryPacket( Packet,NULL,NULL,&Buffer,NULL );
+
+ GotWholeTpPacket = FALSE;
+
+ while ( Buffer != NULL ) {
+
+ NdisQueryBuffer(
+ Buffer,
+ (PVOID *)&Memory,
+ &MemoryLength
+ );
+
+ if ( MemoryLength > TmpBufSize ) {
+ MemoryLength = TmpBufSize;
+ }
+
+ RtlMoveMemory( TmpBuf1,Memory,MemoryLength );
+
+ TmpBufSize -= MemoryLength;
+ TmpBuf1 += MemoryLength;
+
+ if (TmpBufSize == 0 ) {
+ GotWholeTpPacket = TRUE;
+ break;
+ }
+
+ NdisGetNextBuffer( Buffer,&Buffer );
+ }
+
+ if ( GotWholeTpPacket == TRUE ) {
+ Signature = ((PSTRESS_PACKET)TmpBuf)->hdr.info.Signature;
+ } else {
+ Signature = 0xffffffff;
+ }
+
+ NdisFreeMemory( TmpBuf,0,0 );
+
+ return Signature;
+}
+
+
+VOID
+TpStressFreePacket(
+ IN PNDIS_PACKET Packet
+ )
+{
+ PNDIS_BUFFER HeadBuffer;
+ PNDIS_BUFFER Buffer;
+ PPROTOCOL_RESERVED ProtRes;
+
+
+ if ( Packet == NULL ) {
+ return;
+ }
+
+ NdisUnchainBufferAtFront( Packet,&HeadBuffer );
+
+ if ( HeadBuffer != NULL ) {
+
+ NdisUnchainBufferAtFront( Packet,&Buffer );
+
+ while ( Buffer != NULL ) {
+ TpFreeBuffer( Buffer );
+ NdisUnchainBufferAtFront( Packet,&Buffer );
+ }
+
+ //
+ // Due to the method used to create the header buffer this
+ // size is now invalid, but will work.
+ //
+
+ HeadBuffer->ByteCount = ( sizeof( STRESS_PACKET ) * 2 );
+
+ NdisFreeMemory( MmGetMdlVirtualAddress( HeadBuffer ),0,0 );
+
+ TpFreeBuffer( HeadBuffer );
+ }
+
+ ProtRes = PROT_RES( Packet );
+
+ ProtRes->Pool.TransmitPool = NULL;
+ ProtRes->InstanceCounters = NULL;
+
+ NdisFreePacket( Packet );
+
+ Packet = NULL;
+}
+
+
+PTP_TRANSMIT_POOL
+TpStressCreateTransmitPool(
+ IN POPEN_BLOCK OpenP,
+ IN NDIS_HANDLE PacketHandle,
+ IN PACKET_MAKEUP PacketMakeUp,
+ IN UCHAR PacketProtocol,
+ IN UCHAR ResponseType,
+ IN INT PacketSize,
+ IN INT NumPackets,
+ IN BOOLEAN ServerPool
+ )
+{
+ NDIS_STATUS Status;
+ PTP_TRANSMIT_POOL TmpPool;
+ PNDIS_PACKET Packet;
+ PPROTOCOL_RESERVED ProtRes;
+ ULONG SequenceNumber = 0;
+ ULONG MaxSequenceNumber = 0;
+ INT NextPacketSize;
+ INT i;
+ UCHAR DestInstance = 0;
+ UCHAR SrcInstance = 0;
+ UCHAR ClientReference = 0;
+ UCHAR ServerReference = 0;
+
+ //
+ // Allocate the Packet Pool Structure
+ //
+
+ Status = NdisAllocateMemory(
+ (PVOID *)&TmpPool,
+ sizeof( TP_TRANSMIT_POOL ),
+ 0,
+ HighestAddress
+ );
+
+ if ( Status != NDIS_STATUS_SUCCESS ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreateTransmitPool: failed to allocate TmpPool\n");
+ }
+ return NULL;
+ } else {
+ NdisZeroMemory( TmpPool,sizeof( TP_TRANSMIT_POOL ));
+ }
+
+ //
+ // and allocate it's SpinLock
+ //
+
+ TmpPool->SpinLockAllocated = FALSE;
+
+ NdisAllocateSpinLock( &TmpPool->SpinLock );
+
+ TmpPool->SpinLockAllocated = TRUE;
+
+ //
+ // Set the Packet Pool Chain to empty
+ //
+
+ TmpPool->Head = NULL;
+ TmpPool->Tail = NULL;
+
+ for ( i=0;i<NumPackets-1;i++ ) {
+
+ if ( ServerPool == TRUE ) {
+
+ Packet = TpStressCreateTruncatedPacket(
+ OpenP,
+ PacketHandle,
+ PacketProtocol,
+ ResponseType
+ );
+ } else {
+
+ if ( OpenP->Stress->Arguments->PacketType == RANDOMSIZE ) {
+
+ NextPacketSize = TpGetRandom(
+ sizeof( STRESS_PACKET ),
+ PacketSize
+ );
+
+ } else { // ( OpenP->Arguments->Packet_Size == FIXEDSIZE )
+
+ NextPacketSize = PacketSize;
+ }
+
+ Packet = TpStressCreatePacket(
+ OpenP,
+ PacketHandle,
+ PacketMakeUp,
+ DestInstance,
+ SrcInstance,
+ PacketProtocol,
+ ResponseType,
+ NULL_ADDRESS,
+ NextPacketSize,
+ 0, // BufferSize
+ SequenceNumber,
+ MaxSequenceNumber,
+ ClientReference,
+ ServerReference,
+ FALSE
+ );
+ }
+
+ if ( Packet == NULL ) {
+ IF_TPDBG ( TP_DEBUG_RESOURCES ) {
+ TpPrint0("TpStressCreateTransmitPool: could not allocate packet for pool.\n");
+ }
+ TpStressFreeTransmitPool( TmpPool );
+ return NULL;
+ }
+
+ ProtRes = PROT_RES( Packet );
+ ProtRes->Pool.NextPacket = TmpPool->Head;
+ TmpPool->Head = Packet;
+
+ if ( i == 0 ) {
+ TmpPool->Tail = Packet;
+ }
+ }
+
+ //
+ // Initialize the NumPackets var and the allocation counters
+ //
+
+ TmpPool->Allocated = 0;
+ TmpPool->Deallocated = 0;
+
+ return TmpPool;
+}
+
+
+VOID
+TpStressFreeTransmitPool(
+ IN PTP_TRANSMIT_POOL TpTransmitPool
+ )
+{
+ PNDIS_PACKET Packet;
+ PPROTOCOL_RESERVED ProtRes;
+
+ if ( TpTransmitPool == NULL ) {
+ return;
+ }
+
+ //
+ // If the spin lock was allocated free it.
+ //
+
+ if ( TpTransmitPool->SpinLockAllocated == TRUE ) {
+ NdisFreeSpinLock( &TpTransmitPool->SpinLock );
+ }
+
+ //
+ // Unchain and destroy the packets chained in the Packet Pool.
+ //
+
+ while ( TpTransmitPool->Head != NULL ) {
+ Packet = TpTransmitPool->Head;
+
+ ProtRes = PROT_RES( TpTransmitPool->Head );
+ TpTransmitPool->Head = ProtRes->Pool.NextPacket;
+
+ TpStressFreePacket( Packet );
+ }
+
+ //
+ // And free the Packet Pool Structure.
+ //
+
+ NdisFreeMemory( TpTransmitPool,0,0 );
+}
+
+
+PNDIS_PACKET
+TpStressAllocatePoolPacket(
+ IN PTP_TRANSMIT_POOL TpTransmitPool,
+ IN PINSTANCE_COUNTERS Counters
+ )
+{
+ PPROTOCOL_RESERVED ProtRes;
+ PNDIS_PACKET Packet;
+
+ NdisAcquireSpinLock( &TpTransmitPool->SpinLock );
+
+ if ( TpTransmitPool->Head == NULL ) {
+ NdisReleaseSpinLock( &TpTransmitPool->SpinLock );
+ return NULL;
+ }
+
+ Packet = TpTransmitPool->Head;
+
+ ProtRes = PROT_RES( Packet );
+ TpTransmitPool->Head = ProtRes->Pool.NextPacket;
+
+ if ( TpTransmitPool->Head == NULL ) {
+ TpTransmitPool->Tail = NULL;
+ }
+
+ TpTransmitPool->Allocated++;
+
+ NdisReleaseSpinLock( &TpTransmitPool->SpinLock );
+
+ ProtRes->Pool.TransmitPool = TpTransmitPool;
+ ProtRes->InstanceCounters = Counters;
+
+ return Packet;
+}
+
+
+VOID
+TpStressSetPoolPacketInfo(
+ IN POPEN_BLOCK OpenP,
+ IN OUT PNDIS_PACKET Packet,
+ IN PUCHAR DestAddr,
+ IN UCHAR DestInstance,
+ IN UCHAR SrcInstance,
+ IN ULONG SequenceNumber,
+ IN ULONG MaxSequenceNumber,
+ IN UCHAR ClientReference,
+ IN UCHAR ServerReference
+ )
+{
+ PNDIS_BUFFER Buffer;
+ PUCHAR Memory;
+ UINT Length;
+ PSTRESS_PACKET StrPacket;
+
+ NdisQueryPacket( Packet,NULL,NULL,&Buffer,NULL );
+
+ NdisQueryBuffer( Buffer,(PVOID *)&Memory,&Length );
+
+ StrPacket = (PSTRESS_PACKET)Memory;
+
+ StrPacket->hdr.info.DestInstance = DestInstance;
+ StrPacket->hdr.info.SrcInstance = SrcInstance;
+ StrPacket->hdr.info.CheckSum = 0xFFFFFFFF;
+
+ StrPacket->sc.SequenceNumber = SequenceNumber;
+ StrPacket->sc.MaxSequenceNumber = MaxSequenceNumber;
+ StrPacket->sc.ClientReference = ClientReference;
+ StrPacket->sc.ServerReference = ServerReference;
+
+ TpInitPoolMediaHeader( &StrPacket->hdr,OpenP->Media,DestAddr );
+
+
+ StrPacket->sc.CheckSum = TpSetCheckSum(
+ (PUCHAR)&StrPacket->hdr.info,
+ sizeof( STRESS_PACKET ) -
+ ( sizeof( ULONG ) +
+ OpenP->Media->HeaderSize )
+ );
+
+}
+
+
+VOID
+TpStressSetTruncatedPacketInfo(
+ IN POPEN_BLOCK OpenP,
+ IN OUT PNDIS_PACKET Packet,
+ IN PUCHAR DestAddr,
+ IN INT PacketSize,
+ IN UCHAR DestInstance,
+ IN UCHAR SrcInstance,
+ IN ULONG SequenceNumber,
+ IN ULONG MaxSequenceNumber,
+ IN UCHAR ClientReference,
+ IN UCHAR ServerReference,
+ IN ULONG DataBufferOffset
+ )
+{
+ PNDIS_BUFFER Buffer;
+ PNDIS_BUFFER NextBuffer;
+ PUCHAR Memory;
+ UINT Length;
+ LONG DataBufferSize;
+ PSTRESS_PACKET TpPacket;
+ BOOLEAN Reset;
+ static BOOLEAN IntroduceFalsePageInfo;
+ register UINT PageCount1;
+ register UINT PageCount2;
+
+ Reset = FALSE;
+
+ NdisQueryPacket( Packet,NULL,NULL,&Buffer,NULL );
+
+ NdisQueryBuffer(
+ Buffer,
+ (PVOID *)&Memory,
+ &Length
+ );
+
+ TpPacket = (PSTRESS_PACKET)Memory;
+
+ TpPacket->hdr.info.PacketSize = PacketSize;
+ TpPacket->hdr.info.DestInstance = DestInstance;
+ TpPacket->hdr.info.SrcInstance = SrcInstance;
+ TpPacket->hdr.info.CheckSum = 0xFFFFFFFF;
+
+ TpPacket->sc.SequenceNumber = SequenceNumber;
+ TpPacket->sc.MaxSequenceNumber = MaxSequenceNumber;
+ TpPacket->sc.ClientReference = ClientReference;
+ TpPacket->sc.ServerReference = ServerReference;
+ TpPacket->sc.DataBufOffset = DataBufferOffset;
+
+ TpInitTruncatedMediaHeader(
+ &TpPacket->hdr,
+ OpenP->Media,
+ DestAddr,
+ PacketSize
+ );
+
+ TpPacket->sc.CheckSum = TpSetCheckSum(
+ (PUCHAR)&TpPacket->hdr.info,
+ sizeof( STRESS_PACKET ) -
+ ( sizeof( ULONG ) +
+ OpenP->Media->HeaderSize )
+ );
+
+ NdisGetNextBuffer( Buffer,&NextBuffer );
+
+ DataBufferSize = PacketSize - sizeof( STRESS_PACKET );
+
+ TP_ASSERT( DataBufferSize >= 0 );
+
+ if ( DataBufferSize == 0 ) {
+ DataBufferSize = 1;
+ Reset = TRUE;
+ }
+
+ // test
+ {
+ PMDL TmpMdl;
+ ULONG TmpSize;
+ PVOID VirtualAddress;
+
+ TmpMdl = (PMDL)NextBuffer;
+ VirtualAddress = OpenP->Stress->DataBuffer[0]+DataBufferOffset;
+
+ TmpSize = COMPUTE_PAGES_SPANNED(VirtualAddress, DataBufferSize);
+ if (((TmpMdl->Size - sizeof(MDL)) >> 2L) < TmpSize)
+ {
+ TpPrint0("TpStressSetTruncatePacketInfo: bad mdl size\n");
+ TpPrint1("New Mdl size = %d\n", TmpMdl->Size);
+ TpPrint1("DataBufferSize = %d\n", DataBufferSize);
+ TpPrint1("PagesSpanned = %d\n", TmpSize);
+ TpPrint1("MdlPages = %d\n", (TmpMdl->Size - sizeof(MDL)) >> 2L);
+ TpBreakPoint();
+ }
+ }
+
+ IoBuildPartialMdl(
+ OpenP->Stress->DataBufferMdl[0],
+ (PMDL)NextBuffer,
+ (PVOID)(OpenP->Stress->DataBuffer[0]+DataBufferOffset),
+ DataBufferSize
+ );
+
+ if ( Reset == TRUE ) {
+ NextBuffer->ByteCount = 0;
+ }
+
+ Packet->Private.TotalLength = PacketSize;
+
+
+
+
+ PageCount1 = ADDRESS_AND_SIZE_TO_SPAN_PAGES( MmGetMdlVirtualAddress( NextBuffer ), MmGetMdlByteCount( NextBuffer ) );
+ PageCount2 = ADDRESS_AND_SIZE_TO_SPAN_PAGES( MmGetMdlVirtualAddress( Buffer ), MmGetMdlByteCount( Buffer ) );
+
+
+ if ( IntroduceFalsePageInfo ) {
+ IntroduceFalsePageInfo = FALSE;
+ Packet->Private.PhysicalCount = (PageCount1 + PageCount2) | 0x08000000 ;
+ } else {
+ IntroduceFalsePageInfo = TRUE;
+ Packet->Private.PhysicalCount = PageCount1 + PageCount2;
+ }
+
+}
+
+
+
+VOID
+TpStressFreePoolPacket(
+ IN OUT PNDIS_PACKET Packet
+ )
+{
+ PPROTOCOL_RESERVED ProtRes;
+ PTP_TRANSMIT_POOL TpTransmitPool;
+
+ //
+ // Determine the location of the Test Protocol Packet Pool to return
+ // this packet to.
+ //
+
+ ProtRes = PROT_RES( Packet );
+ TpTransmitPool = ProtRes->Pool.TransmitPool;
+
+ //
+ // Null out the Packets NextPacket pointer. It will be placed the
+ // end of the Packet Pool chain.
+ //
+
+ ProtRes->Pool.TransmitPool = NULL;
+ ProtRes->InstanceCounters = NULL;
+
+ //
+ // Take the SpinLock which guards the Packet Pool
+ //
+
+ NdisAcquireSpinLock( &TpTransmitPool->SpinLock );
+
+ //
+ // If the Packet Pool's Head pointer is NULL the poll is
+ // empty, and this packet is at the Head and the Tail.
+ //
+
+ if ( TpTransmitPool->Head == NULL ) {
+
+ //
+ // Chain the packet to the head of the Packet Pool Chain.
+ //
+
+ TpTransmitPool->Head = Packet;
+
+ } else {
+
+ //
+ // Else chain the packet to the end of the Packet Pool Chain.
+ //
+
+ ProtRes = PROT_RES( TpTransmitPool->Tail );
+ ProtRes->Pool.NextPacket = Packet;
+ }
+
+ //
+ // Finally point the Packet Pool Struct Tail pointer at this packet,
+ // and incremented the Deallocated Packets counter.
+ //
+
+ TpTransmitPool->Tail = Packet;
+ TpTransmitPool->Deallocated++;
+
+ //
+ // And release the Packet Pool SpinLock.
+ //
+
+ NdisReleaseSpinLock( &TpTransmitPool->SpinLock );
+}
+
+//
+// Functional Packet Routines
+//
+
+
+PTP_PACKET
+TpFuncInitPacketHeader(
+ IN POPEN_BLOCK OpenP,
+ IN INT PacketSize
+ )
+
+// ---------------
+//
+// Routine Description:
+//
+// Arguments:
+//
+// Return Value:
+//
+// ----------------
+
+{
+ NDIS_STATUS Status;
+ PTP_PACKET TmpBuffer;
+ PUCHAR DataField;
+ INT DataFieldSize;
+ USHORT i;
+
+ Status = NdisAllocateMemory((PVOID *)&TmpBuffer,
+ PacketSize,
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG ( TP_DEBUG_RESOURCES )
+ {
+ TpPrint0("TpFuncInitPacketHeader: failed to allocate TmpBuffer\n");
+ }
+ return NULL;
+
+ }
+ else
+ {
+ NdisZeroMemory( (PVOID)TmpBuffer,PacketSize );
+ }
+
+ if ( !TpInitMediaHeader(&TmpBuffer->u.F2.hdr1,
+ OpenP->Media,
+ OpenP->Send->DestAddress,
+ OpenP->StationAddress,
+ PacketSize))
+ {
+ NdisFreeMemory( TmpBuffer,0,0 );
+ return NULL;
+ }
+
+
+ //
+ // initialize the packet information header
+ //
+
+ TmpBuffer->u.F2.hdr1.info.Signature = FUNC1_PACKET_SIGNATURE;
+ TmpBuffer->u.F2.hdr1.info.DestInstance = OpenP->OpenInstance;
+ TmpBuffer->u.F2.hdr1.info.SrcInstance = 0;
+ TmpBuffer->u.F2.hdr1.info.PacketSize = PacketSize;
+ TmpBuffer->u.F2.hdr1.info.PacketType = FUNC1_PACKET_TYPE;
+ TmpBuffer->u.F2.hdr1.info.u.PacketNumber = (UCHAR)OpenP->Send->PacketsSent;
+
+ //
+ // and set the checksum in the header.
+ //
+
+ TmpBuffer->u.F2.hdr1.info.CheckSum =TpSetCheckSum((PUCHAR)&TmpBuffer->u.F2.hdr1.info,
+ sizeof( PACKET_INFO ) - sizeof( ULONG ));
+
+
+ if ( OpenP->Send->ResendPackets == TRUE )
+ {
+ //
+ // We are building a resend packet, fill in the FUNC_PACKET info
+ // for the internal packet, and determine the start of the test
+ // data field.
+ //
+
+ if ( !TpInitMediaHeader(&TmpBuffer->u.F2.hdr2,
+ OpenP->Media,
+ OpenP->Send->ResendAddress,
+ OpenP->Send->DestAddress,
+ ( PacketSize - sizeof( FUNC1_PACKET))))
+ {
+ NdisFreeMemory( TmpBuffer,0,0 );
+ return NULL;
+ }
+
+
+ TmpBuffer->u.F2.hdr2.info.Signature = FUNC2_PACKET_SIGNATURE;
+ TmpBuffer->u.F2.hdr2.info.DestInstance = OpenP->OpenInstance;
+ TmpBuffer->u.F2.hdr2.info.SrcInstance = 0;
+ TmpBuffer->u.F2.hdr2.info.PacketSize = PacketSize - sizeof( FUNC1_PACKET );
+ TmpBuffer->u.F2.hdr2.info.PacketType = FUNC2_PACKET_TYPE;
+ TmpBuffer->u.F2.hdr2.info.u.PacketNumber = (UCHAR)OpenP->Send->PacketsSent;
+
+ DataField = (PUCHAR)((PUCHAR)TmpBuffer + (ULONG)sizeof( FUNC2_PACKET ));
+
+ //
+ // Now set the checksum value for the header.
+ //
+
+ TmpBuffer->u.F2.hdr2.info.CheckSum = TpSetCheckSum((PUCHAR)&TmpBuffer->u.F2.hdr2.info,
+ sizeof( PACKET_INFO ) - sizeof( ULONG ));
+
+ }
+ else
+ {
+ //
+ // Otherwise this is just a standard packet with no resend
+ // packet contained within. Mark it as such, a set the data field
+ // pointer to the beginning of the data field.
+ //
+
+ DataField = (PUCHAR)((PUCHAR)TmpBuffer + (ULONG)sizeof( FUNC1_PACKET ) );
+
+ }
+
+ DataFieldSize = PacketSize - (ULONG)( DataField - (PUCHAR)TmpBuffer );
+
+ for ( i = 0 ; i < (USHORT)DataFieldSize ; i++ )
+ {
+ DataField[i] = (UCHAR)( i % 256 );
+ }
+
+ return TmpBuffer;
+}
+
+
+ULONG
+TpSetCheckSum(
+ IN PUCHAR Buffer,
+ IN ULONG BufLen
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PUCHAR TmpBuffer = Buffer;
+ ULONG TmpCheckSum = 0;
+ ULONG i;
+
+ for ( i = 0 ; i < BufLen ; i++ ) {
+ TmpCheckSum += (ULONG)*TmpBuffer++;
+ }
+
+ return ~TmpCheckSum;
+}
+/*
+
+VOID
+TpSetCheckSum(
+ IN PUCHAR Buffer,
+ IN ULONG BufLen,
+ IN PULONG CheckSum
+ )
+
+/ *++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--* /
+
+{
+ PUCHAR TmpBuffer = Buffer;
+ ULONG TmpCheckSum = 0;
+ ULONG i;
+
+ return;
+
+ for ( i = 0 ; i < BufLen ; i++ ) {
+ TmpCheckSum += (ULONG)*TmpBuffer++;
+ }
+
+ *CheckSum = ~TmpCheckSum;
+}
+*/
+
+
+BOOLEAN
+TpCheckSum(
+ IN PUCHAR Buffer,
+ IN ULONG BufLen,
+ IN PULONG CheckSum
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PUCHAR TmpBuffer = Buffer;
+ ULONG TmpCheckSum = 0;
+ ULONG i;
+
+ return TRUE;
+
+ for ( i = 0 ; i < BufLen ; i++ ) {
+ TmpCheckSum += (ULONG)*TmpBuffer++;
+ }
+
+ if (( *CheckSum + TmpCheckSum ) != -1 ) {
+ TP_ASSERT( FALSE );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+PNDIS_PACKET
+TpFuncAllocateSendPacket(
+ IN POPEN_BLOCK OpenP
+ )
+
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+--*/
+
+{
+ NDIS_STATUS Status;
+ PPROTOCOL_RESERVED ProtRes;
+ PNDIS_PACKET Packet;
+ PNDIS_BUFFER Buffer;
+ PUCHAR TmpBuf;
+ INT TmpBufSize;
+ INT MdlSize;
+ INT i;
+
+ //
+ // Make sure that this is a legal packetsize, and if it isn't,
+ // then set it to the nearest valid size.
+ //
+
+ if (( OpenP->Send->ResendPackets == FALSE ) &&
+ ( OpenP->Send->PacketSize < sizeof( FUNC1_PACKET ))) {
+
+ OpenP->Send->PacketSize = sizeof( FUNC1_PACKET );
+
+ TpPrint0("TpFuncAllocateSendPacket: PacketSize to small for packet type.\n");
+ TpPrint1("TpFuncAllocateSendPacket: Using %d\n",OpenP->Send->PacketSize);
+
+
+ } else if (( OpenP->Send->ResendPackets == TRUE ) &&
+ ( OpenP->Send->PacketSize < sizeof( FUNC2_PACKET ))) {
+
+ OpenP->Send->PacketSize = sizeof( FUNC2_PACKET );
+
+ TpPrint0("TpFuncAllocateSendPacket: Invalid PacketSize for packet type.\n");
+ TpPrint1("TpFuncAllocateSendPacket: Using %d\n",OpenP->Send->PacketSize);
+
+ } else if ( OpenP->Send->PacketSize >
+ (ULONG)OpenP->Media->MaxPacketLen ) {
+
+ OpenP->Send->PacketSize = (ULONG)OpenP->Media->MaxPacketLen;
+
+ TpPrint0("TpFuncAllocateSendPacket: PacketSize to large for media.\n");
+ TpPrint1("TpFuncAllocateSendPacket: Using %d\n",OpenP->Send->PacketSize);
+ }
+
+ NdisAllocatePacket(
+ &Status,
+ &Packet,
+ OpenP->Send->PacketHandle
+ );
+
+ if ( Status != NDIS_STATUS_SUCCESS ) {
+
+ TpPrint1("TpFuncAllocateSendPacket: NdisAllocatePacket failed %s\n",
+ TpGetStatus( Status ));
+ return NULL;
+ }
+
+ ProtRes = PROT_RES( Packet );
+ ProtRes->Pool.PacketHandle = &OpenP->Send->PacketHandle;
+ ProtRes->InstanceCounters = OpenP->Send->Counters;
+
+ TmpBufSize = OpenP->Send->PacketSize;
+
+ TmpBuf = (PUCHAR)TpFuncInitPacketHeader( OpenP,TmpBufSize );
+
+ if ( TmpBuf == NULL ) {
+ TpPrint0("TpFuncAllocateSendPacket: failed to initialize Packet Header\n");
+ return NULL;
+ }
+
+ //
+ // Functional packets are made up of two small buffers at the beginning
+ // of the MDL chain followed by one large buffer at the end of the chain.
+ // If there is not enough room in the packet the buffer chain will be
+ // affected accordingly.
+ //
+
+ for ( i=0;i<2;i++ ) {
+
+ //
+ // Select the size of the first and second buffer.
+ //
+
+ MdlSize = TpGetRandom( OpenP->Media->HeaderSize,0x64 );
+
+ if ( MdlSize > TmpBufSize ) {
+
+ //
+ // If it is larger than the remaining packet size, then
+ // we will use only the remaining packet.
+ //
+
+ MdlSize = TmpBufSize;
+ }
+
+ //
+ // Create a buffer (MDL) using this portion of the packet.
+ //
+
+ Buffer = TpAllocateBuffer( TmpBuf,MdlSize );
+
+ if ( Buffer == NULL ) {
+ TpPrint0("TpFuncAllocateSendPacket: failed to create the MDL\n");
+ TpFuncFreePacket( Packet,OpenP->Send->PacketSize );
+ return (PNDIS_PACKET)NULL;
+ }
+
+ //
+ // And chain it to the back of the packet.
+ //
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ //
+ // reset the packet size counters and see if we are out of packet.
+ //
+
+ TmpBuf += MdlSize;
+ TmpBufSize -= MdlSize;
+
+ if ( TmpBufSize == 0 ) {
+
+ //
+ // if so, then return the packet we have made.
+ //
+
+ return Packet;
+ }
+ }
+
+ //
+ // Otherwise tack on the remainder of the buffer as the last mdl
+ // in the chain.
+ //
+
+ Buffer = TpAllocateBuffer( TmpBuf,TmpBufSize );
+
+ NdisChainBufferAtBack( Packet,Buffer );
+
+ if ( Buffer == NULL ) {
+ TpPrint0("TpFuncAllocateSendPacket: failed to create the MDL\n");
+ TpFuncFreePacket( Packet,OpenP->Send->PacketSize );
+ return NULL;
+ }
+
+ return Packet;
+}
+
+
+
+VOID
+TpFuncFreePacket(
+ PNDIS_PACKET Packet,
+ ULONG PacketSize
+ )
+
+{
+ PNDIS_BUFFER HeadBuffer;
+ PNDIS_BUFFER Buffer;
+
+ if ( Packet == NULL ) {
+ return;
+ }
+
+ NdisUnchainBufferAtFront( Packet,&HeadBuffer );
+
+ if ( HeadBuffer != NULL ) {
+
+ NdisUnchainBufferAtFront( Packet,&Buffer );
+
+ while ( Buffer != NULL ) {
+ TpFreeBuffer( Buffer );
+ NdisUnchainBufferAtFront( Packet,&Buffer );
+ }
+
+ HeadBuffer->ByteCount = PacketSize;
+
+ NdisFreeMemory( MmGetMdlVirtualAddress( HeadBuffer ),0,0 );
+
+ TpFreeBuffer( HeadBuffer );
+ }
+
+ NdisFreePacket( Packet );
+}