傳統方式接收報文時,當網絡卡接收到報文後會產生硬體中斷,進而報文會通過協議棧,最後到達應用層,這個過程需要核心協議棧的處理。 和傳統報文接收不同,當應用層想要接收來自網絡卡的報文時, 應用層通過while死迴圈的方式,呼叫rte_eth_rx_burst介面輪詢接收來自網絡卡的報文,相當於繞過了核心協議棧,將核心旁路了。通過輪詢的方式,報文不經過核心,提高了網路**效能,同時也降低了核心與使用者態系統呼叫的開銷。
來看下報文接收的整體流程。當網絡卡接收到報文時將會產生硬體中斷,通知dma控制器接收報文。dma控制器會從網絡卡接收佇列中將報文拷貝到硬體接收空間(也就是描述符空間)指向的位址位置,也就是mbuf。最終dma控制器將報文從網絡卡接收佇列中拷貝到mbuf來。 應用層通過while死迴圈,輪詢呼叫rte_eth_rx_burst介面,從這個mbuf軟體接收空間中獲取報文。
現在來看下eth_igb_recv_pkts介面的實現過程。
首先根據應用層最後一次獲取報文的位置,進而從描述符佇列找到待被應用層接收的描述符。此時會判斷描述符中的status_error是否已經打上了dd標記,有dd標記說明dma控制器已經把報文放到mbuf中了。這裡解釋下dd標記,當dma控制器將接收到的報文儲存到描述符指向的mbuf空間時,由dma控制器打上dd標記,表示dma控制器已經把報文放到mbuf中了。應用層在獲取完報文後,需要清除dd標記。
找到了描述符的位置,也就找到了mbuf空間。此時會根據描述符裡面儲存的資訊,填充mbuf結構。例如填充報文的長度,vlanid, rss等資訊。填充完mbuf後,將這個mbuf儲存到應用層傳進來的結構中,返回給應用層,這樣應用層就獲取到了這個報文。
uint16_t eth_igb_recv_pkts
(void
*rx_queue,
struct rte_mbuf *
*rx_pkts, uint16_t nb_pkts)
;//找到了描述符的位置,也就從軟體佇列中找到了mbuf
rxe =
&sw_ring[rx_id]
; rx_id++
; rxm = rxe->mbuf;
//填充mbuf
pkt_len =
(uint16_t)
(rte_le_to_cpu_16
(rxd.wb.upper.length)
- rxq->crc_len)
; rxm->data_off = rte_pktmbuf_headroom;
rxm->nb_segs =1;
rxm->pkt_len = pkt_len;
rxm->data_len = pkt_len;
rxm->port = rxq->port_id;
rxm->hash.rss = rxd.wb.lower.hi_dword.rss;
rxm->vlan_tci =
rte_le_to_cpu_16
(rxd.wb.upper.vlan)
;//儲存到應用層
rx_pkts[nb_rx++
]= rxm;
}}
需要注意的是,將mbuf的位址儲存到描述符中,此時會將dd標記給清0,這樣dma控制器就認為這個mbuf裡面的內容已經被應用層接收了,收到新報文後可以重新放到這個mbuf中。
uint16_t eth_igb_recv_pkts
(void
*rx_queue,
struct rte_mbuf *
*rx_pkts, uint16_t nb_pkts)
}
先整體來看下報文的傳送流程。當應用層需要傳送報文時,呼叫rte_eth_tx_burst介面,將報文放到軟體傳送空間,也就是mbuf空間中。同時將mbuf的位址寫入到硬體傳送空間,也就是描述符空間。dma控制器讀取描述符空間,就知道需要從描述符指向的位置,也就是mbuf中獲取報文,然後通過網絡卡傳送出去。
來看下**的實現過程。應用層呼叫rte_eth_tx_burst介面來傳送報文,函式內部會呼叫pmd使用者態驅動的傳送報文介面。如果是e1000網絡卡,則pmd使用者態驅動傳送報文的介面為eth_igb_xmit_pkts
//傳送報文
uint16_t rte_eth_tx_burst
(uint8_t port_id, uint16_t queue_id,
struct rte_mbuf *
*tx_pkts, uint16_t nb_pkts)
當應用層要發包時,eth_igb_xmit_pkts內部會將應用層的報文放到軟體佇列中。在軟體佇列中找到了最後一次傳送的的位置後,就可以將報文放到這個軟體佇列相應位置上。應用層要傳送的報文有可能是需要分片的,每乙個分片報文都會占用軟體佇列中的乙個元素。某個報文的所有分片報文所占用的軟體佇列元素,last_id都指向同乙個軟體佇列元素。
}需要注意的是,這個傳送過程,也是將mbuf、dma控制器、描述符佇列關聯起來的過程。
uint16_t eth_igb_xmit_pkts
(void
*tx_queue,
struct rte_mbuf *
*tx_pkts, uint16_t nb_pkts)
while
(m_seg !=
null);
}
到此為止,dpdk報文的傳送,接收流程已經分析完成 演算法(二十五)
1 給定兩個不字串,求出最長公共子串行的長度。int longestpublicsubsequence string x,string y else return math.max longestpublicsubsequence x.substring 1 y.substring 0 longes...
Effective C 之二十五
要點 提供不會丟擲異常的swap函式。swap自stl引入後就成為異常安全 exception safe 程式設計的基石。在條款11避免自賦值時已談到過。stl中swap的預設實現是通過臨時變數實現交換。但是對某些型別這是很低效的,例如pimpl只需要交換指標即可。之後,meyers提出在std命名...
Linux基礎(二十五)
進入linux字元介面方式有字元介面 圖形介面下的終端以及虛擬控制台等方式。在字元介面下,虛擬控制台的選擇可以通過按下 alt 鍵和1個功能鍵來實現,功能鍵通常為f1 f6鍵。比如使用者登入後,按下 alt f2 鍵,使用者可以看 login 提示符,說明使用者進入了第2個虛擬控制台。然後只需利用按...