1. 程式人生 > >linux 3.10 的中斷收包筆記

linux 3.10 的中斷收包筆記

 

來看下NAPI和非NAPI的區別:

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

(2) 非NAPI的核心介面為netif_rx(),NAPI的核心介面為napi_schedule(),或者類似的__napi_schedule之類的,總之都是在硬中斷中呼叫對應的函式。

(3) 非NAPI使用共享的CPU佇列softnet_data->input_pkt_queue,NAPI使用裝置記憶體(或者

裝置驅動程式的接收環)。

crash> struct softnet_data--------------會建立一個percpu變數
struct
softnet_data { struct Qdisc *output_queue; struct Qdisc **output_queue_tailp; struct list_head poll_list;------各個napi_struct的poll_list 串接在這個成員 struct sk_buff *completion_queue; struct sk_buff_head process_queue;----這個就是從input_pkt_queue 中取下的連結串列,用兩個成員是為了減少鎖衝突 unsigned int processed; unsigned
int time_squeeze; unsigned int cpu_collision; unsigned int received_rps;
#ifdef CONFIG_RPS
struct softnet_data *rps_ipi_list;
    struct call_single_data csd;
    struct softnet_data *rps_ipi_next;
    unsigned int cpu;
    unsigned int input_queue_head;
    unsigned int input_queue_tail;
#endif unsigned
int dropped; struct sk_buff_head input_pkt_queue;----入向的報文,非napi模式的,就放這個鏈 struct napi_struct backlog;---這個napi裝置是虛擬的,為了能適配napi模式的poll,它的poll函式初始化為process_backlog }
不支援napi的時候,網絡卡驅動將收到的報文,構造skb,然後呼叫netif_rx-->netif_rx_internal-->enqueue_to_backlog 這個流程用於將skb塞入到指定cpu的 softnet_data 變數的 input_pkt_queue,為了相容napi的收包模式,之前初始化的napi裝置,也就是 softnet_data 的backlog成員,

將 利用 ____napi_schedule(sd, &sd->backlog); 來加入對應的poll_list中,這樣觸發軟中斷之後,會在 net_rx_action 函式中處理。

那 net_rx_action 它的流程就比較簡單了,它首先將 當前cpu的  softnet_data 變數 的poll_list鏈摘到一個臨時鏈裡面,然後迴圈呼叫napi_poll,

napi_poll 就根據不同napi_struct結構的配額,呼叫napi_struct的poll函式,對於剛加入的backlog成員來說,它的poll函式就是之前初始化的process_backlog ,這樣就在軟中斷中統一了各個 poll函數了。
static int napi_poll(struct napi_struct *n, struct list_head *repoll)
{
。。。
    if (test_bit(NAPI_STATE_SCHED, &n->state)) {
        work = n->poll(n, weight);//呼叫這個napi自己的poll函式,對於backlog這個napi_struct 來說,就是 process_backlog函數了,比如對於ixgbe驅動,pll為ixgbe_poll
        trace_napi_poll(n);
    }
。。。。

 

當網絡卡支援napi介面,會如何處理收到的報文呢,其實就是利用 napi_schedule或者__napi_schedule,只要加入到了 softnet_data 的poll_list ,就等著報文來了。比如看一下i40e的驅動情況:

stap -d i40e netif_rx.stp
System Call Monitoring Started (10 seconds)...
WARNING: DWARF expression stack underflow in CFI
 0xffffffff815930b0 : __napi_schedule+0x0/0x50 [kernel]-----------把napi_struct 加入到對應poll_list,然後觸發收包NET_RX_SOFTIRQ軟中斷
 0xffffffffc01ce4a9 : i40e_msix_clean_rings+0x39/0x50 [i40e]
 0xffffffff81136e44 : __handle_irq_event_percpu+0x44/0x1c0 [kernel]
 0xffffffff81136ff2 : handle_irq_event_percpu+0x32/0x80 [kernel]
 0xffffffff8113707c : handle_irq_event+0x3c/0x60 [kernel]
 0xffffffff81139d7f : handle_edge_irq+0x7f/0x150 [kernel]
 0xffffffff8102d314 : handle_irq+0xe4/0x1a0 [kernel]
 0xffffffff816c9d9d : __irqentry_text_start+0x4d/0xf0 [kernel]
 0xffffffff816bc362 : ret_from_intr+0x0/0x15 [kernel]

有一點點不同的是,在 netif_rx 中是需要申請skb,然後來將skb掛到收包佇列去,而napi_schedule呼叫的各個napi裝置的poll函式,由於實現的不一樣,所以skb有可能是取的ring_buf

帶的skb,然後將skb推送到協議棧。