Share via


Cancelando dados de rede com anéis de rede

Os drivers de cliente NetAdapterCx cancelam dados de rede quando a estrutura invoca sua função de retorno de chamada EvtPacketQueueCancel para uma fila de pacotes. Esse retorno de chamada é onde os drivers de cliente executam qualquer processamento necessário antes que a estrutura exclua as filas de pacotes.

Cancelando uma fila de transmissão

Em sua função de retorno de chamada EvtPacketQueueCancel para uma fila de transmissão, você tem a oportunidade de concluir quaisquer pacotes de transmissão pendentes. Ao contrário de uma fila de recebimento, você não precisava fazer isso. Se você deixar pacotes pendentes, NetAdapterCx chamará seu EvtPacketQueueAdvance para a fila de transmissão, em que você os processará como parte de sua operação regular.

Se o hardware der suporte ao cancelamento de transmissões em andamento, você também deverá avançar o iterador pós-pacote do anel líquido além de todos os pacotes cancelados. Isso pode se parecer com o seguinte exemplo:

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

Se o hardware não der suporte ao cancelamento, esse retorno de chamada poderá retornar sem tomar medidas.

Cancelando uma fila de recebimento

Em sua função de retorno de chamada EvtPacketQueueCancel para uma fila de recebimento, você deve concluir todos os pacotes de recebimento pendentes. Se você não retornar todos os pacotes, o sistema operacional não excluirá a fila e o NetAdapterCx deixará de chamar seus retornos de chamada para a fila.

Para retornar pacotes, primeiro você deve tentar indicar quaisquer recebimentos que possam ter sido indicados enquanto o caminho de recebimento estava sendo desabilitado e, em seguida, definir todos os pacotes a serem ignorados e retornar todos os fragmentos para o sistema operacional. Isso pode se parecer com o exemplo de código a seguir.

Observação

Este exemplo deixa de fora os detalhes para indicar recebimentos. Para obter um exemplo de código de recebimento de dados, consulte Recebendo dados de rede com anéis de rede.

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