summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/testprot/tpdrvr/stress.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ndis/testprot/tpdrvr/stress.c')
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/stress.c2503
1 files changed, 2503 insertions, 0 deletions
diff --git a/private/ntos/ndis/testprot/tpdrvr/stress.c b/private/ntos/ndis/testprot/tpdrvr/stress.c
new file mode 100644
index 000000000..c19e6a0e3
--- /dev/null
+++ b/private/ntos/ndis/testprot/tpdrvr/stress.c
@@ -0,0 +1,2503 @@
+// *****************************
+//
+// Copyright (c) 1990 Microsoft Corporation
+//
+// Module Name:
+//
+// tpstress.c
+//
+// Abstract:
+//
+// This module implements the Test Protocol Stress routines and the
+// basic controls for stressing the MAC.
+//
+// Author:
+//
+// Tom Adams (tomad) 15-Dec-1990
+//
+// Environment:
+//
+// Kernel mode
+//
+// Revision History:
+//
+// Sanjeev Katariya(sanjeevk)
+// 3-16-93 Bug#2874: TpStressFreeResources().
+// 4-8-93 Bug#2874: Added routine TpStressFreePostResetResources() to be able to
+// call it thru the routine and its associated completion routine.
+// 4-8-1993 Added ARCNET Support
+// 5-14-1993 Bug#6583 Re-arranged and cleaned up TpStressDpc for CYCLICAL testing
+//
+// Tim Wynsma (timothyw)
+// 5-18-94 Fixed warnings; general cleanup
+//
+// ****************************
+
+#include <ndis.h>
+#include <string.h>
+
+#include "tpdefs.h"
+#include "media.h"
+#include "tpprocs.h"
+
+//
+// Forward references
+//
+
+VOID
+TpStressDpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ );
+
+VOID
+TpStressServerDpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ );
+
+VOID
+TpStressStatsDpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ );
+
+VOID
+TpStressEndReqDpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ );
+
+VOID
+TpStressFinalDpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ );
+
+VOID
+TpStressFreeClient(
+ IN POPEN_BLOCK OpenP
+ );
+
+VOID
+TpStressFreeServer(
+ IN POPEN_BLOCK OpenP
+ );
+
+VOID
+TpStressFreePostResetResources(
+ IN POPEN_BLOCK OpenP
+ );
+
+VOID
+TpStressRegister2Dpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ );
+
+//
+// ********************
+//
+
+
+NDIS_STATUS
+TpStressStart(
+ IN POPEN_BLOCK OpenP,
+ IN PSTRESS_ARGUMENTS StressArguments
+ )
+
+// --------------------
+//
+// Routine Description:
+//
+// This is the main routine of the NDIS 3.0 Stress Tool. This routine
+// opens the proper MAC adapter, creates the data structures used to
+// control the test, runs the specific test, and then cleans up.
+//
+// The flow of an actual test is controlled through a series of packet
+// protocols sent from a Client machine to any responding Server machines.
+// Initially the Client sends a REGISTER_REQ packet to an agreed upon
+// address that all servers have registered as a multicast address. Any
+// Server receiving this packet responds directly to the Client with a
+// REGISTER_RESP packet stating that the Server will participate in the
+// test. At this point the Client begins to send the actual test packets,
+// TEST_REQ, to each registered Server, who in turn responds with a
+// TEST_RESP packet. At the end of a test run the Client sends each
+// Server a STATS_REQ packet requesting that the Server print it's test
+// statistic. Finally the Client sends a TEST_END packet which causes
+// each Server to tear down it's test control data structures and end
+// the test.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+// ----------------------
+
+{
+ NDIS_STATUS Status;
+ PNDIS_PACKET Packet = NULL;
+ PSTRESS_ARGUMENTS Args = NULL;
+ PSERVER_INFO Server = NULL;
+ INT i, j;
+ INT ClientNumPackets = 100; // put in environment.
+ INT ServerNumPackets = 100;
+ UINT PacketFilter;
+ LARGE_INTEGER DueTime;
+ PPENDING PPend;
+
+ //
+ // Set the StartStarted flag to true indicating that we are running
+ // a stress test, it will be set to false later if the initialization
+ // fails. Set the stress cleanup flags Final and Ended to false.
+ // This will disable any early unexpected cleanup.
+ //
+
+ OpenP->Stress->StressStarted = TRUE;
+ OpenP->Stress->StressFinal = FALSE;
+ OpenP->Stress->StressEnded = FALSE;
+
+ //
+ // Increment the reference count on the OpenBlock stating that an async
+ // test is running and must be ended prior to closing the adapter on this
+ // open.
+ //
+
+ TpAddReference( OpenP );
+
+ //
+ // Initialize the test arguments structure using the arguments passed
+ // in from the command line.
+ //
+
+ OpenP->Stress->Arguments = StressArguments;
+
+ //
+ // Set up new Args pointer for easier access to the arguments.
+ //
+
+ Args = OpenP->Stress->Arguments;
+
+ //
+ // Initialize the random number generator.
+ //
+
+ TpSetRandom();
+
+ //
+ // Initialize the data buffer used for the data in each packet.
+ //
+
+ TpStressInitDataBuffer( OpenP,2 * OpenP->Media->MaxPacketLen );
+
+ if ( OpenP->Stress->DataBuffer[0] == NULL ||
+ OpenP->Stress->DataBuffer[1] == NULL ||
+ OpenP->Stress->DataBufferMdl[0] == NULL ||
+ OpenP->Stress->DataBufferMdl[1] == NULL )
+ {
+ TpPrint0("TpStressStart: failed to init Data Buffer\n");
+ Status = NDIS_STATUS_RESOURCES;
+ goto clean_up;
+ }
+
+ //
+ // Allocate the global counter storage and zero the counters.
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->GlobalCounters,
+ sizeof( GLOBAL_COUNTERS ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpStressStart: failed to allocate counters.\n");
+ }
+ Status = NDIS_STATUS_RESOURCES;
+ goto clean_up;
+ }
+ else
+ {
+ NdisZeroMemory((PVOID)OpenP->GlobalCounters,sizeof( GLOBAL_COUNTERS ));
+ }
+
+ NdisAllocatePacketPool( &Status,
+ &OpenP->Stress->PacketHandle,
+ 50,
+ sizeof( PROTOCOL_RESERVED ) );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ TpPrint0("TpStressStart: could not allocate OpenP packet pool\n");
+ goto clean_up;
+ }
+ else
+ {
+ OpenP->Stress->PoolInitialized = TRUE;
+ }
+
+ //
+ // Then initialize the PPENDING buffer.
+ //
+
+ TpInitializePending( OpenP->Stress->Pend );
+
+ if (( Args->MemberType == TP_SERVER ) || ( Args->MemberType == BOTH ))
+ {
+ //
+ // Allocate memory for the server storage and packet pool, initialize
+ // it and the CLIENT_INFO array contained.
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Stress->Server,
+ sizeof( SERVER_STORAGE ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ TpPrint0("TpStressStart: could not allocate Server storage memory\n");
+ Status = NDIS_STATUS_RESOURCES;
+ goto clean_up;
+ }
+ else
+ {
+ NdisZeroMemory( OpenP->Stress->Server,sizeof( SERVER_STORAGE ));
+ }
+
+ OpenP->Stress->Server->NumClients = 0 ;
+ OpenP->Stress->Server->ActiveClients = 0;
+ OpenP->Stress->Server->PoolInitialized = FALSE;
+ OpenP->Stress->Server->PadByte = 0xFF;
+ OpenP->Stress->Server->PacketHandle = NULL;
+ OpenP->Stress->Server->TransmitPool = NULL;
+ OpenP->Stress->Server->PadLong = 0xFFFFFFFF;
+
+ for ( i=0 ; i < MAX_CLIENTS ; i++ )
+ {
+ OpenP->Stress->Server->Clients[i].ClientInstance = 0xFF;
+ OpenP->Stress->Server->Clients[i].ClientReference = 0xFF;
+ OpenP->Stress->Server->Clients[i].DataChecking = FALSE;
+ OpenP->Stress->Server->Clients[i].TestEnding = FALSE;
+ OpenP->Stress->Server->Clients[i].ServerResponseType = -1;
+ OpenP->Stress->Server->Clients[i].LastSequenceNumber = 0;
+ OpenP->Stress->Server->Clients[i].Counters = NULL;
+ }
+
+ NdisAllocatePacketPool( &Status,
+ &OpenP->Stress->Server->PacketHandle,
+ 200, // should be environment.server...
+ sizeof( PROTOCOL_RESERVED ) );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ TpPrint0("TpStressStart: could not allocate server packet pool\n");
+ goto clean_up;
+ }
+ else
+ {
+ OpenP->Stress->Server->PoolInitialized = TRUE;
+ }
+
+ //
+ // The server always gets it's TEST_RESP packets from a transmit
+ // pool, so create it now.
+ //
+
+ OpenP->Stress->Server->TransmitPool =
+ TpStressCreateTransmitPool( OpenP,
+ OpenP->Stress->Server->PacketHandle,
+ Args->PacketMakeUp,
+ TEST_RESP,
+ Args->ResponseType,
+ Args->PacketSize,
+ ServerNumPackets,
+ TRUE );
+
+ if ( OpenP->Stress->Server->TransmitPool == NULL )
+ {
+ TpPrint0("TpStressStart: could not create server transmit pool\n");
+ Status = NDIS_STATUS_RESOURCES;
+ goto clean_up;
+ }
+
+ //
+ // Set the stressing flag, thus enabling the TpStress protocol
+ // handler routines, and the stopstress flag to allow the TpStress
+ // Dpc to be queued.
+ //
+
+ OpenP->Stress->Stressing = TRUE;
+ OpenP->Stress->StopStressing = FALSE;
+
+ //
+ // Now setup the card to receive packets.
+ //
+
+ //
+ // STARTCHANGE
+ //
+ if ( OpenP->Media->MediumType == NdisMedium802_5 ) // Tokenring
+ {
+ //
+ // add the stress functional address "C0-00-00-01-00-00"
+ //
+
+ Status = TpStressSetFunctionalAddress( OpenP,
+ (PUCHAR)&OpenP->Environment->StressAddress[2],
+ FALSE );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ TpPrint0("TpStressStart: failed to set Functional Address.\n");
+ goto clean_up;
+ }
+
+ PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_FUNCTIONAL;
+
+ }
+ else if (OpenP->Media->MediumType == NdisMedium802_3) // Ethernet
+ {
+ //
+ // or the stress multicast address "07-07-07-07-07-07"
+ //
+
+ Status = TpStressAddMulticastAddress( OpenP,
+ (PUCHAR)OpenP->Environment->StressAddress,
+ FALSE );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ TpPrint0("TpStressStart: failed to add Test Multicast address.\n");
+ goto clean_up;
+ }
+
+ PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST;
+
+ }
+ else if (OpenP->Media->MediumType == NdisMediumFddi) // Fddi
+ {
+ //
+ // or the stress multicast address "07-07-07-07-07-07"
+ //
+
+ Status = TpStressAddLongMulticastAddress( OpenP,
+ (PUCHAR)OpenP->Environment->StressAddress,
+ FALSE );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ TpPrint0("TpStressStart: failed to add Test Multicast address.\n");
+ goto clean_up;
+ }
+
+ PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_MULTICAST;
+
+ }
+ else if (OpenP->Media->MediumType == NdisMediumArcnet878_2) // ARCNET
+ {
+ //
+ // ARCNET does not support the concept of multicast(group) addressing.
+ // It works it two modes only, either directed or broadcast. So will use
+ // the broadcast for setting up client server connections and thereafter
+ // use the directed addresses
+ //
+ PacketFilter = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_BROADCAST;
+ }
+ //
+ // STOPCHANGE
+ //
+
+
+ //
+ // Set the packet filter to accept the following packet types.
+ //
+
+ Status = TpStressSetPacketFilter( OpenP,PacketFilter );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ TpPrint0("TpStressStart: failed to set packet filter.\n");
+ goto clean_up;
+ }
+
+ if ( Args->MemberType == TP_SERVER )
+ {
+ //
+ // Initialize the DPC used to call TpStressServerDpc, and
+ // TpStressFinalDpc.
+ //
+
+ KeInitializeDpc(&OpenP->Stress->TpStressDpc,
+ TpStressServerDpc,
+ (PVOID)OpenP );
+
+ KeInitializeDpc(&OpenP->Stress->TpStressFinalDpc,
+ TpStressFinalDpc,
+ (PVOID)OpenP );
+
+ //
+ // and then set the flag allowing the receive handler to
+ // accept and process test packets.
+ //
+
+ Args->BeginReceives = TRUE;
+
+ //
+ // The Server's main body of work is performed in the receive
+ // handler, TpStressReceive, and the receive completion routine,
+ // TpStressReceiveComplete. Once the Client sends the END_REQ
+ // packet the server will break out of the busy loop, clean up and
+ // exit. So, for now the server simply queues a DPC at which time
+ // the server examines the stop flags, and if true, cleans up and
+ // exits.
+ //
+
+ //
+ // Queue the first instance of the DPC and return.
+ //
+
+ if ( !KeInsertQueueDpc( &OpenP->Stress->TpStressDpc, NULL, NULL) )
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressStart failed to queue the TpStressServerDpc.\n");
+ }
+ Status = NDIS_STATUS_FAILURE;
+ goto clean_up;
+ }
+ }
+ }
+
+ if (( Args->MemberType == TP_CLIENT ) || ( Args->MemberType == BOTH ))
+ {
+ //
+ // Allocate memory for the client storage and packet pool, initialize
+ // it and the SERVER_INFO array contained.
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Stress->Client,
+ sizeof( CLIENT_STORAGE ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ TpPrint0("TpStressStart: could not allocate client storage.\n");
+ goto clean_up;
+ }
+ else
+ {
+ NdisZeroMemory( OpenP->Stress->Client,sizeof( CLIENT_STORAGE ));
+ }
+
+ OpenP->Stress->Client->NumServers = 0 ;
+ OpenP->Stress->Client->NextServer = 0 ;
+ OpenP->Stress->Client->ActiveServers = 0;
+ OpenP->Stress->Client->PoolInitialized = FALSE;
+ OpenP->Stress->Client->PacketHandle = NULL;
+ OpenP->Stress->Client->TransmitPool = NULL;
+ OpenP->Stress->Client->PacketSize = sizeof( STRESS_PACKET );
+ OpenP->Stress->Client->BufferSize = 1;
+ OpenP->Stress->Client->SizeIncrease = OpenP->Media->MaxPacketLen/150;
+
+ for ( i=0 ; i < MAX_SERVERS ; i++ )
+ {
+ OpenP->Stress->Client->Servers[i].ServerInstance = 0xFF;
+ OpenP->Stress->Client->Servers[i].ClientReference = 0xFF;
+ OpenP->Stress->Client->Servers[i].ServerReference = 0xFF;
+ OpenP->Stress->Client->Servers[i].ServerActive = FALSE;
+ OpenP->Stress->Client->Servers[i].WindowReset = 0;
+ OpenP->Stress->Client->Servers[i].SequenceNumber = 1;
+
+ if ( Args->WindowEnabled == TRUE )
+ {
+ OpenP->Stress->Client->Servers[i].MaxSequenceNumber =
+ OpenP->Environment->WindowSize;
+ }
+ else
+ {
+ OpenP->Stress->Client->Servers[i].MaxSequenceNumber = 0xFFFFFFFF;
+ }
+
+ OpenP->Stress->Client->Servers[i].LastSequenceNumber = 0;
+ OpenP->Stress->Client->Servers[i].PacketDelay = 0;
+ OpenP->Stress->Client->Servers[i].DelayLength = Args->DelayLength;
+ OpenP->Stress->Client->Servers[i].WindowReset = 0;
+ }
+
+ NdisAllocatePacketPool( &Status,
+ &OpenP->Stress->Client->PacketHandle,
+ 200, // 1000, // should 200 be environment...
+ sizeof( PROTOCOL_RESERVED ) );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ TpPrint0("TpStressStart: could not allocate client packet pool\n");
+ goto clean_up;
+ }
+ else
+ {
+ OpenP->Stress->Client->PoolInitialized = TRUE;
+ }
+
+ if ( Args->PacketsFromPool == TRUE )
+ {
+ OpenP->Stress->Client->TransmitPool =
+ TpStressCreateTransmitPool( OpenP,
+ OpenP->Stress->Client->PacketHandle,
+ Args->PacketMakeUp,
+ TEST_REQ,
+ Args->ResponseType,
+ Args->PacketSize,
+ ClientNumPackets,
+ FALSE );
+
+ if ( OpenP->Stress->Client->TransmitPool == NULL )
+ {
+ TpPrint0("TpStressStart: could not create TP packet pool\n");
+ Status = NDIS_STATUS_RESOURCES;
+ goto clean_up;
+ }
+ }
+
+ //
+ // Initialize the DPCs to call TpStressDpc, TpStressReg2Dpc,
+ // TpStressStatsDpc, TpStressEndReqDpc and TpStressFinalDpc.
+ //
+
+ KeInitializeDpc(&OpenP->Stress->TpStressDpc,
+ TpStressDpc,
+ (PVOID)OpenP );
+
+ KeInitializeDpc(&OpenP->Stress->TpStressReg2Dpc,
+ TpStressRegister2Dpc,
+ (PVOID)OpenP );
+
+ KeInitializeDpc(&OpenP->Stress->TpStressStatsDpc,
+ TpStressStatsDpc,
+ (PVOID)OpenP );
+
+ KeInitializeDpc(&OpenP->Stress->TpStressEndReqDpc,
+ TpStressEndReqDpc,
+ (PVOID)OpenP );
+
+ KeInitializeDpc(&OpenP->Stress->TpStressFinalDpc,
+ TpStressFinalDpc,
+ (PVOID)OpenP );
+
+ //
+ // and then set the flag to enable packets being received
+ // to be handled.
+ //
+
+ Args->BeginReceives = TRUE;
+
+ //
+ // Set the stressing flag, thus enabling the TpStress protocol
+ // handler routines, and the stopstress flag to allow the
+ // TpStress Dpc to be queued.
+ //
+
+ OpenP->Stress->Stressing = TRUE;
+ OpenP->Stress->StopStressing = FALSE;
+
+ if ( Args->MemberType == TP_CLIENT )
+ {
+ //
+ // Set the packet filter to accept directed packets only.
+ //
+
+ PacketFilter = NDIS_PACKET_TYPE_DIRECTED;
+
+ Status = TpStressSetPacketFilter( OpenP,PacketFilter );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ TpPrint0("TpStressStart: failed to set packet filter.\n");
+ goto clean_up;
+ }
+ }
+
+ //
+ // We are now ready to begin the test, send several instances
+ // of the REGISTER_REQ packet to the STRESS_MULTICAST/FUNCTIONAL
+ // address.
+ //
+
+ TpPrint0("TpStress: starting search for servers\n");
+
+ PPend = OpenP->Stress->Pend;
+
+ for ( j=0;j<10;j++ )
+ {
+ //
+ // Construct the REGISTER_REQ packet and send it.
+ //
+
+ Packet = TpStressCreatePacket( OpenP,
+ OpenP->Stress->Client->PacketHandle,
+ Args->PacketMakeUp,
+ 0, // ServerInstance
+ OpenP->OpenInstance,
+ REGISTER_REQ,
+ Args->ResponseType,
+ OpenP->Environment->StressAddress,
+ sizeof( STRESS_PACKET ),
+ sizeof( STRESS_PACKET ),
+ (ULONG)j,
+ 0L,0,0,
+ Args->DataChecking );
+
+ if ( Packet == NULL )
+ {
+ TpPrint1("TpStressStart: failed to build REGISTER_REQ packet #%d\n",j);
+ Status = NDIS_STATUS_RESOURCES;
+ goto clean_up;
+ }
+
+ TpStressSend( OpenP,Packet,NULL );
+
+ //
+ // Pause momentarily before sending the next packet.
+ //
+
+ for (;;)
+ {
+ DueTime.HighPart = -1; // So it will be relative.
+ DueTime.LowPart = (ULONG)(-4 * ONE_HUNDREDTH_SECOND );
+ KeDelayExecutionThread(KernelMode, TRUE, &DueTime);
+
+ NdisAcquireSpinLock( &PPend->SpinLock );
+ if (PPend->PendingPackets)
+ {
+ NdisReleaseSpinLock( &PPend->SpinLock );
+ }
+ else
+ {
+ NdisReleaseSpinLock( &PPend->SpinLock );
+ break;
+ }
+ }
+
+ }
+ TpPrint0("TpStress: done with search for servers\n");
+
+ //
+ // If no servers have registered there is no point in running
+ // the test, clean up and return.
+ //
+
+ if ( OpenP->Stress->Client->NumServers == 0 )
+ {
+ TpPrint0("TpStressStart: No servers registered, exiting\n");
+ Status = TP_STATUS_NO_SERVERS;
+ goto clean_up;
+ }
+
+ //
+ // Show what servers are registered.
+ //
+
+ for ( i=0;i<(INT)OpenP->Stress->Client->NumServers;i++ )
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint2("\nServer %d: open %d, ",
+ i, OpenP->Stress->Client->Servers[i].ServerInstance);
+
+ //
+ // STARTCHANGE
+ //
+ if ( OpenP->Media->MediumType == NdisMediumArcnet878_2 )
+ {
+ TpPrint1("address %02X\n", OpenP->Stress->Client->Servers[i].Address[0]);
+ }
+ else
+ {
+ TpPrint6("address %02X-%02X-%02X-%02X-%02X-%02X\n",
+ OpenP->Stress->Client->Servers[i].Address[0],
+ OpenP->Stress->Client->Servers[i].Address[1],
+ OpenP->Stress->Client->Servers[i].Address[2],
+ OpenP->Stress->Client->Servers[i].Address[3],
+ OpenP->Stress->Client->Servers[i].Address[4],
+ OpenP->Stress->Client->Servers[i].Address[5]);
+ }
+ //
+ // STOPCHANGE
+ //
+ }
+ }
+
+ //
+ // Initialize the multi-purpose counter used for the up-for-air
+ // delay, stats dpc and end dpc, and the Register_Req2 counter.
+ //
+
+ OpenP->Stress->FirstIteration = TRUE;
+ OpenP->Stress->Counter = 0;
+ OpenP->Stress->Reg2Counter = 0;
+
+ //
+ // Queue the first instance of the Stress DPC.
+ //
+
+ DueTime.HighPart = -1; // So it will be relative.
+ DueTime.LowPart = (ULONG)(- ( 5 * ONE_SECOND ));
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressTimer,
+ DueTime,
+ &OpenP->Stress->TpStressDpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressStart failed to queue the TpStressDpc.\n");
+ }
+ Status = NDIS_STATUS_FAILURE;
+ goto clean_up;
+ }
+
+ //
+ // Queue the first instance of the Register2 DPC and return.
+ //
+
+ if ( !KeInsertQueueDpc( &OpenP->Stress->TpStressReg2Dpc,
+ NULL,
+ NULL ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressStart failed to queue the TpStressReg2Dpc.\n");
+ }
+ Status = NDIS_STATUS_FAILURE;
+ goto clean_up;
+ }
+ }
+ return NDIS_STATUS_PENDING;
+
+
+clean_up:
+
+ IF_TPDBG ( TP_DEBUG_DISPATCH )
+ {
+ TpPrint1("TpStressStart failed to start: returned %s\n", TpGetStatus( Status ));
+ }
+
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if ( OpenP->Stress->StressIrp != NULL )
+ {
+ OpenP->Stress->StressIrp->IoStatus.Status = Status;
+ }
+
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+
+ return Status;
+}
+
+
+
+VOID
+TpStressDpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ )
+
+// -------
+//
+// Routine Description:
+//
+// Arguments:
+//
+// Return Value:
+//
+// -----------
+
+{
+ POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
+ PSTRESS_ARGUMENTS Args;
+ PCLIENT_STORAGE Client;
+ NDIS_STATUS Status;
+ UCHAR ServerNum;
+ PSERVER_INFO Server;
+ BOOLEAN ContinueSending = TRUE;
+ LARGE_INTEGER DueTime;
+
+ UNREFERENCED_PARAMETER( Dpc );
+ UNREFERENCED_PARAMETER( SysArg1 );
+ UNREFERENCED_PARAMETER( SysArg2 );
+
+ Args = OpenP->Stress->Arguments;
+ Client = OpenP->Stress->Client;
+
+ //
+ // This is the main loop of a stress test, in this loop RANDOM or
+ // FIXED size packets are sent to each server depending on the delay
+ // intervals and window size. Packets are sent one to a server, as
+ // the client loops through each server, and then repeats, if a
+ // window is closed for a given server, or the packet delay has not
+ // been reached that server will be skipped over. The client will
+ // continue to loop thru the servers sending packets until either
+ // all the packets have been sent, or all the iterations have been
+ // iterated. NOTE: setting the ServerActive flag to false on all
+ // the servers will also result in the test ending.
+ //
+
+ //
+ // If this is the beginning of the test, get the Start Time
+ // for later statistics computation.
+ //
+
+ if ( OpenP->Stress->FirstIteration == TRUE )
+ {
+ KeQuerySystemTime( &OpenP->Stress->StartTime );
+ OpenP->Stress->FirstIteration = FALSE;
+ }
+
+ //
+ // If the Stress Irp has been cancelled then clean up and leave.
+ //
+
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if (( OpenP->Stress->StressIrp == NULL ) ||
+ ( OpenP->Stress->StressIrp->Cancel == TRUE ))
+ {
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+ OpenP->Stress->StopStressing = TRUE;
+ }
+ else if ( Client->ActiveServers <= 0 )
+ {
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+
+ //
+ // There are no more active servers so just end the test here.
+ //
+
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint1("TpStressDpc: WARNING - Client Open Instance %d ending test.\n",
+ OpenP->OpenInstance);
+ TpPrint0("\tNo remaining active stress servers\n");
+ }
+
+ OpenP->Stress->StopStressing = TRUE;
+ }
+ else if (( Args->PacketType == RANDOMSIZE ) ||
+ ( Args->PacketType == FIXEDSIZE ))
+ {
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+
+ //
+ // Start looping sending packets until one of the conditions
+ // is met for stopping and requeueing a new DPC to send later.
+ // The possible conditions are Packet Delay not met, Window for
+ // a given server is closed or there are no available packets.
+ //
+
+ while ( ContinueSending == TRUE )
+ {
+ //
+ // As long as there are still packets to send or loops to
+ // iterate continue sending packets.
+ //
+
+ if (( Args->Iterations++ >= Args->TotalIterations ) ||
+ ( Args->AllPacketsSent == TRUE ))
+ {
+ break;
+ }
+ else
+ {
+ //
+ // Set the packets sent flag to true, it will be reset to
+ // false later in the loop if there are really packets left
+ // to send.
+ //
+
+ Args->AllPacketsSent = TRUE;
+
+ //
+ // Now loop through each of the servers starting with the
+ // server we left of with at the end of the last DPC.
+ //
+
+ for ( ServerNum = Client->NextServer;
+ ServerNum < Client->NumServers;
+ ServerNum++ )
+ {
+ Server = &Client->Servers[ServerNum];
+
+ //
+ // If this server is still active and we have not sent all
+ // the packets required to this it, then continue with
+ // the send process.
+ //
+
+ if (( Server->ServerActive == TRUE ) &&
+ ( Server->SequenceNumber <= Args->TotalPackets ))
+ {
+ //
+ // Set the flag indicating there are more packets
+ // to be sent.
+ //
+
+ Args->AllPacketsSent = FALSE;
+
+ //
+ // Now check if the Client has waited long enough to
+ // send another packet to this server.
+ //
+
+ if (( Server->PacketDelay++ >= Server->DelayLength ) &&
+ ( Server->SequenceNumber <= Server->MaxSequenceNumber ))
+ {
+ //
+ // And if so, allocate a packet and send it to
+ // the server.
+ //
+
+ Status = TpStressClientSend(OpenP,
+ Client->PacketHandle,
+ Client->TransmitPool,
+ Server->Address,
+ OpenP->OpenInstance,
+ Server->ServerInstance,
+ TEST_REQ,
+ Server->SequenceNumber,
+ 0, // MaxSeqNum: not used in TEST_REQ pkts.
+ Server->ClientReference,
+ Server->ServerReference,
+ Client->PacketSize,
+ Client->BufferSize );
+
+ if ( Status == NDIS_STATUS_SUCCESS )
+ {
+ Server->SequenceNumber++;
+ Server->PacketDelay = 0;
+ if ( Args->DelayType == RANDOMDELAY )
+ {
+ Server->DelayLength = TpGetRandom(0,Args->DelayLength);
+ }
+ }
+ else
+ {
+ //
+ // No packets available to send now.
+ // Queue a new DPC and exit.
+ //
+
+ ContinueSending = FALSE;
+ break;
+ }
+
+ //
+ // If the window is not open, check to see if the
+ // server is presumed dead.
+ //
+
+ }
+ else if (( Args->WindowEnabled == TRUE ) &&
+ ( Server->PacketDelay > MAX_PACKET_DELAY ))
+ { // Put MaxPacketDelay in environment?
+ //
+ // We have reset this servers window the maximum
+ // number of times and it still is not responding
+ // so we will remove it from the active servers.
+ //
+
+ if ( Server->WindowReset >= MAX_WINDOW_RESETS )
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint2(
+ "TpStressDpc: WARNING - Client Open Instance %d marking Server %d as Inactive.\n",
+ OpenP->OpenInstance,Server->ServerInstance);
+ }
+
+ Server->ServerActive = FALSE;
+ Client->ActiveServers--;
+
+ //
+ // This server may still be alive, so reset the
+ // window to the initial state causing WINDOW_SIZE
+ // more packets to be sent to the server on the
+ // next pass through the loop.
+ //
+
+ }
+ else
+ {
+ //
+ // The packet delay for this server has exceeded
+ // the maximum packet delay, and we are sending
+ // with windowing enabled, so blast out Window
+ // Size more packets.
+ //
+
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint1("TpStressDpc: WARNING - Client Open Instance %d\n",
+ OpenP->OpenInstance);
+ TpPrint2("\tincreasing Server %d MaxSequenceNumber to %d\n",
+ Server->ServerInstance,
+ Server->MaxSequenceNumber +
+ OpenP->Environment->WindowSize );
+ }
+
+ Server->MaxSequenceNumber += OpenP->Environment->WindowSize;
+
+ Server->PacketDelay = 0;
+ Server->WindowReset++;
+ Client->NextServer++;
+
+ ContinueSending = FALSE;
+ break;
+ }
+ Client->NextServer++;
+ break;
+ }
+ else
+ {
+ //
+ // Either the window for this server is closed,
+ // or the delay has not expired. Queue a new DPC,
+ // and exit. We will start with the next server
+ // with the next DPC.
+ //
+
+ Client->NextServer++;
+ ContinueSending = FALSE;
+ break;
+ }
+ }
+ }
+
+ //
+ // We have come to the end of the server array, start again
+ // at the beginning on the next FOR loop.
+ //
+
+ Client->NextServer = 0;
+ }
+ }
+ }
+ else // PacketType == CYCLICAL
+ {
+ //
+ // STARTCHANGE
+ //
+ // SanjeevK
+ //
+ // This piece of code contain one too many nested loops. It needs to be cleaned
+ // The cleanup will be instituted at a later date. For the time being the
+ // loop control will be clearly marked with entry and exit conditions
+ //
+
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+
+ if ( Client->PacketSize == 0 )
+ {
+ //
+ // We have just started the test, so set the PacketSize and
+ // BufferSize to their minimum startimg sizes.
+ //
+
+ Client->PacketSize = sizeof( STRESS_PACKET );
+ Client->BufferSize = 1;
+ }
+
+ //
+ // SanjeevK
+ //
+ // MARK EXTERIOR CONTROL
+ //
+ // NOTE
+ //
+ // All loops have control exit conditions. The code has been semi-cleaned
+ // for recognizable operation. Breaks of jumping between control loops
+ // has been minimized
+ //
+
+ //
+ // This condition if valid gets executed once. If the total iteration count
+ // is greater than 1, the work is DPCd and on re-entering takes on the
+ // values set in the control global arguments. That is why it is very important
+ // to not set the global control values on entry but on exit of a control
+ // since work can be DPC'd from any part within the control loops.
+ //
+
+ if ( Args->Iterations < Args->TotalIterations )
+ {
+ //
+ // FIRST CONTROL LOOP.
+ // Execute until we exceed MAX_PACKET_LENGTH.
+ //
+ while ( Client->PacketSize <= OpenP->Media->MaxPacketLen )
+ {
+ //
+ // SECOND CONTROL LOOP.
+ // Execute till the buffer size has gone
+ // thru a cycle of ( 1,Current Packet Size )
+ //
+ while ( Client->BufferSize <= Client->PacketSize )
+ {
+ //
+ // Disable the above while loop if...
+ //
+
+ if ( Args->PacketMakeUp != KNOWN )
+ {
+ Client->BufferSize = Client->PacketSize;
+ Client->SizeIncrease = 1;
+ }
+
+ //
+ // THIRD CONTROL LOOP
+ // Execute the same code path for all registered/valid stress servers
+ //
+ for (ServerNum=Client->NextServer;ServerNum < Client->NumServers;ServerNum++)
+ {
+ Server = &Client->Servers[ServerNum];
+
+ //
+ // If this server is still active then
+ // continue with the send process.
+ //
+
+ if ( Server->ServerActive == TRUE )
+ {
+ if (( Server->PacketDelay++ >= Server->DelayLength ) &&
+ ( Server->SequenceNumber <= Server->MaxSequenceNumber ))
+ {
+ Status = TpStressClientSend(OpenP,
+ Client->PacketHandle,
+ Client->TransmitPool,
+ Server->Address,
+ OpenP->OpenInstance,
+ Server->ServerInstance,
+ TEST_REQ,
+ Server->SequenceNumber,
+ 0, // MaxSeqNum: not used in TEST_REQ.
+ Server->ClientReference,
+ Server->ServerReference,
+ Client->PacketSize,
+ Client->BufferSize );
+
+ if ( Status == NDIS_STATUS_SUCCESS )
+ {
+ Server->SequenceNumber++;
+ Server->PacketDelay = 0;
+
+ if (Args->DelayType == RANDOMDELAY)
+ {
+ Server->DelayLength = TpGetRandom(0,Args->DelayLength);
+ }
+ }
+ else
+ {
+ //
+ // No packets are available to send now,
+ // So set the flag to queue a new DPC
+ // and exit.
+ //
+ goto breakout;
+ } // END of if ( Status == NDIS_STATUS_SUCCESS )
+ }
+ else if (( Args->WindowEnabled == TRUE ) &&
+ ( Server->PacketDelay > MAX_PACKET_DELAY ))
+ {
+ //
+ // We have reset this servers window the maximum
+ // number of times and it still is not responding
+ // so we will remove it from the active servers.
+ //
+
+ if ( Server->WindowReset >= MAX_WINDOW_RESETS )
+ {
+ //
+ // Since the window size for the server has exceeded
+ // the maximum times it could have been reset, mark this
+ // server as inactive and decrement the number of
+ // active servers by one
+ //
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint2(
+ "TpStressDpc: WARNING - Client Open Instance %d marking Server %d as Inactive.\n",
+ OpenP->OpenInstance,Server->ServerInstance);
+ }
+
+ Server->ServerActive = FALSE;
+ Client->ActiveServers--;
+ }
+ else
+ {
+ //
+ // This server may still be alive, so reset the
+ // window to the initial state causing WINDOW_SIZE
+ // more packets to be sent to the server on the
+ // next pass through the loop.
+
+ //
+ // The packet delay for this server has exceeded
+ // the maximum packet delay, and we are sending
+ // with windowing enabled, so blast out
+ // WindowSize more packets.
+ //
+
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint1("TpStressDpc: WARNING - Client Open Instance %d\n",
+ OpenP->OpenInstance);
+ TpPrint2("\tincreasing Server %d MaxSequenceNumber to %d\n",
+ Server->ServerInstance,
+ Server->MaxSequenceNumber +
+ OpenP->Environment->WindowSize );
+ }
+
+ Server->MaxSequenceNumber += OpenP->Environment->WindowSize;
+
+ Server->PacketDelay = 0;
+ Server->WindowReset++;
+
+ } // END of if ( Server->WindowReset >= MAX_WINDOW_RESETS )
+
+ Client->NextServer++;
+ goto breakout;
+ }
+ else
+ {
+ //
+ // Either the window for this server is closed
+ // or the delay has not expired yet. Queue a
+ // new DPC and exit. We will start with the
+ // next server with the next DPC.
+ //
+
+ Client->NextServer++;
+ ContinueSending = FALSE;
+ goto breakout;
+
+ } // END of if (( Args->WindowEnabled == TRUE ) &&
+ // ( Server->PacketDelay > MAX_PACKET_DELAY ))
+ } // END of if ( Server->ServerActive == TRUE )
+ } // END of FOR loop. Indicates we have dealt with all servers in the list
+
+ //
+ // CONTROL EXIT CONDITION
+ //
+ Client->NextServer = 0;
+
+ //
+ // SanjeevK
+ //
+ // NOTE
+ //
+ // This code section was badly nested within another looping section
+ // This simply needs to reside outside the loop
+ //
+ // ORIGINAL COMMENT
+ //
+ // If we have succesfully sent this packet
+ // to the last server in the list, then
+ // move on to the next packetsize/buffersize
+ // combination.
+ //
+ //
+ Client->BufferSize += Client->SizeIncrease;
+
+ } // END of while ( Client->BufferSize <= Client->PacketSize )
+
+ //
+ // CONTROL EXIT CONDITION
+ //
+ Client->BufferSize = 1;
+ Client->PacketSize += Client->SizeIncrease;
+
+ } // END of while ( Client->PacketSize <= OpenP->Media->MaxPacketLen )
+
+ //
+ // CONTROL EXIT CONDITION
+ //
+ Client->PacketSize = sizeof( STRESS_PACKET);
+
+ //
+ // We have completed one full iteration of CYCLICAL
+ // packets, inc the counter.
+ //
+
+ Args->Iterations++;
+
+ } // END of if ( Args->Iterations < Args->TotalIterations )
+
+ } // END of the else PacketType == CYCLICAL
+
+breakout:
+
+ //
+ // If the StopStress flag has been set by a command line call, or
+ // we have sent all the packets requested or completed the required
+ // number of iterations, then end the stress routine and clean up.
+ //
+
+ if (( OpenP->Stress->StopStressing == TRUE ) ||
+ ( Args->AllPacketsSent == TRUE ) ||
+ ( Args->Iterations >= Args->TotalIterations ))
+ {
+ //
+ // Set the stop stress flag to halt the Register2Dpc routine
+ // now, if it was already set this will do nothing.
+ //
+
+ OpenP->Stress->StopStressing = TRUE;
+ OpenP->Stress->Counter = 0;
+
+ //
+ // Set the time for when to queue the TpStressStatsDpc routine.
+ //
+
+ DueTime.HighPart = -1; // So it will be relative.
+ DueTime.LowPart = (ULONG)(- ( 5 * ONE_SECOND ));
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressTimer,
+ DueTime,
+ &OpenP->Stress->TpStressStatsDpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressDpc set StressEnd timer while timer existed.\n");
+ }
+ }
+ }
+ else
+ {
+ //
+ // Otherwise the test should continue, so insert the next timer in
+ // the timer queue and exit. This will queue the next instance of
+ // the TpStressDpc routine when the timer goes off.
+ //
+
+ if ( OpenP->Stress->Counter == OpenP->Environment->StressDelayInterval )
+ {
+ DueTime.HighPart = -1; // So it will be relative.
+ DueTime.LowPart = (ULONG) (- ((LONG) OpenP->Environment->UpForAirDelay ));
+ OpenP->Stress->Counter = 0;
+ }
+ else
+ {
+ DueTime.HighPart = -1; // So it will be relative.
+ DueTime.LowPart = (ULONG)(- ((LONG) OpenP->Environment->StandardDelay ));
+ OpenP->Stress->Counter++;
+ }
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressTimer,
+ DueTime,
+ &OpenP->Stress->TpStressDpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressDpc set Stress timer while timer existed.\n");
+ }
+ }
+ }
+}
+
+
+
+VOID
+TpStressServerDpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ )
+
+// ---------
+//
+// Routine Description:
+//
+// Arguments:
+//
+// Return Value:
+//
+// ---------
+
+{
+ POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
+ LARGE_INTEGER DueTime;
+
+
+ UNREFERENCED_PARAMETER( Dpc );
+ UNREFERENCED_PARAMETER( SysArg1 );
+ UNREFERENCED_PARAMETER( SysArg2 );
+
+ DueTime.HighPart = -1; // relative time.
+ DueTime.LowPart = (ULONG)(- ( ONE_SECOND ));
+
+ //
+ // If the Stress Irp has been cancelled then clean up and leave.
+ //
+
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if (( OpenP->Stress->StressIrp == NULL ) ||
+ ( OpenP->Stress->StressIrp->Cancel == TRUE ))
+ {
+ OpenP->Stress->StopStressing = TRUE;
+ }
+
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+
+ if ( OpenP->Stress->StopStressing == TRUE )
+ {
+ //
+ // Either we have received an END_TEST packet from the last
+ // Client we are stressing, or we have received a command from
+ // the user interface to stop the test, set the IoStatusBlock
+ // status field, and end it.
+ //
+
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if ( OpenP->Stress->StressIrp != NULL )
+ {
+ OpenP->Stress->StressIrp->IoStatus.Status = NDIS_STATUS_SUCCESS;
+ }
+
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressTimer,
+ DueTime,
+ &OpenP->Stress->TpStressFinalDpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressServerDpc set Stress timer while timer existed.\n");
+ }
+ }
+ }
+ else
+ {
+ //
+ // Otherwise the test should continue, so insert the next timer in
+ // the timer queue and exit. This will queue the next instance of
+ // the TpStressServerDpc routine when the timer goes off.
+ //
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressTimer,
+ DueTime,
+ &OpenP->Stress->TpStressDpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressServerDpc set Stress timer while timer existed.\n");
+ }
+ }
+ }
+}
+
+
+
+VOID
+TpStressStatsDpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ )
+
+// ---------
+//
+// Routine Description:
+//
+// Arguments:
+//
+// Return Value:
+//
+// -----------
+
+{
+ POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
+ PSTRESS_ARGUMENTS Args;
+ PCLIENT_STORAGE Client;
+ UCHAR ServerNum;
+ LARGE_INTEGER DueTime;
+ PNDIS_PACKET Packet;
+
+
+ UNREFERENCED_PARAMETER( Dpc );
+ UNREFERENCED_PARAMETER( SysArg1 );
+ UNREFERENCED_PARAMETER( SysArg2 );
+
+ Args = OpenP->Stress->Arguments;
+ Client = OpenP->Stress->Client;
+
+ //
+ // If the Stress Irp has been cancelled then skip the stats requesting.
+ //
+
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if (( OpenP->Stress->StressIrp != NULL ) &&
+ ( OpenP->Stress->StressIrp->Cancel == FALSE ))
+ {
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+
+ //
+ // Write the client statistics to the Results buffer, and send
+ // STATS_REQ packets to each server request the servers test stats.
+ //
+
+ if ( OpenP->Stress->Counter == 0 )
+ {
+ KeQuerySystemTime( &OpenP->Stress->EndTime );
+ TpCopyClientStatistics( OpenP );
+ TpPrintClientStatistics( OpenP );
+ }
+
+ for ( ServerNum=0 ; ServerNum < Client->NumServers ; ServerNum++ )
+ {
+ Packet = TpStressCreatePacket( OpenP,
+ Client->PacketHandle,
+ Args->PacketMakeUp,
+ Client->Servers[ServerNum].ServerInstance,
+ OpenP->OpenInstance,
+ STATS_REQ,
+ Args->ResponseType,
+ Client->Servers[ServerNum].Address,
+ 64, 32,
+ OpenP->Stress->Counter,
+ OpenP->Stress->Counter,
+ Client->Servers[ServerNum].ClientReference,
+ Client->Servers[ServerNum].ServerReference,
+ Args->DataChecking );
+
+ if ( Packet == NULL )
+ {
+ IF_TPDBG( TP_DEBUG_RESOURCES )
+ {
+ TpPrint0("TpStressDpc: failed to create STATS_REQ Packet\n");
+ }
+ }
+ else
+ {
+ TpStressSend( OpenP,Packet,NULL );
+ }
+ }
+ }
+ else
+ {
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+ OpenP->Stress->StopStressing = TRUE;
+ }
+
+ if ( OpenP->Stress->Counter++ < 10 )
+ {
+ //
+ // requeue the StatsDpc.
+ //
+
+ DueTime.HighPart = -1; // So it will be relative.
+ DueTime.LowPart = (ULONG)(- ( ONE_TENTH_SECOND ));
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressTimer,
+ DueTime,
+ &OpenP->Stress->TpStressStatsDpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressDpc set StressEnd timer while timer existed.\n");
+ }
+ }
+ }
+ else
+ {
+ //
+ // reset the multipurpose counter.
+ //
+
+ OpenP->Stress->Counter = 0;
+
+ //
+ // Then set the next timer for the EndDpc.
+ //
+
+ DueTime.HighPart = -1; // So it will be relative.
+ DueTime.LowPart = (ULONG)(- ( 5 * ONE_SECOND ));
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressTimer,
+ DueTime,
+ &OpenP->Stress->TpStressEndReqDpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressDpc set Stress timer while timer existed.\n");
+ }
+ }
+ }
+}
+
+
+
+VOID
+TpStressEndReqDpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ )
+
+// -------
+//
+// Routine Description:
+//
+// Arguments:
+//
+// Return Value:
+//
+// -------
+
+{
+ POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
+ PSTRESS_ARGUMENTS Args;
+ PCLIENT_STORAGE Client;
+ UCHAR ServerNum;
+ LARGE_INTEGER DueTime;
+ PNDIS_PACKET Packet;
+
+
+ UNREFERENCED_PARAMETER( Dpc );
+ UNREFERENCED_PARAMETER( SysArg1 );
+ UNREFERENCED_PARAMETER( SysArg2 );
+
+ Args = OpenP->Stress->Arguments;
+ Client = OpenP->Stress->Client;
+
+ //
+ // If the Stress Irp has been cancelled then skip the stats requesting.
+ //
+
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if (( OpenP->Stress->StressIrp != NULL ) &&
+ ( OpenP->Stress->StressIrp->Cancel == FALSE ))
+ {
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+
+ //
+ // Send an end request packet to each of the servers.
+ //
+
+ for ( ServerNum=0;ServerNum<Client->NumServers;ServerNum++ )
+ {
+ Packet = TpStressCreatePacket( OpenP,
+ Client->PacketHandle,
+ Args->PacketMakeUp,
+ Client->Servers[ServerNum].ServerInstance,
+ OpenP->OpenInstance,
+ END_REQ,
+ Args->ResponseType,
+ Client->Servers[ServerNum].Address,
+ 64, 32,
+ OpenP->Stress->Counter,
+ OpenP->Stress->Counter,
+ Client->Servers[ServerNum].ClientReference,
+ Client->Servers[ServerNum].ServerReference,
+ Args->DataChecking );
+
+ if ( Packet == NULL )
+ {
+ IF_TPDBG( TP_DEBUG_RESOURCES )
+ {
+ TpPrint0("TpStressDpc: failed to create END_REQ Packet\n");
+ }
+ }
+ else
+ {
+ TpStressSend( OpenP,Packet,NULL );
+ }
+ }
+ }
+ else
+ {
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+ OpenP->Stress->StopStressing = TRUE;
+ }
+
+ if ( OpenP->Stress->Counter++ < 10 )
+ {
+ //
+ // requeue the StatsDpc.
+ //
+
+ DueTime.HighPart = -1; // So it will be relative.
+ DueTime.LowPart = (ULONG)(- ( ONE_TENTH_SECOND ));
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressTimer,
+ DueTime,
+ &OpenP->Stress->TpStressEndReqDpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressDpc set StressEnd timer while timer existed.\n");
+ }
+ }
+ }
+ else
+ {
+ //
+ // reset the multi-purpose counter.
+ //
+
+ OpenP->Stress->Counter = 0;
+
+ //
+ // Then set the next timer for the EndDpc.
+ //
+
+ DueTime.HighPart = -1; // So it will be relative.
+ DueTime.LowPart = (ULONG)(- ( 10 * ONE_SECOND ));
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressTimer,
+ DueTime,
+ &OpenP->Stress->TpStressFinalDpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressDpc set Stress timer while timer existed.\n");
+ }
+ }
+ }
+}
+
+
+
+VOID
+TpStressFinalDpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ )
+
+// --------
+//
+// Routine Description:
+//
+// Arguments:
+//
+// Return Value:
+//
+// --------
+
+{
+ POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
+ NDIS_STATUS Status;
+ PSTRESS_ARGUMENTS Args = NULL;
+ PSERVER_INFO Server = NULL;
+ UINT i;
+ LARGE_INTEGER DueTime;
+
+
+ UNREFERENCED_PARAMETER( Dpc );
+ UNREFERENCED_PARAMETER( SysArg1 );
+ UNREFERENCED_PARAMETER( SysArg2 );
+
+ Args = OpenP->Stress->Arguments;
+
+ //
+ // Check to see if all packets sent on this open have completed,
+ // If they have not all completed see if we have waited long
+ // enough. long enough being 10 one second delayed cycles
+ // through TpStressEndDcp.
+ //
+
+ if ((((( Args->MemberType == TP_CLIENT ) &&
+ ( Args->PacketsFromPool == FALSE )) &&
+ ( OpenP->Stress->Pend->PendingPackets != 0 ))
+
+ //
+ // We are a Client getting each packet from the NdisPacketPool and
+ // all the packets from the NdisPacketPool have not completed, or ...
+ //
+
+ ||
+
+ (( Args->PacketsFromPool == TRUE ) &&
+ ( OpenP->Stress->Pend->PacketPendNumber !=
+ OpenP->Stress->Pend->PacketCompleteNumber )))
+
+ //
+ // We are getting the packets from the TP_PACKET_POOL, and
+ // all the TpPoolPackets that pended have not completed and ...
+ //
+
+ &&
+
+ ( OpenP->Stress->Counter++ < 10 ))
+ {
+
+ //
+ // We have not waited through 10 cycles of TpStressFinalDpc
+ // Then reset the timer for this dpc to try again later.
+ //
+
+ DueTime.HighPart = -1; // So it will be relative.
+ DueTime.LowPart = (ULONG)(- ( 1 * ONE_SECOND ));
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressTimer,
+ DueTime,
+ &OpenP->Stress->TpStressFinalDpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressDpc set Stress timer while timer existed.\n");
+ }
+ }
+ }
+ else
+ {
+ //
+ // Time to clean up, so first check if there are any packets
+ // still in the pending queue representing packets that were
+ // sent, pended, and have not completed. We only do this if
+ // we are a Client, the server only part is handled at the
+ // End_Req packet receipt time.
+ //
+
+ if (( Args->MemberType != TP_SERVER ) &&
+ ( OpenP->Stress->Pend->PendingPackets != 0 ))
+ {
+ //
+ // There are packets in the pend queue, so print out there
+ // addresses, and break.
+ //
+
+ IF_TPDBG( TP_DEBUG_DPC )
+ {
+ TpPrint1("TpStressFinalDpc: The following %d packets are still in the\n",
+ OpenP->Stress->Pend->PendingPackets);
+ TpPrint1(" Client's Pend Queue for Open Instance %d.\n",
+ OpenP->OpenInstance);
+ TpPrint1(" Pend Queue = %lX\n\n", OpenP->Stress->Pend);
+
+ for ( i=0 ; i<NUM_PACKET_PENDS ; i++ )
+ {
+ if (( OpenP->Stress->Pend->Packets[i] != NULL ) &&
+ ( OpenP->Stress->Pend->Packets[i] != (PNDIS_PACKET)-1 ))
+ {
+ TpPrint1("\t\t%lX\n", OpenP->Stress->Pend->Packets[i]);
+ }
+ }
+// TpBreakPoint();
+ }
+ TpInitializePending( OpenP->Stress->Pend );
+ }
+
+ //
+ // Write the stress results into the ioctl buffer to be passed
+ // back to the user application.
+ //
+
+ TpStressWriteResults( OpenP );
+
+ //
+ // if we have set a functional address or added a multicast
+ // address then clear it now.
+ //
+
+ if ( Args->MemberType != TP_CLIENT )
+ {
+ if ( OpenP->Media->MediumType == NdisMedium802_5 ) // Token Ring
+ {
+ Status = TpStressSetFunctionalAddress( OpenP,
+ (PUCHAR)NULL_ADDRESS,
+ TRUE );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ IF_TPDBG( TP_DEBUG_NDIS_CALLS )
+ {
+ TpPrint1(
+ "TpStressServerCleanUp: failed to clear Functional Address--Status = %s\n",
+ TpGetStatus(Status));
+ }
+ }
+ }
+ else if (OpenP->Media->MediumType == NdisMedium802_3) // Ethernet
+ {
+ Status = TpStressAddMulticastAddress( OpenP,
+ (PUCHAR)NULL_ADDRESS,
+ TRUE );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ IF_TPDBG( TP_DEBUG_NDIS_CALLS )
+ {
+ TpPrint1(
+ "TpStressServerCleanUp: failed to delete Multicast Address--Status = %s\n",
+ TpGetStatus(Status));
+ }
+ }
+ }
+ else if (OpenP->Media->MediumType == NdisMediumFddi) // Fddi
+ {
+ Status = TpStressAddLongMulticastAddress( OpenP,
+ (PUCHAR)NULL_ADDRESS,
+ TRUE );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ IF_TPDBG( TP_DEBUG_NDIS_CALLS )
+ {
+ TpPrint1(
+ "TpStressServerCleanUp: failed to delete Multicast Address--Status = %s\n",
+ TpGetStatus(Status));
+ }
+ }
+ } // And if you are Arcnet, do nothing
+ }
+
+ OpenP->Stress->StressFinal = TRUE;
+
+ //
+ // And clear the packet filter on the card by setting it
+ // to null.
+ //
+
+ Status = TpStressSetPacketFilter( OpenP,0 );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ IF_TPDBG( TP_DEBUG_NDIS_CALLS )
+ {
+ TpPrint0("TpStressFinalDpc: failed to reset packet filter.\n");
+ }
+ }
+ }
+}
+
+
+
+VOID
+TpStressCleanUp(
+ IN POPEN_BLOCK OpenP
+ )
+
+// ------
+//
+// Routine Description:
+//
+// This routine is used to clean up after a failed attempt to start a
+// stress test.
+//
+// Arguments:
+//
+// OpenP - a pointer to the OPEN_BLOCK containing the structures to be
+// deallocated.
+//
+// Return Value:
+//
+// None.
+//
+// ------
+
+{
+ PSTRESS_ARGUMENTS Args = NULL;
+ PSERVER_INFO Server = NULL;
+ NDIS_STATUS Status;
+
+ Args = OpenP->Stress->Arguments;
+
+ //
+ // Set the stop stress flag to halt the Register2Dpc routine
+ // now, if it was already set this will do nothing.
+ //
+
+ OpenP->Stress->StopStressing = TRUE;
+ OpenP->Stress->Stressing = FALSE;
+
+ //
+ // if we have set a functional address or added a multicast
+ // address then clear it now.
+ //
+
+ if ( Args->MemberType != TP_CLIENT )
+ {
+ if ( OpenP->Media->MediumType == NdisMedium802_5 )
+ {
+ Status = TpStressSetFunctionalAddress( OpenP,
+ (PUCHAR)NULL_ADDRESS,
+ TRUE );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ IF_TPDBG( TP_DEBUG_NDIS_CALLS )
+ {
+ TpPrint1(
+ "TpStressServerCleanUp: failed to clear Functional Address--Status = %s\n",
+ TpGetStatus(Status));
+ }
+ }
+ }
+ else if (OpenP->Media->MediumType == NdisMedium802_3)
+ {
+ Status = TpStressAddMulticastAddress( OpenP,
+ (PUCHAR)NULL_ADDRESS,
+ TRUE );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ IF_TPDBG( TP_DEBUG_NDIS_CALLS )
+ {
+ TpPrint1(
+ "TpStressServerCleanUp: failed to delete Multicast Address--Status = %s\n",
+ TpGetStatus(Status));
+ }
+ }
+ }
+ else if (OpenP->Media->MediumType == NdisMediumFddi)
+ {
+ Status = TpStressAddLongMulticastAddress( OpenP,
+ (PUCHAR)NULL_ADDRESS,
+ TRUE );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ IF_TPDBG( TP_DEBUG_NDIS_CALLS )
+ {
+ TpPrint1(
+ "TpStressServerCleanUp: failed to delete Multicast Address--Status = %s\n",
+ TpGetStatus(Status));
+ }
+ }
+ } // And if you are ARCNET do nothing
+ }
+
+ //
+ // And clear the packet filter on the card by setting it
+ // to null.
+ //
+
+ Status = TpStressSetPacketFilter( OpenP,0 );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ IF_TPDBG( TP_DEBUG_NDIS_CALLS )
+ {
+ TpPrint0("TpStressFinalDpc: failed to reset packet filter.\n");
+ }
+ }
+
+ OpenP->Stress->StressFinal = TRUE;
+
+ //
+ // Clean up the various data structures allocated during initialization
+ //
+
+ TpStressFreeResources( OpenP );
+
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if ( OpenP->Stress->StressIrp != NULL )
+ {
+ OpenP->Stress->StressIrp->IoStatus.Status = NDIS_STATUS_FAILURE;
+ }
+
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+}
+
+
+
+VOID
+TpStressFreeResources(
+ IN POPEN_BLOCK OpenP
+ )
+
+// -------------
+//
+// Changes in functionality: SanjeevK
+//
+// The RESET should occur prior to resource de-allocation. This is because
+// all requests to the adapter in question working over the OPEN_BLOCK should
+// be completed since they use the resources allocated by the open block in question.
+// After the RESET has completed, the resources are de-allocated
+//
+// Assumption
+//
+// OpenP cannot be a NULL at this point and time
+//
+// Descrption
+//
+// This function is responsible for clearing the adapter followed by dis-associating
+// any resources(memory blocks) which have been associated with an OPEN_BLOCK.
+//
+// -------------
+
+{
+ NDIS_STATUS Status;
+
+
+ // Sanjeevk : STARTCHANGE
+
+ //
+ // Initialize the Open block pointer for RESET
+ //
+ Status = NdisAllocateMemory((PVOID *)&OpenP->ResetReqHndl,
+ sizeof( TP_REQUEST_HANDLE ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpStressFreeResources: unable to allocate Reset Request Handle.\n");
+ }
+
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if ( OpenP->Irp != NULL )
+ {
+ OpenP->Irp->IoStatus.Status = NDIS_STATUS_RESOURCES;
+ }
+
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+ }
+ else
+ {
+ //
+ // Perform the RESET on the adapter
+ //
+ NdisZeroMemory( OpenP->ResetReqHndl,sizeof( TP_REQUEST_HANDLE ));
+
+ //
+ // And initialize the Reset Request block
+ //
+ OpenP->ResetReqHndl->Signature = FUNC_REQUEST_HANDLE_SIGNATURE;
+ OpenP->ResetReqHndl->Open = OpenP;
+ OpenP->ResetReqHndl->RequestPended = TRUE;
+
+ //
+ // Indicate that cleanup is required once the RESET completes
+ // This is to ensure that the either this routine or the completion
+ // routine will take care of the cleanup
+ OpenP->ResetReqHndl->u.RESET_REQ.PostResetStressCleanup = TRUE;
+
+ //
+ // And now issue the RESET
+ //
+ OpenP->Stress->Resetting = TRUE;
+
+ Status = TpStressReset( OpenP );
+
+ }
+
+
+ //
+ // If the RESET has not gotten pended in which case there is the possibility
+ // of a reset failure we will still proceed and free up the resources
+ //
+
+ if ( Status != NDIS_STATUS_PENDING )
+ {
+ //
+ // Indicate that we will take care of the post reset cleanup
+ // and that the completion routine does not have to take care of it
+ //
+ OpenP->ResetReqHndl->u.RESET_REQ.PostResetStressCleanup = FALSE;
+
+ TpStressResetComplete( OpenP,Status );
+
+ //
+ // Free up the various data structures allocated during the
+ // initialization phase.
+ //
+
+ OpenP->Stress->StressEnded = TRUE;
+
+ //
+ // Free up the resources associated with this instance of the stress test
+ //
+ TpStressFreePostResetResources( OpenP );
+
+
+ //
+ // Decrement the reference count on the OpenBlock stating this
+ // instance of an async test is no longer running, and the adapter
+ // may be closed if requested.
+ //
+ TpRemoveReference( OpenP );
+ }
+ // Sanjeevk : STOPCHANGE
+}
+
+
+
+VOID
+TpStressFreeClient(
+ IN POPEN_BLOCK OpenP
+ )
+{
+ UCHAR i;
+
+ if ( OpenP->Stress->Client != NULL )
+ {
+ if ( OpenP->Stress->Arguments->PacketsFromPool == TRUE )
+ {
+ TpStressFreeTransmitPool( OpenP->Stress->Client->TransmitPool );
+ }
+
+ if ( OpenP->Stress->Client->PoolInitialized == TRUE )
+ {
+ NdisFreePacketPool( OpenP->Stress->Client->PacketHandle );
+ OpenP->Stress->Client->PoolInitialized = FALSE;
+ }
+
+ for ( i=0;i<OpenP->Stress->Client->NumServers;i++ )
+ {
+ if ( OpenP->Stress->Client->Servers[i].Counters != NULL )
+ {
+ NdisFreeMemory( (PVOID)OpenP->Stress->Client->Servers[i].Counters,0,0 );
+ }
+ }
+
+ NdisFreeMemory( OpenP->Stress->Client,0,0 );
+ OpenP->Stress->Client = NULL;
+ }
+}
+
+
+
+VOID
+TpStressFreeServer(
+ IN POPEN_BLOCK OpenP
+ )
+{
+ UCHAR i;
+
+ if ( OpenP->Stress->Server != NULL )
+ {
+ TpStressFreeTransmitPool( OpenP->Stress->Server->TransmitPool );
+
+ if ( OpenP->Stress->Server->PoolInitialized == TRUE )
+ {
+ NdisFreePacketPool( OpenP->Stress->Server->PacketHandle );
+ OpenP->Stress->Server->PoolInitialized = FALSE;
+ }
+
+ for ( i=0;i<OpenP->Stress->Server->NumClients;i++ )
+ {
+ if ( OpenP->Stress->Server->Clients[i].Counters != NULL )
+ {
+ NdisFreeMemory( (PVOID)OpenP->Stress->Server->Clients[i].Counters,0,0 );
+ }
+ }
+
+ NdisFreeMemory( OpenP->Stress->Server,0,0 );
+ OpenP->Stress->Server = NULL;
+ }
+}
+
+
+
+VOID
+TpStressFreePostResetResources(
+ IN POPEN_BLOCK OpenP
+ )
+{
+
+ if (( OpenP != NULL ) && ( OpenP->Stress->Arguments != NULL ))
+ {
+ if (( OpenP->Stress->Arguments->MemberType == TP_CLIENT ) ||
+ ( OpenP->Stress->Arguments->MemberType == BOTH ))
+ {
+ TpStressFreeClient( OpenP );
+ }
+
+ if (( OpenP->Stress->Arguments->MemberType == TP_SERVER ) ||
+ ( OpenP->Stress->Arguments->MemberType == BOTH ))
+ {
+ TpStressFreeServer( OpenP );
+ }
+
+ if (OpenP->Stress->PoolInitialized == TRUE )
+ {
+ NdisFreePacketPool( OpenP->Stress->PacketHandle );
+ OpenP->Stress->PoolInitialized = FALSE;
+ }
+
+
+ //
+ // SanjeevK: Free up the data buffer and associated MDL resources
+ //
+ TpStressFreeDataBuffers( OpenP );
+ TpStressFreeDataBufferMdls( OpenP );
+
+
+ NdisFreeMemory( OpenP->Stress->Arguments,0,0 );
+ OpenP->Stress->Arguments = NULL;
+
+ //
+ // Deallocate the global counters, and their spinlock.
+ //
+
+ if ( OpenP->GlobalCounters != NULL )
+ {
+ NdisFreeMemory( (PVOID)OpenP->GlobalCounters,0,0 );
+ OpenP->GlobalCounters = NULL;
+ }
+ }
+}
+
+
+
+VOID
+TpStressRegister2Dpc(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SysArg1,
+ IN PVOID SysArg2
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ POPEN_BLOCK OpenP = ((POPEN_BLOCK)DeferredContext);
+ PSTRESS_ARGUMENTS Args;
+ LARGE_INTEGER DueTime;
+ PNDIS_PACKET Packet;
+
+
+ UNREFERENCED_PARAMETER( Dpc );
+ UNREFERENCED_PARAMETER( SysArg1 );
+ UNREFERENCED_PARAMETER( SysArg2 );
+
+ //
+ // If the Stress Irp has been cancelled then clean up and leave.
+ //
+
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if (( OpenP->Stress->StressIrp == NULL ) ||
+ ( OpenP->Stress->StressIrp->Cancel == TRUE ))
+ {
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+ OpenP->Stress->StopStressing = TRUE;
+ return;
+ }
+
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+
+ if (( OpenP->Stress->StopStressing == FALSE ) &&
+ ( OpenP->Stress->Client->NumServers < MAX_SERVERS ))
+ {
+ Args = OpenP->Stress->Arguments;
+
+ if (( OpenP->Stress->Reg2Counter < 60 ) ||
+ (( OpenP->Stress->Reg2Counter % 60 ) == 0 ))
+ {
+ //
+ // We are now ready to begin the test, send a REGISTER_REQ
+ // packet to the STRESS_MULTICAST/FUNCTIONAL address.
+ //
+ // Construct the REGISTER_REQ2 packet and send it.
+ //
+
+ Packet = TpStressCreatePacket( OpenP,
+ OpenP->Stress->Client->PacketHandle,
+ Args->PacketMakeUp,
+ 0, // ServerInstance
+ OpenP->OpenInstance,
+ REGISTER_REQ2,
+ Args->ResponseType,
+ OpenP->Environment->StressAddress,
+ sizeof( STRESS_PACKET ),
+ sizeof( STRESS_PACKET ),
+ 0,0L,0,0,
+ Args->DataChecking );
+
+ if ( Packet == NULL )
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressRegister2Dpc: failed to build REGISTER_REQ2 packet\n");
+ }
+ }
+ else
+ {
+ TpStressSend( OpenP,Packet,NULL );
+ }
+ }
+
+ //
+ // We will continue requeueing this Dpc for 6 minutes. The first
+ // minute we will send once every second then for the next five
+ // minutes send only one request each minute.
+ //
+
+ if ( OpenP->Stress->Reg2Counter++ < 360 )
+ {
+ //
+ // Now requeue the Dpc to run try again next time.
+ //
+
+ DueTime.HighPart = -1;
+ DueTime.LowPart = (ULONG)(- ( ONE_SECOND ));
+
+ if ( KeSetTimer(&OpenP->Stress->TpStressReg2Timer,
+ DueTime,
+ &OpenP->Stress->TpStressReg2Dpc ))
+ {
+ IF_TPDBG ( TP_DEBUG_DPC )
+ {
+ TpPrint0("TpStressRegister2Dpc set TpStressReg2Timer while timer existed.\n");
+ }
+ }
+ }
+ }
+}
+
+