系列解讀 SMC-R (二):融合 TCP 與 RDMA 的 SMC-R 通訊 | 龍蜥技術

OpenAnolis小助手發表於2022-04-22

文/龍蜥社群高效能網路SIG

一、引言

通過上一篇文章 《 系列解讀SMC-R:透明無感提升雲上 TCP 應用網路效能(一)》我們瞭解到,RDMA  相對於 TCP 具有旁路軟體協議棧、解除安裝網路工作到硬體的特點,能有效增加網路頻寬、降低網路時延與 CPU 負載。而核心網路協議 SMC-R  在利用 RDMA 技術的同時、又進一步完美相容了 socket 介面,能夠透明無感的為 TCP 應用帶來網路效能提升。因此,龍蜥社群高效能網路  SIG 認為 SMC-R 將成為下一代資料中心核心協議的重要組成,對其進行了大量優化,並積極將這些優化回饋到上游 Linux 社群。
本篇文章作為 SMC-R 系列的第二篇,將聚焦一次完整的 SMC-R 通訊流程。通過具體的建連、傳輸、銷燬過程,使讀者進一步體會到 SMC-R 是一個融合了通用 TCP 與高效能 RDMA 的 "hybrid" 解決方案。

二、通訊流程

如前篇所述,使用  SMC-R 協議有兩種方法。其一,是在應用程式中顯式建立 AF_SMC 族的 socket;其二,是利用 LD_PRELOAD 或 ULP +  eBPF 的方式透明的將應用程式中的 AF_INET 族 socket 替換為 AF_SMC 族 socket。我們預設使用 SMC-R  通訊的節點已經載入了 SMC 核心模組,並通過上述方式將應用程式執行在 SMC-R 協議上。接下來, 我們以 first contact  (通訊兩端建立首個連線) 場景為例,介紹 SMC-R 通訊流程。

2.1 確認對端能力

使用  SMC-R 通訊時,我們首先需要確認對端是否同樣支援 SMC-R 協議。因此,SMC-R 協議棧為應用程式建立 SMC 型別 socket  (smc socket) 的同時,還會在核心建立並維護一個與之關聯的 TCP 型別 socket (clcsock),並基於 clcsock  與對端建立起 TCP 連線。

(圖/TCP 握手確認對端 SMC-R 能力)


在  TCP 連線三次握手中,使用 SMC-R 協議的一端傳送的 SYN/ACK 中攜帶了特殊的 TCP 選項 (Kind = 254,Magic  Number = 0xe2d4),用於表明自身支援 SMC-R。通過檢查對端傳送的 SYN/ACK,通訊節點得知其 SMC-R  能力,進而決定是否繼續使用 SMC-R 通訊。

(圖/三次握手攜帶特殊 TCP 選項[1])


(圖/代表 SMC-R 的 TCP 選項)


2.2 協議回退

若在上述 TCP 握手過程中,通訊兩端其一表示無法支援 SMC-R,則進入協議回退 (fallback) 流程。協議回退時,應用程式所持有的 fd 對應的 smc socket 將被替換為 clcsock。從此,應用程式將使用 TCP 協議通訊,從而確保資料傳輸不會因為協議相容問題而中斷。需要注意的是,協議回退僅發生在通訊協商過程中,如前文提到的 TCP 握手階段,或是下文提到的 SMC-R 建連階段。為便於跟蹤診斷,SMC-R 協議詳細分類了潛在的回退可能,使用者可以通過使用者態工具 smc-tools 觀測到協議回退事件及原因。

(圖/smc-tools 觀測回退現象)

2.3 建立SMC-R 連線

若在 TCP 握手中,兩端均表示支援 SMC-R,則進入 SMC-R 建連流程。SMC-R 連線的建立依賴 TCP 連線傳遞控制訊息,這種控制訊息被稱為 Connection Layer Control (CLC) 訊息。

(圖/使用 CLC 訊息建立 SMC-R 連線)


CLC  訊息的主要職責是同步通訊兩端的 RDMA 資源以及共享記憶體等資訊。使用 CLC 訊息建立 SMC-R 連線的過程與 SSL 握手類似,主要包含  Proposal、Accept、Decline、Confirm 等語義。在建連過程中,若遇到不可恢復的異常 (如 RDMA 資源失效)  導致後續 SMC-R 通訊無法繼續,也將觸發前文所述的協議回退流程。

(圖/SMC-R 握手過程[1])
First contact 場景下,由於通訊兩端首次接觸,兩者間尚不存在使用 RDMA 通訊的條件。所以,在建立首個 SMC-R 連線時,還將建立 SMC-R 通訊所需的 RDMA 資源,建立 RDMA 鏈路,申請 RDMA 記憶體。

