windows-nt/Source/XPSP1/NT/net/netbeui/sys/packet.c
2020-09-26 16:20:57 +08:00

1830 lines
48 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1989, 1990, 1991 Microsoft Corporation
Module Name:
packet.c
Abstract:
This module contains code that implements the TP_PACKET object, which
describes a DLC I-frame at some point in its lifetime. Routines are
provided to allocate packets for shipment, to ship packets, to reference
packets, to dereference packets, to mark a connection as waiting for a
packet to become available, to satisfy the next waiting connection for
a packet, and to destroy packets (return them to the pool).
Author:
David Beaver (dbeaver) 1-July-1991
Environment:
Kernel mode
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// This is temporary; this is the quota that we charge for a receive
// packet for now, until we fix the problem with token-ring needing
// big packets and using all the memory. The number is the actual
// value for Ethernet.
//
#if 1
#define RECEIVE_BUFFER_QUOTA(_DeviceContext) 1533
#else
#define RECEIVE_BUFFER_QUOTA(_DeviceContext) (_DeviceContext)->ReceiveBufferLength
#endif
#define PACKET_POOL_GROW_COUNT 32
#if DBG
ULONG NbfCreatePacketThreshold = 5;
extern ULONG NbfPacketPanic;
#endif
NDIS_STATUS
NbfAllocateNdisSendPacket(
IN PDEVICE_CONTEXT DeviceContext,
OUT PNDIS_PACKET *NdisPacket
)
/*++
Routine Description:
This routine allocates a recieve packet from the receive packet pool.
It Grows the packet pool if necessary.
NOTE: This routine is called with the device context spinlock
held, or at such a time as synchronization is unnecessary.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
UIFrame - Returns a pointer to the frame, or NULL if no storage
can be allocated.
Return Value:
None.
--*/
{
PNBF_POOL_LIST_DESC SendPacketPoolDesc;
NDIS_STATUS NdisStatus;
KIRQL oldirql;
NdisStatus = NDIS_STATUS_RESOURCES;
ACQUIRE_SPIN_LOCK (&DeviceContext->SendPoolListLock, &oldirql);
for (SendPacketPoolDesc = DeviceContext->SendPacketPoolDesc;
SendPacketPoolDesc != NULL;
SendPacketPoolDesc = SendPacketPoolDesc->Next) {
NdisAllocatePacket (
&NdisStatus,
NdisPacket,
SendPacketPoolDesc->PoolHandle);
if (NdisStatus == NDIS_STATUS_SUCCESS) {
RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
return(NdisStatus);
}
}
if (NdisStatus != NDIS_STATUS_SUCCESS) {
if ((DeviceContext->MemoryLimit != 0) &&
((DeviceContext->MemoryUsage +
PACKET_POOL_GROW_COUNT *
(sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG))) >
DeviceContext->MemoryLimit)) {
PANIC("NBF: Could not grow packet pool: limit\n");
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_LIMIT,
106,
DeviceContext->UIFrameLength,
UI_FRAME_RESOURCE_ID);
RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
return(NdisStatus);
}
}
DeviceContext->MemoryUsage +=
(PACKET_POOL_GROW_COUNT *
(sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG)));
// Allocate Packet pool descriptors for dynamic packet allocation.
SendPacketPoolDesc = ExAllocatePoolWithTag(
NonPagedPool,
sizeof(NBF_POOL_LIST_DESC),
NBF_MEM_TAG_POOL_DESC);
if (SendPacketPoolDesc == NULL) {
RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
return(NdisStatus);
}
RtlZeroMemory(SendPacketPoolDesc, sizeof(NBF_POOL_LIST_DESC));
SendPacketPoolDesc->NumElements =
SendPacketPoolDesc->TotalElements = PACKET_POOL_GROW_COUNT;
// To track packet pools in NDIS allocated on NBF's behalf
#if NDIS_POOL_TAGGING
SendPacketPoolDesc->PoolHandle = (NDIS_HANDLE) NDIS_PACKET_POOL_TAG_FOR_NBF;
#endif
NdisAllocatePacketPoolEx ( &NdisStatus, &SendPacketPoolDesc->PoolHandle,
PACKET_POOL_GROW_COUNT, 0, sizeof (SEND_PACKET_TAG));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
#if DBG
NbfPrint1 ("NbfGrowSendPacketPool: NdisInitializePacketPool failed, reason: %s.\n",
NbfGetNdisStatus (NdisStatus));
#endif
RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
ExFreePool (SendPacketPoolDesc);
return(NdisStatus);
}
NdisSetPacketPoolProtocolId (SendPacketPoolDesc->PoolHandle, NDIS_PROTOCOL_ID_NBF);
SendPacketPoolDesc->Next = DeviceContext->SendPacketPoolDesc;
DeviceContext->SendPacketPoolDesc = SendPacketPoolDesc;
RELEASE_SPIN_LOCK (&DeviceContext->SendPoolListLock, oldirql);
NdisAllocatePacket ( &NdisStatus, NdisPacket,
SendPacketPoolDesc->PoolHandle);
return(NdisStatus);
}
NDIS_STATUS
NbfAllocateNdisRcvPacket(
IN PDEVICE_CONTEXT DeviceContext,
OUT PNDIS_PACKET *NdisPacket
)
/*++
Routine Description:
This routine allocates a recieve packet from the receive packet pool.
It Grows the packet pool if necessary.
NOTE: This routine is called with the device context spinlock
held, or at such a time as synchronization is unnecessary.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
UIFrame - Returns a pointer to the frame, or NULL if no storage
can be allocated.
Return Value:
None.
--*/
{
PNBF_POOL_LIST_DESC RcvPacketPoolDesc;
NDIS_STATUS NdisStatus;
KIRQL oldirql;
NdisStatus = NDIS_STATUS_RESOURCES;
ACQUIRE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, &oldirql);
for (RcvPacketPoolDesc = DeviceContext->ReceivePacketPoolDesc;
RcvPacketPoolDesc != NULL;
RcvPacketPoolDesc = RcvPacketPoolDesc->Next) {
NdisAllocatePacket (
&NdisStatus,
NdisPacket,
RcvPacketPoolDesc->PoolHandle);
if (NdisStatus == NDIS_STATUS_SUCCESS) {
RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
return(NdisStatus);
}
}
if (NdisStatus != NDIS_STATUS_SUCCESS) {
if ((DeviceContext->MemoryLimit != 0) &&
((DeviceContext->MemoryUsage +
PACKET_POOL_GROW_COUNT *
(sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG))) >
DeviceContext->MemoryLimit)) {
PANIC("NBF: Could not grow packet pool: limit\n");
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_LIMIT,
106,
DeviceContext->UIFrameLength,
UI_FRAME_RESOURCE_ID);
RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
return(NdisStatus);
}
}
DeviceContext->MemoryUsage +=
(PACKET_POOL_GROW_COUNT *
(sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG)));
// Allocate Packet pool descriptors for dynamic packet allocation.
RcvPacketPoolDesc = ExAllocatePoolWithTag(
NonPagedPool,
sizeof(NBF_POOL_LIST_DESC),
NBF_MEM_TAG_POOL_DESC);
if (RcvPacketPoolDesc == NULL) {
RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
return(NdisStatus);
}
RtlZeroMemory(RcvPacketPoolDesc, sizeof(NBF_POOL_LIST_DESC));
RcvPacketPoolDesc->NumElements =
RcvPacketPoolDesc->TotalElements = PACKET_POOL_GROW_COUNT;
// To track packet pools in NDIS allocated on NBF's behalf
#if NDIS_POOL_TAGGING
RcvPacketPoolDesc->PoolHandle = (NDIS_HANDLE) NDIS_PACKET_POOL_TAG_FOR_NBF;
#endif
NdisAllocatePacketPoolEx ( &NdisStatus, &RcvPacketPoolDesc->PoolHandle,
PACKET_POOL_GROW_COUNT, 0, sizeof (RECEIVE_PACKET_TAG));
if (NdisStatus != NDIS_STATUS_SUCCESS) {
#if DBG
NbfPrint1 ("NbfGrowSendPacketPool: NdisInitializePacketPool failed, reason: %s.\n",
NbfGetNdisStatus (NdisStatus));
#endif
RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
ExFreePool (RcvPacketPoolDesc);
return(NdisStatus);
}
NdisSetPacketPoolProtocolId (RcvPacketPoolDesc->PoolHandle, NDIS_PROTOCOL_ID_NBF);
RcvPacketPoolDesc->Next = DeviceContext->ReceivePacketPoolDesc;
DeviceContext->ReceivePacketPoolDesc = RcvPacketPoolDesc;
RELEASE_SPIN_LOCK (&DeviceContext->RcvPoolListLock, oldirql);
NdisAllocatePacket ( &NdisStatus, NdisPacket,
RcvPacketPoolDesc->PoolHandle);
return(NdisStatus);
}
VOID
NbfAllocateUIFrame(
IN PDEVICE_CONTEXT DeviceContext,
OUT PTP_UI_FRAME *TransportUIFrame
)
/*++
Routine Description:
This routine allocates storage for a UI frame. Some initialization
is done here.
NOTE: This routine is called with the device context spinlock
held, or at such a time as synchronization is unnecessary.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
UIFrame - Returns a pointer to the frame, or NULL if no storage
can be allocated.
Return Value:
None.
--*/
{
NDIS_STATUS NdisStatus;
PNDIS_PACKET NdisPacket;
PSEND_PACKET_TAG SendTag;
PTP_UI_FRAME UIFrame;
PNDIS_BUFFER NdisBuffer;
PNBF_POOL_LIST_DESC SendPacketPoolDesc;
if ((DeviceContext->MemoryLimit != 0) &&
((DeviceContext->MemoryUsage + DeviceContext->UIFrameLength) >
DeviceContext->MemoryLimit)) {
PANIC("NBF: Could not allocate UI frame: limit\n");
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_LIMIT,
106,
DeviceContext->UIFrameLength,
UI_FRAME_RESOURCE_ID);
*TransportUIFrame = NULL;
return;
}
UIFrame = (PTP_UI_FRAME) ExAllocatePoolWithTag (
NonPagedPool,
DeviceContext->UIFrameLength,
NBF_MEM_TAG_TP_UI_FRAME);
if (UIFrame == NULL) {
PANIC("NBF: Could not allocate UI frame: no pool\n");
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_POOL,
206,
DeviceContext->UIFrameLength,
UI_FRAME_RESOURCE_ID);
*TransportUIFrame = NULL;
return;
}
RtlZeroMemory (UIFrame, DeviceContext->UIFrameLength);
DeviceContext->MemoryUsage += DeviceContext->UIFrameLength;
NdisStatus = NbfAllocateNdisSendPacket(DeviceContext, &NdisPacket);
#if 0
for (SendPacketPoolDesc = DeviceContext->SendPacketPoolDesc;
SendPacketPoolDesc != NULL;
SendPacketPoolDesc = SendPacketPoolDesc->Next) {
NdisAllocatePacket (
&NdisStatus,
&NdisPacket,
SendPacketPoolDesc->PoolHandle);
if (NdisStatus == NDIS_STATUS_SUCCESS)
break;
}
#endif
if (NdisStatus != NDIS_STATUS_SUCCESS) {
ExFreePool (UIFrame);
#if 0
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_SPECIFIC,
306,
0,
UI_FRAME_RESOURCE_ID);
#endif
*TransportUIFrame = NULL;
return;
}
UIFrame->NdisPacket = NdisPacket;
UIFrame->DataBuffer = NULL;
SendTag = (PSEND_PACKET_TAG)NdisPacket->ProtocolReserved;
SendTag->Type = TYPE_UI_FRAME;
SendTag->Frame = UIFrame;
SendTag->Owner = DeviceContext;
//
// Make the packet header known to the packet descriptor
//
NdisAllocateBuffer(
&NdisStatus,
&NdisBuffer,
DeviceContext->NdisBufferPool,
UIFrame->Header,
DeviceContext->UIFrameHeaderLength);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_SPECIFIC,
406,
0,
UI_FRAME_RESOURCE_ID);
NdisFreePacket (NdisPacket);
ExFreePool (UIFrame);
*TransportUIFrame = NULL;
return;
}
NdisChainBufferAtFront (NdisPacket, NdisBuffer);
++DeviceContext->UIFrameAllocated;
*TransportUIFrame = UIFrame;
} /* NbfAllocateUIFrame */
VOID
NbfDeallocateUIFrame(
IN PDEVICE_CONTEXT DeviceContext,
IN PTP_UI_FRAME TransportUIFrame
)
/*++
Routine Description:
This routine frees storage for a UI frame.
NOTE: This routine is called with the device context spinlock
held, or at such a time as synchronization is unnecessary.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
UIFrame - A pointer to the frame.
Return Value:
None.
--*/
{
PNDIS_PACKET NdisPacket = TransportUIFrame->NdisPacket;
PNDIS_BUFFER NdisBuffer;
NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer);
if (NdisBuffer != NULL) {
NdisFreeBuffer (NdisBuffer);
}
NdisFreePacket (NdisPacket);
ExFreePool (TransportUIFrame);
--DeviceContext->UIFrameAllocated;
DeviceContext->MemoryUsage -= DeviceContext->UIFrameLength;
} /* NbfDeallocateUIFrame */
VOID
NbfAllocateSendPacket(
IN PDEVICE_CONTEXT DeviceContext,
OUT PTP_PACKET *TransportSendPacket
)
/*++
Routine Description:
This routine allocates storage for a send packet. Some initialization
is done here.
NOTE: This routine is called with the device context spinlock
held, or at such a time as synchronization is unnecessary.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
TransportSendPacket - Returns a pointer to the packet, or NULL if no
storage can be allocated.
Return Value:
None.
--*/
{
PTP_PACKET Packet;
NDIS_STATUS NdisStatus;
PNDIS_PACKET NdisPacket;
PSEND_PACKET_TAG SendTag;
PNDIS_BUFFER NdisBuffer;
PNBF_POOL_LIST_DESC SendPacketPoolDesc;
if ((DeviceContext->MemoryLimit != 0) &&
((DeviceContext->MemoryUsage + DeviceContext->PacketLength) >
DeviceContext->MemoryLimit)) {
PANIC("NBF: Could not allocate send packet: limit\n");
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_LIMIT,
107,
DeviceContext->PacketLength,
PACKET_RESOURCE_ID);
*TransportSendPacket = NULL;
return;
}
Packet = (PTP_PACKET)ExAllocatePoolWithTag (
NonPagedPool,
DeviceContext->PacketLength,
NBF_MEM_TAG_TP_PACKET);
if (Packet == NULL) {
PANIC("NBF: Could not allocate send packet: no pool\n");
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_POOL,
207,
DeviceContext->PacketLength,
PACKET_RESOURCE_ID);
*TransportSendPacket = NULL;
return;
}
RtlZeroMemory (Packet, DeviceContext->PacketLength);
DeviceContext->MemoryUsage += DeviceContext->PacketLength;
NdisStatus = NbfAllocateNdisSendPacket(DeviceContext, &NdisPacket);
#if 0
for (SendPacketPoolDesc = DeviceContext->SendPacketPoolDesc;
SendPacketPoolDesc != NULL;
SendPacketPoolDesc = SendPacketPoolDesc->Next) {
NdisAllocatePacket (
&NdisStatus,
&NdisPacket,
SendPacketPoolDesc->PoolHandle);
if (NdisStatus == NDIS_STATUS_SUCCESS)
break;
}
#endif
if (NdisStatus != NDIS_STATUS_SUCCESS) {
ExFreePool (Packet);
#if 0
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_SPECIFIC,
307,
0,
PACKET_RESOURCE_ID);
#endif
*TransportSendPacket = NULL;
return;
}
NdisAllocateBuffer(
&NdisStatus,
&NdisBuffer,
DeviceContext->NdisBufferPool,
Packet->Header,
DeviceContext->PacketHeaderLength);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_SPECIFIC,
407,
0,
PACKET_RESOURCE_ID);
NdisFreePacket (NdisPacket);
ExFreePool (Packet);
*TransportSendPacket = NULL;
return;
}
NdisChainBufferAtFront (NdisPacket, NdisBuffer);
Packet->NdisPacket = NdisPacket;
SendTag = (PSEND_PACKET_TAG)NdisPacket->ProtocolReserved;
SendTag->Type = TYPE_I_FRAME;
SendTag->Frame = Packet;
SendTag->Owner = DeviceContext;
Packet->Type = NBF_PACKET_SIGNATURE;
Packet->Size = sizeof (TP_PACKET);
Packet->Provider = DeviceContext;
Packet->Owner = NULL; // no connection/irpsp yet.
Packet->Action = PACKET_ACTION_IRP_SP;
Packet->PacketizeConnection = FALSE;
Packet->PacketNoNdisBuffer = FALSE;
Packet->ProviderInterlock = &DeviceContext->Interlock;
// KeInitializeSpinLock (&Packet->Interlock);
++DeviceContext->PacketAllocated;
*TransportSendPacket = Packet;
} /* NbfAllocateSendPacket */
VOID
NbfDeallocateSendPacket(
IN PDEVICE_CONTEXT DeviceContext,
IN PTP_PACKET TransportSendPacket
)
/*++
Routine Description:
This routine frees storage for a send packet.
NOTE: This routine is called with the device context spinlock
held, or at such a time as synchronization is unnecessary.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
TransportSendPacket - A pointer to the send packet.
Return Value:
None.
--*/
{
PNDIS_PACKET NdisPacket = TransportSendPacket->NdisPacket;
PNDIS_BUFFER NdisBuffer;
NdisUnchainBufferAtFront (NdisPacket, &NdisBuffer);
if (NdisBuffer != NULL) {
NdisFreeBuffer (NdisBuffer);
}
NdisFreePacket (NdisPacket);
ExFreePool (TransportSendPacket);
--DeviceContext->PacketAllocated;
DeviceContext->MemoryUsage -= DeviceContext->PacketLength;
} /* NbfDeallocateSendPacket */
VOID
NbfAllocateReceivePacket(
IN PDEVICE_CONTEXT DeviceContext,
OUT PNDIS_PACKET *TransportReceivePacket
)
/*++
Routine Description:
This routine allocates storage for a receive packet. Some initialization
is done here.
NOTE: This routine is called with the device context spinlock
held, or at such a time as synchronization is unnecessary.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
TransportReceivePacket - Returns a pointer to the packet, or NULL if no
storage can be allocated.
Return Value:
None.
--*/
{
NDIS_STATUS NdisStatus;
PNDIS_PACKET NdisPacket;
PRECEIVE_PACKET_TAG ReceiveTag;
//
// This does not count in DeviceContext->MemoryUsage because
// the storage is allocated when we allocate the packet pool.
//
NdisStatus = NbfAllocateNdisRcvPacket(DeviceContext, &NdisPacket);
#if 0
NdisAllocatePacket (
&NdisStatus,
&NdisPacket,
DeviceContext->ReceivePacketPoolDesc->PoolHandle);
#endif
if (NdisStatus != NDIS_STATUS_SUCCESS) {
#if 0
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_SPECIFIC,
309,
0,
RECEIVE_PACKET_RESOURCE_ID);
#endif
*TransportReceivePacket = NULL;
return;
}
ReceiveTag = (PRECEIVE_PACKET_TAG)(NdisPacket->ProtocolReserved);
ReceiveTag->PacketType = TYPE_AT_INDICATE;
++DeviceContext->ReceivePacketAllocated;
*TransportReceivePacket = NdisPacket;
} /* NbfAllocateReceivePacket */
VOID
NbfDeallocateReceivePacket(
IN PDEVICE_CONTEXT DeviceContext,
IN PNDIS_PACKET TransportReceivePacket
)
/*++
Routine Description:
This routine frees storage for a receive packet.
NOTE: This routine is called with the device context spinlock
held, or at such a time as synchronization is unnecessary.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
TransportReceivePacket - A pointer to the packet.
Return Value:
None.
--*/
{
NdisFreePacket (TransportReceivePacket);
--DeviceContext->ReceivePacketAllocated;
} /* NbfDeallocateReceivePacket */
VOID
NbfAllocateReceiveBuffer(
IN PDEVICE_CONTEXT DeviceContext,
OUT PBUFFER_TAG *TransportReceiveBuffer
)
/*++
Routine Description:
This routine allocates storage for a receive buffer. Some initialization
is done here.
NOTE: This routine is called with the device context spinlock
held, or at such a time as synchronization is unnecessary.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
TransportReceiveBuffer - Returns a pointer to the buffer, or NULL if no
storage can be allocated.
Return Value:
None.
--*/
{
PBUFFER_TAG BufferTag;
NDIS_STATUS NdisStatus;
PNDIS_BUFFER NdisBuffer;
if ((DeviceContext->MemoryLimit != 0) &&
((DeviceContext->MemoryUsage + RECEIVE_BUFFER_QUOTA(DeviceContext)) >
DeviceContext->MemoryLimit)) {
PANIC("NBF: Could not allocate receive buffer: limit\n");
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_LIMIT,
108,
RECEIVE_BUFFER_QUOTA(DeviceContext),
RECEIVE_BUFFER_RESOURCE_ID);
*TransportReceiveBuffer = NULL;
return;
}
//
// The Aligned doesn't help since the header makes it unaligned.
//
BufferTag = (PBUFFER_TAG)ExAllocatePoolWithTag (
NonPagedPoolCacheAligned,
DeviceContext->ReceiveBufferLength,
NBF_MEM_TAG_RCV_BUFFER);
if (BufferTag == NULL) {
PANIC("NBF: Could not allocate receive buffer: no pool\n");
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_POOL,
208,
DeviceContext->ReceiveBufferLength,
RECEIVE_BUFFER_RESOURCE_ID);
*TransportReceiveBuffer = NULL;
return;
}
DeviceContext->MemoryUsage += RECEIVE_BUFFER_QUOTA(DeviceContext);
//
// point to the buffer for NDIS
//
NdisAllocateBuffer(
&NdisStatus,
&NdisBuffer,
DeviceContext->NdisBufferPool,
BufferTag->Buffer,
DeviceContext->MaxReceivePacketSize);
if (NdisStatus != NDIS_STATUS_SUCCESS) {
PANIC("NBF: Could not allocate receive buffer: no buffer\n");
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_SPECIFIC,
308,
0,
RECEIVE_BUFFER_RESOURCE_ID);
ExFreePool (BufferTag);
*TransportReceiveBuffer = NULL;
return;
}
BufferTag->Length = DeviceContext->MaxReceivePacketSize;
BufferTag->NdisBuffer = NdisBuffer;
++DeviceContext->ReceiveBufferAllocated;
*TransportReceiveBuffer = BufferTag;
} /* NbfAllocateReceiveBuffer */
VOID
NbfDeallocateReceiveBuffer(
IN PDEVICE_CONTEXT DeviceContext,
IN PBUFFER_TAG TransportReceiveBuffer
)
/*++
Routine Description:
This routine frees storage for a receive buffer.
NOTE: This routine is called with the device context spinlock
held, or at such a time as synchronization is unnecessary.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
TransportReceiveBuffer - A pointer to the buffer.
Return Value:
None.
--*/
{
NdisFreeBuffer (TransportReceiveBuffer->NdisBuffer);
ExFreePool (TransportReceiveBuffer);
--DeviceContext->ReceiveBufferAllocated;
DeviceContext->MemoryUsage -= RECEIVE_BUFFER_QUOTA(DeviceContext);
} /* NbfDeallocateReceiveBuffer */
NTSTATUS
NbfCreatePacket(
PDEVICE_CONTEXT DeviceContext,
PTP_LINK Link,
PTP_PACKET *Packet
)
/*++
Routine Description:
This routine allocates a packet from the device context's pool,
and prepares the MAC and DLC headers for use by the connection.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
Link - The link the packet will be sent over.
Packet - Pointer to a place where we will return a pointer to the
allocated packet.
Return Value:
NTSTATUS - status of operation.
--*/
{
KIRQL oldirql;
PSINGLE_LIST_ENTRY s;
PTP_PACKET ThePacket;
PDLC_I_FRAME DlcHdr;
#if DBG
PNBF_HDR_CONNECTION NbfHdr;
#endif
typedef struct _SIXTEEN_BYTES {
ULONG Data[4];
} SIXTEEN_BYTES, *PSIXTEEN_BYTES;
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
IF_NBFDBG (NBF_DEBUG_RESOURCE) {
NbfPrint0 ("NbfCreatePacket: Entered.\n");
}
//
// Make sure that structure packing hasn't happened.
//
ASSERT (sizeof(NBF_HDR_CONNECTION) == 14);
#if defined(NBF_UP)
s = DeviceContext->PacketPool.Next;
if (s != NULL) {
DeviceContext->PacketPool.Next = s->Next;
}
#else
s = ExInterlockedPopEntryList (
&DeviceContext->PacketPool,
&DeviceContext->Interlock);
#endif
if (s == NULL) {
NbfGrowSendPacketPool(DeviceContext);
#if defined(NBF_UP)
s = DeviceContext->PacketPool.Next;
if (s != NULL) {
DeviceContext->PacketPool.Next = s->Next;
}
#else
s = ExInterlockedPopEntryList (
&DeviceContext->PacketPool,
&DeviceContext->Interlock);
#endif
if (s == NULL) {
#if DBG
++Link->CreatePacketFailures;
if ((ULONG)Link->CreatePacketFailures >= NbfCreatePacketThreshold) {
if (NbfPacketPanic) {
NbfPrint1 ("NbfCreatePacket: PANIC! no more packets in provider's pool (%d times).\n",
Link->CreatePacketFailures);
}
Link->CreatePacketFailures = 0;
}
#endif
ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
++DeviceContext->PacketExhausted;
RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
return STATUS_INSUFFICIENT_RESOURCES;
}
}
#if DBG
Link->CreatePacketFailures = 0;
#endif
ThePacket = CONTAINING_RECORD (s, TP_PACKET, Linkage);
//
// NOTE: ThePacket->Action and ThePacket->Owner are filled
// in by the caller of this function.
//
ThePacket->ReferenceCount = 1; // automatic ref count of 1.
ThePacket->Link = NULL; // no link yet.
ThePacket->PacketSent = FALSE;
ASSERT (ThePacket->Action == PACKET_ACTION_IRP_SP);
ASSERT (ThePacket->PacketNoNdisBuffer == FALSE);
ASSERT (ThePacket->PacketizeConnection == FALSE);
//
// Initialize the MAC header for this packet, using the connection's
// link pre-built header.
//
if (Link->HeaderLength <= 14) {
*(PSIXTEEN_BYTES)ThePacket->Header = *(PSIXTEEN_BYTES)Link->Header;
} else {
RtlCopyMemory(
ThePacket->Header,
Link->Header,
Link->HeaderLength);
//
// Initialize the TP_FRAME_CONNECTION header for this packet.
//
DlcHdr = (PDLC_I_FRAME)&(ThePacket->Header[Link->HeaderLength]);
DlcHdr->Dsap = DSAP_NETBIOS_OVER_LLC;
DlcHdr->Ssap = DSAP_NETBIOS_OVER_LLC;
#if DBG
DlcHdr->SendSeq = 0; // known values, will assist debugging.
DlcHdr->RcvSeq = 0; // these are assigned at shipment time.
#endif
}
#if DBG
NbfHdr = (PNBF_HDR_CONNECTION)&(ThePacket->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]);
NbfHdr->Command = 0xff; // to assist debugging-- assigned later.
NbfHdr->Data1 = 0xff; // to assist debugging-- assigned later.
NbfHdr->Data2Low = 0xff; // to assist debugging-- assigned later.
NbfHdr->Data2High = 0xff; // to assist debugging-- assigned later.
TRANSMIT_CORR(NbfHdr) = 0xffff; // to assist debugging-- assigned later.
RESPONSE_CORR(NbfHdr) = 0xffff; // to assist debugging-- assigned later.
NbfHdr->DestinationSessionNumber = 0xff; // to assist debugging-- assigned later.
NbfHdr->SourceSessionNumber = 0xff; // to assist debugging-- assigned later.
#endif
*Packet = ThePacket; // return pointer to the packet.
return STATUS_SUCCESS;
} /* NbfCreatePacket */
NTSTATUS
NbfCreateRrPacket(
PDEVICE_CONTEXT DeviceContext,
PTP_LINK Link,
PTP_PACKET *Packet
)
/*++
Routine Description:
This routine allocates an RR packet from the device context's pool,
and prepares the MAC and DLC headers for use by the connection.
It first looks in the special RR packet pool, then in the regular
packet pool.
Arguments:
DeviceContext - Pointer to our device context to charge the packet to.
Link - The link the packet will be sent over.
Packet - Pointer to a place where we will return a pointer to the
allocated packet.
Return Value:
NTSTATUS - status of operation.
--*/
{
PSINGLE_LIST_ENTRY s;
PTP_PACKET ThePacket;
PDLC_I_FRAME DlcHdr;
NTSTATUS Status;
#if DBG
PNBF_HDR_CONNECTION NbfHdr;
#endif
typedef struct _SIXTEEN_BYTES {
ULONG Data[4];
} SIXTEEN_BYTES, *PSIXTEEN_BYTES;
IF_NBFDBG (NBF_DEBUG_RESOURCE) {
NbfPrint0 ("NbfCreateRrPacket: Entered.\n");
}
//
// Make sure that structure packing hasn't happened.
//
ASSERT (sizeof(NBF_HDR_CONNECTION) == 14);
#if defined(NBF_UP)
s = DeviceContext->RrPacketPool.Next;
if (s != NULL) {
DeviceContext->RrPacketPool.Next = s->Next;
}
#else
s = ExInterlockedPopEntryList (
&DeviceContext->RrPacketPool,
&DeviceContext->Interlock);
#endif
if (s == NULL) {
#if DBG
++Link->CreatePacketFailures;
if ((ULONG)Link->CreatePacketFailures >= NbfCreatePacketThreshold) {
if (NbfPacketPanic) {
NbfPrint1 ("NbfCreateRrPacket: PANIC! no more packets in provider's pool (%d times).\n",
Link->CreatePacketFailures);
}
Link->CreatePacketFailures = 0;
}
#endif
//
// Try to get one from the regular pool, and mark it so
// it goes back there.
//
Status = NbfCreatePacket(
DeviceContext,
Link,
Packet);
if (Status == STATUS_SUCCESS) {
(*Packet)->Action = PACKET_ACTION_NULL;
}
return Status;
}
#if DBG
Link->CreatePacketFailures = 0;
#endif
ThePacket = CONTAINING_RECORD (s, TP_PACKET, Linkage);
//
// NOTE: ThePacket->Owner is filled in by the caller of this
// function.
//
ThePacket->ReferenceCount = 1; // automatic ref count of 1.
ThePacket->Link = NULL; // no link yet.
ThePacket->PacketSent = FALSE;
ASSERT (ThePacket->Action == PACKET_ACTION_RR);
ASSERT (ThePacket->PacketNoNdisBuffer == FALSE);
//
// Initialize the MAC header for this packet, using the connection's
// link pre-built header.
//
if (Link->HeaderLength <= 14) {
*(PSIXTEEN_BYTES)ThePacket->Header = *(PSIXTEEN_BYTES)Link->Header;
} else {
RtlCopyMemory(
ThePacket->Header,
Link->Header,
Link->HeaderLength);
//
// Initialize the TP_FRAME_CONNECTION header for this packet.
//
DlcHdr = (PDLC_I_FRAME)&(ThePacket->Header[Link->HeaderLength]);
DlcHdr->Dsap = DSAP_NETBIOS_OVER_LLC;
DlcHdr->Ssap = DSAP_NETBIOS_OVER_LLC;
#if DBG
DlcHdr->SendSeq = 0; // known values, will assist debugging.
DlcHdr->RcvSeq = 0; // these are assigned at shipment time.
#endif
}
#if DBG
NbfHdr = (PNBF_HDR_CONNECTION)&(ThePacket->Header[Link->HeaderLength + sizeof(DLC_I_FRAME)]);
NbfHdr->Command = 0xff; // to assist debugging-- assigned later.
NbfHdr->Data1 = 0xff; // to assist debugging-- assigned later.
NbfHdr->Data2Low = 0xff; // to assist debugging-- assigned later.
NbfHdr->Data2High = 0xff; // to assist debugging-- assigned later.
TRANSMIT_CORR(NbfHdr) = 0xffff; // to assist debugging-- assigned later.
RESPONSE_CORR(NbfHdr) = 0xffff; // to assist debugging-- assigned later.
NbfHdr->DestinationSessionNumber = 0xff; // to assist debugging-- assigned later.
NbfHdr->SourceSessionNumber = 0xff; // to assist debugging-- assigned later.
#endif
*Packet = ThePacket; // return pointer to the packet.
return STATUS_SUCCESS;
} /* NbfCreateRrPacket */
VOID
NbfDestroyPacket(
PTP_PACKET Packet
)
/*++
Routine Description:
This routine destroys a packet, thereby returning it to the pool. If
it is determined that there is at least one connection waiting for a
packet to become available (and it just has), then the connection is
removed from the device context's list and AdvanceSend is called to
prep the connection further.
Arguments:
Packet - Pointer to a packet to be returned to the pool.
Return Value:
none.
--*/
{
PDEVICE_CONTEXT DeviceContext;
PTP_CONNECTION Connection;
PLIST_ENTRY p;
PNDIS_BUFFER HeaderBuffer;
PNDIS_BUFFER NdisBuffer;
ULONG Flags;
IF_NBFDBG (NBF_DEBUG_RESOURCE) {
NbfPrint2 ("NbfDestroyPacket: Entered, Packet: %lx, NdisPacket: %lx\n",
Packet, Packet->NdisPacket);
}
DeviceContext = Packet->Provider;
//
// Strip off and unmap the buffers describing data and header.
//
if (Packet->PacketNoNdisBuffer) {
//
// If the NDIS_BUFFER chain is not ours, then we can't
// start unchaining since that would mess up the queue;
// instead we just drop the rest of the chain after the
// header.
//
NdisQueryPacket (Packet->NdisPacket, NULL, NULL, &HeaderBuffer, NULL);
ASSERT (HeaderBuffer != NULL);
NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
NdisRecalculatePacketCounts (Packet->NdisPacket);
Packet->PacketNoNdisBuffer = FALSE;
} else {
NdisUnchainBufferAtFront (Packet->NdisPacket, &HeaderBuffer);
ASSERT (HeaderBuffer != NULL);
//
// Return all the NDIS_BUFFERs to the system.
//
NdisUnchainBufferAtFront (Packet->NdisPacket, &NdisBuffer);
while (NdisBuffer != NULL) {
NdisFreeBuffer (NdisBuffer);
NdisUnchainBufferAtFront (Packet->NdisPacket, &NdisBuffer);
}
NDIS_BUFFER_LINKAGE(HeaderBuffer) = (PNDIS_BUFFER)NULL;
NdisChainBufferAtFront (Packet->NdisPacket, HeaderBuffer);
}
//
// invoke the packet deallocate action specified in this packet.
//
switch (Packet->Action) {
case PACKET_ACTION_NULL:
// PANIC ("NbfDestroyPacket: no action.\n");
Packet->Action = PACKET_ACTION_IRP_SP;
break;
case PACKET_ACTION_IRP_SP:
IF_NBFDBG (NBF_DEBUG_REQUEST) {
NbfPrint2 ("NbfDestroyPacket: Packet %x deref IrpSp %x.\n", Packet, Packet->Owner);
}
NbfDereferenceSendIrp("Destroy packet", (PIO_STACK_LOCATION)(Packet->Owner), RREF_PACKET);
break;
case PACKET_ACTION_CONNECTION:
NbfDereferenceConnection ("Destroy packet", (PTP_CONNECTION)(Packet->Owner), CREF_FRAME_SEND);
Packet->Action = PACKET_ACTION_IRP_SP;
break;
case PACKET_ACTION_END:
NbfDereferenceConnection ("SessionEnd destroyed", (PTP_CONNECTION)(Packet->Owner), CREF_FRAME_SEND);
NbfDereferenceConnection ("SessionEnd destroyed", (PTP_CONNECTION)(Packet->Owner), CREF_LINK);
Packet->Action = PACKET_ACTION_IRP_SP;
break;
case PACKET_ACTION_RR:
#if defined(NBF_UP)
((PSINGLE_LIST_ENTRY)&Packet->Linkage)->Next =
DeviceContext->RrPacketPool.Next;
DeviceContext->RrPacketPool.Next =
&((PSINGLE_LIST_ENTRY)&Packet->Linkage)->Next;
#else
ExInterlockedPushEntryList (
&DeviceContext->RrPacketPool,
(PSINGLE_LIST_ENTRY)&Packet->Linkage,
&DeviceContext->Interlock);
#endif
return;
default:
IF_NBFDBG (NBF_DEBUG_RESOURCE) {
NbfPrint1 ("NbfDestroyPacket: invalid action (%ld).\n", Packet->Action);
}
ASSERT (FALSE);
}
//
// Put the packet back for use again.
//
#if defined(NBF_UP)
((PSINGLE_LIST_ENTRY)&Packet->Linkage)->Next =
DeviceContext->PacketPool.Next;
DeviceContext->PacketPool.Next =
&((PSINGLE_LIST_ENTRY)&Packet->Linkage)->Next;
#else
ExInterlockedPushEntryList (
&DeviceContext->PacketPool,
(PSINGLE_LIST_ENTRY)&Packet->Linkage,
&DeviceContext->Interlock);
#endif
//
// If there is a connection waiting to ship out more packets, then
// wake it up and start packetizing again.
//
// We do a quick check without the lock; there is a small
// window where we may not take someone off, but this
// window exists anyway and we assume that more packets
// will be freed in the future.
//
if (IsListEmpty (&DeviceContext->PacketWaitQueue)) {
return;
}
ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
if (!(IsListEmpty(&DeviceContext->PacketWaitQueue))) {
//
// Remove a connection from the "packet starved" queue.
//
p = RemoveHeadList (&DeviceContext->PacketWaitQueue);
Connection = CONTAINING_RECORD (p, TP_CONNECTION, PacketWaitLinkage);
Connection->OnPacketWaitQueue = FALSE;
RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
//
// If this connection is starved because it couldn't send a
// control packet (SI, SC, RO, RC, or DA) then start that
// operation up again. Otherwise, just start packetizing.
//
if (Connection->Flags & CONNECTION_FLAGS_STARVED) {
Flags = Connection->Flags & CONNECTION_FLAGS_STARVED;
if ((Flags & (Flags-1)) != 0) {
//
// More than one bit is on, use only the low one
// (an arbitrary choice).
//
#if DBG
DbgPrint ("NBF: Connection %lx has two flag bits on %lx\n", Connection, Connection->Flags);
#endif
Flags &= ~(Flags-1);
}
Connection->Flags &= ~Flags;
if ((Connection->Flags & CONNECTION_FLAGS_W_PACKETIZE) ||
(Connection->Flags & CONNECTION_FLAGS_STARVED)) {
//
// We are waiting for both a specific packet and
// to packetize, or for two specific packets, so
// put ourselves back on the queue.
//
ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
if (!Connection->OnPacketWaitQueue) {
Connection->OnPacketWaitQueue = TRUE;
InsertTailList(
&DeviceContext->PacketWaitQueue,
&Connection->PacketWaitLinkage);
}
RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
}
RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
if (Flags & CONNECTION_FLAGS_SEND_SI) {
NbfSendSessionInitialize (Connection);
} else if (Flags & CONNECTION_FLAGS_SEND_SC) {
NbfSendSessionConfirm (Connection);
} else if (Flags & CONNECTION_FLAGS_SEND_RO) {
NbfSendReceiveOutstanding (Connection);
} else if (Flags & CONNECTION_FLAGS_SEND_RC) {
NbfSendReceiveContinue (Connection);
} else if (Flags & CONNECTION_FLAGS_SEND_SE) {
NbfSendSessionEnd (
Connection,
FALSE);
} else if (Flags & CONNECTION_FLAGS_SEND_DA) {
NbfSendDataAck (Connection);
} else {
IF_NBFDBG (NBF_DEBUG_PACKET) {
NbfPrint0 ("NbfDestroyPacket: connection flags mismanaged.\n");
}
}
} else {
//
// Place the connection on the packetize queue and start
// packetizing the next connection to be serviced. If he
// is already on the packetize queue for some reason, then
// don't do this.
//
// We shouldn't be packetizing in this case!! - adb (7/3/91).
// This used to be a check that did nothing if FLAGS_PACKETIZE
// was set, but if that happens something is wrong...
//
ASSERT (Connection->Flags & CONNECTION_FLAGS_W_PACKETIZE);
Connection->Flags &= ~CONNECTION_FLAGS_W_PACKETIZE;
Connection->SendState = CONNECTION_SENDSTATE_PACKETIZE;
if ((Connection->Flags & CONNECTION_FLAGS_READY) &&
!(Connection->Flags & CONNECTION_FLAGS_PACKETIZE)) {
Connection->Flags |= CONNECTION_FLAGS_PACKETIZE;
NbfReferenceConnection ("Packet available", Connection, CREF_PACKETIZE_QUEUE);
ExInterlockedInsertTailList(
&DeviceContext->PacketizeQueue,
&Connection->PacketizeLinkage,
&DeviceContext->SpinLock);
}
RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
PacketizeConnections (DeviceContext);
}
} else {
RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
}
} /* NbfDestroyPacket */
VOID NbfGrowSendPacketPool(PDEVICE_CONTEXT DeviceContext)
{
NDIS_STATUS NdisStatus;
PNBF_POOL_LIST_DESC SendPacketPoolDesc;
PTP_PACKET TransportSendPacket;
UINT i;
if ((DeviceContext->MemoryLimit != 0) &&
((DeviceContext->MemoryUsage + DeviceContext->PacketLength) >
DeviceContext->MemoryLimit)) {
PANIC("NBF: Could not grow send packet pool: limit\n");
NbfWriteResourceErrorLog(
DeviceContext,
EVENT_TRANSPORT_RESOURCE_LIMIT,
107,
DeviceContext->PacketLength,
PACKET_RESOURCE_ID);
return;
}
for (i = 0; i < PACKET_POOL_GROW_COUNT; i += 1) {
NbfAllocateSendPacket(DeviceContext, &TransportSendPacket);
if (TransportSendPacket != NULL) {
ExInterlockedPushEntryList(&(DeviceContext)->PacketPool,
(PSINGLE_LIST_ENTRY)&TransportSendPacket->Linkage,
&(DeviceContext)->Interlock);
}
else {
break;
}
}
if (i == PACKET_POOL_GROW_COUNT) {
return;
}
#ifdef DBG
DbgBreakPoint();
#endif // DBG
}
#if DBG
VOID
NbfReferencePacket(
PTP_PACKET Packet
)
/*++
Routine Description:
This routine increases the number of reasons why a packet cannot be
discarded.
Arguments:
Packet - Pointer to a packet to be referenced.
Return Value:
none.
--*/
{
LONG result;
IF_NBFDBG (NBF_DEBUG_PACKET) {
NbfPrint3 ("NbfReferencePacket: Entered, NdisPacket: %lx Packet: %lx Ref Count: %lx.\n",
Packet->NdisPacket, Packet, Packet->ReferenceCount);
}
result = InterlockedIncrement (&Packet->ReferenceCount);
ASSERT (result >= 0);
} /* NbfReferencePacket */
VOID
NbfDereferencePacket(
PTP_PACKET Packet
)
/*++
Routine Description:
This routine dereferences a transport packet by decrementing the
reference count contained in the structure. If, after being
decremented, the reference count is zero, then this routine calls
NbfDestroyPacket to remove it from the system.
Arguments:
Packet - Pointer to a packet object.
Return Value:
none.
--*/
{
LONG result;
result = InterlockedDecrement (&Packet->ReferenceCount);
//
// If we have deleted all references to this packet, then we can
// destroy the object. It is okay to have already released the spin
// lock at this point because there is no possible way that another
// stream of execution has access to the packet any longer.
//
IF_NBFDBG (NBF_DEBUG_PACKET) {
NbfPrint1 ("NbfDereferencePacket: Entered, result: %lx\n", result);
}
ASSERT (result >= 0);
if (result == 0) {
NbfDestroyPacket (Packet);
}
} /* NbfDereferencePacket */
#endif
VOID
NbfWaitPacket(
PTP_CONNECTION Connection,
ULONG Flags
)
/*++
Routine Description:
This routine causes the specified connection to be put into a wait
state pending the availability of a packet to send the specified
frame.
Arguments:
Connection - Pointer to the connection object to be paused.
Flags - Bitflag indicating which specific frame should be resent.
Return Value:
none.
--*/
{
PDEVICE_CONTEXT DeviceContext;
IF_NBFDBG (NBF_DEBUG_PACKET) {
NbfPrint0 ("NbfWaitPacket: Entered.\n");
}
DeviceContext = Connection->Provider;
ACQUIRE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
//
// Now put this connection on the device context's PacketWaitQueue,
// but only if it isn't already queued there. This state is managed
// with the OnPacketWaitQueue variable.
//
// If the connection is stopping, don't queue him either.
//
if ((Connection->Flags & CONNECTION_FLAGS_READY) ||
(Flags == CONNECTION_FLAGS_SEND_SE)) {
ACQUIRE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
//
// Turn on the bitflag that indicates which frame we couldn't send.
//
#if DBG
if (Flags == CONNECTION_FLAGS_SEND_SE) {
DbgPrint ("NBF: Inserting connection %lx on PacketWait for SESSION_END\n", Connection);
}
#endif
Connection->Flags |= Flags;
if (!Connection->OnPacketWaitQueue) {
Connection->OnPacketWaitQueue = TRUE;
InsertTailList (
&DeviceContext->PacketWaitQueue,
&Connection->PacketWaitLinkage);
}
RELEASE_DPC_SPIN_LOCK (&DeviceContext->SpinLock);
}
RELEASE_DPC_SPIN_LOCK (Connection->LinkSpinLock);
} /* NbfWaitPacket */
#if MAGIC
VOID
NbfSendMagicBullet (
IN PDEVICE_CONTEXT DeviceContext,
IN PTP_LINK Link
)
/*++
Routine Description:
This routine sends a magic bullet on the net that can be used to trigger
sniffers or other such things.
Arguments:
DeviceContext - pointer to the device context
Link - This is needed to call NbfCreatePacket
Return Value:
none.
--*/
{
NTSTATUS Status;
NDIS_STATUS NdisStatus;
PTP_UI_FRAME RawFrame;
PUCHAR Header;
PNDIS_BUFFER NdisBuffer;
UINT i;
UNREFERENCED_PARAMETER (Link); // no longer needed
Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
if (!NT_SUCCESS (Status)) { // couldn't make frame.
#if DBG
DbgPrint ("NbfSendMagicBullet: Couldn't allocate frame!\n");
#endif
return;
}
NdisAllocateBuffer(
&NdisStatus,
&NdisBuffer,
DeviceContext->NdisBufferPool,
DeviceContext->MagicBullet,
32);
if (NdisStatus == NDIS_STATUS_SUCCESS) {
Header = (PUCHAR)&RawFrame->Header;
for (i=0;i<6;i++) {
Header[i] = MAGIC_BULLET_FOOD;
Header[i+6] = DeviceContext->LocalAddress.Address[i];
}
Header[12] = 0;
Header[13] = (UCHAR)(DeviceContext->UIFrameHeaderLength + 18);
for (i=14;i<DeviceContext->UIFrameHeaderLength;i++) {
Header[i] = MAGIC_BULLET_FOOD;
}
NdisChainBufferAtBack (RawFrame->NdisPacket, NdisBuffer);
NbfSendUIFrame (
DeviceContext,
RawFrame,
FALSE); // no loopback
}
return;
}
#endif