|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
arapdbg.c
Abstract:
This module implements all debug utilities used by ARAP
Author:
Shirish Koti
Revision History: 26 March 1997 Initial Version
--*/
#include <atalk.h>
#pragma hdrstop
// File module number for errorlogging
#define FILENUM ARAPDBG
#define ALIGN8(Ptr) ( (((ULONG_PTR)(Ptr))+7) & (~7) )
//
// The following are debug-only routines. These routines help us catch bad
// things before they do damage, and help us sleep better at night.
//
#if DBG
DWORD ArapDbgDumpOnDisconnect = 0;
//***
//
// Function: ArapProcessSniff
// Stores the sniff irp. Next time some connection needs to return
// the sniff info, use this irp.
//
// Parameters: pIrp - the Sniff irp to process
//
// Return: result of the operation
//
//***$
NTSTATUS ArapProcessSniff( IN PIRP pIrp ) { KIRQL OldIrql; PARAP_SEND_RECV_INFO pSndRcvInfo;
ARAPTRACE(("Entered ArapProcessSniff (%lx)\n",pIrp));
ACQUIRE_SPIN_LOCK(&ArapSpinLock, &OldIrql);
// store the irp (we can only have one Sniff irp at a time)
ASSERT (ArapSniffIrp == NULL);
if (ArapSniffIrp != NULL) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("ArapProcessSniff: Sniff irp %lx already in progress!\n", ArapSniffIrp));
pSndRcvInfo = (PARAP_SEND_RECV_INFO)pIrp->AssociatedIrp.SystemBuffer; pSndRcvInfo->StatusCode = ARAPERR_IRP_IN_PROGRESS; RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql); return( STATUS_SUCCESS ); }
ArapSniffIrp = pIrp;
RELEASE_SPIN_LOCK(&ArapSpinLock, OldIrql);
return(STATUS_PENDING); }
//***
//
// Function: ArapDumpSniffInfo
// If we have collected enough sniff info, complete the sniff irp
//
// Parameters: pArapConn - connection in question
//
// Return: TRUE if we returned info to dll, FALSE otherwise
//
//***$
BOOLEAN ArapDumpSniffInfo( IN PARAPCONN pArapConn ) {
PIRP pIrp; DWORD dwBytesToDll; NTSTATUS ReturnStatus=STATUS_SUCCESS;
// if we don't have a sniff buffer (or no bytes in it), get out
if (!pArapConn->pDbgTraceBuffer || pArapConn->SniffedBytes == 0) { return(FALSE); }
//
// if we have less than 500 bytes in the buffer, and we aren't disconnecting
// or disconnected, don't complete the irp as yet
// (it's ok not have spinlock here)
//
if ((pArapConn->SniffedBytes < 500) && (pArapConn->State == MNP_UP )) { return(FALSE); }
ARAP_GET_SNIFF_IRP(&pIrp);
// no sniff irp available? can't do much, leave
if (!pIrp) { return(FALSE); }
dwBytesToDll = ArapFillIrpWithSniffInfo(pArapConn,pIrp) + sizeof(ARAP_SEND_RECV_INFO);
// ok, complete that irp now!
ARAP_COMPLETE_IRP(pIrp, dwBytesToDll, STATUS_SUCCESS, &ReturnStatus);
return(TRUE);
}
//***
//
// Function: ArapFillIrpWithSniffInfo
// Copy the sniff bytes into the irp
//
// Parameters: pArapConn - connection in question
// pIrp - the irp to fill data in
// (except in one case, this irp will be the sniff irp.
// The exception case is where disconnect has occured and
// and at that time, a sniff irp wasn't available. In that
// case, we use the select irp that's carrying the disconnect
// info to send the remaining sniff bytes).
//
// Return: Number of sniff bytes that were copied in
//
//***$
DWORD ArapFillIrpWithSniffInfo( IN PARAPCONN pArapConn, IN PIRP pIrp ) { PARAP_SEND_RECV_INFO pSndRcvInfo=NULL; KIRQL OldIrql; DWORD SniffedBytes; PBYTE pStartData; DWORD dwBytesToDll;
ACQUIRE_SPIN_LOCK(&pArapConn->SpinLock, &OldIrql);
pSndRcvInfo = (PARAP_SEND_RECV_INFO)pIrp->AssociatedIrp.SystemBuffer;
//
// if buffer is smaller than how much data we have, adjust by ignoring
// bytes in the beginning of the buffer
//
if (pSndRcvInfo->DataLen < pArapConn->SniffedBytes) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("ArapFill...Info: chopping %d bytes in the beginning\n", (pArapConn->SniffedBytes - pSndRcvInfo->DataLen)));
pStartData = pArapConn->pDbgTraceBuffer + (pArapConn->SniffedBytes - pSndRcvInfo->DataLen);
pArapConn->SniffedBytes = pSndRcvInfo->DataLen; } else { pStartData = pArapConn->pDbgTraceBuffer; }
SniffedBytes = pArapConn->SniffedBytes;
// ok, copy the data in
RtlCopyMemory( &pSndRcvInfo->Data[0], pStartData, SniffedBytes );
pArapConn->pDbgCurrPtr = pArapConn->pDbgTraceBuffer;
pArapConn->SniffedBytes = 0;
RELEASE_SPIN_LOCK(&pArapConn->SpinLock, OldIrql);
// set the info (contexts need to be set each time in case of select)
pSndRcvInfo->AtalkContext = pArapConn; pSndRcvInfo->pDllContext = pArapConn->pDllContext; pSndRcvInfo->DataLen = SniffedBytes; pSndRcvInfo->StatusCode = ARAPERR_NO_ERROR;
return(SniffedBytes);
}
//***
//
// Function: DbgChkRcvQIntegrity
// This routine looks at the first buffer on the receive queue and
// verifies that things look reasonable
//
// Parameters: pArapConn - the connection in question
//
// Return: TRUE if things look reasonable, FALSE otherwise
//
// NOTES: IMPORTANT: spinlock must be held before calling this routine
//
//***$
BOOLEAN DbgChkRcvQIntegrity( IN PARAPCONN pArapConn ) { PLIST_ENTRY pList; PARAPBUF pArapBuf; PBYTE packet; USHORT SrpLen;
pList = pArapConn->ReceiveQ.Flink; if (pList == &pArapConn->ReceiveQ) { return( TRUE ); }
if (!(pArapConn->Flags & ARAP_CONNECTION_UP)) { return( TRUE ); }
pArapBuf = CONTAINING_RECORD(pList, ARAPBUF, Linkage);
// wait until more bytes show up
if (pArapBuf->DataSize < 6) { return( TRUE ); }
packet = pArapBuf->CurrentBuffer;
GETSHORT2SHORT(&SrpLen, pArapBuf->CurrentBuffer);
if (SrpLen > ARAP_MAXPKT_SIZE_INCOMING) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("ARAP: packet too big (%d bytes) in %lx)\n",SrpLen,pArapBuf));
return(FALSE); }
if ((packet[2] != 0x50) && (packet[2] != 0x10)) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("ARAP: wrong DGroup byte (%x) in %lx)\n",packet[2],pArapBuf));
return(FALSE); }
if (packet[2] == 0x50) { if ((packet[3] != 0) || (packet[4] != 0) || (packet[5] != 2)) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("ARAP (%lx): wrong LAP hdr in %lx)\n",pArapBuf));
return(FALSE); } }
return( TRUE ); }
//***
//
// Function: DbgDumpBytes
// This routine dumps first 64 bytes from a buffer to the debugger
//
// Parameters: pDbgMsg - string to print before the bytes (optional)
// pBuffer - buffer from which to dump the bytes
// BufLen - how big is the buffer
// DumpLevel - if this matches ArapDumpLevel, we dump the bytes
//
// Return: Nothing
//
//***$
VOID DbgDumpBytes( IN PBYTE pDbgMsg, IN PBYTE pBuffer, IN DWORD BufLen, IN DWORD DumpLevel ) { BYTE OutBuf[400]; DWORD NextIndex; DWORD dwBytesToDump;
if (ArapDumpLevel != DumpLevel) { return; }
if (pDbgMsg) { DbgPrint("%s (pkt len = %d)\n",pDbgMsg,BufLen); } else { DbgPrint("Dumping packet (pkt len = %d)\n",BufLen); }
// dump the first 64 bytes
dwBytesToDump = (BufLen <= 64)? BufLen : 64;
dwBytesToDump = (dwBytesToDump < ArapDumpLen)?dwBytesToDump:ArapDumpLen;
DbgDumpBytesPart2( pBuffer, OutBuf, dwBytesToDump, &NextIndex );
OutBuf[NextIndex] = '\n'; OutBuf[NextIndex+1] = 0;
DbgPrint("%s",OutBuf); }
//***
//
// Function: DbgDumpBytesPart2
// This is a helper routine for the DbgDumpBytes routine
//***$
VOID DbgDumpBytesPart2( IN PBYTE pBuffer, OUT PBYTE OutBuf, IN DWORD BufLen, OUT DWORD *NextIndex ) { BYTE Byte; BYTE nibble; DWORD i, j;
j = 0; OutBuf[j++] = ' '; OutBuf[j++] = ' '; OutBuf[j++] = ' '; OutBuf[j++] = ' ';
for (i=0; i<BufLen; i++ ) { Byte = pBuffer[i];
nibble = (Byte >> 4); OutBuf[j++] = (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
nibble = (Byte & 0x0f); OutBuf[j++] = (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
OutBuf[j++] = ' ';
if (((i+1) % 16) == 0) { OutBuf[j++] = '\n'; OutBuf[j++] = ' '; OutBuf[j++] = ' '; OutBuf[j++] = ' '; OutBuf[j++] = ' '; } else if (((i+1) % 8) == 0) { OutBuf[j++] = ' '; } }
*NextIndex = j;
return; }
//***
//
// Function: DbgDumpNetworkNumbers
// This routine dumps out all the network ranges that exist on the
// network.
//
// Parameters: None
//
// Return: Nothing
//
//***$
VOID DbgDumpNetworkNumbers( IN VOID ) { KIRQL OldIrql; PRTE pRte, pNext; int i;
ACQUIRE_SPIN_LOCK(&AtalkRteLock, &OldIrql);
for (i = 0; i < NUM_RTMP_HASH_BUCKETS; i++) { for (pRte = AtalkRoutingTable[i]; pRte != NULL; pRte = pNext) { pNext = pRte->rte_Next;
ACQUIRE_SPIN_LOCK_DPC(&pRte->rte_Lock);
DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, (" pRte: %lx LowEnd %lx HighEnd %lx\n", pRte,pRte->rte_NwRange.anr_FirstNetwork,pRte->rte_NwRange.anr_LastNetwork)); RELEASE_SPIN_LOCK_DPC(&pRte->rte_Lock); } }
RELEASE_SPIN_LOCK(&AtalkRteLock, OldIrql); }
//***
//
// Function: DbgTrackInfo
// This routine tracks various information, useful in arriving at
// optimum buffer sizes, etc.
//
// Parameters: pArapConn - the connection in question
// Size - size of the buffer (incoming, outgoing, as appropriate)
// TrackingWhat - what are we tracking (sends, recvs etc.)
//
// Return: Nothing
//
//***$
VOID DbgTrackInfo( IN PARAPCONN pArapConn, IN DWORD Size, IN DWORD TrackingWhat ) { //
// track the MNP send sizes (how many are 0-10 bytes, 11-20 bytes, etc.)
//
if (TrackingWhat == 1) { ArapDbgMnpSendSizes[Size/10]++;
return; } }
//***
//
// Function: ArapDbgTrace
// This routine traces (keeps a log) of all the events (data going
// in/out, acks going in/out, error conditions etc.
//
// Parameters: pArapConn - the connection in question
// Location - who is logging this event (the location decides what
// the other parms are going to be)
// Context - depends on Location (e.g.could be data buffer)
// dwInfo1 - depends on Location
// dwInfo2 - depends on Location
// dwInfo3 - depends on Location
//
// Return: Nothing
//
// NOTE: Spinlock is assumed to be held
//
//***$
VOID ArapDbgTrace( IN PARAPCONN pArapConn, IN DWORD Location, IN PVOID Context, IN DWORD dwInfo1, IN DWORD dwInfo2, IN DWORD dwInfo3 ) { LARGE_INTEGER CurrTime; LARGE_INTEGER DiffTime; PBYTE pStartTrace; PBYTE pTrace; PBUFFER_DESC pBuffDesc; PARAPBUF pArapBuf; PMNPSENDBUF pMnpSendBuf; PBYTE pCurrBuff; DWORD BufLenSoFar=0; USHORT Delta; BYTE Priority; DWORD BytesCopied=0; DWORD BytesAvailable; USHORT DbgInfoLen; PSNIFF_INFO pSniff; DWORD i;
if (!pArapConn->pDbgTraceBuffer) { return; }
KeQuerySystemTime(&CurrTime);
DiffTime = RtlLargeIntegerSubtract(CurrTime, ArapDbgLastTraceTime);
ArapDbgLastTraceTime = CurrTime;
// do the conversion to get ms
Delta = (USHORT)(DiffTime.LowPart);
pSniff = (PSNIFF_INFO)(pArapConn->pDbgCurrPtr);
pTrace = pStartTrace = &pSniff->Frame[0];
// put signature (starting of a "frame")
pSniff->Signature = ARAP_SNIFF_SIGNATURE;
// time since last event
pSniff->TimeStamp = (DWORD)AtalkGetCurrentTick();
// who is logging this info
pSniff->Location = (USHORT)Location;
//
// ok, now see who has called us and log the relevant info
// If we can't find the Location, it's ok: we have the Location number
// logged and and that's adequate (that's why we can't find Location)
//
switch (Location) { // data to client is about to be compressed: copy some info
case 11205:
pBuffDesc = (PBUFFER_DESC)Context; Priority = (BYTE)dwInfo1;
while (pBuffDesc) { if (pBuffDesc->bd_Flags & BD_CHAR_BUFFER) { pCurrBuff = pBuffDesc->bd_CharBuffer; BytesAvailable = pBuffDesc->bd_Length; }
else { pCurrBuff = MmGetSystemAddressForMdlSafe( pBuffDesc->bd_OpaqueBuffer, NormalPagePriority);
if (pCurrBuff == NULL) { goto error_end; } BytesAvailable = MmGetMdlByteCount(pBuffDesc->bd_OpaqueBuffer); }
//
// if this buffer descriptor contains (usually exclusively) the
// ARAP header, then get some info out of it and skip those bytes
//
if ((pCurrBuff[2] == 0x10 || pCurrBuff[2] == 0x50) && (pCurrBuff[3] == 0) && (pCurrBuff[4] == 0) && (pCurrBuff[5] == 2)) { *pTrace++ = pCurrBuff[0]; // srplen byte 1
*pTrace++ = pCurrBuff[1]; // srplen byte 2
*pTrace++ = pCurrBuff[2]; // ARAP or Atalk packet
*pTrace++ = Priority; BytesAvailable -= 6; pCurrBuff += 6; }
// copy first 48 bytes of the data packet
while (BytesAvailable && BytesCopied < 48) { *pTrace++ = *pCurrBuff++; BytesCopied++; BytesAvailable--; }
pBuffDesc = pBuffDesc->bd_Next; }
break;
// we are sending out an ack
case 11605:
*pTrace++ = (BYTE)dwInfo1; // sequence num in our ack
*pTrace++ = (BYTE)dwInfo2; // rcv credit in our ack
break;
// we are queuing compressed send bytes
case 21205:
*pTrace++ = (BYTE)dwInfo2; // priority of the send
*pTrace++ = (BYTE)dwInfo3; // Start sequence for this send
*pTrace++ = (BYTE)(pArapConn->MnpState.NextToSend-1); // end sequence
BytesAvailable = dwInfo1; // len of compressed data
pCurrBuff = (PBYTE)Context; // buffer with compressed data
// copy first 24 bytes of the compressed data
while (BytesAvailable && BytesCopied < 24) { *pTrace++ = *pCurrBuff++; BytesCopied++; BytesAvailable--; }
break;
// ArapExtractSRP: we're handing over 1 srp for routing or to dll
case 21105:
pArapBuf = (PARAPBUF)Context; pCurrBuff = pArapBuf->CurrentBuffer; BytesAvailable = pArapBuf->DataSize;
// copy first 48 bytes of the decompressed data
while (BytesAvailable && BytesCopied < 48) { *pTrace++ = *pCurrBuff++; BytesCopied++; BytesAvailable--; } break;
// we just recvd a packet in ArapRcvIndication
case 30105:
BytesAvailable = dwInfo1-7; // lookahead size, minus start,stop,crc
pCurrBuff = ((PBYTE)Context)+3; // lookahead buffer plus 3 start
PUTSHORT2SHORT(pTrace,(USHORT)BytesAvailable); pTrace += sizeof(USHORT);
// copy first 24 bytes of the compressed data
while (BytesAvailable && BytesCopied < 24) { *pTrace++ = *pCurrBuff++; BytesCopied++; BytesAvailable--; }
break;
// we recvd a 0-len packet!
case 30106:
break;
// we decompressed the incoming data
case 30110:
// how much was the decompressed length
PUTSHORT2SHORT(pTrace,(USHORT)dwInfo1); pTrace += sizeof(USHORT);
if (dwInfo1 == 0) { break; }
pArapBuf = (PARAPBUF)Context;
BytesAvailable = pArapBuf->DataSize; // len of decompressed data
pCurrBuff = pArapBuf->CurrentBuffer;
// copy first 48 bytes of the decompressed data
while (BytesAvailable && BytesCopied < 48) { *pTrace++ = *pCurrBuff++; BytesCopied++; BytesAvailable--; }
break;
// attempting send when state was >= MNP_LDISCONNECTING
case 30305:
*pTrace = (BYTE)dwInfo1; // store pArapConn->State
break;
// we just sent out a packet in ArapNdisSend()
case 30320:
pMnpSendBuf = (PMNPSENDBUF)Context; *pTrace++ = pMnpSendBuf->SeqNum;
// how big is the MNP packet
PUTSHORT2SHORT(pTrace,pMnpSendBuf->DataSize); pTrace += sizeof(USHORT);
*pTrace++ = (BYTE)dwInfo1; // is this a retransmission
BytesAvailable = pMnpSendBuf->DataSize; pCurrBuff = (&pMnpSendBuf->Buffer[0]) + 3; // skip start bytes
// copy first 24 bytes of the compressed data
while (BytesAvailable && BytesCopied < 24) { *pTrace++ = *pCurrBuff++; BytesCopied++; BytesAvailable--; }
default:
break;
}
DbgInfoLen = (USHORT)(pTrace - pStartTrace);
pSniff->FrameLen = DbgInfoLen;
pArapConn->pDbgCurrPtr = (PBYTE)ALIGN8(pTrace);
// fill up the round-up space with 0s
for (NOTHING; pTrace < pArapConn->pDbgCurrPtr; pTrace++) { *pTrace = 0; }
// make sure we haven't overrun this buffer
ASSERT(*((DWORD *)&(pArapConn->pDbgTraceBuffer[ARAP_SNIFF_BUFF_SIZE-4])) == 0xcafebeef);
// how many more bytes did we add to the sniff buff?
pArapConn->SniffedBytes += (DWORD)(pArapConn->pDbgCurrPtr - (PBYTE)pSniff);
//
// if we are about to overflow, just reset the pointer to beginning
// (do it while we have still 200 bytes left)
//
BufLenSoFar = (DWORD)(pArapConn->pDbgCurrPtr - pArapConn->pDbgTraceBuffer);
error_end:
if (BufLenSoFar > ARAP_SNIFF_BUFF_SIZE-200) { DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_INFO, ("ArapDbgTrace: resetting debug buffer, Sniff data LOST!\n"));
pArapConn->pDbgCurrPtr = pArapConn->pDbgTraceBuffer;
pArapConn->SniffedBytes = 0; } }
//***
//
// Function: ArapDbgTrace
// This routine records history of MNP level packet exchange
//
// Parameters: pArapConn - the connection in question
// Seq - sequence number (if applicable)
// FrameType - LT, LA etc.
//
// Return: Nothing
//
// NOTE: Spinlock is assumed to be held
//
//***$
VOID ArapDbgMnpHist( IN PARAPCONN pArapConn, IN BYTE Seq, IN BYTE FrameType ) { LARGE_INTEGER TimeNow; DWORD ThisDelta; DWORD DbgMnpIndex;
KeQuerySystemTime(&TimeNow);
if (TimeNow.HighPart == pArapConn->LastTimeStamp.HighPart) { ThisDelta = (TimeNow.LowPart - pArapConn->LastTimeStamp.LowPart); } else { ThisDelta = (0xffffffff - pArapConn->LastTimeStamp.LowPart + TimeNow.LowPart); }
// convert 100's ns to ms
ThisDelta = (ThisDelta/10000);
pArapConn->LastTimeStamp = TimeNow;
pArapConn->DbgMnpHist[pArapConn->DbgMnpIndex].TimeStamp = ThisDelta; pArapConn->DbgMnpHist[pArapConn->DbgMnpIndex].FrameInfo = (FrameType << 16); pArapConn->DbgMnpHist[pArapConn->DbgMnpIndex].FrameInfo |= Seq;
// wrap-around if necessary
if ((++pArapConn->DbgMnpIndex) >= DBG_MNP_HISTORY_SIZE) { pArapConn->DbgMnpIndex = 0; }
}
//***
//
// Function: ArapDbgDumpMnpHistory
// This routine dumps history of MNP level packet exchange
//
// Parameters: pArapConn - the connection in question
//
// Return: Nothing
//
//***$
VOID ArapDbgDumpMnpHist( IN PARAPCONN pArapConn ) { DWORD i; DWORD dwTmp; DWORD dwDelta; BYTE TmpSeq;
if (!ArapDbgDumpOnDisconnect) { return; }
DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("DerefArapConn: Past history on %lx .....\n", pArapConn));
// dump all info: old info first
for (i=pArapConn->DbgMnpIndex; i<DBG_MNP_HISTORY_SIZE; i++) { dwDelta = pArapConn->DbgMnpHist[i].TimeStamp; dwTmp = (pArapConn->DbgMnpHist[i].FrameInfo & 0xffff0000); TmpSeq = (BYTE)(pArapConn->DbgMnpHist[i].FrameInfo & 0x000000ff); switch (dwTmp) { case 0x40000 : DbgPrint(" %6ld NT sends %x\n",dwDelta,TmpSeq);break; case 0x50000 : DbgPrint(" %6ld NT acks %x\n",dwDelta,TmpSeq);break; case 0x140000: DbgPrint(" %6ld Mac sends %x\n",dwDelta,TmpSeq);break; case 0x150000: DbgPrint(" %6ld Mac acks %x\n",dwDelta,TmpSeq);break; default : DbgPrint(" %6ld Unknown: %lx\n",dwDelta,pArapConn->DbgMnpHist[i].FrameInfo); } }
// dump the current info
for (i=0; i<pArapConn->DbgMnpIndex; i++) { dwDelta = pArapConn->DbgMnpHist[i].TimeStamp; dwTmp = (pArapConn->DbgMnpHist[i].FrameInfo & 0xffff0000); TmpSeq = (BYTE)(pArapConn->DbgMnpHist[i].FrameInfo & 0x000000ff); switch (dwTmp) { case 0x40000 : DbgPrint(" %6ld NT sends %x\n",dwDelta,TmpSeq);break; case 0x50000 : DbgPrint(" %6ld NT acks %x\n",dwDelta,TmpSeq);break; case 0x140000: DbgPrint(" %6ld Mac sends %x\n",dwDelta,TmpSeq);break; case 0x150000: DbgPrint(" %6ld Mac acks %x\n",dwDelta,TmpSeq);break; default : DbgPrint(" %6ld Unknown: %lx\n",dwDelta,pArapConn->DbgMnpHist[i].FrameInfo); } } }
//***
//
// Function: ArapDumpNdisPktInfo
// walk the ARAP connections list and find out how many Ndis packets
// are in use right now
//
// Parameters: nothing
//
// Return: nothing
//
//***$
VOID ArapDumpNdisPktInfo( IN VOID ) { PARAPCONN pArapConn; PLIST_ENTRY pConnList; PLIST_ENTRY pList; PMNPSENDBUF pMnpSendBuf; KIRQL OldIrql; DWORD GrandTotal; DWORD ReXmit; DWORD ReXmitInNdis; DWORD Fresh; DWORD FreshInNdis; DWORD ThisConn; DWORD NumConns;
if (!RasPortDesc) { return; }
ACQUIRE_SPIN_LOCK(&RasPortDesc->pd_Lock, &OldIrql);
pConnList = RasPortDesc->pd_ArapConnHead.Flink;
GrandTotal = 0; NumConns = 0;
DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("NdisPacketInfo: counting total number of ndis packets used by ARAP....\n"));
//
// first, let's find the right connection to work on
//
while (pConnList != &RasPortDesc->pd_ArapConnHead) { ReXmit = 0; ReXmitInNdis = 0; Fresh = 0; FreshInNdis = 0; ThisConn = 0;
pConnList = pConnList->Flink;
pArapConn = CONTAINING_RECORD(pConnList, ARAPCONN, Linkage);
ACQUIRE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
pList = pArapConn->RetransmitQ.Flink;
// collect all buffers on the retransmit queue first
while (pList != &pArapConn->RetransmitQ) { pList = pList->Flink;
pMnpSendBuf = CONTAINING_RECORD(pList, MNPSENDBUF, Linkage); ReXmit++; if (pMnpSendBuf->Flags == 1) { ReXmitInNdis++; } }
pList = pArapConn->HighPriSendQ.Flink;
// collect all buffers on the fresh send
while (pList != &pArapConn->HighPriSendQ) { pList = pList->Flink;
pMnpSendBuf = CONTAINING_RECORD(pList, MNPSENDBUF, Linkage); Fresh++; if (pMnpSendBuf->Flags == 1) { FreshInNdis++; } }
ThisConn = ReXmit+ReXmitInNdis+Fresh+FreshInNdis;
DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, (" %ld packets on %lx, %d in Ndis (%d+%d+%d+%d)\n", ThisConn,pArapConn,ReXmitInNdis,ReXmit,ReXmitInNdis,Fresh,FreshInNdis));
GrandTotal += ThisConn; NumConns++;
RELEASE_SPIN_LOCK_DPC(&pArapConn->SpinLock);
}
RELEASE_SPIN_LOCK(&RasPortDesc->pd_Lock, OldIrql);
DBGPRINT(DBG_COMP_RAS, DBG_LEVEL_ERR, ("NdisPacketInfo: total of %ld Ndis Packets on %d connections\n", GrandTotal, NumConns));
}
#endif // DBG
|