本文基於dpdk-1.8.0分析。
網絡卡驅動模型一般包含三層,即,pci 匯流排裝置、網絡卡裝置以及網絡卡裝置的私有資料結構,即將裝置的共性一層層的抽象,pci 匯流排裝置包含網絡卡裝置,網絡卡裝置又包含其私有資料結構。
在 dpdk 中,首先會註冊裝置驅動,然後查詢當前系統有哪些 pci設 備,並通過 pci_id 為 pci 裝置找到對應的驅動,最後呼叫驅動初始化裝置。
以e1000網絡卡驅動為例說明。
在1.8.0版本中,網絡卡驅動的註冊使用了一種奇技淫巧的方法,使用 gcc attribute 擴充套件屬性的 constructor 屬性,使得網絡卡驅動的註冊在程式main函式之前就執行了。
static struct rte_driver pmd_igb_drv =
使用 attribute 的 constructor 屬性,在 main 函式執行前,就執行 rte_eal_driver_register() 函式,將 pmd_igb_drv 驅動掛到全域性 dev_driver_list 鍊錶上。
呼叫 rte_eal_init() ---> rte_eal_pci_init() 函式,查詢當前系統中有哪些網絡卡,分別是什麼型別,並將它們掛到全域性鍊錶 pci_device_list 上。
1、首先初始化全域性鍊錶 pci_driver_list、pci_device_list。用於掛載pci驅動及pci裝置。
2、pci_scan()通過讀取 /sys/bus/pci/devices/ 目錄下的資訊,掃瞄當前系統的pci裝置,並初始化,並按照pci位址從大到小的順序掛在到 pci_debice_list 上。
int rte_eal_pci_init(void)
tailq_init(&pci_driver_list);
tailq_init(&pci_device_list);
/* for debug purposes, pci can be disabled */
if (internal_config.no_pci)
return 0;
if (pci_scan() < 0)
rte_eth_driver_register() 主要是指定pci裝置的初始化函式為 rte_eth_dev_init(),以及註冊pci驅動,將pci驅動掛到 pci_driver_list 全域性鍊錶上。
void
rte_eth_driver_register(struct eth_driver *eth_drv)
其中,rte_igb_pmd 資料結構如下,指定e1000網絡卡的初始化函式是 eth_igb_dev_init()。
static struct eth_driver rte_igb_pmd = ;
root@ubuntu:~# ls -ltr/sys/bus/pci/devices/0000\:00\:09.0/uio/uio0/maps/
total 0
drwxr-xr-x 2 root root 0 nov 19 15:32 map0
root@ubuntu:~# ls -ltr/sys/bus/pci/devices/0000\:00\:09.0/uio/uio0/maps/map0/
total 0
-r--r--r-- 1 root root 4096 nov 19 15:32size
-r--r--r-- 1 root root 4096 nov 19 15:32offset
-r--r--r-- 1 root root 4096 nov 19 15:32addr
-r--r--r-- 1 root root 4096 nov 19 15:34name
root@ubuntu:~#
d、檢查pci裝置和uio裝置在記憶體匯流排上的實體地址是否一致。如果一致,對 /dev/uioid 檔案 mmap 一段記憶體空間,並將其記錄在 pci_map->addr 和 rte_pci_device->mem_resource.addr 中。
root@ubuntu:~# cat/sys/bus/pci/devices/0000\:00\:09.0/uio/uio0/maps/map0/addr
0xf0440000
root@ubuntu:~#
root@ubuntu:~# cat/sys/bus/pci/devices/0000\:00\:09.0/resource
0x00000000f0440000 0x00000000f045ffff0x0000000000040200
0x0000000000000000 0x00000000000000000x0000000000000000
0x000000000000d248 0x000000000000d24f0x0000000000040101
0x0000000000000000 0x00000000000000000x0000000000000000
0x0000000000000000 0x00000000000000000x0000000000000000
0x0000000000000000 0x00000000000000000x0000000000000000
0x0000000000000000 0x00000000000000000x0000000000000000
0x0000000000000000 0x00000000000000000x0000000000000000
0x0000000000000000 0x00000000000000000x0000000000000000
0x0000000000000000 0x00000000000000000x0000000000000000
0x0000000000000000 0x00000000000000000x0000000000000000
0x0000000000000000 0x00000000000000000x0000000000000000
0x0000000000000000 0x00000000000000000x0000000000000000
root@ubuntu:~#
tailq_entry(uio_resource) next;
struct rte_pci_addr pci_addr;
char path[path_max];
size_t nb_maps;
struct uio_map maps[pci_max_resource];
3、呼叫 rte_eth_dev_init() 初始化pci裝置。
a、首先,呼叫 rte_eth_dev_allocate() 在全域性陣列 rte_eth_devices 中分配乙個網絡卡裝置。並在全域性陣列 rte_eth_dev_data 中為網絡卡裝置的資料域分配空間。
eth_dev = &rte_eth_devices[nb_ports];
eth_dev->data = &rte_eth_dev_data[nb_ports];
並呼叫 rte_zmalloc() 為網絡卡裝置的私有資料結構分配空間。
rte_eth_dev->rte_eth_dev_data->dev_private = rte_zmalloc(sizeof(struct e1000_adapter));
b、呼叫 eth_igb_dev_init() 初始化網絡卡裝置。首先設定網絡卡裝置的操作函式集,以及收包、發包函式。
eth_dev->dev_ops = ð_igb_ops;
eth_dev->rx_pkt_burst = ð_igb_recv_pkts;
eth_dev->tx_pkt_burst = ð_igb_xmit_pkts;
c、註冊中斷處理函式。
文章**
DPDK 收發包處理流程(一)(網絡卡驅動註冊)
本文基於dpdk 1.8.0分析。網絡卡驅動模型一般包含三層,即,pci匯流排裝置 網絡卡裝置以及網絡卡裝置的私有資料結構,即將裝置的共性一層層的抽象,pci匯流排裝置包含網絡卡裝置,網絡卡裝置又包含其私有資料結構。在dpdk中,首先會註冊裝置驅動,然後查詢當前系統有哪些pci裝置,並通過pci i...
網絡卡驅動收發包過程
網絡卡工作在物理層和資料鏈路層,主要由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位元組的前...