Gestione del buffer di dati di rete
La gestione del buffer è una funzionalità che consente ai driver client della scheda di interfaccia di rete (NIC) e al sistema operativo di interagire durante l'allocazione di buffer di dati dei pacchetti dalla memoria di sistema per i percorsi di dati di trasmissione (Tx) e ricezione (Rx). Ciò può comportare prestazioni più veloci per la scheda di interfaccia di rete, una gestione della durata della memoria più semplice per il driver client della scheda di interfaccia di rete e un maggiore controllo per il sistema sulla memoria.
Vantaggi della gestione del buffer in NetAdapterCx
La scelta della posizione in cui i buffer di dati vengono allocati dalla memoria di sistema per i payload dei pacchetti è fondamentale per le prestazioni del percorso dati. In NetAdapterCx il modello di gestione del buffer è ottimizzato per l'hardware della scheda di interfaccia di rete con supporto DMA e il modo migliore per consentire ai driver client di sfruttarne i vantaggi consiste nel consentire al sistema di allocare buffer di dati per conto dei percorsi Tx e Rx. Tuttavia, i driver client possono comunque influenzare la posizione e il modo in cui il sistema alloca i buffer di dati in modo che possano essere facilmente utilizzati dall'hardware del client.
Si consideri una tipica scheda di interfaccia di rete con supporto per DMA, ad esempio. Questo approccio offre vantaggi utili:
- I buffer di dati vengono allocati e liberati dal sistema. Pertanto, il driver client viene liberato dal carico di gestione della durata della memoria.
- Il sistema assicura che i buffer di dati allocati siano pronti per DMA per l'hardware NIC in base alle funzionalità dichiarate dal driver client. Quindi, il driver client può semplicemente programmare i buffer di dati nel proprio hardware così come è senza eseguire altre operazioni di mapping DMA.
- Il sistema può prendere in considerazione le esigenze delle applicazioni di livello superiore durante l'allocazione dei buffer di dati, in modo da poter decidere di ottimizzare le prestazioni end-to-end globali anziché solo le prestazioni end-to-end locali.
Per le schede di interfaccia di rete non compatibili con DMA come un dongle di rete basato su USB o per altre schede di interfaccia di rete avanzate/software, il modello di gestione del buffer offre anche un'opzione per lasciare completamente la gestione del buffer dei dati al driver client.
Come sfruttare la gestione del buffer
Importante
Se l'hardware è in grado di supportare DMA, è necessario creare un oggetto WDFDMAENABLER prima di impostare le funzionalità Rx e Tx. Quando si configura l'oggetto WDFDMAENABLER con la struttura WDF_DMA_ENABLER_CONFIG , assicurarsi di impostare il membro WdmDmaVersionOverride su 3 per specificare DMA versione 3.
Per acconsentire esplicitamente alla gestione del buffer, seguire questa procedura:
- Quando si avvia la scheda net, ma prima di chiamare NetAdapterStart, comunicare al sistema le funzionalità e i vincoli del buffer dei dati dell'hardware usando rispettivamente la struttura di dati NET_ADAPTER_RX_CAPABILITIES e NET_ADAPTER_TX_CAPABILITIES per il percorso Rx e Tx.
- Inizializzare le due strutture di funzionalità chiamando una delle funzioni di inizializzazione. Ad esempio, un driver client NIC con supporto per DMA userà NET_ADAPTER_TX_CAPABILITIES_INIT_FOR_DMA e NET_ADAPTER_RX_CAPABILITIES_INIT_SYSTEM_MANAGED_DMA per dichiarare le relative capablità DMA hardware e per indicare al sistema di gestire completamente i buffer di dati per suo conto.
- Passare le strutture delle funzionalità Tx e Rx inizializzate al metodo NetAdapterSetDatapathCapabilities.
Esempio
L'esempio seguente illustra i passaggi di base descritti nella sezione precedente per iniziare a usare gestione buffer nel driver client della scheda di interfaccia di rete. L'esempio usa DMA sia per Tx che per Rx, quindi in precedenza ha creato un oggetto WDFDMAENABLER archiviato nello spazio di contesto del dispositivo.
Si noti che l'esempio imposta anche alcuni suggerimenti sui buffer di frammenti dopo l'inizializzazione delle strutture delle funzionalità Tx e Rx. Questi hint possono essere usati da NetAdapterCx e driver di protocollo per migliorare le prestazioni.
La gestione degli errori è stata interrotta per maggiore chiarezza.
VOID
MyAdapterSetDatapathCapabilities(
_In_ NETADAPTER Adapter
)
{
// Get the device context
PMY_DEVICE_CONTEXT deviceContext = GetMyContextFromDevice(Adapter);
// Set various capabilities such as link layer MTU size, link layer capabilities, and power capabilities
...
// Initialize the Tx DMA capabilities structure
NET_ADAPTER_DMA_CAPABILITIES txDmaCapabilities;
NET_ADAPTER_DMA_CAPABILITIES_INIT(&txDmaCapabilities,
deviceContext->dmaEnabler);
// Set Tx capabilities
NET_ADAPTER_TX_CAPABILITIES txCapabilities;
NET_ADAPTER_TX_CAPABILITIES_INIT_FOR_DMA(&txCapabilities,
&txDmaCapabilities,
1);
txCapabilities.FragmentRingNumberOfElementsHint = deviceContext->NumTransmitControlBlocks * MAX_PHYS_BUF_COUNT;
txCapabilities.MaximumNumberOfFragments = MAX_PHYS_BUF_COUNT;
// Initialize the Rx DMA capabilities structure
NET_ADAPTER_DMA_CAPABILITIES rxDmaCapabilities;
NET_ADAPTER_DMA_CAPABILITIES_INIT(&rxDmaCapabilities,
deviceContext->dmaEnabler);
// Set Rx capabilities
NET_ADAPTER_RX_CAPABILITIES rxCapabilities;
NET_ADAPTER_RX_CAPABILITIES_INIT_SYSTEM_MANAGED_DMA(&rxCapabilities,
&rxDmaCapabilities,
MAX_PACKET_SIZE + FRAME_CRC_SIZE + RSVD_BUF_SIZE,
1);
rxCapabilities.FragmentBufferAlignment = 64;
rxCapabilities.FragmentRingNumberOfElementsHint = deviceContext->NumReceiveBuffers;
// Set the adapter's datapath capabilities
NetAdapterSetDatapathCapabilities(Adapter,
&txCapabilities,
&rxCapabilities);
}