系列解讀SMC-R:透明無感提升雲上 TCP 應用網路效能(一)| 龍蜥技術

OpenAnolis小助手發表於2022-03-31

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

引言

Shared  Memory Communication over RDMA (SMC-R) 是一種基於 RDMA 技術、相容 socket  介面的核心網路協議,由 IBM 提出並在 2017 年貢獻至 Linux 核心。SMC-R 能夠幫助 TCP 網路應用程式透明使用  RDMA,獲得高頻寬、低時延的網路通訊服務。 阿里云云上作業系統 Alibaba Cloud Linux 3 以及龍蜥社群開源作業系統 Anolis 8 配合神龍彈性 RDMA (eRDMA) 首次將 SMC-R 帶上雲上場景,助力雲上應用獲得更好的網路效能: 《技術揭祕:阿里雲釋出第四代神龍 ,SMC-R 讓網路效能提升 20%》。
由於 RDMA 技術在資料中心領域的廣泛使用,龍蜥社群高效能網路 SIG 認為 SMC-R 將成為下一代資料中心核心協議棧的重要方向之一。為此,我們對其進行了大量的優化,並積極將這些優化回饋到上游 Linux 社群。 目前,龍蜥社群高效能網路 SIG 是除 IBM 以外最大的 SMC-R 程式碼貢獻團體。由於 SMC-R 相關中文資料極少,我們希望通過一系列文章,讓更多的國內讀者瞭解並接觸 SMC-R,也歡迎有興趣的讀者加入龍蜥社群高效能網路 SIG 一起溝通交流 (二維碼見文末)
本篇作為系列文章的第一篇,將從巨集觀的角度帶領讀者初探 SMC-R。

一、從 RDMA 談起

Shared  Memory Communication over RDMA 的名稱包含了 SMC-R 網路協議的一大特點——基於 RDMA。因此,在介紹  SMC-R 前我們先來看看這個高效能網路領域中的絕對主力:Remote Direct Memory Access (RDMA) 技術。

1.1 為什麼需要 RDMA ?

隨著資料中心、分散式系統、高效能運算領域的快速發展,網路裝置效能進步顯著,主流物理網路頻寬已達到了 25-100 Gb/s,網路時延也進入了十微秒的時代。
然而, 網路裝置效能提升的同時一個問題也逐漸顯露:網路效能與 CPU 算力逐漸失配。 傳統網 絡中,負責網路報文封裝、解析和使用者態/核心態間資料搬運的 CPU 在高速增長的網路頻寬面前逐 漸顯得力不從心,面臨越來越大的壓力。
以  TCP/IP 網路的一次資料傳送與接收過程為例。傳送節點 CPU 首先將資料從使用者態記憶體拷貝至核心態記憶體,在核心態協議棧中完成資料包封裝;再由  DMA 控制器將封裝好的資料包搬運到 NIC 上傳送到對端。接收端 NIC 獲得資料包後通過 DMA  控制器搬運到核心態記憶體中,由核心協議棧解析,層層剝離幀首或包頭後再由 CPU 將有效負載 (payload)  拷貝到使用者態記憶體中,完成一次資料傳輸。
(圖/ 傳統 TCP/IP 網路傳輸模型
在這一過程中,CPU 需要負責:
1)使用者態與核心態間的資料拷貝。
2)網路報文的封裝、解析工作。
這些工作“重複低階”,佔用了大量 CPU 資源 (如 100 Gb/s 的網路卡跑到滿頻寬需要打滿多個 CPU 核資源),使得 CPU 在資料密集型場景下無法將算力用到更有益的地方。
所以,解決網路效能與 CPU 算力失配問題成為了高效能網路發展的關鍵。考慮到摩爾定律逐漸失效,CPU 效能短時間內發展緩慢, 將網路資料處理工作從 CPU 解除安裝到硬體裝置的思路就成為了主流解決方案。 這使得以往專用於特定高效能領域的 RDMA 在通用場景下得到愈來愈多的應用。

1.2 RDMA 的優勢

