Newer New API 小註解

話說我們的 kernel 從 2.6.12 進版到 2.6.34 時, 網路速度似乎有點下滑. 為了瞭解這個進版對網路 driver 有什麼影響, 我發現了這個改良版的 New API – Newer New API.

原來的 New API [1] 是做啥的呢? 它是為了避免 CPU 太忙所產生的處理方式.

早期網路 driver 在收到 packet 的時候, 都會發 IRQ (interrupt request)去通知 CPU 搬 data. 隨著網路的速度愈來愈快, CPU 漸漸就沒辦法做這麼瑣碎的雜事了. 假如一個 MTU 是 1500 Bytes, 那麼, 15 Mbps 的影片就會在每秒發出 15,000,000 / (1,500 x 8) = 10000 / 8 = 1250 個中斷. [2].

只要網路流量低, 那麼 IRQ 還是可以用. 一旦網路流量超過某個界限, CPU 就改用 Polling (輪詢) 的方式去撈 data. 這就是 NAPI 的基本觀念. 由於不是看到 packet 就發 IRQ, 把更多 data 留在 buffer 裡, 也可以減低 re-order 的機會. 萬一 CPU 根本處理不了那麼多 data, 新的資料會直接覆蓋掉舊的, 不會讓 CPU 到了來不及的最後關頭才丟棄資料 [1].

在這組 API 裡面, 支援了設定網卡工作模式 (IRQ or Pollng), 進入或退出工作模式的幾個 function call.

到了 Linux 2.6.24, NAPI 的名字仍然被沿用, 但是內容已經更新了.  主要的改變分為幾點:

1. NAPI 和 net_device 不再是一對一, 一個 network device 可以支援好幾個 port, 每個 port 根據自己忙碌的程度, 決定它在哪一種工作模式.

2. 註冊輪詢的 API 異動

void netif_rx_schedule(struct net_device *dev); 

void netif_napi_add(struct net_device *dev, struct napi_struct *napi,  int (*poll)(struct napi_struct *, int), int weight)

也就是說原來可以加入輪詢的 API 多了指定獨立資料結構的 struct napi_struct *napi, 輪詢方法的  int (*poll)(struct napi_struct *, int), 也把 weight 從 dev→weight 的資料結構中拔出來明確指定.

3. 輪詢的 prototype 也改了, 不再依據 device.

int (*poll)(struct net_device *dev, int *budget); 

int (*poll)(struct napi_struct *napi, int budget); 

4.  關閉輪詢功能的 API 當然也改了, 以前是關 net_device, 現在是關某個輪詢方法. 

__netif_rx_complete(dev)

void netif_rx_complete(struct net_device *dev,  struct napi_struct *napi); 

更細微的改動我就不列了. 我好奇的是, 如果 driver 是用舊的 NAPI 寫的, 直接拿到 2.6.24 以後的版本去用, 會不會註冊不了 polling function, 只好一直發 IRQ 而導致 performance 不好呢?還是根本編不過?

今天已經快睡著又變餓了, 明天再繼續研究這個問題. 

[後記]

看了 Wireless network 的 driver, 裡面果然都是用 tasklet.

[ref]

1. New API

2. Linux网络性能优化方法简析

3. Linux kernel 2.6.24 Porting 雜記.

4. NAPI 技术在 Linux 网络驱动上的应用和完善

分類: 技術,標籤: , 。這篇內容的永久連結

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *