天天看點

rdma 程式設計詳解1.相關名詞解釋2. Verbs API 

1.相關名詞解釋

1.1 rdma-core

指開源RDMA使用者态軟體協定棧,(使用者空間的驅動)包含使用者态架構、各廠商使用者态驅動、API幫助手冊以及開發自測試工具等。

rdma-core在github上維護,我們的使用者态Verbs API實際上就是它實作的。https://github.com/linux-rdma/rdma-core

1.2 kernel RDMA subsystem

指開源的Linux核心中的RDMA子系統,(核心空間的驅動)包含RDMA核心架構及各廠商的驅動。

RDMA子系統跟随Linux維護,是核心的的一部分。一方面提供核心态的Verbs API,一方面負責對接使用者态的接口。

1.3 OFED

全稱為OpenFabrics Enterprise Distribution,是一個開源軟體包集合,其中包含核心架構和驅動、使用者架構和驅動、以及各種中間件、測試工具和API文檔。

開源OFED由OFA組織負責開發、釋出和維護,它會定期從rdma-core和核心的RDMA子系統取軟體版本,并對各商用OS發行版進行适配。除了協定棧和驅動外,還包含了perftest等測試工具。

除了開源OFED之外,各廠商也會提供定制版本的OFED軟體包,比如華為的HW_OFED和Mellanox的MLNX_OFED。這些定制版本基于開源OFED開發,由廠商自己測試和維護,會在開源軟體包基礎上提供私有的增強特性,并附上自己的配置、測試工具等。

以上三者是包含關系。無論是使用者态還是核心态,整個RDMA社群非常活躍,架構幾乎每天都在變動,都是平均每兩個月一個版本。而OFED會定期從兩個社群中取得代碼,進行功能和相容性測試後釋出版本,時間跨度較大,以年為機關計。

1.4 Mellanox 的OFED下載下傳安裝

wget http://content.mellanox.com/ofed/MLNX_OFED-4.3-1.0.1.0/MLNX_OFED_LINUX-4.3-1.0.1.0-rhel7.2-x86_64.tgz

tar -xvf  MLNX_OFED_LINUX-4.3-1.0.1.0-rhel7.2-x86_64.tgz

cd MLNX_OFED_LINUX-4.3-1.0.1.0-rhel7.2-x86_64/

yum install lsof tcl tk libxml2-python -y

yum install createrepo.noarch -y

yum install python-devel -y

./mlnxofedinstall --dpdk --upstream-libs --add-kernel-support

安裝完成後會提示:

/etc/init.d/openibd restart 

在執行restart時,可能需要首先執行(modprobe -rv  ib_isert rpcrdma ib_srpt),否則會restart失敗

 安裝完了需要restart

rdma 程式設計詳解1.相關名詞解釋2. Verbs API 

1.4.1安裝過程中遇到的問題

 驅動下載下傳位址:

驅動下載下傳位址:
https://www.mellanox.com/page/products_dyn?product_family=26&mtag=linux_sw_drivers&ssn=e76bu2ei7i1dcniinql196evj4
           

Linux InfiniBand Drivers

安裝過程中遇到的問題

rdma 程式設計詳解1.相關名詞解釋2. Verbs API 

解決方法

vi /usr/src/kernels/3.10.0-693.21.1.el7.x86_64/arch/x86/Makefile  166行,把ifneq到endif之間注釋掉

rdma 程式設計詳解1.相關名詞解釋2. Verbs API 

 1.4.2 源碼包

rdma 程式設計詳解1.相關名詞解釋2. Verbs API 

2. Verbs API 

廣義的Verbs API主要由兩大部分組成verbs和rdma_cm

Verbs API 操作RDMA的函數接口,也就是說業界的RDMA應用,要麼直接基于這組API編寫,要麼基于在Verbs API上又封裝了一層接口的各種中間件編寫。(rdma_cm)