RDMA (Remote Direct Memory Access) 是一種遠端記憶體直接訪問技術,自提出以來經過 20 餘年的發展已經成為了高效能網路的重要組成。那麼 RDMA 是如何完成一次資料傳輸的呢?
圖/使用者態 RDMA 網路傳輸模型
RDMA 網路 (使用者態模式) 中,具備 RDMA 能力的網路卡 RNIC 直接從傳送端使用者態記憶體中取得資料,在網路卡中完成資料封裝後傳輸到接收端,再由接收端 RNIC 將資料解析剝離,將有效負載 (payload) 直接放入使用者態記憶體中完成資料傳輸。
這一過程中 CPU 除了必要的控制面功能外,幾乎不用參與資料傳輸。資料就像是通過 RNIC 直接寫入到遠端節點的記憶體中一樣。因此,與傳統網路相比,RDMA 將 CPU 從網路傳輸中解放了出來,使得網路傳輸就像是遠端記憶體直接訪問一樣方便快捷。
(圖/傳統網路與 RDMA 網路協議棧對比)
對比傳統網路協議,RDMA 網路協議具有以下三個特點:
1.旁路軟體協議棧
RDMA  網路依賴 RNIC 在網路卡內部完成資料包封裝與解析,旁路了網路傳輸相關的軟體協議棧。對於使用者態應用程式,RDMA  網路的資料路徑旁路了整個核心;對於核心應用程式,則旁路了核心中的部分協議棧。由於旁路了軟體協議棧,將資料處理工作解除安裝到了硬體裝置,因而 RDMA  能夠有效降低網路時延。
2.CPU 解除安裝
RDMA 網路中,CPU 僅負責控制面工作。資料路徑上,有效負載由 RNIC 的 DMA 模組在應用緩衝區和網路卡緩衝區中拷貝 (應用緩衝區提前註冊,授權網路卡訪問的前提下),不再需要 CPU 參與資料搬運,因此可以降低網路傳輸中的 CPU 佔用率。
3.記憶體直接訪問
RDMA 網路中,RNIC 一旦獲得遠端記憶體的訪問許可權, 即可直接向遠端記憶體中寫入或從遠端記憶體中讀出資料,不需要遠端節點參與,非常適合大塊資料傳輸。

二、回到 SMC-R

通過上述介紹,相信讀者對 RDMA 主要特點以及效能優勢有了初步的瞭解。不過,雖然 RDMA 技術能夠帶來可喜的網路效能提升,但是想使用 RDMA 透明提升現有 TCP 應用的網路效能仍有困難,這是因為 RDMA 網路的使用依賴一系列新的語義介面, 包括 ibverbs 介面與 rdmacm 介面 ( 後統稱 verbs 介面)。
部分  ibverbs與rdmacm介面 [1]
相較於傳統 POSIX socket 介面, verbs 介面數量多,且更接近硬體語義 對於已有的基於 POSIX socket 介面實現的 TCP 網路應用,想要享受 RDMA 帶來的效能紅利就不得不對應用程式進行大量改造,成本巨大。
因此,我們希望能夠在使用 RDMA 網路的同時沿用 socket 介面,使現有 socket 應用程式透明的享受 RDMA 服務。針對這一需求,業界提出了以下兩個方案:
其一,是基於 libvma 的使用者態方案。libvma  的原理是通過 LD_PRELOAD 來將應用所有 socket 呼叫引入自定義實現,在自定義實現中呼叫 verbs  介面,完成資料收發。但是,由於實現在使用者態,libvma 一方面缺少核心統一資源管理,另一方面對 socket 介面的相容性較差。
其二,是基於 SMC-R 的核心態方案。作為核心態協議棧,SMC-R  對 TCP 應用的相容性相較於使用者態方案會好很多,這種 100% 相容意味著極低的推廣和複用成本。此外,實現在核心態使得 SMC-R  協議棧中的 RDMA 資源能夠被使用者態不同程式共享,提高資源利用率的同時降低頻繁資源申請與釋放的開銷。不過,完全相容 socket  介面就意味著需要犧牲極致的 RDMA 效能 (因為使用者態 RDMA 程式可以做到資料路徑旁路核心與零拷貝,而 SMC-R 為了相容 socket  介面,無法實現零拷貝),但這也換來相容與易用,以及對比 TCP  協議棧的透明效能提升。未來,我們還計劃擴充介面,以犧牲小部分相容性的代價將零拷貝特性應用於 SMC-R,使它的效能得到進一步改善。

2.1 透明替換 TCP

