[經驗分享] NSADI RSOCKETS使用經驗分享
作者/黃俊源
前言
HPE NonStop X系列主機的NSADI (NonStop Application Direct Interface)產品支援RDMA (Remote Direct Memory Access)通訊模式,採用RDMA可大幅降低傳輸延遲時間與系統CPU資源耗用。目前NSADI產品提供下列三種使用方式。
一、IB Verbs/RDMA CM (Communication Manager):
RDMA_CM是一個通訊管理函式庫,提供NonStop X與Linux間建立一個可靠的資料傳輸,此種API是以socket為基礎,並且納入Queue Pair (QP)語法,透過指定的RDMA設備進行通訊,資料傳輸則為message-based模式。
二、RDMA Sockets (rsockets):
屬於IB Verbs/RDMA CM的前端,rsockets可直接套用在一般socket-based的程式,基本上只需將sockets API轉換為對應的rsockets API,實際上程式只需要對原有socket-level API名稱前加上r,例如rrecv()、rsend()。
三、Preload Library:
允許原有socket-based應用程式可以在不修改程式情況下,bind library後直接進行RDMA資料傳輸。
這三種方式中,如果以IB Verbs開發,除了需宣告繁複的元件外,首先需要建立protection domain、completion channel、completion queue,而且之後需要建立queue pair,接著便需保留記憶體空間位置,針對記憶體註冊到對應的pd,而且針對接收與發送均需個別註冊對應的記憶體空間,在等候資料接收或是發送是否完成期間,還需針對completion queue做poll以便後續確認是否完成,接著poll動作後面還需要呼叫requesting notification,後續還需取得completion queue的event以便確認動作是否完成,而且還需要針對這個event做acknowledged ,這樣才完成一個簡單的發送或接收的動作。
相較於IB Verbs,rsockets則相對簡單許多,它的使用與行為像sockets,連線方式像sockets,byte streaming transfer像sockets,因此可以簡單轉換現有sockets程式,直接架構在RDMA環境底下,如同下面的架構圖,可以忽略RDMA CM底層所需控制的工作,用戶便可直接開發類似sockets程式之rsockest程式做RDMA資料傳輸。

