網絡卡工作在物理層和資料鏈路層,主要由phy/mac晶元、tx/rx fifo、dma等組成,其中網線通過變壓器接phy晶元、phy晶元通過mii接mac晶元、mac晶元接pci匯流排
phy晶元主要負責:csma/cd、模數轉換、編譯碼、串並轉換
mac晶元主要負責:
intel的千兆網絡卡以82575/82576為代表、萬兆網絡卡以82598/82599為代表
ixgbe_adapter包含ixgbe_q_vector陣列(乙個ixgbe_q_vector對應乙個中斷),ixgbe_q_vector包含napi_struct
硬中斷函式把napi_struct加入cpu的poll_list,軟中斷函式net_rx_action()遍歷poll_list,執行poll函式
1、網絡卡驅動建立tx descriptor ring(一致性dma記憶體),將tx descriptor ring的匯流排位址寫入網絡卡暫存器tdba
2、協議棧通過dev_queue_xmit()將sk_buff下送網絡卡驅動
3、網絡卡驅動將sk_buff放入tx descriptor ring,更新tdt
4、dma感知到tdt的改變後,找到tx descriptor ring中下乙個將要使用的descriptor
5、dma通過pci匯流排將descriptor的資料快取區複製到tx fifo
6、複製完後,通過mac晶元將資料報傳送出去
7、傳送完後,網絡卡更新tdh,啟動硬中斷通知cpu釋放資料快取區中的資料報
sw將sk_buff掛載到從next_to_use開始的n個descriptor,next_to_use += n,tail = next_to_use(寫網絡卡暫存器tdt)
hw使用dma讀從head開始的m個descriptor的sk_buff,傳送成功後回寫dd(descriptor done),head += m
sw將從next_to_clean的開始的l個sk_buff移出tx ring buffer並清理,next_to_clean += l
注意:每次掛載完sk_buff後,tail和next_to_use指向同乙個descriptor
1、網絡卡驅動建立rx descriptor ring(一致性dma記憶體),將rx descriptor ring的匯流排位址寫入網絡卡暫存器rdba
2、網絡卡驅動為每個descriptor分配sk_buff和資料快取區,流式dma對映資料快取區,將資料快取區的匯流排位址儲存到descriptor
3、網絡卡接收資料報,將資料報寫入rx fifo
4、dma找到rx descriptor ring中下乙個將要使用的descriptor
5、整個資料報寫入rx fifo後,dma通過pci匯流排將rx fifo中的資料報複製到descriptor的資料快取區
6、複製完後,網絡卡啟動硬中斷通知cpu資料快取區中已經有新的資料報了,cpu執行硬中斷函式:
7、ksoftirqd執行軟中斷函式net_rx_action():
8、網絡卡驅動通過netif_receive_skb()將sk_buff上送協議棧
sw向從next_to_use開始的n個descriptor補充sk_buff,next_to_use += n,tail = next_to_use(寫網絡卡暫存器rdt)
hw寫frame到從head開始的m個descriptor的sk_buff,寫完後回寫eop(end of packet),head += m
sw將從next_to_clean開始的l個sk_buff移出rx ring buffer並上送協議棧,next_to_clean += l,向從next_to_use開始的l個descriptor補充sk_buff,next_to_use += l,tail = next_to_use
注意:每次補充完sk_buff後,tail和next_to_use指向同乙個sk_buff
do_irq()是cpu處理硬中斷的總入口
// 在e1000_request_irq()中註冊硬中斷,中斷函式為e1000_intr()
irq_handler_t handler = e1000_intr;
err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
netdev);
// 在net_dev_init()中註冊軟中斷,中斷函式為net_rx_action()
open_softirq(net_rx_softirq, net_rx_action);
// 在e1000_probe()中註冊napi的poll函式為e1000_clean()
netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
// 在net_dev_init()中註冊非napi的poll函式為process_backlog()
queue->backlog.poll = process_backlog;
在netif_rx()中把skb加入cpu的softnet_data
int netif_rx(struct sk_buff *skb)
napi_schedule(&queue->backlog); // 排程queue->backlog
goto enqueue; // 將skb加入佇列尾部
}__get_cpu_var(netdev_rx_stat).dropped++;
local_irq_restore(flags);
kfree_skb(skb);
return net_rx_drop;
}
網絡卡驅動收發包過程
網絡卡工作在物理層和資料鏈路層,主要由phy mac晶元 tx rx fifo dma等組成,其中網線通過變壓器接phy晶元 phy晶元通過mii接mac晶元 mac晶元接pci匯流排 phy晶元主要負責 csma cd 模數轉換 編譯碼 串並轉換 mac晶元主要負責 intel的千兆網絡卡以825...
網絡卡驅動收發包過程
網絡卡工作在物理層和資料鏈路層,主要由phy mac晶元 tx rx fifo dma等組成,其中網線通過變壓器接phy晶元 phy晶元通過mii接mac晶元 mac晶元接pci匯流排 phy晶元主要負責 csma cd 模數轉換 編譯碼 串並轉換 mac晶元主要負責 位元流和幀的轉換 7位元組的前...
Linux 網絡卡驅動學習(五)(收發包具體過程)
裝置初始化函式 網路裝置驅動在 linux 核心中是以核心模組的形式存在的,對應於模組的初始化,需要提供乙個初始化函式來初始化網路裝置的硬體暫存器 配置 dma 以及初始化相關核心變數等。裝置初始化函式在核心模組被載入時呼叫,它的函式形式如下 static int init xx init void...