2.3.1 建立 RDMA 資源
SMC-R 建連初期,兩端根據應用程式傳遞的  IP 地址在本地尋找可用 (如相同 Pnet ID) 的 RDMA 裝置,並基於找到的裝置建立必要的 RDMA 資源,包括 Queue  Pair (QP),Completion Queue (CQ),Memory Region (MR),Protect Domain (PD)  等等。
其中,QP 與 CQ 是 RDMA 通訊的基礎,提供了一套 RDMA 使用者 (如 SMC 核心協議棧) 與 RDMA 裝置 (RNIC) 之間的非同步通訊機制。
QP 本質是存放工作任務  (Work Request, WR) 的工作佇列 (Work Queue, WQ)。負責傳送任務的 WQ 稱為 Send Queue  (SQ),負責接收任務的 WQ 稱為 Receive Queue (RQ),兩者總是成對出現,稱為 QP。使用者將希望 RNIC  完成的任務打包為工作佇列元素 (Work Queue Element, WQE),post 到 QP 中。RNIC 從 QP 中取出  WQE,完成 WQE 中定義的工作。

CQ 本質是存放工作完成資訊  (Work Completion, WC) 的佇列。RNIC 完成 WR 後,將完成資訊打包為完成佇列元素 (Completion Queue  Element, CQE) 放入 CQ 中。使用者從 CQ 中 poll 出 CQE,獲悉 RNIC 已經完成某個 WR。

(圖/)RDMA 工作佇列模型)

2.3.2 建立 RDMA 鏈路

通訊兩端將已建立的  RDMA 資源通過 CLC 訊息同步到對端,進而在兩端之間建立起基於 RC (Reliable Connection) QP 的 RDMA  鏈路。SMC-R 中將這種點對點邏輯上的 RDMA 鏈路稱為 SMC-R Link。一條 SMC-R Link 承載著多條 SMC-R  連線的資料流量。

(圖/SMC Link)

若通訊節點之間存在不止一對可用的 RNIC,則會建立不止一條 Link。這些 Link 在邏輯上組成一個小組,稱為 SMC-R Link Group。

(圖/SMC-R Link Group)
在  Linux 實現中,每個 Link Group 具備 1-3 條 Link,最多承載 255 條 SMC-R 連線。這些連線被均衡的關聯到  Link Group 的某一 Link 上。應用程式通過 SMC-R 連線傳送的資料將由關聯的 Link (也即 RDMA 鏈路) 傳輸。
同一個  Link Group 中,所有的 Link 互相“平等”。這個“平等”體現在同一 Link Group 中的 Link 具備訪問 Group  中所有 SMC-R 連線收發緩衝區 (下文提到的 sndbuf 與 RMB) 的許可權,具備承載任意 SMC-R 連線資料流的能力。因此,當某一  Link 失效時 (如 RNIC down),關聯此 Link 的所有連線可以遷移到同 Link Group 的另一條 Link 上。這使得  SMC-R 通訊穩定可靠,具備一定的容災能力。
SMC-R  中,Link (Group) 在 first contact 時建立,在最後一條 SMC-R 連線斷開一段時間 (Linux 實現中為 10  mins) 後銷燬,具備比連線更長的生命週期。First contact 之後建立的 SMC-R 連線都將嘗試複用已有的 Link  (Group)。這樣的設計充分利用了已有的 RDMA 資源,避免了頻繁建立與銷燬帶來的額外開銷。

2.3.3 申請 RDMA 記憶體

SMC-R 協議棧為每條 SMC-R 連線分配了獨屬的收發緩衝區:sndbuf (傳送緩衝區) 與 RMB (接收緩衝區,Remote Memory Buffer)。這是兩片地址連續,長度在 16 KB ~ 512 KB 間的核心態 ring buffer。

(圖/SMC-R 連線 ring buffer)

其中,sndbuf  用於存放連線待傳送的資料,被註冊為 DMA 記憶體。本地 RNIC 裝置可以直接訪問 sndbuf,從中取走有效負載 (payload)。而  RMB 用於存放遠端節點 RNIC 寫入的資料,即連線待接收的資料。由於需要被遠端節點訪問,因此 RMB 被註冊為 RDMA 記憶體。
註冊 RDMA 記憶體的過程稱為 Memory Registration,主要完成以下操作:
  • 生成地址翻譯表
RDMA  使用者 (如本地/遠端 SMC-R 協議棧) 通常使用虛擬地址 (VA) 描述記憶體,而 RNIC 則通過實體地址 (PA) 定址。RNIC 從  WQE 或資料包中取得資料 VA 後通過查表得到 PA,進而訪問正確記憶體空間。因此 Memory Registration  首要任務就是形成目標記憶體的地址翻譯表。
  • Pin 住記憶體
