首頁 > 軟體

Linux核心的netpoll框架與netconsole

2020-06-16 18:00:23

雖然和網路相關,但是它卻不是網路協定棧的一部分,這就是netpoll。

它只是一個出入口的處理框架。所謂的網路,它的終端節點就是主機,資料從主機的網絡卡發出,經過一個出口處理過程,網絡卡接收到一個封包,經過一個入口處理過程,這一出一入的過程處理分為兩種方式:

1.中斷的方式

出口處理過程-資料排入傳送佇列,讀取特定暫存器值,待網絡卡狀態適合傳送式,傳送,等待傳送後的中斷通知,繼續。

入口處理過程-資料被網絡卡收到,網絡卡中斷CPU,CPU進而處理資料接收的過程。

網路協定棧下接的就是這種中斷的出入口處理方式。

2.poll的方式

出口處理過程-資料排入傳送佇列,讀取特定暫存器值,待網絡卡狀態適合傳送式,傳送,不等待傳送後的中斷通知,繼續讀取暫存器以及根據佇列情況權衡是否適合傳送。

入口處理過程-資料被網絡卡收到,等待poll邏輯在適當的時候去主動poll網絡卡,若有資料,則將其從特定的網絡卡快取讀出。

Linux netpoll就是利用的這種方式。這種方式完全不依賴中斷。

事實總是比說起來更麻煩。

要講清楚這個有點混亂的主題,不得不引入第三種出入口處理方式,那就是中斷和poll結合的方式,這就是NAPI方式。我把三種方式的圖示先給出:

a.中斷方式

b.poll方式

c.NAPI方式

理解了這個,剩下的就都理解了。至於為何會有NAPI,在本文中只能簡單說一句:在高速高頻寬網路中,封包持續到來,每一個包中斷一次CPU的話,CPU有點吃不消,反而耽誤了CPU處理這些封包,如果之前的封包還沒有處理完,最好的辦法就是將封包排入一個佇列,然後沉默,不要打擾CPU,等CPU空下來的時候,自己去poll這些佇列裡面的封包,這就是NAPI。

純中斷的方式我們都很熟悉,也是最直接的方式。然而為何要有純poll的方式呢?使用純poll的場合在中斷完全不起作用的情況下。舉一個例子,系統panic之後。此時中斷控制器將可能被disable掉,無論如何,此時的機器已經和外界失聯了,然而如果此時必須需要一個方式對外界通告自己的死因的話,這種netpoll的方式就派上用場了,因為它是純手工的,完全不依賴系統的中斷機制。另外一種場合比panic好一些,那就是協定棧故障,如果使用中斷或者NAPI的方式,由於它上接的就是協定棧,netif_receive_skb中又沒有什麼HOOK點,此時使用netpoll可以改變封包的處理路徑,通過一個agent可以實現遠端debug。

不要把中斷想象的太神秘。它無非也就是一個通知機制,告訴CPU,現在請查詢我的狀態,該幹啥就幹啥。事實上,當CPU收到網絡卡中斷的時候,它也不知道該幹啥,它只會呼叫中斷處理常式,其內部會去讀取一寫暫存器的狀態,然後才能知道現在該幹什麼,比如可以傳送封包,比如收到一個封包等。既然如此,即使在關中斷的情形下,如果不依靠中斷,CPU擇機主動呼叫一下網絡卡的中斷處理常式,讀取一寫暫存器的狀態,是不是也能知道該幹什麼呢?答案當然是肯定的了!這就是netpoll的邏輯,它使用兩步完成任務:

1.主動呼叫網絡卡的中斷處理常式,獲取當前該傳送封包還是接收到一個封包;

2.直接hard_xmit封包或者使用NAPI的介面去poll網絡卡的資料。

Linux netpoll的總體圖示如下:

這個圖示中附帶了netconsole的原理,沒想到他是如此的簡單。我記得我曾經寫過一個模組,將panic後的資訊發到遠端,這個是受到了一個xtables-addons模組的啟發,起初失敗了,但是最後我仔細debug了核心程式碼後,成功了。在成功的過程中,發現了很多以前不知道的東西。但是現在看看netconsole吧,它什麼複雜的東西都不需要,只需要兩步:

1.註冊一個console,此後核心buffer的資訊就會發到這個console;

2.該console下接netpoll的netpoll_send_skb,此後由netpoll邏輯來處理。

即便在panic後,中斷已經被關了,甚至中斷控制器都關閉的情況下,只要網絡卡沒有進水,資料依然可以收發,它完全不依賴中斷和協定棧。這簡直太棒了!關於netconsole,我寫多少都不如核心的Document來的好:$kernel/Documentation/networking/netconsole.txt.

netpoll是Linux核心中的一種在協定棧不可用或者中斷機制異常的情況下與外界通訊的手段,當然它也是一種繞開協定棧的方法。這個位置足夠底層,寫出來的東西也肯定比基於Netfilter的更好玩。Netfilter是在協定棧的特殊點捕獲封包的,而netpoll卻可以在網絡卡之上直接捕獲封包,它們甚至連協定棧的最底端都到不了。以後,如果想在核心態直接發包,再也不用PACKET通訊端從使用者態開始了,構造一個封包,直接通過netpoll介面發出。問題是,它採用手工觸發中斷處理常式的方式,效率如何待測試。因此這種機制最好還是限制於偵錯和少量核心審計資訊的傳送吧。用它做VPN,我覺得懸...

本文永久更新連結地址http://www.linuxidc.com/Linux/2015-05/117637.htm


IT145.com E-mail:sddin#qq.com