Verbs API向使用者提供了有關RDMA的一切功能,典型的包括:注冊MR、建立QP、Post Send、Poll CQ等等。

對于Linux系統來說,Verbs的功能由rdma-core和核心中的RDMA子系統提供,分為使用者空間驅動的 Verbs api和核心空間驅動的Verbs api,分别用于使用者态和核心态的RDMA 程式。

rdma 程式設計詳解1.相關名詞解釋2. Verbs API 

2.1 rdma_cm和verbs的差別

 2.1.1 互相關系

1> rdma_cm依賴ib_verbs

2> ib_verbs和rdma_cm 都是Mellanox公司提供的兩個動态連結庫。(這兩個庫的API ,queue pair (QP)  類似于 TCP的sockets)

3> rdma_cm連接配接管理器庫,包含了對ib_verbs的封裝或具體化,通過verbs API 對硬體進行通路。

   rdma_post_send  = ibv_post_send(qp,wr.opcode=IBV_WR_SEND,bad_wr)  

   rdma_post_read  = ibv_post_send(qp,wr.opcode=IBV_WR_RDMA_READ ,bad_wr) 

  rdma_post_write  = ibv_post_send(qp,wr.opcode=IBV_WR_RDMA_WRITE,bad_wr) 

2.1.2 libibverbs和librdmacm的差別

在infiniband/verbs.h中,定義了ibv_post_send()和ibv_post_recv()操作,分别表示,将wr釋出到SQ和RQ中,至于是什麼操作(send or write/read),和wr中的opcode有關。

對ibv_post_send()來說,對應的是struct ibv_send_wr,其中有opcode,表示操作碼,有SEND/WRITE/READ等。

對于ibv_post_recv()來說,對應的是struct ibv_recv_wr,沒有操作碼,因為隻有接收一個動作,是以不需要定義其它的操作碼。但是發送來說,有三類。

在rdma/rdma_verbs.h中,有rdma_post_send(),rdma_post_recv(),rdma_post_read(),rdma_post_write()。

rdma_post_send():把wr釋出到QP的SQ中,需要mr

rdma_post_recv():把wr釋出到QP的RQ中,需要mr

rdma_post_read():把wr釋出到QP的SQ中,執行RDMA READ操作,需要遠端位址和rkey,以及本地存儲位址和長度,以及mr

rdma_post_write():把wr釋出到QP的SQ中,RDMA WRITE操作,需要遠端的被寫入位址和rkey,以及本地要發送資料的位址和長度,以及mr

是以rdma/rdma_verbs.h中的四種通信函數其實和infiniband/verbs.h中的兩種方法是一緻的。

ibv_post_send()對應rdma_post_send()、rdma_post_write()

ibv_post_recv()對應rdma_post_recv(),rdma_post_read()

2.2 IB_VERBS

接口以ibv_xx(使用者态)或者ib_xx(核心态)作為字首,是最基礎的程式設計接口,使用IB_VERBS就足夠編寫RDMA應用了。

比如:

ibv_create_qp() 用于建立QP

ibv_post_send() 用于下發Send WR

ibv_poll_cq() 用于從CQ中輪詢CQE

2.3 RDMA_CM

以rdma_為字首,主要分為兩個功能:

1)CMA(Connection Management Abstraction)---- 建連連接配接管理

在Socket和Verbs API基礎上實作的,用于CM建鍊并交換資訊的一組接口。CM建鍊是在Socket基礎上封裝為QP實作,從使用者的角度來看,是在通過QP交換之後資料交換所需要的QPN,Key等資訊。

比如:

rdma_listen()用于監聽鍊路上的CM建鍊請求。

rdma_connect()用于确認CM連接配接。

2)CM VERBS                                                        ----收發資料

RDMA_CM也可以用于資料交換 (收發資料),相當于在verbs API上又封裝了一套資料交換接口。

比如:

rdma_post_read()可以直接下發RDMA READ操作的WR,而不像ibv_post_send(),需要在參數中指定操作類型為READ。

