driver: use IoAllocateMdl without being too clever
Windows 7 doesn't like our trick of sticking MDLs into the NBL context area. So we do things more traditionally, by allocating an MDL with IoAllocateMdl and freeing it with IoFreeMdl. This means that we have to keep track of the MDL between allocation and free time, and we don't have any more miniport reserved pointers left in the NBL. So instead we walk the MdlChain field of the first NB, and free the one that has an address living inside of the non-partial MDL. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
1269f86c76
commit
b2374dadb6
@ -412,6 +412,16 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net
|
|||||||
KeSetEvent(&Ctx->Device.Receive.ActiveNbls.Empty, IO_NO_INCREMENT, FALSE);
|
KeSetEvent(&Ctx->Device.Receive.ActiveNbls.Empty, IO_NO_INCREMENT, FALSE);
|
||||||
KeReleaseInStackQueuedSpinLock(&LockHandle);
|
KeReleaseInStackQueuedSpinLock(&LockHandle);
|
||||||
WriteULongRelease(&Ring->Head, TunNblGetOffset(CompletedNbl));
|
WriteULongRelease(&Ring->Head, TunNblGetOffset(CompletedNbl));
|
||||||
|
const MDL *TargetMdl = Ctx->Device.Receive.Mdl;
|
||||||
|
for (MDL *Mdl = NET_BUFFER_FIRST_MDL(NET_BUFFER_LIST_FIRST_NB(CompletedNbl)); Mdl; Mdl = Mdl->Next)
|
||||||
|
{
|
||||||
|
if (MmGetMdlVirtualAddress(Mdl) < MmGetMdlVirtualAddress(TargetMdl) ||
|
||||||
|
(UCHAR *)MmGetMdlVirtualAddress(Mdl) + MmGetMdlByteCount(Mdl) >
|
||||||
|
(UCHAR *)MmGetMdlVirtualAddress(TargetMdl) + MmGetMdlByteCount(TargetMdl))
|
||||||
|
continue;
|
||||||
|
IoFreeMdl(Mdl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
NdisFreeNetBufferList(CompletedNbl);
|
NdisFreeNetBufferList(CompletedNbl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -507,20 +517,17 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
RingHead = TUN_RING_WRAP(RingHead + AlignedPacketSize, RingCapacity);
|
RingHead = TUN_RING_WRAP(RingHead + AlignedPacketSize, RingCapacity);
|
||||||
MDL *Mdl;
|
MDL *Mdl = IoAllocateMdl(NULL, PacketSize, FALSE, FALSE, NULL);
|
||||||
NET_BUFFER_LIST *Nbl = NdisAllocateNetBufferAndNetBufferList(Ctx->NblPool, sizeof(*Mdl), 0, NULL, 0, 0);
|
if (!Mdl)
|
||||||
if (!Nbl)
|
|
||||||
goto skipNbl;
|
goto skipNbl;
|
||||||
Mdl = (MDL *)NET_BUFFER_LIST_CONTEXT_DATA_START(Nbl);
|
|
||||||
IoBuildPartialMdl(
|
IoBuildPartialMdl(
|
||||||
Ctx->Device.Receive.Mdl,
|
Ctx->Device.Receive.Mdl,
|
||||||
Mdl,
|
Mdl,
|
||||||
(UCHAR *)MmGetMdlVirtualAddress(Ctx->Device.Receive.Mdl) + (ULONG)(Packet->Data - (UCHAR *)Ring),
|
(UCHAR *)MmGetMdlVirtualAddress(Ctx->Device.Receive.Mdl) + (ULONG)(Packet->Data - (UCHAR *)Ring),
|
||||||
PacketSize);
|
PacketSize);
|
||||||
NET_BUFFER *Nb = NET_BUFFER_LIST_FIRST_NB(Nbl);
|
NET_BUFFER_LIST *Nbl = NdisAllocateNetBufferAndNetBufferList(Ctx->NblPool, 0, 0, Mdl, 0, PacketSize);
|
||||||
NET_BUFFER_FIRST_MDL(Nb) = NET_BUFFER_CURRENT_MDL(Nb) = Mdl;
|
if (!Nbl)
|
||||||
NET_BUFFER_DATA_LENGTH(Nb) = PacketSize;
|
goto cleanupMdl;
|
||||||
NET_BUFFER_DATA_OFFSET(Nb) = NET_BUFFER_CURRENT_MDL_OFFSET(Nb) = 0;
|
|
||||||
Nbl->SourceHandle = Ctx->MiniportAdapterHandle;
|
Nbl->SourceHandle = Ctx->MiniportAdapterHandle;
|
||||||
NdisSetNblFlag(Nbl, NblFlags);
|
NdisSetNblFlag(Nbl, NblFlags);
|
||||||
NET_BUFFER_LIST_INFO(Nbl, NetBufferListFrameType) = (PVOID)NblProto;
|
NET_BUFFER_LIST_INFO(Nbl, NetBufferListFrameType) = (PVOID)NblProto;
|
||||||
@ -556,6 +563,8 @@ TunProcessReceiveData(_Inout_ TUN_CTX *Ctx)
|
|||||||
cleanupNbl:
|
cleanupNbl:
|
||||||
ExReleaseSpinLockShared(&Ctx->TransitionLock, Irql);
|
ExReleaseSpinLockShared(&Ctx->TransitionLock, Irql);
|
||||||
NdisFreeNetBufferList(Nbl);
|
NdisFreeNetBufferList(Nbl);
|
||||||
|
cleanupMdl:
|
||||||
|
IoFreeMdl(Mdl);
|
||||||
skipNbl:
|
skipNbl:
|
||||||
InterlockedIncrementNoFence64((LONG64 *)&Ctx->Statistics.ifInDiscards);
|
InterlockedIncrementNoFence64((LONG64 *)&Ctx->Statistics.ifInDiscards);
|
||||||
KeWaitForSingleObject(&Ctx->Device.Receive.ActiveNbls.Empty, Executive, KernelMode, FALSE, NULL);
|
KeWaitForSingleObject(&Ctx->Device.Receive.ActiveNbls.Empty, Executive, KernelMode, FALSE, NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user