NAPI vs Interrupt adattativi


12

Qualcuno potrebbe spiegare come vengono utilizzate due seguenti tecnologie per mitigare l'overhead di interrupt con un carico di rete elevato?

  1. Adaptive-rx / Adaptive-tx e
  2. NAPI;

Gradirei una risposta che spieghi la differenza più vicina al livello dei sorgenti del kernel Linux? Inoltre vorrei sapere come forzare la scheda di rete a polling / interrompere la modalità coalescenza a carico che è ~ 400 Mbps.

Più sfondo:

Il problema sembra essere che i driver bnx2 ed e1000 ignorano il comando "ethtool -C adaptive-rx on". Ciò è probabilmente dovuto al fatto che tali driver non supportano gli interrupt adattivi. Anche se il manuale di riferimento del programmatore Broadcom afferma che questa funzione dovrebbe essere supportata dall'hardware NIC BCM5709.

Così ho deciso di provare NAPI e ridurre il peso da 64 a 16 nella chiamata di funzione netif_napi_add () per forzare la scheda NIC in modalità polling con un carico molto più basso, ma sfortunatamente non ha funzionato. Immagino che NAPI non abbia bisogno di alcun supporto hardware speciale in NIC, è corretto?

L'hardware che sto usando è BCN5709 NIC (utilizza driver bnx2). E il sistema operativo è Ubuntu 10.04. La CPU è XEON 5620.

Risposte:


18

Il principio principale alla base della moderazione degli interrupt è generare meno di un interrupt per frame ricevuto (o un interrupt per completamento del frame di trasmissione), riducendo il sovraccarico del sistema operativo rilevato durante la manutenzione degli interrupt. Il controller BCM5709 supporta un paio di metodi nell'hardware per interruzioni di coalescenza, tra cui:

  • Genera un interrupt dopo aver ricevuto X frame (rx-frames in ethtool)
  • Genera un interrupt quando non si ricevono più frame dopo X usecs (rx-usecs in ethtool)

Il problema con l'utilizzo di questi metodi hardware è che è necessario selezionarli per ottimizzare la velocità effettiva o la latenza, non è possibile avere entrambi. La generazione di un interrupt per ciascun frame ricevuto (rx-frame = 1) riduce al minimo la latenza, ma lo fa a un costo elevato in termini di sovraccarico del servizio di interrupt. L'impostazione di un valore più grande (ad esempio rx-frame = 10) riduce il numero di cicli della CPU consumati generando un solo interrupt per ogni dieci frame ricevuti, ma si verificherà anche una latenza più elevata per i primi frame in quel gruppo di dieci.

L'implementazione NAPI tenta di sfruttare il fatto che il traffico arriva in gruppi, in modo da generare immediatamente un interrupt sul primo frame ricevuto, quindi passare immediatamente alla modalità polling (ovvero disabilitare gli interrupt) perché più traffico sarà chiuso dietro. Dopo aver eseguito il polling per un numero di frame (16 o 64 nella tua domanda) o un intervallo di tempo, il driver riattiverà gli interrupt e ricomincerà da capo.

Se si dispone di un carico di lavoro prevedibile, è possibile selezionare valori fissi per uno dei precedenti (NAPI, rx-frame, rx-usecs) che offrono il giusto compromesso, ma la maggior parte dei carichi di lavoro varia e si finisce per fare alcuni sacrifici. È qui che entrano in gioco adaptive-rx / adaptive-tx. L'idea è che il driver monitora costantemente il carico di lavoro (frame ricevuti al secondo, dimensione dei frame, ecc.) E sintonizza lo schema di coalescenza di interruzione hardware per ottimizzare la latenza in situazioni di traffico ridotto o ottimizzare il throughput in situazioni di traffico elevato. È una teoria interessante, ma può essere difficile da implementare nella pratica. Solo pochi driver lo implementano (vedi http://fxr.watson.org/fxr/search?v=linux-2.6&string=use_adaptive_rx_coalesce ) e i driver bnx2 / e1000 non sono in quella lista.

Per una buona descrizione di come dovrebbe funzionare ciascun campo di coalescenza di ethtool, dai un'occhiata alle definizioni per la struttura ethtool_coalesce al seguente indirizzo:

http://fxr.watson.org/fxr/source/include/linux/ethtool.h?v=linux-2.6#L111

Per la tua particolare situazione (throughput di ~ 400Mb / s), suggerirei di ottimizzare i valori dei frame rx e dei valori rx-usecs per le migliori impostazioni per il tuo carico di lavoro. Osserva sia l'overhead dell'ISR sia la sensibilità della tua applicazione (httpd? Ecc.) Alla latenza.

Dave


1
Hai detto che "L' implementazione NAPI tenta di sfruttare il fatto che il traffico arriva in gruppi, in modo da generare immediatamente un interrupt sul primo frame ricevuto , quindi passare immediatamente alla modalità polling ". Ma nel wiki ha detto che NAPI non usa mai interrupt di processo, ma esegue il polling ogni determinato periodo di tempo : en.wikipedia.org/wiki/New_API Citazione esatta: "Il kernel può controllare periodicamente l'arrivo dei pacchetti di rete in arrivo senza essere interrotto , che elimina il sovraccarico dell'elaborazione degli interrupt. " Dov'è la verità?
Alex,

1
@Alex Gli interrupt di processo devono essere utilizzati per comunicare al kernel che c'è traffico da ricevere. Un gestore di interrupt "vecchio stile" pianifica la ricezione del pacchetto, quindi riattiva gli interrupt. Un gestore di interrupt NAPI disabilita gli interrupt, pianifica un poller e riattiva gli interrupt. Il poller esegue la ricezione dei pacchetti per un determinato numero di pacchetti e finché il traffico è attivo per il servizio, il poller continua a funzionare, con l'obiettivo di prevenire interruzioni improvvise, allontanando sempre il traffico dalla scheda di rete. Quando il traffico si interrompe, il poller esce e il sistema torna in attesa di un interrupt.
suprjami,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.