我正在编写Windows过滤平台内核模式驱动程序,该驱动程序的目标是捕获特定层上的所有流量,并将此流量传回用户模式,以便进行进一步分析。驱动程序永远不需要阻止任何流量,classifyOut始终设置为FWP_ACTION_CONTINUE
。
我的Classify函数使用以下代码对接收的数据包进行排队。
classifyOut->actionType = FWP_ACTION_CONTINUE;
do
{
if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
{
break;
}
if (layerData != NULL)
{
PNET_BUFFER_LIST netBufferList = (PNET_BUFFER_LIST) layerData;
PNET_BUFFER netBuffer = NET_BUFFER_LIST_FIRST_NB(netBufferList);
if (packetQueueSize >= 2048)
{
ExInterlockedRemoveHeadList(&packetQueue, &packetQueueLock);
packetQueueSize--;
}
ULONG netBufferSize = NET_BUFFER_DATA_LENGTH(netBuffer);
PACKET_ITEM* allocatedPacket = InitalizePacketItem(
netBuffer,
netBufferSize
);
if (allocatedPacket == NULL)
{
classifyOut->actionType = FWP_ACTION_BLOCK;
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
break;
}
ExInterlockedInsertTailList(
&packetQueue,
&allocatedPacket->listEntry,
&packetQueueLock
);
allocatedPacket = NULL;
packetQueueSize++;
}
} while (FALSE);
PACKET_ITEM
结构定义如下
typedef struct _PACKET_ITEM { LIST_ENTRY listEntry; PVOID data; ULONG dataLen; } PACKET_ITEM;
我正在使用反向调用模型将此数据包数据从内核模式传递到用户模式。一旦检测到已发送正确的IOCTL,就会在内核驱动程序中使用以下代码。
status = WdfRequestRetrieveOutputBuffer(request, 0, &buffer, &bufferSize);
if (!NT_SUCCESS(status))
{
break;
}
PLIST_ENTRY listEntry = ExInterlockedRemoveHeadList(&packetQueue, &packetQueueLock);
if (listEntry == NULL)
{
break;
}
PACKET_ITEM* packetItem = CONTAINING_RECORD(
listEntry,
struct _PACKET_ITEM,
listEntry
);
RtlCopyMemory(
buffer,
packetItem->data,
packetItem->dataLen);
status = STATUS_SUCCESS;
WdfRequestCompleteWithInformation(
request,
status,
packetItem->dataLen
);
FreePacketItem(packetItem);
此代码似乎会在一段时间后大幅减慢网络速度,例如在尝试在网络浏览器中加载网站时会导致超时。
我认为这是由自旋锁和通过网络传输的大量数据包引起的,这些数据包是由此驱动程序捕获的。
我的问题如下
classifyOut->actionType
并在分配任何内存之前返回此值以将数据复制到我的队列中。我认为这可以防止发生减速?