Отмена сетевых данных с помощью сетевых кругов

Клиентские драйверы NetAdapterCx отменяют сетевые данные, когда платформа вызывает функцию обратного вызова EvtPacketQueueCancel для очереди пакетов. Этот обратный вызов позволяет клиентским драйверам выполнять любую обработку, необходимую перед удалением платформой очередей пакетов.

Отмена очереди передачи

В функции обратного вызова 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 перестает вызывать обратные вызовы для очереди.

Чтобы вернуть пакеты, необходимо сначала попытаться указать все получаемые сообщения, которые могли быть указаны при отключении пути получения, а затем задать все пакеты, которые будут игнорироваться, и вернуть все фрагменты в ОС. Это может выглядеть, как в следующем примере кода.

Примечание

В этом примере не указаны сведения о получении. Пример кода получения данных см. в разделе Получение сетевых данных с помощью сетевых кругов.

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;
}