現代 OS 會置換暫不使用的記憶體資料,這將導致地址翻譯表中的對映關係失效。因此,Memory Registration 會將目標記憶體 pin 住,鎖定 VA-to-PA 對映關係。
  • 限制記憶體訪問許可權
為避免記憶體非法訪問,Memory  Registration 會為目標記憶體生成兩把記憶體金鑰:Local Key (l_key) 和 Remote Key  (r_key)。記憶體金鑰實質是一串序列,本地或遠端憑藉  l_key 或 r_key 訪問 RDMA 記憶體,確保記憶體訪問合法。
SMC-R 中,遠端節點訪問本地 RMB 所需的 addr 與 r_key 被封裝為遠端訪問令牌 (Remote Token, rtoken),通過 CLC 訊息傳遞到遠端,使其具備遠端訪問本地 RMB 的許可權。
SMC-R 連線銷燬後,對應的 sndbuf 與 RMB 將被回收到 Link Group 維護的記憶體池中,供後續新連線複用,以此減小 RDMA 記憶體建立/銷燬對建連效能的影響。


(圖/sndbuf / RMB 記憶體池)


2.4 驗證 SMC-R Link

由於 first contact 場景下新建立的 SMC-R Link 尚未經過驗證,所以在正式使用 Link 傳輸應用資料前,通訊兩端會基於 Link 傳送 Link Layer Control (LLC) 訊息,用於檢驗 Link 是否可用。

(圖/使用 LLC 訊息確認 SMC Link 可用)LLC 訊息通常為請求-回覆模式,用於傳輸 Link 層面的控制資訊,如新增/刪除/確認 Link,確認/刪除 r_key 等。

(圖/LLC 訊息請求-回覆模式)
型別
說明
ADD_LINK
向 Link Group 中新增新的 Link。
CONFIRM_LINK
確認新建立的 Link 是否能夠正常工作。
DELETE_LINK
刪除一個特定的 Link 或整個 Link Group。
CONFIRM_RKEY
新增 RMB 時通知 Link 對端。
DELETE_RKEY
刪除一個或多個 RMB 時通知 Link 對端。
TEST_LINK
確認 Link 是否健康、活躍。
(表/典型 LLC 訊息含義)

LLC 訊息的傳輸基於 RDMA 的 SEND 操作完成,與之相對的是後文提到的 RDMA WRITE 操作。

(圖/SEND 操作)
SEND 操作又被稱為“雙邊操作”,這是因為 SEND 操作要通訊兩端都參與進來。一次 SEND 的傳輸過程為:
  • 接收端 RDMA 使用者 (SMC-R 核心協議棧) 向本地 RQ 中 Post RWQE,RWQE 中記錄了待接收資料的長度以及預留記憶體地址;
  • 傳送端 RDMA 使用者 (SMC-R 核心協議棧) 向本地 SQ 中 Post SWQE,SWQE 中記錄了待傳送資料長度和記憶體地址。傳送端 RNIC 根據 SWQE 記錄的資訊取出相應長度的資料傳送到對端;
  • 接收端 RNIC 接收到資料後,取出 RQ 中的第一個 RWQE,依照其中記錄的記憶體地址和長度存放資料;

通過在 Link 上收發 CONFIRM_LINK 型別的 LLC 訊息,通訊兩端確認了新建立的 Link 具備 RDMA 通訊的能力,可以用於傳輸 SMC-R 連線資料。

2.5 基於共享記憶體通訊

通過上述重重步驟,first contact 場景下 SMC-R 建連工作終於結束。接下來,應用程式將通過已建立好的 SMC-R 連線傳輸資料。
(圖/基於 RDMA 共享記憶體通訊)

應用程式下發到 SMC-R 連線中的資料由關聯的 Link 通過 RDMA WRITE 操作寫入遠端節點 RMB 中。

(圖/RDMA WRITE 操作)
與上文提到的 SEND 操作不同,RDMA WRITE 又被稱為“單邊操作”。這是因為資料傳輸只有 RDMA WRITE 發起的一方參與,而接收資料一方的 RDMA 使用者完全不參與資料傳輸,也不知曉資料的到來。一次 RDMA WRITE 操作過程如下:
  • 前期準備階段,接收端 RDMA 使用者 (SMC-R 核心協議棧) 將接收緩衝區註冊為 RDMA 記憶體,將遠端訪問金鑰 rkey 告知傳送端,使其擁有直接訪問接收端記憶體的許可權,這個過程我們在前文介紹過。
  • 傳送端  RDMA 使用者 (SMC-R 核心協議棧) 向 SQ 中 post SWQE。與 SEND 不同的是,RDMA WRITE 的 SWQE  中不僅包含資料在本地的記憶體地址和長度,還包含資料即將存放在接收端的記憶體地址,以及訪問接收端記憶體所需的 r_key。傳送端 RNIC 根據  SWQE 中記錄的資訊將資料傳輸到接收端。
  • 接收端 RNIC 核實資料包中的 r_key,將資料存放到指定記憶體地址中。此時的接收端 RDMA 使用者並不知道資料已經被寫入記憶體。
