使用网环取消网络数据

当框架为数据包队列调用其 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;
}