SMC-R  is an open sockets over RDMA protocol that provides transparent  exploitation of RDMA (for TCP based applications) while preserving key  functions and qualities of service from the TCP/IP ecosystem that  enterprise level servers/network depend on!

摘自:

openfabrics.org/images/eventpresos/workshops2014/IBUG/presos/Thursday/PDF/05_SMC-R_Update.pdf


SMC-R 作為一套與 TCP/IP 協議平行,向上相容 socket 介面,底層使用 RDMA 完成共享記憶體通訊的核心協議棧,其設計意圖是為 TCP 應用提供透明的 RDMA 服務,同時保留了 TCP/IP 生態系統中的關鍵功能。
為此,SMC-R 在核心中定義了新的網路協議族 AF_SMC,其 proto_ops 與 TCP 行為完全一致。

/* must look like tcp */
static const struct proto_ops smc_sock_ops = {
  .family    = PF_SMC,
  .owner    = THIS_MODULE,
  .release  = smc_release,
  .bind    = smc_bind,
  .connect  = smc_connect,
  .socketpair  = sock_no_socketpair,
  .accept    = smc_accept,
  .getname  = smc_getname,
  .poll    = smc_poll,
  .ioctl    = smc_ioctl,
  .listen    = smc_listen,
  .shutdown  = smc_shutdown,
  .setsockopt  = smc_setsockopt,
  .getsockopt  = smc_getsockopt,
  .sendmsg  = smc_sendmsg,
  .recvmsg  = smc_recvmsg,
  .mmap    = sock_no_mmap,
  .sendpage  = smc_sendpage,
  .splice_read  = smc_splice_read,
};

由於 SMC-R 協議支援與 TCP 行為一致的 socket 介面,使用 SMC-R 協議非常簡單。總體來說有兩個方法:
(圖/SMC-R 的使用方法)
其一,使用 SMC-R 協議族 AF_SMC 開發。通過建立 AF_SMC 型別的 socket,應用程式的流量將進入到 SMC-R 協議棧;
其二,透明替換協議棧。將應用程式建立的 TCP 型別 socket 透明替換為 SMC 型別 socket。 透明替換可以通過以下兩種方式實現:

  • 使用  LD_PRELOAD 實現協議棧透明替換。在執行 TCP 應用程式時預載入一個動態庫。在動態庫中實現自定義 socket() 函式,將 TCP  應用程式建立的 AF_INET 型別 socket 轉換為 AF_SMC 型別的 socket,再呼叫標準 socket 建立流程,從而將  TCP 應用流量引入 SMC-R 協議棧。

int socket(int domain, int type, int protocol)
{
  int rc;
  if (!dl_handle)
    initialize();
  /* check if socket is eligible for AF_SMC */
  if ((domain == AF_INET || domain == AF_INET6) &&
      // see kernel code, include/linux/net.h, SOCK_TYPE_MASK
      (type & 0xf) == SOCK_STREAM &&
      (protocol == IPPROTO_IP || protocol == IPPROTO_TCP)) {
    dbg_msg(stderr, "libsmc-preload: map sock to AF_SMC\n");
    if (domain == AF_INET)
      protocol = SMCPROTO_SMC;
    else /* AF_INET6 */
      protocol = SMCPROTO_SMC6;
    domain = AF_SMC;
  }
  rc = (*orig_socket)(domain, type, protocol);
  return rc;
}

開源使用者態工具集 smc-tools 中的 smc_run 指令即實現上述功能 [2]

  • 通過 ULP + eBPF 實現協議棧透明替換。 SMC-R 支援 TCP ULP 是 龍蜥社群高效能網路 SIG 貢獻到上游 Linux 社群的新特性。 使用者可以通過 setsockopt() 指定新建立的 TCP 型別 socket 轉換為 SMC 型別 socket。 同時,為避免應用程式改造,使用者可以通過  eBPF 在合適的 hook 點 (如  BPF_CGROUP_INET_SOCK_CREATE、BPF_CGROUP_INET4_BIND、BPF_CGROUP_INET6_BIND  等) 注入 setsockopt(),實現透明替換。 這種方式更適合在容器場景下可以依據自定義規則,批量的完成協議轉換。