由於  RDMA WRITE 操作不需要接收端 RDMA  使用者參與,因此非常適合大量資料的直接寫入。不過,由於接收端並不知曉資料到來,傳送端寫入資料後需要通過 SEND 操作傳送控制訊息通知接收端。在  SMC-R 中,這種控制訊息稱為 Connection Data Control (CDC) 訊息。CDC 訊息中包含 RMB  相關控制資訊用以同步資料讀寫。
內容
含義
Sequence number
CDC 訊息序列號
Alert token
傳送此訊息的 SMC-R 連線 ID
Producer cursor
RMB 資料生產遊標 (寫者更新)
Producer cursor wrap seqno
RMB 資料生產 wrap 次數 (寫者更新)
Consumer cursor
RMB 資料消費 遊標 (讀者更新)
Consumer cursor wrap seqno
RMB 資料消費wrap 次數 (讀者更新)
(表/CDC 訊息主要內容)

在系列文章的第一篇中我們提到,SMC-R 名稱中的“共享記憶體”指的是接收端的 RMB。結合上述的 RDMA WRITE 操作與 CDC 訊息,SMC-R 的共享記憶體通訊流程可以總結為:

(圖/共享記憶體通訊細節)
  • 傳送端的資料通過 socket 介面,由應用緩衝區拷貝至核心 sndbuf 中 (圖中未畫出 sndbuf)
  • 協議棧通過 RDMA WRITE 單邊操作將資料寫入接收端 RMB 中
  • 傳送端通過 SEND 雙邊操作傳送 CDC 訊息告知接收端有新的資料到來
  • 接收端從 RMB 中拷貝資料至應用緩衝區
  • 接收端通過 SEND 雙邊操作傳送 CDC 訊息告知傳送端 RMB 中部分資料已被使用


2.6 連線關閉與資源銷燬

結束資料傳輸後,主動關閉方發起  SMC-R 連線關閉流程。與 TCP 相似,SMC-R 連線也存在半關閉/全關閉狀態。斷開的 SMC-R 連線與 Link (Group)  解綁,相關的 sndbuf 與 RMB 也將被回收到記憶體池中,等待複用。同時,與 SMC-R 連線關聯的 TCP 連線也進入關閉流程,最終釋放。

若 Link (Group) 中不再存在活躍的 SMC-R 連線,則等待一段時間後 (Linux 實現中為 10 mins) 進入Link (Group) 銷燬流程。銷燬  Link (Group) 將釋放與之相關的所有 RDMA 資源,包括 QP、CQ、PD、MR、以及所有的 sndbuf 與 RMB。Link  (Group) 銷燬後,再次建立 SMC-R 連線則需要重新經歷 first contact 流程。

三、總結

本篇作為  SMC-R 系列文章的第二篇,以 first contact 場景為例,介紹了完整的 SMC-R 通訊流程。包括:通過 TCP 握手確認對端  SMC-R 能力;使用 TCP 連線傳遞 CLC 訊息,交換 RDMA 資源、建立 RDMA 鏈路、建立 SMC-R 連線;通過 RDMA  SEND 操作傳送 LLC 訊息驗證 Link 可用;基於 Link 使用 RDMA WRITE 傳輸應用程式資料,並利用 CDC 訊息同步  RMB 中資料變化;關閉 SMC-R、TCP 連線,銷燬 RDMA 資源等一系列過程。
上述過程充分體現了 SMC-R 的 "hybrid" 特點。SMC-R  既利用了 TCP 的通用性 ,如通過 TCP 連線確認對端能力,建立 SMC-R 連線與 RDMA 鏈路;又利用了 RDMA 的高效能  ,如通過 Link 傳輸應用程式資料流量。正因為如此,SMC-R 能夠在相容現有 TCP/IP 生態系統關鍵功能的同時為 TCP  應用提供透明無感的網路效能提升。

參考說明:

[1]連結可移步龍蜥公眾號(OpenAnolis龍蜥)2022年4月20日相同推送檢視。


—— 完 ——

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70004278/viewspace-2888245/,如需轉載,請註明出處,否則將追究法律責任。

相關文章