mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1280 lines
42 KiB
1280 lines
42 KiB
/*++
|
|
|
|
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:
|
|
|
|
--*/
|
|
|
|
#include <ndis.h>
|
|
#include <string.h>
|
|
|
|
#include "tpdefs.h"
|
|
#include "media.h"
|
|
#include "tpprocs.h"
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
TpStressReceive(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_HANDLE MacReceiveContext,
|
|
IN PVOID HeaderBuffer,
|
|
IN UINT HeaderBufferSize,
|
|
IN PVOID LookaheadBuffer,
|
|
IN UINT LookaheadBufferSize,
|
|
IN UINT PacketSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext);
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PNDIS_PACKET Packet;
|
|
PCLIENT_STORAGE Client;
|
|
PSERVER_STORAGE Server;
|
|
PSTRESS_ARGUMENTS Args;
|
|
PPACKET_INFO pi;
|
|
PSTRESS_CONTROL sc;
|
|
UCHAR NextClient;
|
|
UCHAR NextServer;
|
|
INT NewPacketSize;
|
|
INT NumResponses;
|
|
BOOLEAN NewClient;
|
|
BOOLEAN NewServer;
|
|
PUCHAR DestAddr;
|
|
PUCHAR SrcAddr;
|
|
|
|
DestAddr = (PUCHAR)HeaderBuffer + (ULONG)OpenP->Media->DestAddrOffset;
|
|
SrcAddr = (PUCHAR)HeaderBuffer + (ULONG)OpenP->Media->SrcAddrOffset;
|
|
|
|
//
|
|
// pi is the packet information section of the test prot packet header,
|
|
// sc is the stress control section of the testprot packet header. We
|
|
// will us pi and sc to quickly reference info in the header.
|
|
//
|
|
|
|
pi = (PPACKET_INFO)LookaheadBuffer;
|
|
|
|
sc = (PSTRESS_CONTROL)((PUCHAR)LookaheadBuffer +
|
|
(ULONG)sizeof( PACKET_INFO ));
|
|
|
|
if ( !TpCheckSum(
|
|
(PUCHAR)pi,
|
|
sizeof( STRESS_PACKET ) -
|
|
( sizeof( ULONG ) + OpenP->Media->HeaderSize ),
|
|
(PULONG)&sc->CheckSum
|
|
)) {
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->GlobalCounters->CorruptRecs;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
}
|
|
|
|
Client = OpenP->Stress->Client;
|
|
Server = OpenP->Stress->Server;
|
|
Args = OpenP->Stress->Arguments;
|
|
|
|
switch( pi->u.PacketProtocol ) {
|
|
|
|
//
|
|
// A REGISTER_REQ(2) packet is a request from a TP_CLIENT to
|
|
// participate in a stress test. If this packet is from a new
|
|
// client then a response packet will be set back to the client,
|
|
// the client will be added to the Clients array, and its counters
|
|
// and control structures for the test will be reset. If this is
|
|
// an old client, then we will just reset the counters and control
|
|
// structures.
|
|
//
|
|
|
|
case REGISTER_REQ:
|
|
case REGISTER_REQ2:
|
|
|
|
//
|
|
// Is this packet really destined for us, check that the
|
|
// destination address matches the stress address.
|
|
//
|
|
|
|
if ( RtlCompareMemory(
|
|
DestAddr,
|
|
OpenP->Environment->StressAddress,
|
|
OpenP->Media->AddressLen ) !=
|
|
OpenP->Media->AddressLen ) {
|
|
|
|
//
|
|
// the destination address does not match the stress
|
|
// address, we should never have received this packet!
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->GlobalCounters->InvalidPacketRecs;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// This packet is a request from a Client to register.
|
|
// Are we a Server?
|
|
//
|
|
|
|
} else if ( Args->MemberType == TP_CLIENT ) {
|
|
|
|
//
|
|
// No! We are not a Server, ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
} else {
|
|
|
|
//
|
|
// If there is room, see if this is a new client and if so
|
|
// register it, and send a REGISTER_RESP packet.
|
|
//
|
|
|
|
if ( Server->NumClients < MAX_CLIENTS ) {
|
|
|
|
NextClient = 0;
|
|
NewClient = TRUE;
|
|
|
|
//
|
|
// See if we have already registered this client.
|
|
//
|
|
|
|
while ( NextClient < Server->NumClients ) {
|
|
|
|
//
|
|
// If the Src Address matches a previously registered
|
|
// Client, and the Open Instance of that Client matches
|
|
// the Src Instance then we have already registered
|
|
// this Client, reset the counters, send a response,
|
|
// but ignore it. Otherwise this is a new Client so
|
|
// register it properly.
|
|
//
|
|
|
|
if (( RtlCompareMemory(
|
|
SrcAddr,
|
|
Server->Clients[NextClient].Address,
|
|
OpenP->Media->AddressLen ) ==
|
|
(ULONG)OpenP->Media->AddressLen )
|
|
|
|
&&
|
|
|
|
( pi->SrcInstance ==
|
|
Server->Clients[NextClient].ClientInstance )) {
|
|
|
|
//
|
|
// We have already registered with this client.
|
|
//
|
|
|
|
NewClient = FALSE;
|
|
break;
|
|
|
|
} else {
|
|
|
|
//
|
|
// This is not a match , try the next one.
|
|
//
|
|
|
|
NextClient++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// This REGISTER_REQ(2) packet is from a New Client, and we
|
|
// have room for it, so register it.
|
|
//
|
|
|
|
if ( NewClient == TRUE ) {
|
|
|
|
IF_TPDBG ( TP_DEBUG_DPC ) {
|
|
TpPrint0("TpStressReceive: REGISTER_REQ(2) - Registering Client\n");
|
|
}
|
|
|
|
//
|
|
// set up the CLIENT_INFO data structure and initialize it.
|
|
//
|
|
|
|
NextClient = Server->NumClients++;
|
|
++Server->ActiveClients;
|
|
Server->Clients[NextClient].ClientReference = NextClient;
|
|
Server->Clients[NextClient].ClientInstance = pi->SrcInstance;
|
|
Server->Clients[NextClient].ServerResponseType = sc->ResponseType;
|
|
Server->Clients[NextClient].DataChecking = sc->DataChecking;
|
|
Server->Clients[NextClient].LastSequenceNumber = 0;
|
|
|
|
RtlMoveMemory(
|
|
Server->Clients[NextClient].Address,
|
|
SrcAddr,
|
|
OpenP->Media->AddressLen
|
|
);
|
|
|
|
//
|
|
// Now allocate and initialize the instances counter
|
|
//
|
|
|
|
Status = NdisAllocateMemory(
|
|
(PVOID *)&Server->Clients[NextClient].Counters,
|
|
sizeof( INSTANCE_COUNTERS ),
|
|
0,
|
|
HighestAddress
|
|
);
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS ) {
|
|
IF_TPDBG (TP_DEBUG_RESOURCES) {
|
|
TpPrint0("TpStressReceive: failed to allocate counters.\n");
|
|
}
|
|
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
|
|
} else {
|
|
|
|
NdisZeroMemory(
|
|
(PVOID)Server->Clients[NextClient].Counters,
|
|
sizeof( INSTANCE_COUNTERS )
|
|
);
|
|
}
|
|
} else if ( pi->u.PacketProtocol == REGISTER_REQ ) {
|
|
|
|
NdisZeroMemory(
|
|
(PVOID)Server->Clients[NextClient].Counters,
|
|
sizeof( INSTANCE_COUNTERS )
|
|
);
|
|
|
|
Server->Clients[NextClient].ServerResponseType = sc->ResponseType;
|
|
Server->Clients[NextClient].DataChecking = sc->DataChecking;
|
|
Server->Clients[NextClient].LastSequenceNumber = 0;
|
|
}
|
|
|
|
if (( pi->u.PacketProtocol == REGISTER_REQ ) ||
|
|
( NewClient == TRUE )) {
|
|
|
|
//
|
|
// Then build a REGISTER_RESP packet to register with, and
|
|
// send it to the Client.
|
|
//
|
|
|
|
do {
|
|
Packet = TpStressCreatePacket(
|
|
OpenP,
|
|
Server->PacketHandle,
|
|
Args->PacketMakeUp,
|
|
pi->SrcInstance,
|
|
OpenP->OpenInstance,
|
|
REGISTER_RESP,
|
|
Args->ResponseType,
|
|
SrcAddr,
|
|
sizeof( STRESS_PACKET ),
|
|
sizeof( STRESS_PACKET ),
|
|
sc->SequenceNumber,
|
|
sc->SequenceNumber +
|
|
OpenP->Environment->WindowSize,
|
|
NextClient,
|
|
0,
|
|
Args->DataChecking
|
|
);
|
|
|
|
if ( Packet == NULL ) {
|
|
IF_TPDBG ( TP_DEBUG_RESOURCES ) {
|
|
TpPrint0("TpStressReceive: failed to create REGISTER_RESP Packet\n");
|
|
}
|
|
}
|
|
} while ( Packet == NULL );
|
|
|
|
//
|
|
// And send it.
|
|
//
|
|
|
|
TpStressSend( OpenP,Packet,NULL );
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// A REGISTER_RESP packet is a response from a TP_SERVER to a
|
|
// previously sent REGISTER_REQ(2) that the server will be
|
|
// participating in the next stress test. If this packet is from
|
|
// a new server then the server will be added to the Server array,
|
|
// and its counters and control structures for the test will be
|
|
// reset. If the response packet is from an old client, then we
|
|
// will just reset the counters.
|
|
//
|
|
|
|
case REGISTER_RESP:
|
|
|
|
//
|
|
// Is this packet really destined for us, check that the
|
|
// destination address matches the local card address we
|
|
// queried and stored in the OPEN_BLOCK.
|
|
//
|
|
|
|
if ( RtlCompareMemory(
|
|
DestAddr,
|
|
OpenP->StationAddress,
|
|
OpenP->Media->AddressLen ) !=
|
|
OpenP->Media->AddressLen ) {
|
|
|
|
//
|
|
// the destination address does not match the local card
|
|
// address, we should never have received this packet!
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->GlobalCounters->InvalidPacketRecs;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// This packet is a response from a Server to register. Are we a Client?
|
|
//
|
|
|
|
} else if ( Args->MemberType == TP_SERVER ) {
|
|
|
|
//
|
|
// No! We are not a Client, ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
} else {
|
|
|
|
if ( Client->NumServers < MAX_SERVERS ) {
|
|
|
|
NextServer = 0;
|
|
NewServer = TRUE;
|
|
|
|
//
|
|
// See if this is a new server.
|
|
//
|
|
|
|
while ( NextServer < Client->NumServers ) {
|
|
|
|
if (( RtlCompareMemory(
|
|
SrcAddr,
|
|
Client->Servers[NextServer].Address,
|
|
OpenP->Media->AddressLen) ==
|
|
(ULONG)OpenP->Media->AddressLen )
|
|
|
|
&&
|
|
|
|
( pi->SrcInstance ==
|
|
Client->Servers[NextServer].ServerInstance )) {
|
|
|
|
//
|
|
// This server has already registered, ignore it.
|
|
//
|
|
|
|
NewServer = FALSE;
|
|
break;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Not this server, try the next one.
|
|
//
|
|
|
|
NextServer++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( NewServer == TRUE ) {
|
|
|
|
IF_TPDBG ( TP_DEBUG_DPC ) {
|
|
TpPrint0("TpStressReceive: REGISTER_RESP - Registering Server\n");
|
|
}
|
|
|
|
//
|
|
// set up the SERVER_INFO data structure and initialize it.
|
|
//
|
|
|
|
NextServer = Client->NumServers++;
|
|
NextServer = Client->ActiveServers++;
|
|
|
|
Client->Servers[NextServer].ServerReference = NextServer;
|
|
Client->Servers[NextServer].ClientReference = sc->ClientReference;
|
|
Client->Servers[NextServer].ServerInstance = pi->SrcInstance;
|
|
Client->Servers[NextServer].ServerActive = TRUE;
|
|
Client->Servers[NextServer].LastSequenceNumber = 0;
|
|
|
|
RtlMoveMemory(
|
|
Client->Servers[NextServer].Address,
|
|
SrcAddr,
|
|
OpenP->Media->AddressLen
|
|
);
|
|
|
|
//
|
|
// Now allocate and initialize the instances counter
|
|
//
|
|
|
|
Status = NdisAllocateMemory(
|
|
(PVOID *)&Client->Servers[NextServer].Counters,
|
|
sizeof( INSTANCE_COUNTERS ),
|
|
0,
|
|
HighestAddress
|
|
);
|
|
|
|
if ( Status != NDIS_STATUS_SUCCESS ) {
|
|
IF_TPDBG (TP_DEBUG_RESOURCES) {
|
|
TpPrint0("TpStressReceive: failed to allocate counters.\n");
|
|
}
|
|
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
break;
|
|
|
|
} else {
|
|
|
|
NdisZeroMemory(
|
|
(PVOID)Client->Servers[NextServer].Counters,
|
|
sizeof( INSTANCE_COUNTERS )
|
|
);
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Old Server, reset the statistics counters.
|
|
//
|
|
|
|
NdisZeroMemory(
|
|
(PVOID)Client->Servers[NextServer].Counters,
|
|
sizeof( INSTANCE_COUNTERS )
|
|
);
|
|
|
|
Client->Servers[NextServer].LastSequenceNumber = 0;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// A TEST_REQ packet is the standard test packet sent from a the
|
|
// client to each of the servers participating in the test. This
|
|
// packet is evaluated for data integrity, counted, and the required
|
|
// response packet is returned to the client.
|
|
//
|
|
|
|
case TEST_REQ:
|
|
|
|
//
|
|
// Is this packet really destined for us, check that the
|
|
// destination address matches the local card address we
|
|
// queried and stored in the OPEN_BLOCK.
|
|
//
|
|
|
|
if ( RtlCompareMemory(
|
|
DestAddr,
|
|
OpenP->StationAddress,
|
|
OpenP->Media->AddressLen ) !=
|
|
OpenP->Media->AddressLen ) {
|
|
|
|
//
|
|
// the destination address does not match the local card
|
|
// address, we should never have received this packet!
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->GlobalCounters->InvalidPacketRecs;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// This packet is a test request from a Client. Are we a Server?,
|
|
//
|
|
|
|
} else if ( Args->MemberType == TP_CLIENT ) {
|
|
|
|
//
|
|
// No! We are not a Server, ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
//
|
|
// Is this a client we have previously registered with?
|
|
//
|
|
|
|
} else if (( RtlCompareMemory(
|
|
SrcAddr,
|
|
Server->Clients[sc->ClientReference].Address,
|
|
OpenP->Media->AddressLen) !=
|
|
(ULONG)OpenP->Media->AddressLen )
|
|
|
|
||
|
|
|
|
( pi->SrcInstance !=
|
|
Server->Clients[sc->ClientReference].ClientInstance )) {
|
|
|
|
//
|
|
// No! We should ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
//
|
|
// Is this packet destined for our open instance or another
|
|
// open instance of the same card?
|
|
//
|
|
|
|
} else if (( RtlCompareMemory(
|
|
SrcAddr,
|
|
Server->Clients[sc->ClientReference].Address,
|
|
OpenP->Media->AddressLen) ==
|
|
(ULONG)OpenP->Media->AddressLen)
|
|
|
|
&&
|
|
|
|
( pi->DestInstance != OpenP->OpenInstance )) {
|
|
|
|
//
|
|
// No, this packet is for some other open instance.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
} else {
|
|
|
|
if ( Args->BeginReceives == FALSE ) {
|
|
|
|
IF_TPDBG ( TP_DEBUG_DPC ) {
|
|
TpPrint0("TpStressReceive: received TEST_REQ packet, not initialized\n");
|
|
}
|
|
// Increment receive counter for accounting purposes.
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Has this packet arrived out of order?
|
|
//
|
|
|
|
if ( sc->SequenceNumber <= Server->Clients[sc->ClientReference].LastSequenceNumber ) {
|
|
IF_TPDBG ( TP_DEBUG_NDIS_ERROR ) {
|
|
TpPrint0("\nTpStressReceive: PACKET ARRIVED OUT OF ORDER, OR ARRIVED TWICE !!!\n");
|
|
TpPrint3("TEST_REQ Packet: Sequence Number %d @ 0x%lX, expected greater than %d.\n\n",
|
|
sc->SequenceNumber, HeaderBuffer,
|
|
Server->Clients[sc->ClientReference].LastSequenceNumber);
|
|
TpBreakPoint();
|
|
}
|
|
} else {
|
|
Server->Clients[sc->ClientReference].LastSequenceNumber = sc->SequenceNumber;
|
|
}
|
|
|
|
if ( Server->Clients[sc->ClientReference].DataChecking == TRUE ) {
|
|
|
|
if (( pi->PacketSize - sizeof( STRESS_PACKET )) > 0 ) {
|
|
|
|
TpStressCheckPacketData(
|
|
OpenP,
|
|
MacReceiveContext,
|
|
sc->DataBufOffset,
|
|
pi->PacketSize,
|
|
Server->Clients[sc->ClientReference].Counters
|
|
);
|
|
}
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++Server->Clients[sc->ClientReference].Counters->Receives;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
switch( Server->Clients[sc->ClientReference].ServerResponseType ) {
|
|
|
|
case NO_RESPONSE:
|
|
|
|
NumResponses = 0;
|
|
break;
|
|
|
|
case FULL_RESPONSE:
|
|
|
|
NumResponses = 1;
|
|
NewPacketSize = pi->PacketSize;
|
|
break;
|
|
|
|
case ACK_EVERY:
|
|
|
|
NumResponses = 1;
|
|
NewPacketSize = sizeof( STRESS_PACKET );
|
|
break;
|
|
|
|
case ACK_10_TIMES:
|
|
|
|
NumResponses = 10;
|
|
NewPacketSize = sizeof( STRESS_PACKET );
|
|
break;
|
|
|
|
default:
|
|
IF_TPDBG ( TP_DEBUG_DPC ) {
|
|
TpPrint0("TpStressReceive: Unknown Response Type\n");
|
|
}
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->GlobalCounters->CorruptRecs;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
break;
|
|
}
|
|
|
|
while ( NumResponses-- > 0 ) {
|
|
|
|
//
|
|
// if send now, build and send a TEST_RESP packet
|
|
//
|
|
|
|
TpStressServerSend(
|
|
OpenP,
|
|
Server->TransmitPool,
|
|
SrcAddr,
|
|
pi->SrcInstance,
|
|
OpenP->OpenInstance,
|
|
sc->SequenceNumber,
|
|
sc->SequenceNumber +
|
|
OpenP->Environment->WindowSize,
|
|
sc->ClientReference,
|
|
sc->ServerReference,
|
|
NewPacketSize,
|
|
sc->DataBufOffset
|
|
);
|
|
}
|
|
|
|
//
|
|
// else queue send for TpStressReceiveComplete send
|
|
//
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// A TEST_RESP packet is the response from a server to a client's
|
|
// TEST_REQ packet. This packet is checked for data integrity,
|
|
// counted, and discarded.
|
|
//
|
|
|
|
case TEST_RESP:
|
|
|
|
//
|
|
// Is this packet really destined for us, check that the
|
|
// destination address matches the local card address we
|
|
// queried and stored in the OPEN_BLOCK.
|
|
//
|
|
|
|
if ( RtlCompareMemory(
|
|
DestAddr,
|
|
OpenP->StationAddress,
|
|
OpenP->Media->AddressLen ) !=
|
|
OpenP->Media->AddressLen ) {
|
|
|
|
//
|
|
// the destination address does not match the local card
|
|
// address, we should never have received this packet!
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->GlobalCounters->InvalidPacketRecs;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// This packet is a test response from a Server. Are we a Client?
|
|
//
|
|
|
|
} else if ( Args->MemberType == TP_SERVER ) {
|
|
|
|
//
|
|
// No! We are not a Client, ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
//
|
|
// Is this a Server that has previously registered with us?
|
|
//
|
|
|
|
} else if (( RtlCompareMemory(
|
|
SrcAddr,
|
|
Client->Servers[sc->ServerReference].Address,
|
|
OpenP->Media->AddressLen) !=
|
|
(ULONG)OpenP->Media->AddressLen )
|
|
|
|
||
|
|
|
|
( pi->SrcInstance !=
|
|
Client->Servers[sc->ServerReference].ServerInstance )) {
|
|
|
|
//
|
|
// No! We should ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
//
|
|
// Is this packet destined for this open instance or another
|
|
// open instance of the same card?
|
|
//
|
|
|
|
} else if (( RtlCompareMemory(
|
|
SrcAddr,
|
|
Client->Servers[sc->ServerReference].Address,
|
|
OpenP->Media->AddressLen) ==
|
|
(ULONG)OpenP->Media->AddressLen)
|
|
|
|
&&
|
|
|
|
( pi->DestInstance != OpenP->OpenInstance )) {
|
|
|
|
//
|
|
// This packet is for some other open instance, ignore it.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Has this packet arrived out of order?
|
|
//
|
|
|
|
if ( sc->SequenceNumber <= Client->Servers[sc->ServerReference].LastSequenceNumber ) {
|
|
|
|
if (( Args->ResponseType == ACK_10_TIMES ) &&
|
|
( sc->SequenceNumber == Client->Servers[sc->ServerReference].LastSequenceNumber )) {
|
|
; // This is okay, we expect 10 packets with same
|
|
// number ignore packet.
|
|
} else {
|
|
|
|
//
|
|
// A Packet has arrived out or order, PANIC!
|
|
//
|
|
|
|
IF_TPDBG ( TP_DEBUG_DPC ) {
|
|
TpPrint0("\nTpStressReceive: PACKET ARRIVED OUT OF ORDER, OR ARRIVED TWICE !!!\n");
|
|
TpPrint3("TEST_RESP Packet: Sequence Number %d @ 0x%lX, expected greater than %d.\n\n",
|
|
sc->SequenceNumber, HeaderBuffer,
|
|
Client->Servers[sc->ServerReference].LastSequenceNumber);
|
|
TpBreakPoint();
|
|
}
|
|
}
|
|
} else {
|
|
Client->Servers[sc->ServerReference].LastSequenceNumber = sc->SequenceNumber;
|
|
}
|
|
|
|
if ( Args->WindowEnabled == TRUE ) {
|
|
Client->Servers[sc->ServerReference].MaxSequenceNumber = sc->MaxSequenceNumber;
|
|
} else {
|
|
Client->Servers[sc->ServerReference].MaxSequenceNumber = 0xFFFFFFFF;
|
|
}
|
|
|
|
//
|
|
// We have received a packet from this server so zero its
|
|
// window resetting counter in case it has any strikes
|
|
// against it.
|
|
//
|
|
|
|
Client->Servers[sc->ServerReference].WindowReset = 0;
|
|
|
|
//
|
|
// Update the instance receive counters for the Server
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++Client->Servers[sc->ServerReference].Counters->Receives;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
if ( Args->DataChecking == TRUE ) {
|
|
|
|
if (( pi->PacketSize - sizeof( STRESS_PACKET )) > 0 ) {
|
|
|
|
TpStressCheckPacketData(
|
|
OpenP,
|
|
MacReceiveContext,
|
|
sc->DataBufOffset,
|
|
pi->PacketSize,
|
|
Client->Servers[sc->ServerReference].Counters
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// A STATS_REQ packet is a request by the client at the end of
|
|
// a stress test for the server to return the statistics.
|
|
//
|
|
|
|
case STATS_REQ:
|
|
|
|
//
|
|
// Is this packet really destined for us, check that the
|
|
// destination address matches the local card address we
|
|
// queried and stored in the OPEN_BLOCK.
|
|
//
|
|
|
|
if ( RtlCompareMemory(
|
|
DestAddr,
|
|
OpenP->StationAddress,
|
|
OpenP->Media->AddressLen ) !=
|
|
OpenP->Media->AddressLen ) {
|
|
|
|
//
|
|
// the destination address does not match the local card
|
|
// address, we should never have received this packet!
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->GlobalCounters->InvalidPacketRecs;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// This packet is a Statistics request from a Client.
|
|
// Are we a Server?,
|
|
//
|
|
|
|
} else if ( Args->MemberType == TP_CLIENT ) {
|
|
|
|
//
|
|
// No! We are not a Server, ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
//
|
|
// Is this a client we have previously registered with?
|
|
//
|
|
|
|
} else if (( RtlCompareMemory(
|
|
SrcAddr,
|
|
Server->Clients[sc->ClientReference].Address,
|
|
OpenP->Media->AddressLen ) !=
|
|
(ULONG)OpenP->Media->AddressLen )
|
|
|
|
||
|
|
|
|
( pi->SrcInstance !=
|
|
Server->Clients[sc->ClientReference].ClientInstance )) {
|
|
|
|
//
|
|
// No! We should ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
//
|
|
// Is this packet destined for our open instance or another
|
|
// open instance on the same card?
|
|
//
|
|
|
|
} else if (( pi->DestInstance != OpenP->OpenInstance )
|
|
|
|
&&
|
|
|
|
( RtlCompareMemory(
|
|
SrcAddr,
|
|
Server->Clients[sc->ClientReference].Address,
|
|
OpenP->Media->AddressLen ) ==
|
|
(ULONG)OpenP->Media->AddressLen )) {
|
|
|
|
//
|
|
// This packet is for some other open instance, ignore it.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
} else {
|
|
|
|
//
|
|
// We need to respond to the client's request for the
|
|
// test statistics, so create a STATS_RESP packet,
|
|
//
|
|
|
|
Packet = TpStressCreatePacket(
|
|
OpenP,
|
|
Server->PacketHandle,
|
|
KNOWN,
|
|
pi->SrcInstance,
|
|
OpenP->OpenInstance,
|
|
STATS_RESP,
|
|
Args->ResponseType,
|
|
SrcAddr,
|
|
|
|
sizeof( STRESS_PACKET ) +
|
|
sizeof( INSTANCE_COUNTERS ) +
|
|
sizeof( GLOBAL_COUNTERS ), // PacketSize
|
|
|
|
sizeof( STRESS_PACKET ) +
|
|
sizeof( INSTANCE_COUNTERS ) +
|
|
sizeof( GLOBAL_COUNTERS ), // BufferSize
|
|
|
|
sc->SequenceNumber,
|
|
sc->SequenceNumber,
|
|
sc->ClientReference,
|
|
sc->ServerReference,
|
|
FALSE
|
|
);
|
|
|
|
if ( Packet == NULL ) {
|
|
IF_TPDBG(TP_DEBUG_RESOURCES) {
|
|
TpPrint0("TpStressReceive: failed to create STATS_RESP Packet\n");
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// Write the statistics into the packet,
|
|
//
|
|
|
|
TpWriteServerStatistics(
|
|
OpenP,
|
|
Packet,
|
|
&Server->Clients[sc->ClientReference]
|
|
);
|
|
|
|
if ( sc->SequenceNumber == 0 ) {
|
|
|
|
//
|
|
// Maybe instead of checking the SequenceNumber is
|
|
// zero, the first packet, we should have a flag in
|
|
// the server for this in case we miss the first
|
|
// STATS_REQ packet.
|
|
//
|
|
|
|
TpPrintServerStatistics(
|
|
OpenP,
|
|
&Server->Clients[sc->ClientReference]
|
|
);
|
|
}
|
|
|
|
//
|
|
// And send it back to the Client.
|
|
//
|
|
|
|
TpStressSend( OpenP,Packet,NULL );
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// A STATS_RESP packet is the server responding to a clients
|
|
// request for stress statistics. The stats a bundled in the
|
|
// data field of the packet. The client will read them into
|
|
// the local buffer and discard the packet.
|
|
//
|
|
|
|
case STATS_RESP:
|
|
|
|
//
|
|
// Is this packet really destined for us, check that the
|
|
// destination address matches the local card address we
|
|
// queried and stored in the OPEN_BLOCK.
|
|
//
|
|
|
|
if ( RtlCompareMemory(
|
|
DestAddr,
|
|
OpenP->StationAddress,
|
|
OpenP->Media->AddressLen ) !=
|
|
OpenP->Media->AddressLen ) {
|
|
|
|
//
|
|
// the destination address does not match the local card
|
|
// address, we should never have received this packet!
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->GlobalCounters->InvalidPacketRecs;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// This packet is a Statistics response from a Server.
|
|
// Are we a Client?
|
|
//
|
|
|
|
} else if ( Args->MemberType == TP_SERVER ) {
|
|
|
|
//
|
|
// No! We are not a Client, ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
//
|
|
// Is this a Server that has previously registered with us?
|
|
//
|
|
|
|
} else if (( RtlCompareMemory(
|
|
SrcAddr,
|
|
Client->Servers[sc->ServerReference].Address,
|
|
OpenP->Media->AddressLen) !=
|
|
(ULONG)OpenP->Media->AddressLen )
|
|
|
|
||
|
|
|
|
( pi->SrcInstance !=
|
|
Client->Servers[sc->ServerReference].ServerInstance )) {
|
|
|
|
//
|
|
// No! We should ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
//
|
|
// Is this packet destined for our open instance or another
|
|
// open instance on the same card?
|
|
//
|
|
|
|
} else if (( pi->DestInstance != OpenP->OpenInstance ) &&
|
|
( RtlCompareMemory(
|
|
SrcAddr,
|
|
Client->Servers[sc->ServerReference].Address,
|
|
OpenP->Media->AddressLen) ==
|
|
(ULONG)OpenP->Media->AddressLen )) {
|
|
|
|
//
|
|
// This packet is for some other open instance, ignore it.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Copy the server's stats to the Stress Results buffer.
|
|
//
|
|
|
|
TpCopyServerStatistics(
|
|
OpenP,
|
|
LookaheadBuffer,
|
|
sc->ServerReference
|
|
);
|
|
}
|
|
|
|
break;
|
|
|
|
//
|
|
// AN END_REQ packet is a notification by a client that the stress
|
|
// test has completed. The server decrements the number of clients,
|
|
// and discards the packet.
|
|
//
|
|
|
|
case END_REQ:
|
|
{
|
|
UINT i;
|
|
|
|
//
|
|
// Is this packet really destined for us, check that the
|
|
// destination address matches the local card address we
|
|
// queried and stored in the OPEN_BLOCK.
|
|
//
|
|
|
|
if ( RtlCompareMemory(
|
|
DestAddr,
|
|
OpenP->StationAddress,
|
|
OpenP->Media->AddressLen ) !=
|
|
OpenP->Media->AddressLen ) {
|
|
|
|
//
|
|
// the destination address does not match the local card
|
|
// address, we should never have received this packet!
|
|
//
|
|
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->GlobalCounters->InvalidPacketRecs;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
//
|
|
// This packet is an end request from a Client. Are we a Server?,
|
|
//
|
|
|
|
} else if ( Args->MemberType == TP_CLIENT ) {
|
|
|
|
//
|
|
// No! We are not a Server, ignote this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
//
|
|
// Is this a client we have previously registered with?
|
|
//
|
|
|
|
} else if (( RtlCompareMemory(
|
|
SrcAddr,
|
|
Server->Clients[sc->ClientReference].Address,
|
|
OpenP->Media->AddressLen) !=
|
|
(ULONG)OpenP->Media->AddressLen )
|
|
|
|
||
|
|
|
|
( pi->SrcInstance !=
|
|
Server->Clients[sc->ClientReference].ClientInstance )) {
|
|
|
|
//
|
|
// No! We should ignore this packet.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
//
|
|
// Is this packet destined for our open instance or another
|
|
// open instance on the same card?
|
|
//
|
|
|
|
} else if (( pi->DestInstance != OpenP->OpenInstance )
|
|
|
|
&&
|
|
|
|
( RtlCompareMemory(
|
|
SrcAddr,
|
|
Server->Clients[sc->ClientReference].Address,
|
|
OpenP->Media->AddressLen) ==
|
|
(ULONG)OpenP->Media->AddressLen)) {
|
|
|
|
//
|
|
// This packet is for some other open instance, ignore it.
|
|
//
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
|
|
} else {
|
|
|
|
if ( Server->Clients[sc->ClientReference].TestEnding == FALSE ) {
|
|
Server->Clients[sc->ClientReference].TestEnding = TRUE;
|
|
--Server->ActiveClients;
|
|
}
|
|
|
|
//
|
|
// If we are running as only a server, and there are packets
|
|
// remaining in the Pend Queue, display them to the debug
|
|
// screen.
|
|
//
|
|
|
|
if (( Args->MemberType == TP_SERVER ) &&
|
|
( OpenP->Stress->Pend->PendingPackets != 0 )) {
|
|
|
|
//
|
|
// There are packets in the pend queue, so print out
|
|
// the packet addresses and break.
|
|
//
|
|
|
|
IF_TPDBG( TP_DEBUG_DPC ) {
|
|
|
|
TpPrint1("TpStressEndDpc: The following %d packets are still in the\n",
|
|
OpenP->Stress->Pend->PendingPackets);
|
|
TpPrint1(" Server'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();
|
|
|
|
//
|
|
// And set the PendingPackets counter to zero, so
|
|
// we will not print this message on the remainder
|
|
// of the END_REQ packets that we receive.
|
|
//
|
|
|
|
OpenP->Stress->Pend->PendingPackets = 0;
|
|
}
|
|
|
|
TpInitializePending( OpenP->Stress->Pend );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
IF_TPDBG ( TP_DEBUG_DPC ) {
|
|
TpPrint0("TpStressReceive: Unknown Packet Protocol\n");
|
|
}
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->GlobalCounters->CorruptRecs;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
|
|
Status = NDIS_STATUS_NOT_RECOGNIZED;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
TpStressReceiveComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
POPEN_BLOCK OpenP = ((POPEN_BLOCK)ProtocolBindingContext);
|
|
ULONG i;
|
|
|
|
if (( OpenP->Stress != NULL ) &&
|
|
( OpenP->Stress->Client != NULL )) {
|
|
|
|
for ( i=0;i<MAX_SERVERS;i++ ) {
|
|
|
|
if ( OpenP->Stress->Client->Servers[i].Counters != NULL ) {
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->Stress->Client->Servers[i].Counters->ReceiveComps;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (( OpenP->Stress != NULL ) &&
|
|
( OpenP->Stress->Server != NULL )) {
|
|
|
|
for ( i=0;i<MAX_CLIENTS;i++ ) {
|
|
|
|
if ( OpenP->Stress->Server->Clients[i].Counters != NULL ) {
|
|
NdisAcquireSpinLock( &OpenP->SpinLock );
|
|
++OpenP->Stress->Server->Clients[i].Counters->ReceiveComps;
|
|
NdisReleaseSpinLock( &OpenP->SpinLock );
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|