天天看點

網絡收包流程-封包從網卡驅動到網絡層(或者網橋)的流程(非NAPI、NAPI)(一)

1.上圖(網上的沒我這個詳細,哈哈):

網絡收包流程-封包從網卡驅動到網絡層(或者網橋)的流程(非NAPI、NAPI)(一)

2.具體說明NAPI和非NAPI的差別:

(1) 支援NAPI的網卡驅動必須提供輪詢方法poll()。

(2) 非NAPI的核心接口為netif_rx(),NAPI的核心接口為napi_schedule()。

(3) 非NAPI使用共享的CPU隊列softnet_data->input_pkt_queue,NAPI使用裝置記憶體(或者裝置驅動程式的接收環)。

net_rx函數的作用:

    a.為skb配置設定記憶體

    b.從網卡copy記憶體到skb空間

netif_rx的作用:

     a.将net_rx從網卡擷取的skb,放到目前cpu的softnet_data公共等待隊列input_pkt_queue,即enqueue_to_backlog-->__skb_queue_tail(&sd->input_pkt_queue, skb);

     b.将process_backlog加入到目前cpu的softnet_data的poll_list中,即enqueue_to_backlog-->____napi_schedule->list_add_tail(&napi->poll_list, &sd->poll_list);

     c.觸發軟中斷,即__raise_softirq_irqoff(NET_RX_SOFTIRQ);

napi_schedule的作用:

     a.将特定于硬體的poll_list加入到目前cpu的softnet_data的poll_list(container_of函數即可通過poll_list獲得對應的napi_struct結構體,進而可以獲得poll函數)

     b.觸發軟中斷,即__raise_softirq_irqoff(NET_RX_SOFTIRQ);

         注意:NAPI方式的skb直接從裝置記憶體獲得,不用自己維護記憶體

3.中斷方式與NAPI的結合:

             NAPI 的核心在于:在一個繁忙網絡,每次有網絡資料包到達時,不需要都引發中斷,因為高頻率的中斷可能會影響系統的整體效率,假象一個場景,我們此時使用标準的 100M 網卡,可能實際達到的接收速率為 80MBits/s,而此時資料包平均長度為 1500Bytes,則每秒産生的中斷數目為:

                                80M bits/s / (8  * 1500 Byte) = (80 * 1024 * 1024) bit/s / (8  * 1500 Byte) = 6990 個中斷 /s

           每秒6990個中斷,對于系統是個很大的壓力,此時其實可以轉為使用輪詢 (polling) 來處理,而不是中斷;但輪詢在網絡流量較小的時沒有效率,是以低流量時,基于中斷的方式則比較合适,這就是 NAPI 出現的原因,在低流量時候使用中斷接收資料包,而在高流量時候則使用基于輪詢的方式接收。

4.NAPI方式的優勢:NAPI 适合處理高速率資料包的處理,而帶來的好處則是:

     1.中斷緩和 (Interrupt mitigation),由上面的例子可以看到,在高流量下,網卡産生的中斷可能達到每秒幾千次,而如果每次中斷都需要系統來處理,是一個很大的壓力,而 NAPI 使用輪詢時是禁止了網卡的接收中斷的,這樣會減小系統進行中斷的壓力。

     2.資料包節流 (Packet throttling),NAPI 之前的 Linux NIC 驅動總在接收到資料包之後産生一個 IRQ,接着在中斷服務例程裡将這個 skb 加入本地的 softnet_data,然後觸發本地 NET_RX_SOFTIRQ 軟中斷後續處理。如果包速過高,因為 IRQ 的優先級高于 SoftIRQ,導緻系統的大部分資源都在響應中斷,但 softnet 的隊列大小有限,接收到的超額資料包也隻能丢掉,是以這時這個模型是在用寶貴的系統資源做無用功。而 NAPI 則在這樣的情況下,直接把包丢掉,不會繼續将需要丢掉的資料包扔給核心去處理,這樣,網卡将需要丢掉的資料包盡可能的早丢棄掉,核心将不可見需要丢掉的資料包,這樣也減少了核心的壓力。

5.NAPI的實作原理:

        假定某個網絡擴充卡此前沒有分組到達,但從現在開始,分組将以高頻率頻繁到達。這就是NAPI裝置的情況,如下所述。

(1) 第一個分組将導緻網絡擴充卡發出IRQ。為防止進一步的分組導緻發出更多的IRQ,驅動程式會在硬中斷處理流程中關閉該擴充卡的Rx IRQ。并将該擴充卡放置到一個輪詢表上。

(2) 隻要擴充卡上還有分組需要處理,核心就一直對輪詢表上的裝置進行輪詢。

(3) 重新啟用Rx中斷。

        如果在新的分組到達時,舊的分組仍然處于處理過程中,工作不會因額外的中斷而減速。雖然對裝置驅動程式(和一般意義上的核心代碼)來說輪詢通常是一個很差的方法,但在這裡該方法沒有什麼不利之處:在沒有分組還需要處理時,将停止輪詢,裝置将回複到通常的IRQ驅動的運作方式。在沒有中斷支援的情況下,輪詢空的接收隊列将不必要地浪費時間,但NAPI并非如此。

        NAPI的另一個優點是可以高效地丢棄分組。如果核心确信因為有很多其他工作需要處理,而導緻無法處理任何新的分組,那麼網絡擴充卡可以直接丢棄分組,無須複制到核心。

隻有裝置滿足如下兩個條件時,才能實作NAPI方法。

(1) 裝置必須能夠保留多個接收的分組,例如儲存到DMA環形緩沖區中。下文将該緩沖區稱為Rx緩沖區。

(2) 該裝置必須能夠禁用用于分組接收的IRQ。而且,發送分組或其他可能通過IRQ進行的操作,都仍然必須是啟用的。

       如果系統中有多個裝置,會怎麼樣呢?這是通過循環輪詢各個裝置來解決的。

網絡收包流程-封包從網卡驅動到網絡層(或者網橋)的流程(非NAPI、NAPI)(一)

6.具體網卡的舉例說明:

網絡收包流程-封包從網卡驅動到網絡層(或者網橋)的流程(非NAPI、NAPI)(一)

繼續閱讀