rdma_post_ud_send()可以直接傳入遠端QPN,指向遠端的AH,本地緩沖區指針等資訊觸發一次UD SEND操作。

傳統以太網的使用者,基于Socket API來編寫應用程式;而RDMA的使用者,基于Verbs API來編寫應用程式。

RDMA有三種協定IB/iWARP/RoCE,設計Verbs API通過統一接口,讓同一份RDMA程式程式可以無視底層的硬體和鍊路差異運作在不同的環境中。

2.4 常用API介紹

  • device_list ibv_get_device_list()

使用者擷取可用的RDMA裝置清單,會傳回一組可用裝置的指針。

  • device_context ibv_open_device(device)

打開一個可用的RDMA裝置,傳回其上下文指針(這個指針會在以後用來對這個裝置進行各種操作)。

  • device_attr, errno ibv_query_device(device_context*)

查詢一個裝置的屬性/能力,比如其支援的最大QP,CQ數量等。傳回裝置的屬性結構體指針,以及錯誤碼。

  • pd ibv_alloc_pd(device_context)

申請PD。該函數會傳回一個PD的指針。(PD(記憶體)保護域

  • mr ibv_reg_mr(pd, addr, length, access_flag)

注冊MR。使用者傳入要注冊的記憶體的起始位址和長度,以及這個MR将要從屬的PD和它的通路權限(本地讀/寫,遠端讀/寫等),傳回一個MR的指針給使用者。

  • cq ibv_create_cq(device_context, cqe_depth, ...)

建立CQ。使用者傳入CQ的最小深度(驅動實際申請的可能比這個值大),然後該函數傳回CQ的指針

  • qp ibv_create_qp(pd, qp_init_attr)

建立QP。使用者傳入PD和一組屬性(包括RQ和SQ綁定到的CQ、QP綁定的SRQ、QP的能力、QP類型等),向使用者傳回QP的指針

  • errno ibv_modiy_qp(qp, attr, attr_mask)

修改QP。使用者傳入QP的指針,以及表示要修改的屬性的掩碼和要修改值。修改的内容可以是QP狀态、對端QPN(QP的序号)、QP能力、端口号和重傳次數等等。如果失敗,該函數會傳回錯誤碼。Modify QP最重要的作用是讓QP在不同的狀态間遷移,完成RST-->INIT-->RTR-->RTS的狀态機轉移後才具備下發Send WR的能力。也可用來将QP切換到ERROR狀态。

  • errno ibv_destroy_qp(qp)

銷毀QP。即銷毀QP相關的軟體資源。其他的資源也都有類似的銷毀接口。

  • event_info, errno ibv_get_async_event(device_context)

從事件隊列中擷取一個異步事件,傳回異步事件的資訊(事件來源,事件類型等)以及錯誤碼

  • bad_wr, errno ibv_post_send(qp, wr)

向一個QP下發一個Send WR,參數wr是一個結構體,包含了WR的所有資訊。包括wr_id、sge數量、操作碼(SEND/WRITE/READ等以及更細分的類型)。

WR的結構會根據服務類型和操作類型有所差異,比如RC服務的WRITE和READ操作的WR會包含遠端記憶體位址和R_Key,UD服務類型會包含AH,遠端QPN和Q_Key等。

WR經由驅動進一步處理後,會轉化成WQE下發給硬體。

出錯之後,該接口會傳回出錯的WR的指針以及錯誤碼。

  • bad_wr, errno ibv_post_recv(qp, wr)

專門用來下發RECV操作WR的接口

  • num, wc ibv_poll_cq(cq, max_num)

從完成隊列CQ中輪詢CQE,使用者需要提前準備好記憶體來存放WC,并傳入可以接收多少個WC。該接口會傳回一組WC結構體(其内容包括wr_id,狀态,操作碼,QPN等資訊)以及WC的數量

繼續閱讀