1. 程式人生 > >netback的tasklet排程問題及網絡卡丟包的簡單分析

netback的tasklet排程問題及網絡卡丟包的簡單分析

最近在萬兆網絡卡上測試,出現了之前千兆網絡卡沒有出現的一個現象,tasklet版本的netback下,vm進行發包測試,發現vif的interrupt預設繫結在cpu0上,但是vm發包執行時發現host上面cpu1, cpu2的ksoftirqd很高。

從之前的理解上來說,包從netfront出來通過eventchannel notify觸發vif的irq處理函式,然後tasklet_schedule呼叫tx_action,通過一系列處理流程把包發給網絡卡。所以vif的interrupt綁在哪個cpu上,發包的時候,那個cpu的si%高才對。

仔細檢視tasklet的程式碼發現,除了interrupt處理函式裡面會呼叫tasklet_schedule之外,還有一個地方會呼叫,就是netif_idx_release, 這個是配合grant map使用的一個回撥函式。當skb從網絡卡發出之後,kfree_skb時候,會呼叫page註冊的一個回撥,告訴netback,這個skb傳送完成了,你可以給netfront 傳送response了,然後順便tasklet_schedule一把。

所以從這裡,就不難看出,cpu1, cpu2上softirq高,tasklet也高, 是因為網絡卡中斷都在cpu1, cpu2上。

開始我有點犯傻,覺得tx的時候,怎麼會觸發網絡卡中斷呢,不應該是rx的時候才有的。後來看了igb的驅動,才發現真的傻。

網絡卡發完包,得把skb回收啊,這個時候,就是通過觸發之前request_irq的函式來完成的,收包發包都走這一個函式。

就拿線上萬兆網絡卡ixgbe來說

中斷處理函式是ixgbe_msix_clean_many,裡面呼叫napi_schedule, 走到ixgbe_poll。這個函式就是我們上面提到的收包發包都在這個裡面處理的。

它會先呼叫ixgbe_clean_tx_irq, 對之前tx傳送的包進行回收處理(ixgbe_unmap_and_free_tx_resource),接著呼叫ixgbe_clean_rx_irq

這個裡面會rx_ring裡面的rx_buffer_info包括的skb,呼叫協議棧的收包函式,扔給上層處理,ixgbe_receive_skb->napi_gro_receive->netif_receive_skb

這個rx_ring的count在網絡卡驅動載入時預設是1024,我們設定了最大上限4096個,是驅動裡面每次接收完一批包的時候,就會ixgbe_alloc_rx_buffers 分配一批新的skb和page

pci_dma對映好給硬體去收包

這裡第一個tasklet排程到cpu1, cpu2的問題就能解釋, vm發包觸發了網絡卡的cpu1, cpu2上的中斷,一直到軟中斷,kfree_skb,觸發idx_release,接著tasklet_schedule, 然後tx_action就一直在這兩個cpu上,然後vif發包下來觸發中斷的時候,呼叫maybe_schedule_tx_action,裡面會判斷當前pending是否小於max/2,如果小於才去呼叫tasklet_schedule,這樣即使被呼叫,可能tasklet已經在運行了。為什麼之前千兆網路沒怎麼出現,可能是因為idx_release被呼叫的變快了吧,沒去確認,這已經不重要了。

剛好還有一個網絡卡丟包的問題,跟網絡卡驅動有點關係,有個測試發現物理口收了14w的包,丟了45w的包,ethtool -S 看到的話是rx_fifo_errors, 這大概就表明因為沒有buffer導致的。剛剛上面也講到rx_buffer,是在處理完一批請求之後再去分配一批新的buffer,總共就4096個。如果cpu處理變慢,那麼外面大壓力發過來的情況下,就會有很多丟包,跟cpu的處理能力有關。