static int smc_ulp_init(struct sock *sk)
{
    struct socket *tcp = sk->sk_socket;
    struct net *net = sock_net(sk);
    struct socket *smcsock;
    int protocol, ret;
    
    /* only TCP can be replaced */
    if (tcp->type != SOCK_STREAM || sk->sk_protocol != IPPROTO_TCP ||
        (sk->sk_family != AF_INET && sk->sk_family != AF_INET6))
        return -ESOCKTNOSUPPORT;
    /* don't handle wq now */
    if (tcp->state != SS_UNCONNECTED || !tcp->file || tcp->wq.fasync_list)
        return -ENOTCONN;
    
    if (sk->sk_family == AF_INET)
        protocol = SMCPROTO_SMC;
    else
        protocol = SMCPROTO_SMC6;
    
    smcsock = sock_alloc();
    if (!smcsock)
        return -ENFILE;
    
    <...>
}

SEC("cgroup/connect4")
int replace_to_smc(struct bpf_sock_addr *addr)
{
    int pid = bpf_get_current_pid_tgid() >> 32;
    long ret;
    
    /* use-defined rules/filters, such as pid, tcp src/dst address, etc...*/
    if (pid != DESIRED_PID)
        return 0;
    
    <...>
        
    ret = bpf_setsockopt(addr, SOL_TCP, TCP_ULP, "smc", sizeof("smc"));
    if (ret) {
        bpf_printk("replace TCP with SMC error: %ld\n", ret);
        return 0;
    }
    return 0;
}


綜合上述介紹,TCP 應用程式 透明 使用 RDMA 服務可以體現在以下兩個方面:
2.2 S MC-R 架構
(圖/SMC-R 架構)
SMC-R 協議棧在系統內部處於 socket 層以下,RDMA 核心 verbs 層以上。是一個具備 "hybrid" 特點的核心網路協議棧。這裡的 "hybrid" 主要體現在 SMC-R 協議棧中混合了 RDMA 流與 TCP 流:

資料流量基於 RDMA 網路傳輸

SMC-R 使用 RDMA 網路來傳遞使用者態應用程式的資料,使應用程式透明的享受到 RDMA 帶來的效能紅利,即上圖中黃色部分所示。
傳送端應用程式的資料流量通過  socket 介面從應用緩衝區來到核心記憶體空間;接著通過 RDMA 網路直接寫入遠端節點的一個核心態 ringbuf (remote  memory buffer, RMB) 中;最後由遠端節點 SMC-R 協議棧將資料從 RMB 拷貝到接收端應用緩衝區中。
圖/SMC-R 共享記憶體通訊
顯然,SMC-R 名稱中的共享記憶體通訊指的就是基於遠端節點 RMB 進行通訊。與傳統的本地共享記憶體通訊相比,SMC-R 將通訊兩端擴充為了兩個分離的節點,利用 RDMA 實現了基於“遠端”共享記憶體的通訊。
(圖/主流 RDMA 實現)
目前, RDMA 網路的主流實現有三種:InfiniBand、RoCE 和 iWARP。 其中,RoCE  作為在高效能與高成本中權衡的方案,在使用 RDMA  的同時相容乙太網協議,既保證了不錯的網路效能,同時也降低了網路組建成本,因此倍受企業青睞,Linux 上游社群版本的 SMC-R 也因此使用  RoCE v1 和 v2 作為其 RDMA 實現。
而 iWARP 則是基於 TCP 實現了 RDMA,突破了其餘兩者對無損網路的剛性需求。iWARP 具備更好的可擴充性,非常適用於雲上場景。阿里雲彈性 RDMA (eRDMA) 基於 iWARP 將 RDMA 技術帶到雲上。 阿里雲作業系統 Alibaba Cloud Linux 3 與龍蜥社群開源作業系統 Anolis 8 中的 SMC-R 也進一步支援了 eRDMA (iWARP),使雲上使用者透明無感的使用 RDMA 網路。

依賴 TCP 流建立連線

