dpdk之(十) 基礎模組之rte mbuf詳解

2021-08-01 07:34:13 字數 2983 閱讀 7511

rte_mbuf

本文假定報文的長度不超過rte_mbuf->buf_len的長度。

mbuf由緩衝池rte_mempool管理,rte_mempool在初始化時一次申請多個mbuf,申請的mbuf個數和長度都由使用者指定。巨集mbuf_size是例子程式中使用的mbuf長度:

#define mbuf_size (2048 + sizeof(struct rte_mbuf) + rte_pktmbuf_headroom)

用下面函式向rte_mempool申請乙個mbuf:

struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp);

巨集rte_mbuf_scatter_gather定義rte_mbuf是否支援拷貝功能。

dpdk接收報文並把報文上送上層應用的過程中,報文傳輸是「零拷貝」,即不需要拷貝報文內容,只需要傳送mbuf位址。然而在乙個報文上送給多個應用時,仍然需要對報文做拷貝並送給不同的應用。librte_mbuf採用「複製rte_mbuf,共享data資料域」的方式實現報文的拷貝函式rte_pktmbuf_clone(),函式原型如下:

struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md, struct rte_mempool *mp)

rte_pktmbuf_clone()函式首先申請乙個新的rte_mbuf,我們稱這個mbuf為indirect buffer,用mi表示,引數md稱為direct buffer。函式將md的各結構體成員(引用計數refcnt除外)一一複製給mi,同時將md的引用計數refcnt增1。此時,mi->pkt.data指向md的data資料域。

rte_pktmbuf_clone()要求引數md必須是direct buffer,我們可以通過判斷md->buf_addr – sizeof(struct rte_mbuf) == md 是否為真,確定md是否為direct buffer,該功能由巨集rte_mbuf_direct(mb)實現。

注意:rte_pktmbuf_clone()提供的拷貝機制在某些場景不一定適用,如多個應用競爭data資料域。為避免競爭的發生,使用者可以通過拷貝data資料域實現自己的clone()。具體實現參考openvswitch-dpdk-1.1。

用下面函式釋放乙個mbuf,釋放過程即把mbuf歸還到rte_mempool中:

void rte_pktmbuf_free(struct rte_mbuf *m);

根據m的引用計數和m的indirect/direct型別,rte_pktmbuf_free()分以下方式釋放m:

如果m的引用計數大於1,則只將m的引用計數減1,函式返回;

如果m的引用計數是1且m是direct型別,則將m的引用計數置0,然後把m歸還mempool,函式返回;

如果m的引用計數是1且m是indirect型別,則rte_pktmbuf_free()將m引用計數置0,同時將m對應的direct buffer的引用計數減1(減1後引用計數為0則把direct buffer歸還mempool),把m歸還mempool,函式返回;

rte_pktmbuf_free()通過巨集rte_mbuf_from_baddr(m->buf_addr)找到m對應的direct buffer,巨集實現如下:

#define rte_mbuf_from_baddr(ba) (((struct rte_mbuf *)(ba)) - 1)

rte_pktmbuf_free()通過判斷m != rte_mbuf_from_baddr(m->buf_addr)是否為真判斷m的indirect/direct型別。

rte_mbuf的結構與linux核心協議棧的skb_buf相似,在儲存報文的記憶體塊前後分別保留headroom和tailroom,以方便應用解封報文。headroom預設128位元組,可以通過巨集rte_pktmbuf_headroom調整。

我們可以通過m->pkt.data – m->buf_addr計算出headroom長度,通過m->buf_len – m->pkt.data_len – headroom_size計算出tailroom長度。這些計算過程都由以下函式實現:

uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m)

uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)

m->pkt.data += 14;

m->pkt.data_len -= 14;

m->pkt.pkt_len -= 14;

這些操作已經由rte_pktmbuf_adj()實現,函式原型如下:

char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len)

m->pkt.data -= 14;

m->pkt.data_len += 14;

m->pkt.pkt_len += 14;

這些操作由rte_pktmbuf_prepend()實現,函式原型如下:

char *rte_pktmbuf_prepend(struct rte_mbuf *m, uint16_t len)

如果需要在tailroom 中加入n個位元組資料,我們可以通過以下操作完成:

tail = m->pkt.data + m->pkt.data_len; // tail記錄tailroom首位址

m->pkt.data_len += n;

m->pkt.pkt_len += n;

librte_mbuf還提供了rte_pktmbuf_trim()函式,用來移除mbuf中data資料域的最後n個位元組,函式實現如下:

m->pkt.data_len -= n;

m->pkt.pkt_len -= n;

函式原型如下:

int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)

python基礎之模組之sys模組

sys模組的功能 sys是python中較為常用的乙個模組,他提供了對python指令碼執行時的環境的操作。sys功能 1 sys.argv 將python指令碼執行時的指令碼名以及引數作為乙個list,並輸出。2 sys.path 返回乙個list,該list為當前指令碼的path環境變數 pyt...

DPDK學習之開篇介紹

1 前言 記得剛開始工作的時,老大將我安排到資料麵組,當時第一次聽說 資料面 這個概念,感覺挺新鮮的。誤打誤撞就開始搞了,剛開始接觸的時候,由於不懂其中的原理,覺得很神奇,因為報文的 是在應用層,通過乙個程序進行 而傳統的報文 是基於核心的,要想控制報文,需要寫驅動程式。後面接觸了一段時間,發現原來...

python模組基礎之OS模組

os模組簡單的來說它是乙個python的系統程式設計的操作模組,可以處理檔案和目錄這些我們日常手動需要做的操作。import os 匯入os模組 help os 檢視os模組幫助文件,裡面詳細的模組相關函式和使用方法 1 os.sep 更改作業系統中的路徑分隔符。2 os.getcwd 獲取當前路徑...