網絡子係統19_積壓設備
// 1.積壓設備的目的: // napi設備,非napi設備同一處理接口,linux為所有不使用napi的驅動程序,提供了一個虛擬設備,叫做積壓設備。 // 2.與積壓設備有關的數據結構: // 2.1 每個cpu都有一個積壓設備,保存在softnet_data->backlog_dev // 2.2 每個cpu都有一個積壓設備的輸入隊列,保存在softnet_data->input_pkt_queue,所有非napi設備的入口skb,均掛載到此隊列。 // 2.3 內核為積壓設備的提供poll函數,process_backlog // 積壓設備的poll函數 // 調用路徑:net_rx_action->process_backlog // 參數: // backlog_dev,積壓設備 // budget,函數此次運行可以處理的skb配額 // 返回值: // <0 , 表明設備還有待處理的入口幀,此時設備仍然在poll_list中,且設備處於關中斷狀態 // =0 , 表明設備已經處理完所有的入口幀,此時設備已經從poll_list中刪除,可接收重新調度,設備中斷已開啟 // 函數主要任務: // 1.函數運行不能超過1個jiffies,處理的skb不能超過配額 // 2.在關中斷的情況下,從softnet->input_pkt_queue取下入口skb,後開中斷 // 2.1 如果有入口skb // 2.1.1 通過netif_receive_skb向上層協議傳遞skb // 2.1.2 遞減入口設備的引用計數 // 2.2 如果在運行時間不足1個jiffies,並且沒有超過配額的情況下,處理完了入口隊列的所有skb // 2.2.1 更新設備的可用配額 // 2.2.2 由於已經沒有入口數據,因此將擠壓設備從調度隊列poll_list上取下來 // 2.2.3 清除積壓設備的調度標誌,表示設備可以接收下一次調度 // 2.2.4 如果之前入口隊列滿,被設置了throttle,則在入口隊列為空時,清除throttle // 注:在入口隊列滿,設置了throttle,之後的入口數據都會被丟棄,直到入口隊列為空,清除throttle之後,才開始重新接收入口數據。 1.1 static int process_backlog(struct net_device *backlog_dev, int *budget) { int work = 0; //此次調用可以處理的skb為 設備剩餘配額,傳入的配置中的較小者 int quota = min(backlog_dev->quota, *budget); struct softnet_data *queue = &__get_cpu_var(softnet_data); unsigned long start_time = jiffies; for (;;) { struct sk_buff *skb; struct net_device *dev; //關閉本cpu中斷,因為input_pkt_queue可能會在中斷中被修改 local_irq_disable(); //從input_pkt_queue上退出一個skb skb = __skb_dequeue(&queue->input_pkt_queue); if (!skb) goto job_done; //開中斷 local_irq_enable(); dev = skb->dev; //將skb向上傳遞 netif_receive_skb(skb); //遞減接收此skb的dev的引用計數 dev_put(dev); //消費流量個數-1 work++; //此函數運行時間應該 < 1 jiffies if (work >= quota || jiffies - start_time > 1) break; } //將設備的配額減去實際消費的流量個數 backlog_dev->quota -= work; //將打算讓設備消費的流量個數中減去實際消費的流量個數 *budget -= work; return -1; //表示接收隊列為空 job_done: backlog_dev->quota -= work; *budget -= work; //將積壓設備從poll_list上刪除 list_del(&backlog_dev->poll_list); smp_mb__before_clear_bit(); //清除積壓設備__LINK_STATE_RX_SCHED標識,表示積壓設備重新可以接收調度 netif_poll_enable(backlog_dev); //如果此cpu的輸入隊列已經關閉,開啟輸入隊列 if (queue->throttle) queue->throttle = 0; //開本cpu中斷 local_irq_enable(); return 0; } // 對積壓設備的調度 // 調用路徑 : 非napi設備的接收中斷->netif_rx 2.1 int netif_rx(struct sk_buff *skb) { ... netif_rx_schedule(&queue->backlog_dev); ... }
最後更新:2017-04-03 15:22:09