除 RDMA 流外,SMC-R 還會為每個 SMC-R 連線配備一條 TCP 連線,兩者具有相同的生命週期。TCP 流在 SMC-R 協議棧中主要擔負以下職責:
1)動態發現對端 SMC-R 能力
在  SMC-R 連線建立前,通訊兩端並不知道對端是否同樣支援 SMC-R。因此,兩端會首先建立一條 TCP 連線。在 TCP  連線三次握手的過程中通過傳送攜帶特殊的 TCP 選項的 SYN 包表示支援 SMC-R,同時檢驗對端傳送的 SYN 包中的 TCP 選項。
(圖/表示 SMC-R 能力的 TCP 選項)
2)回退
若在上述過程中,通訊兩端其一無法支援  SMC-R 協議,或是在 SMC-R 連線建立過程中無法繼續,則 SMC-R 協議棧將回退至 TCP 協議棧。回退過程中,SMC-R  協議棧將應用程式持有的檔案描述符對應的 socket 替換為 TCP 連線的 socket。應用程式的流量將通過這條 TCP  連線承載,以保證資料傳輸不會中斷。
3)幫助建立 SMC-R 連線
若通訊兩端均支援 SMC-R 協議,則將通過 TCP 連線交換 SMC-R 連線建立訊息 (建連過程類似 SSL 握手)。此外,還需要使用此 TCP 連線交換兩側的 RDMA 資源資訊,幫助建立用於資料傳輸的 RDMA 鏈路。
通過上述介紹,相信讀者對 SMC-R 總體架構有了初步的瞭解。SMC-R 作為一個 "hybrid" 解決方案,充分利用了 TCP 流的通用性和 RDMA 流的高效能。後面的文章中我們將對 SMC-R 中的一次完整通訊過程進行分析,屆時讀者將進一步體會到 "hybrid" 這一特點。
本篇作為 SMC-R 系列文章的首篇,希望能夠起到一個引子的作用。回顧本篇,我們主要回答了這幾個問題:
1、為什麼要基於 RDMA ?
因為 RDMA 能夠帶來網路效能提升 (吞吐/時延/CPU佔用率);
2、為什麼 RDMA 能夠帶來效能提升?
因為旁路了大量軟體協議棧,將 CPU 從網路傳輸過程中解放出來,使資料傳輸就像直接寫入遠端記憶體一樣簡單;
3、為什麼需要 SMC-R ?
因為 RDMA 應用基於 verbs 介面實現,已有的 TCP socket 應用若想使用 RDMA 技術改造成本高;
4、SMC-R 有什麼優勢?
SMC-R 完全相容 socket 介面,模擬 TCP socket 介面行為。使 TCP 使用者態應用程式能夠透明使用 RDMA 服務,不做任何改造就可以享受 RDMA 帶來的效能優勢。
5、 SMC-R 的架構特點?
SMC-R 架構具有 "hybrid" 的特點,融合了 RDMA 流與 TCP 流。SMC-R 協議使用 RDMA 網路傳輸應用資料,使用 TCP 流確認對端 SMC-R 能力、幫助建立 RDMA 鏈路。

參考引用連結可移步龍蜥公眾號(OpenAnolis龍蜥)2022年3月30日相同推送檢視。(若有程式碼不明部分也可同樣移步公眾號檢視)
—— 完 ——
加入龍蜥社群

加入微信群:新增社群助理-龍蜥社群小龍(微信:openanolis_assis),備註【龍蜥】與你同在;加入釘釘群:掃描下方釘釘群二維碼。歡迎開發者/使用者加入龍蜥社群(OpenAnolis)交流,共同推進龍蜥社群的發展,一起打造一個活躍的、健康的開源作業系統生態!

關於龍蜥社群

龍蜥社群OpenAnolis)是由 企事業單位、高等院校、科研單位、非營利性組織、個人等在自願、平等、開源、協作的基礎上組成的非盈利性開源社群。龍蜥社群成立於 2020 年 9 月,旨在構建一個開源、中立、開放的Linux 上游發行版社群及創新平臺。

龍蜥社群成立的短期目標是開發龍蜥作業系統(Anolis OS)作為 CentOS 停服後的應對方案,構建一個相容國際 Linux 主流廠商的社群發行版。中長期目標是探索打造一個面向未來的作業系統,建立統一的開源作業系統生態,孵化創新開源專案,繁榮開源生態。

目前, 龍蜥OS 8.4 已釋出,支援 X86_64 、Arm64、LoongArch 架構,完善適配飛騰、海光、兆芯、鯤鵬、龍芯等晶片,並提供全棧國密支援。

歡迎加入我們,一起打造面向未來的開源作業系統!


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

相關文章