《圖一》
NonStop目前所支援的RSOCKETS
目前NSADI的rsockets僅支援TCP-based socket並且指定SOCK_STREAM type,其他如UDP/SOCK_DGRAM等連線方式並不支援。而且目前NonStop rsockets屬於blocking I/O,目前尚不支援nonblocking,因此這也確保所呼叫的function return後代表I/O完成,相對應使用的變數均可安心異動或是使用。
NonStop rsockets主要是以Linux版本的rsockets的應用為依據,因此針對回傳的錯誤訊息可能與標準TCP/IP sockets有所不同。詳細各function可能會傳的error code,可以參考OSS上man對各function之說明。
目前NonStop X所支援的RSOCKETS API依功能分類列出如下:
一、連線部分:
rsocket、rbind、rlisten、raccept、rconnect、rshutdown、rclose。
- rsocket目前僅支援SOCK_STREAM。
- rbind不可使用INADDR_ANY。
二、資料傳輸:
rrecv、rrecvfrom、rrecvmsg、rread、rreadv、rsend、rsendto、rsendmsg、rwrite、rwritev。
三、Socket參數設定:rsetsockopt、rgetsockopt。
- 針對rsocket option,目前NonStop支援SOL_SOCKET level包含SO_RCVBUF、SO_SNDBUF、SO_KEEPALIVE、SO_OOBINLINE。
- 雖然socket send/recv buffer可做設定,不過針對這設定值上限不可超過1MB,建議針對rsockets可以不須指定socket send/recv buffer。當資料要傳送或是接收時,直接指定應用於傳送或接收的message pointer即可,不過需注意的是目前NSADI並沒有針對這個message大小做設限,因此所使用的記憶體空間均會取自於系統,所以這部分需小心注意。另外針對發送與接收需指定不同的message pointer,以避免發生複寫。
四、其他API:
rgetpeername、rgetsockname。
rsocket程式編譯注意事項
目前NSADI僅支援OSS 64bit program開發,編譯時相關注意事項彙整如下:
一、library位置放置於/G/SYSTEM/ZXDLL/WUIBDLL,編譯時link library可以指定-lwuibdll以便連結。
二、編譯時需要指定-D_PRELOAD_SUPPORT_FUNCTIONS的compiler directive。
三、NSADI相關include file均放置於/usr/include/infiniband以及/usr/include/rdma底下,因此於編譯時亦可考慮指定-I/usr/include/infiniband -I/usr/include/rdma路徑位置。
另外,Linux端rsocket程式針對編譯時相關注意事項彙整如下:
一、Linux程式編譯rsocket時需要連結兩個library檔案,因此於編譯時需指定-lrdmacm –libverbs。
二、如果編譯一般TCP/IP socket程式採用preload方式執行時,可不須指定-lrdmacm –libverbs,不過於程式執行時需指定
LD_PRELOAD=/usr/lib64/rsocket/librspreload.so.1
後面再指定object名稱;若以preload方式啟動程式,如下列範例:
/usr/lib64/rsocket/librspreload.so.1 ./client -p 21262 10.1.3.0
NonStop X與Linux程式編譯範例分述如下:
一、OSS make file範例:
二、Linux make file範例:
程式邏輯範例說明
一、Server端邏輯範例:
- 建立socket
sock = rsocket(AF_INET , SOCK_STREAM , 0);
- 設定local要綁定的IP address,NSADI所使用的IP address必須依照external server configuration規範指定IP address。
server.sin_family = AF_INET;
server.sin_addr.s_addr = ip_addr;
server.sin_port = htons(port);
- 針對socket綁定IP address。
rbind(sock,(struct sockaddr *)&server , sizeof(server));
- 針對socket執行listen等待連線需求。
rlisten(sock , 3);
- 接收連線需求。
client_sock = raccept(sock, (struct sockaddr *)&client, (socklen_t*)&c);
- 資料接收及資料發送。
read_size = rrecv(client_sock ,msg_ptr , (except_size - recv_len), 0);
send_size = rsend(client_sock , server_reply , msg_size , 0);
- 結束連線。
rclose(sock);
二、Client端邏輯範例:
- 建立socket
sock = rsocket(AF_INET , SOCK_STREAM , 0);
- 設定連接到server端的IP address,NSADI所使用的IP address必須依照external server configuration規範指定IP address。
server.sin_family = AF_INET;
server.sin_addr.s_addr = ip_addr;
server.sin_port = htons(port);
- 連接到server端。
ret = rconnect(sock , (struct sockaddr *)&server , sizeof(server));
- 資料接收及資料發送。
send_size = rsend(sock , message , msg_size , 0);
read_size = rrecv(sock ,msg_ptr , (except_size - recv_len), 0);
- 結束連線。
rclose(sock);
NSADI IP address使用規範
NonStop端所使用的IP address A.B.C.D規範如下:
A:系統預設值為10。
B:由於OSS process所使用的physical resource type屬於CPU,故依照程式透過X或是Y的路徑決定。如果是透過X則為1,如果是Y則為129。
C:對應Expand Node number,可以透過SYSINFO指令確認。其輸出如下列範例

D:OSS process直接對應到所在CPU number。
Linux端其InfiniBand網卡須設定的IP address A.B.C.D規範如下:
A:比照NonStop端使用10的預設值。
B:依樣區分透過X或是Y的路徑決定。故可應用之數值如下表:

C:比照NonStop端,對應Expand Node number。
D:設定0(Linux based instance)。
舉例:
若Expand node number為252,如果於NonStop端CPU 2底下啟動server,Linux端啟動client,NonStop透過X fabric與Linux端連線,則server需指定IP address為10.1.252.2,client端IP address可指定為10.10.252.0。如果同樣環境改以Y fabric,則server需指定IP address為10.129.252.2,client端IP address則調整為10.138.252.0。
結論
藉由rsockets API可以比照原有TCP/IP socket程式簡單升級成以NSADI介面進行RDMA溝通,不過由於現階段主要提供SOCK_STREAM以及blocking I/O,因此原有TCP/IP程式仍需做相對應的調整。不過相較於IB verbs而言,簡化應用門檻,亦可達到高速傳遞及減少系統資源使用之優勢,適用於NonStop與Linux端資料大量交換和低延遲需求之應用。
參考資料
1.NonStop Application Direct Interface Reference Manual
2.Sean Hefty rsockets workshop
3.HPE David J & Nelson Wong support