使用网环取消网络数据
当框架为数据包队列调用其 EvtPacketQueueCancel 回调函数时,NetAdapterCx 客户端驱动程序会取消网络数据。 在此回调中,客户端驱动程序在框架删除数据包队列之前执行所需的任何处理。
取消传输队列
在传输队列的 EvtPacketQueueCancel 回调函数中,你有机会完成任何未完成的传输数据包。 与接收队列不同,不需要这样做。 如果保留未完成的数据包,NetAdapterCx 会为传输队列调用 EvtPacketQueueAdvance ,你可以在其中将其作为常规操作的一部分进行处理。
如果硬件支持取消正在进行的传输,则还应将网络环的后数据包迭代器推进到所有取消的数据包之后。 这可能如以下示例所示:
void
MyEvtTxQueueCancel(
NETPACKETQUEUE TxQueue
)
{
// Get the transmit queue's context to retrieve the net ring collection
PMY_TX_QUEUE_CONTEXT txQueueContext = MyGetTxQueueContext(TxQueue);
NET_RING_COLLECTION const * ringCollection = txQueueContext->RingCollection;
NET_RING * packetRing = ringCollection->Rings[NET_RING_TYPE_PACKET];
UINT32 currentPacketIndex = packetRing->BeginIndex;
UINT32 packetEndIndex = packetRing->EndIndex;
while (currentPacketIndex != packetEndIndex)
{
// Mark this packet as canceled with the scratch field, then move past it
NET_PACKET * packet = NetRingGetPacketAtIndex(packetRing, currentPacketIndex);
packet->Scratch = 1;
currentPacketIndex = NetRingIncrementIndex(packetRing, currentPacketIndex);
}
packetRing->BeginIndex = packetRing->EndIndex;
}
如果硬件不支持取消,则无需执行操作即可返回此回调。
取消接收队列
在接收队列的 EvtPacketQueueCancel 回调函数中,必须完成任何未完成的接收数据包。 如果未返回所有数据包,则操作系统不会删除队列,NetAdapterCx 会停止为队列调用回调。
若要返回数据包,应首先尝试指示禁用接收路径时可能已指示的任何接收,然后将所有数据包设置为忽略,并将所有片段返回到 OS。 这可能类似于下面的代码示例。
注意
此示例遗漏了指示接收的详细信息。 有关接收数据的代码示例,请参阅 使用 Net Ring 接收网络数据。
void
MyEvtRxQueueCancel(
NETPACKETQUEUE RxQueue
)
{
// Get the receive queue's context to retrieve the net ring collection
PMY_RX_QUEUE_CONTEXT rxQueueContext = MyGetRxQueueContext(RxQueue);
NET_RING_COLLECTION const * ringCollection = rxQueueContext->RingCollection;
NET_RING * packetRing = ringCollection->Rings[NET_RING_TYPE_PACKET];
NET_RING * fragmentRing = ringCollection->Rings[NET_RING_TYPE_FRAGMENT];
UINT32 currentPacketIndex = packetRing->BeginIndex;
UINT32 packetEndIndex = packetRing->EndIndex;
// Set hardware register for cancellation
...
//
// Indicate receives
...
//
// Get all packets and mark them for ignoring
currentPacketIndex = packetRing->BeginIndex;
while(currentPacketIndex != packetEndIndex)
{
NET_PACKET * packet = NetRingGetPacketAtIndex(packetRing, currentPacketIndex);
packet->Ignore = 1;
currentPacketIndex = NetRingIncrementIndex(packetRing, currentPacketIndex);
}
packetRing->BeginIndex = packetRing->EndIndex;
// Return all fragments to the OS
fragmentRing->BeginIndex = fragmentRing->EndIndex;
}