windows-nt/Source/XPSP1/NT/net/tcpip/driver/tcp/9x/ipr9x.c
2020-09-26 16:20:57 +08:00

228 lines
4.8 KiB
C

/*++
Copyright (c) 1999-2000 Microsoft Corporation
Module Name:
ipr9x.c
Abstract:
This file contains the implementation of IP Receive buffer
list manager. On Windows ME this is done to avoid
fragmenting the non-paged pool when receive buffers are not
pre-posted by AFVXD.
Author:
Scott Holden (sholden) 30-Apr-2000
--*/
#include "precomp.h"
#include "addr.h"
#include "tcp.h"
#include "tcb.h"
#include "tcprcv.h"
#include "tcpsend.h"
#include "tcpconn.h"
#include "tcpdeliv.h"
#include "tlcommon.h"
#include "tcpipbuf.h"
#include "pplasl.h"
#include "mdl2ndis.h"
HANDLE TcpIprDataPoolSmall = NULL;
HANDLE TcpIprDataPoolMedium = NULL;
HANDLE TcpIprDataPoolLarge = NULL;
#if DBG
ULONG TcpIprAllocs = 0;
ULONG TcpIprFrees = 0;
ULONG TcpIprAllocMisses = 0;
#endif // DBG
//
// The three buffer pool sizes are based on MTU. 576 for PPP, 1500 for ethernet,
// and 8K+ for loopback and ATM. Since for 8K buffers we really need a little
// more than 8K, we will allocate a full three pages
//
#define SMALL_TCP_IPR_BUFFER_SIZE (sizeof(IPRcvBuf) + sizeof(HANDLE) + 576)
#define MEDIUM_TCP_IPR_BUFFER_SIZE (sizeof(IPRcvBuf) + sizeof(HANDLE) + 1500)
#define LARGE_TCP_IPR_BUFFER_SIZE (3 * 4096)
//* UnInitTcpIprPools - Destroys TCP IPRcvBuffer lookaside lists.
//
// Uninitializes the lookasides lists for TCP buffered data.
//
// Input: None.
//
// Returns: None.
//
VOID
UnInitTcpIprPools(VOID)
{
PplDestroyPool(TcpIprDataPoolSmall);
PplDestroyPool(TcpIprDataPoolMedium);
PplDestroyPool(TcpIprDataPoolLarge);
}
//* InitTcpIprPools - Initializes TCP IPRcvBuffer lookaside lists.
//
// Initializes the lookaside lists for buffer data.
//
// Input: None.
//
// Returns: TRUE, if successful, else FALSE.
//
BOOLEAN
InitTcpIprPools(VOID)
{
BOOLEAN Status = TRUE;
TcpIprDataPoolSmall = PplCreatePool(NULL, NULL, 0,
SMALL_TCP_IPR_BUFFER_SIZE, 'BPCT', 512);
if (TcpIprDataPoolSmall == NULL) {
Status = FALSE;
goto done;
}
TcpIprDataPoolMedium = PplCreatePool(NULL, NULL, 0,
MEDIUM_TCP_IPR_BUFFER_SIZE, 'BPCT', 256);
if (TcpIprDataPoolMedium == NULL) {
Status = FALSE;
goto done;
}
TcpIprDataPoolLarge = PplCreatePool(NULL, NULL, 0,
LARGE_TCP_IPR_BUFFER_SIZE, 'BPCT', 64);
if (TcpIprDataPoolLarge == NULL) {
Status = FALSE;
}
done:
if (Status == FALSE) {
UnInitTcpIprPools();
}
return (Status);
}
//* AllocTcpIpr - Allocates the IPRcvBuffer from lookaside lists.
//
// A utility routine to allocate a TCP owned IPRcvBuffer. This routine
// attempts to allocate the RB from an appropriate lookaside list, el
//
// Input: BufferSize - Size of data to buffer.
//
// Returns: Pointer to allocated IPR.
//
IPRcvBuf *
AllocTcpIpr(ULONG BufferSize, ULONG Tag)
{
PCHAR Buffer;
IPRcvBuf *Ipr = NULL;
LOGICAL FromList = FALSE;
ULONG AllocateSize;
HANDLE BufferPool = NULL;
ULONG Depth;
// Real size that we need.
AllocateSize = BufferSize + sizeof(HANDLE) + sizeof(IPRcvBuf);
if (AllocateSize <= LARGE_TCP_IPR_BUFFER_SIZE) {
//
// Pick the buffer pool to allocate from.
//
if (AllocateSize <= SMALL_TCP_IPR_BUFFER_SIZE) {
BufferPool = TcpIprDataPoolSmall;
} else if (AllocateSize <= MEDIUM_TCP_IPR_BUFFER_SIZE) {
BufferPool = TcpIprDataPoolMedium;
} else {
BufferPool = TcpIprDataPoolLarge;
}
Buffer = PplAllocate(BufferPool, &FromList);
} else {
//
// Allocate from NP pool.
//
Buffer = CTEAllocMemLow(AllocateSize, Tag);
}
if (Buffer == NULL) {
goto done;
}
#if DBG
if (FromList == FALSE) {
InterlockedIncrement(&TcpIprAllocMisses);
}
#endif // DBG
// Store buffer pool so we know how to free the buffer.
*((HANDLE *)Buffer) = BufferPool;
// Get IPR.
Ipr = (IPRcvBuf *) (Buffer + sizeof(HANDLE));
// Set up IPR fields appropriately.
Ipr->ipr_owner = IPR_OWNER_TCP;
Ipr->ipr_next = NULL;
Ipr->ipr_buffer = (PCHAR) Ipr + sizeof(IPRcvBuf);
Ipr->ipr_size = BufferSize;
#if DBG
InterlockedIncrement(&TcpIprAllocs);
#endif // DBG
done:
return (Ipr);
}
//* FreeTcpIpr - Frees the IPRcvBuffer to the correct lookaside list.
//
// A utility routine to free a TCP owned IPRcvBuffer.
//
// Input: Ipr - Pointer the RB.
//
// Returns: None.
//
VOID
FreeTcpIpr(IPRcvBuf *Ipr)
{
HANDLE BufferPool;
PCHAR Buffer;
// Get real start of buffer.
Buffer = (PCHAR) Ipr - sizeof(HANDLE);
// Get the pool handle.
BufferPool = *((HANDLE *) Buffer);
if (BufferPool) {
PplFree(BufferPool, Buffer);
} else {
CTEFreeMem(Buffer);
}
#if DBG
InterlockedIncrement(&TcpIprFrees);
#endif // DBG
return;
}