Kernel Source片段 -- 收包(2)軟中斷處理函數

kernel version:2.6.32.61


系統有資源處理軟中斷時,會查看軟中斷向量表,調用對應的handler。
網絡收包時軟中斷處理函數是net_rx_action。是在net_dev_init中初始化的:
net/core/dev.c

5654 static int __init net_dev_init(void)
5655 {
...
5708         open_softirq(NET_TX_SOFTIRQ, net_tx_action);
5709         open_softirq(NET_RX_SOFTIRQ, net_rx_action);
...
5717 }

軟中斷處理函數,主要動作是輪詢poll_list,然後調用poll處理。如果這個設備所有包都處理完後就將其從poll_list中移除。
這裏分爲兩種情況,
1) 設備驅動支持NAPI
2) 設備驅動不支持NAPI
對於支持NAPI的驅動,在poll_list中的poll函數是需要設備自己實現的,設備擁有自己的隊列,不需要共享CPU隊列,因此不需要關閉中斷。
對於不支持NAPI的驅動,poll函數就是process_backlog,設備需要共享CPU隊列,而在軟中斷處理時是可以被中斷打斷的,因此對於CPU隊列操作時需要關閉中斷。


以下是net_rx_action的代碼:
net/core/dev.c

2834 static void net_rx_action(struct softirq_action *h)
2835 {
2836         struct list_head *list = &__get_cpu_var(softnet_data).poll_list;
2837         unsigned long time_limit = jiffies + 2;
2838         int budget = netdev_budget;
2839         void *have;
2840 
2841         local_irq_disable();
2842 
// 遍歷poll_list
2843         while (!list_empty(list)) {
2844                 struct napi_struct *n;
2845                 int work, weight;
2846 
2847                 /* If softirq window is exhuasted then punt.
2848                  * Allow this to run for 2 jiffies since which will allow
2849                  * an average latency of 1.5/HZ.
2850                  */
// CPU時間用完或者budget用完就要釋放CPU
2851                 if (unlikely(budget <= 0 || time_after_eq(jiffies, time_limit)))
2852                         goto softnet_break;
2853 
2854                 local_irq_enable();
2855 
2856                 /* Even though interrupts have been re-enabled, this
2857                  * access is safe because interrupts can only add new
2858                  * entries to the tail of this list, and only ->poll()
2859                  * calls can remove this head entry from the list.
2860                  */
2861                 n = list_entry(list->next, struct napi_struct, poll_list);
2862 
2863                 have = netpoll_poll_lock(n);
2864 
2865                 weight = n->weight;
2866 
2867                 /* This NAPI_STATE_SCHED test is for avoiding a race
2868                  * with netpoll's poll_napi().  Only the entity which
2869                  * obtains the lock and sees NAPI_STATE_SCHED set will
2870                  * actually make the ->poll() call.  Therefore we avoid
2871                 work = 0;
2872                 if (test_bit(NAPI_STATE_SCHED, &n->state)) {
// 調用poll函數處理
2873                         work = n->poll(n, weight);
2874                         trace_napi_poll(n);
2875                 }
2876 
2877                 WARN_ON_ONCE(work > weight);
2878 
2879                 budget -= work;
2880 
2881                 local_irq_disable();
2882 
2883                 /* Drivers must not modify the NAPI state if they
2884                  * consume the entire weight.  In such cases this code
2885                  * still "owns" the NAPI instance and therefore can
2886                  * move the instance around on the list at-will.
2887                  */
2888                 if (unlikely(work == weight)) {
2889                         if (unlikely(napi_disable_pending(n))) {
2890                                 local_irq_enable();
2891                                 napi_complete(n);
2892                                 local_irq_disable();
2893                         } else
2894                                 list_move_tail(&n->poll_list, list);
2895                 }
2896 
2897                 netpoll_poll_unlock(have);
2898         }
2899 out:
2900         local_irq_enable();
2901 
2902 #ifdef CONFIG_NET_DMA
2903         /*
2904          * There may not be any more sk_buffs coming right now, so push
2905          * any pending DMA copies to hardware
2906          */
2907         dma_issue_pending_all();
2908 #endif
2909 
2910         return;
2911 
2912 softnet_break:
2913         __get_cpu_var(netdev_rx_stat).time_squeeze++;
2914         __raise_softirq_irqoff(NET_RX_SOFTIRQ);
2915         goto out;
2916 }


發佈了64 篇原創文章 · 獲贊 9 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章