范實(shí)戰(zhàn):RoCEv2包格式抓包與PFC/MTU排障)
簡(jiǎn)介《InfiniBand架構(gòu)規(guī)范1.4版》是面向數(shù)據(jù)中心、高性能計(jì)算與存儲(chǔ)網(wǎng)絡(luò)研發(fā)人員的IBTA官方標(biāo)準(zhǔn)文檔適合網(wǎng)絡(luò)架構(gòu)師、驅(qū)動(dòng)與固件工程師及RDMA學(xué)習(xí)者系統(tǒng)查閱。全文以Volume 1通用規(guī)范為主體覆蓋InfiniBand基本概念、協(xié)議層次、HCA、CA、交換機(jī)與點(diǎn)對(duì)點(diǎn)串行連接等組件以及隊(duì)列對(duì)、完成隊(duì)列、QoS、錯(cuò)誤處理、連接管理與路由等核心機(jī)制。包內(nèi)共1個(gè)PDF文件約12.64MB為2020年4月發(fā)布的Release 1.4最終版含修訂記錄、虛擬化附錄與RoCE-v1、RoCE-v2附錄可據(jù)此理解無(wú)損以太網(wǎng)上的RDMA實(shí)現(xiàn)及IPv4/IPv6支持差異。已有2859人學(xué)習(xí)便于對(duì)照標(biāo)準(zhǔn)原文核查RoCEv2部署、虛擬化場(chǎng)景與協(xié)議細(xì)節(jié)也可作為IB網(wǎng)絡(luò)設(shè)計(jì)、問(wèn)題定位和版本演進(jìn)梳理的案頭參考。1. 為什么一份 2020 年的 IB 規(guī)范還值得翻從一次 RDMA 寫(xiě)帶寬掉底說(shuō)起InfiniBand 架構(gòu)規(guī)范卷 1 的 1.4 版是 2020 年定稿的 IB 標(biāo)準(zhǔn)文檔RoCEv2 的封裝、虛擬化附錄以及包格式字段都能在這份規(guī)范里找到對(duì)應(yīng)條款。前陣子幫人看一個(gè) RDMA 寫(xiě)帶寬掉底的問(wèn)題小包 ping 正常ib_write_bw一跑大包就掉到接近零換網(wǎng)卡、換線都沒(méi)用最后翻回規(guī)范第 5 章的 BTH 和包格式再對(duì)照第 3 章的 QoS 與 MTU 約束才把問(wèn)題鎖在 PFC 優(yōu)先級(jí)和路徑 MTU 不一致上。這份卷 1 適合做 RDMA 應(yīng)用、驅(qū)動(dòng)適配、鏈路測(cè)試和集群運(yùn)維的人放在手邊當(dāng)查詢手冊(cè)它不是讀完就能跑的命令集但能讓你在抓包和計(jì)數(shù)器之間找到能對(duì)得上的字段依據(jù)。2. 規(guī)范卷 1 的骨架從目錄到四層模型怎么讀2.1 文檔組織與版本差異1.4 到底加了什么卷 1 的主干并不厚但章節(jié)之間的引用關(guān)系很密。第 1 章是概念總覽第 2 章是詞匯表第 3 章講架構(gòu)組件、隊(duì)列、保護(hù)域、分區(qū)、虛擬通道和服務(wù)質(zhì)量第 4 章講尋址第 5 章講數(shù)據(jù)包格式。真正的查詢?nèi)肟谠诘?3 章和第 5 章前者告訴你一個(gè) QP 為什么需要 PD 和 P_Key后者告訴你抓到的 12 字節(jié) BTH 里每個(gè)字段對(duì)應(yīng)什么。1.4 版把虛擬化附錄與 RoCE-v1、RoCE-v2 附錄補(bǔ)了進(jìn)來(lái)同時(shí)修正了早期版本第 9 章遺留的錯(cuò)誤這些變化對(duì)做 RoCE 和虛擬化直通的人是直接可用的材料。版本差異不必背但要知道自己手里的實(shí)現(xiàn)對(duì)應(yīng)哪一版。下面這張表按規(guī)范里的修訂記錄整理讀舊代碼或舊驅(qū)動(dòng)時(shí)尤其有用版本發(fā)布日期關(guān)鍵變化讀的時(shí)候關(guān)注什么1.02000-09-26首個(gè)正式版本基礎(chǔ)架構(gòu)與包格式的起點(diǎn)1.0.a2001-06-19只做錯(cuò)誤修正不加新功能舊實(shí)現(xiàn)兼容性對(duì)照1.12002-11-06增加新特性更新 SA 與 CM 類連接管理與服務(wù)代理1.22004-09-07增加附錄 A7 到 A10整合勘誤附錄編號(hào)開(kāi)始變多1.2.12004-11-30增加附錄 A11 到 A13注意第 9 章早期錯(cuò)誤1.32015-03-03把 XRC 整合進(jìn)主體XRC 不再只是附錄1.42020-04-07增加虛擬化、RoCE-v1、RoCE-v2 附錄修正第 9 章錯(cuò)誤虛擬化與 RoCE 落地我一般不會(huì)從第 1 頁(yè)順讀而是先用文本工具把目錄和附錄抽出來(lái)建一個(gè)“問(wèn)題到章節(jié)”的索引。常見(jiàn)做法是# 把 PDF 轉(zhuǎn)成保留版式的文本便于 grep 章節(jié)和附錄 pdftotext -layout ib-vol1-1.4.pdf ib-vol1-1.4.txt # 找章、附錄、RoCE、Virtualization 這些關(guān)鍵詞所在行 grep -nE ^Chapter|^Annex|RoCE|Virtualization ib-vol1-1.4.txt | head -80pdftotext的-layout參數(shù)會(huì)盡量保留原始排版表格和目錄不會(huì)擠成一行g(shù)rep -nE里的^Chapter和^Annex用來(lái)定位一級(jí)章節(jié)RoCE和Virtualization用來(lái)直接跳到 1.4 新增的附錄。文件名按你手里的實(shí)際文件替換即可這里只是占位。抽完文本后先看第 3 章和第 5 章的標(biāo)題層級(jí)再?zèng)Q定要不要讀第 4 章尋址能省掉大量來(lái)回翻頁(yè)。注意不同 PDF 閱讀器對(duì)目錄書(shū)簽的生成質(zhì)量不一樣文本抽取出來(lái)的章節(jié)號(hào)可能帶空格或換行g(shù)rep 時(shí)把模式放寬一點(diǎn)別只匹配一種寫(xiě)法。2.2 四層架構(gòu)與組件CA、交換機(jī)、路由器、管理實(shí)體規(guī)范把 IB 分成物理層、鏈路層、網(wǎng)絡(luò)層、傳輸層再加上層協(xié)議。物理層管 SerDes、碼型和鏈路速率鏈路層管 LRH、流量控制、VL 和鏈路級(jí)重傳網(wǎng)絡(luò)層管 GRH 和跨子網(wǎng)路由傳輸層管 BTH、QP、PSN、ACK 和可靠傳輸。組件側(cè)最常打交道的四類是 HCA、交換機(jī)、路由器和通道適配器里的管理實(shí)體。HCA 是主機(jī)側(cè)發(fā)起和接收 RDMA 的端點(diǎn)交換機(jī)負(fù)責(zé)子網(wǎng)內(nèi)轉(zhuǎn)發(fā)路由器負(fù)責(zé)子網(wǎng)間轉(zhuǎn)發(fā)SM 和 SMA 負(fù)責(zé)子網(wǎng)初始化與配置下發(fā)。做應(yīng)用的人通常只關(guān)心 HCA 和 QP做鏈路排障的人必須把交換機(jī)側(cè)的分區(qū)、SL 到 VL 映射、MTU 一起看。組件規(guī)范里的角色落地時(shí)看什么HCA主機(jī)通道適配器承載 QP、CQ、PD、MR端口狀態(tài)、GID 表、MTU、P_Key交換機(jī)子網(wǎng)內(nèi)按 LID 轉(zhuǎn)發(fā)維護(hù)分區(qū)和 VL端口計(jì)數(shù)器、PFC 水線、SL-VL 映射路由器子網(wǎng)間按 GRH 轉(zhuǎn)發(fā)路由表、MTU、跨子網(wǎng) GIDSM/SMA子網(wǎng)管理下發(fā) LID、分區(qū)、路由SM 是否運(yùn)行、配置是否下發(fā)成功GSA通用服務(wù)代理服務(wù)注冊(cè)、名稱解析、連接管理選型上原生 IB 和 RoCE 的分界不在“誰(shuí)更快”而在管理模型和網(wǎng)絡(luò)邊界。原生 IB 有集中的 SMLID 路由和分區(qū)配置由 SM 下發(fā)鏈路層自帶信用流控RoCEv2 把 IB 傳輸層套在 UDP 上跨 IP 網(wǎng)段要靠路由和 DSCP/ECN無(wú)損能力依賴 PFC 和 ECN 配置。你要是做跨網(wǎng)段、多租戶或云上環(huán)境RoCEv2 的附錄比原生 IB 的鏈路層章節(jié)更值得先讀。檢查本機(jī)能力時(shí)用下面這組命令就夠# 看 PCIe 上是否有 RDMA 或高速以太網(wǎng)設(shè)備 lspci -nn | grep -i -E infiniband|ethernet # 看 RDMA 設(shè)備、端口狀態(tài)、MTU、GID 表 ibv_devinfo -v # 看 RDMA 設(shè)備與 netdev 的綁定關(guān)系 rdma link showibv_devinfo -v是最值得記住的一條它會(huì)把端口狀態(tài)、鏈路層類型、MTU、GID 表都列出來(lái)GID 表里的 index 就是后面ib_write_bw -x要填的值。rdma link show用來(lái)確認(rèn)你操作的 RDMA 設(shè)備到底綁在哪個(gè)網(wǎng)卡上避免抓包抓錯(cuò)接口。lspci只是用來(lái)確認(rèn)設(shè)備被系統(tǒng)識(shí)別不參與后續(xù)參數(shù)選擇。2.3 從規(guī)范到實(shí)驗(yàn)搭一個(gè)最小 IB/RoCE 驗(yàn)證環(huán)境最小驗(yàn)證環(huán)境不需要復(fù)雜拓?fù)鋬膳_(tái)支持 RDMA 的機(jī)器一塊能跑 RoCEv2 的網(wǎng)卡交換機(jī)直連或背靠背直連都行。軟件側(cè)需要 rdma-core、perftest、iproute2、tcpdump 和 Wireshark。先把兩端網(wǎng)卡配到同一網(wǎng)段MTU 設(shè)成 4092 或 1024再用ping -M do驗(yàn)證路徑 MTU最后跑ib_write_bw。這里的關(guān)鍵不是把帶寬跑多高而是讓“規(guī)范字段、抓包結(jié)果、計(jì)數(shù)器”三件事能對(duì)上。# node-a配置網(wǎng)卡與 MTUens1f0 換成你的實(shí)際網(wǎng)卡名 sudo ip link set ens1f0 mtu 4092 up sudo ip addr add 192.168.100.1/24 dev ens1f0 # node-b配置對(duì)端 sudo ip link set ens1f0 mtu 4092 up sudo ip addr add 192.168.100.2/24 dev ens1f0 # 在 node-a 上驗(yàn)證路徑 MTU-M do 禁止分片 ping -M do -s 4000 192.168.100.2ip link set mtu 4092里的 4092 是 IB/RoCE 常見(jiàn)的 MTU 檔位不是以太網(wǎng)默認(rèn)的 1500兩端和中間交換機(jī)必須一致。ping -M do -s 4000用來(lái)確認(rèn) 4000 字節(jié)負(fù)載能否不分片通過(guò)如果這里就失敗后面的 RDMA 大包一定翻車。網(wǎng)段只是示例換成你環(huán)境里的地址即可。接下來(lái)用 perftest 建立最小流量。服務(wù)端先起客戶端再連# node-a服務(wù)端rxe0 換成 ibv_devinfo 里看到的設(shè)備名 ib_write_bw -d rxe0 -x 3 --report_gbits # node-b客戶端-x 指定 GID index地址為服務(wù)端 IP ib_write_bw -d rxe0 -x 3 --report_gbits 192.168.100.1-d指定 RDMA 設(shè)備-x指定 GID 表索引--report_gbits讓輸出用 Gb/s 顯示。GID index 不是隨便填的RoCEv2 的 IPv4 GID 和 RoCEv1 的 GID 在表里是不同的條目填錯(cuò)會(huì)表現(xiàn)為建鏈?zhǔn)』蚺懿黄饋?lái)。先用ibv_devinfo -v看 GID 表確認(rèn)哪個(gè) index 對(duì)應(yīng) IPv4 或 IPv6再填到-x后面。兩端 MTU 不一致時(shí)小包能過(guò)、大包會(huì)卡住這也是后面避坑章要展開(kāi)的典型現(xiàn)象。參數(shù)常見(jiàn)值作用MTU1024 / 4092決定單包負(fù)載上限兩端和交換機(jī)要一致GID index由ibv_devinfo -v查出選擇 RoCEv1 或 RoCEv2 的地址族PFC 優(yōu)先級(jí)3 或 4 等業(yè)務(wù)優(yōu)先級(jí)給 RDMA 流量做無(wú)損隊(duì)列ECN 閾值按交換機(jī)緩存和線速調(diào)讓交換機(jī)提前標(biāo)記擁塞-x與 GID 表對(duì)應(yīng)perftest 選擇本地 GID提示背靠背直連時(shí)沒(méi)有交換機(jī)PFC 和 ECN 的調(diào)優(yōu)空間很小先把 MTU、GID、防火墻這三件事排掉再懷疑網(wǎng)卡或驅(qū)動(dòng)。3. 隊(duì)列對(duì)、傳輸服務(wù)與包格式把規(guī)范里的字段落到抓包里3.1 QP、CQ、PD、MR 的關(guān)系與選型QP 是發(fā)送隊(duì)列和接收隊(duì)列的組合應(yīng)用把工作請(qǐng)求貼到 QP 上硬件按順序執(zhí)行完成后把完成事件放到 CQ。PD 是保護(hù)域QP、MR 都要掛在同一個(gè) PD 下才能互相訪問(wèn)MR 注冊(cè)內(nèi)存后拿到 lkey 和 rkey本地訪問(wèn)用 lkey遠(yuǎn)端訪問(wèn)用 rkey。CQ 負(fù)責(zé)回收完成事件避免應(yīng)用輪詢 QP。選型上RC 適合點(diǎn)對(duì)點(diǎn)可靠傳輸U(kuò)C 適合不需要可靠性的場(chǎng)景UD 適合小消息和多播RD 適合可靠數(shù)據(jù)報(bào)XRC 適合大量 QP 共享一個(gè)接收端緩存的場(chǎng)景。規(guī)范第 3 章把這些對(duì)象的關(guān)系畫(huà)得很清楚但落地時(shí)最容易錯(cuò)的是 PD 和 MR 的歸屬Q(mào)P 和 MR 不在同一個(gè) PD遠(yuǎn)端寫(xiě)就會(huì)失敗。對(duì)象作用常見(jiàn)錯(cuò)誤QP發(fā)送/接收隊(duì)列兩端 QP 類型不一致CQ完成事件隊(duì)列CQ 深度太小事件被覆蓋PD保護(hù)域QP 與 MR 跨 PDMR注冊(cè)內(nèi)存權(quán)限沒(méi)開(kāi) remote writelkey/rkey本地/遠(yuǎn)端訪問(wèn)密鑰rkey 傳錯(cuò)或過(guò)期做最小驗(yàn)證時(shí)ibv_rc_pingpong和ibv_ud_pingpong比直接寫(xiě)代碼更快暴露 QP 類型問(wèn)題。先跑通 pingpong再跑ib_write_bw能把建鏈問(wèn)題和帶寬問(wèn)題分開(kāi)。# 服務(wù)端RC 類型 pingpong ibv_rc_pingpong -d rxe0 -g 3 # 客戶端連接服務(wù)端 ibv_rc_pingpong -d rxe0 -g 3 192.168.100.1-g是 GID index和ib_write_bw的-x含義相近但參數(shù)名不同別混用。RC pingpong 能通說(shuō)明 QP 建鏈、GID、PD 這些基礎(chǔ)路徑?jīng)]問(wèn)題不通就先別急著調(diào)帶寬。3.2 傳輸服務(wù) RC/UC/UD/RD 與 XRC 的邊界RC 是可靠連接一個(gè) QP 對(duì)一端包有 PSN有 ACK/NAK亂序和丟包由硬件重傳UC 是不可靠連接沒(méi)有重傳UD 是不可靠數(shù)據(jù)報(bào)一個(gè) QP 可以收多個(gè)遠(yuǎn)端消息有 4KB 左右的限制RD 是可靠數(shù)據(jù)報(bào)帶重傳但不像 RC 那樣強(qiáng)綁定單連接X(jué)RC 在 1.3 版整合進(jìn)主體1.4 版繼續(xù)保留適合大規(guī)模集群里減少接收端 QP 緩存壓力。選型時(shí)不要只看“可靠”兩個(gè)字UD 在多播和服務(wù)發(fā)現(xiàn)里很常見(jiàn)RD 在需要可靠但不想維護(hù)大量連接時(shí)有用XRC 則要看網(wǎng)卡和驅(qū)動(dòng)是否支持。服務(wù)類型連接性可靠性典型場(chǎng)景注意點(diǎn)RC一對(duì)一可靠、有序存儲(chǔ)、數(shù)據(jù)庫(kù)、HPCQP 數(shù)量隨連接數(shù)增長(zhǎng)UC一對(duì)一不可靠低開(kāi)銷傳輸丟包不重傳UD一對(duì)多不可靠多播、服務(wù)發(fā)現(xiàn)消息大小受限RD多對(duì)一/多對(duì)多可靠大規(guī)模消息實(shí)現(xiàn)支持度要看驅(qū)動(dòng)XRC多對(duì)一共享可靠大規(guī)模集群需要兩端和網(wǎng)卡支持規(guī)范里對(duì) XRC 的描述在 1.3 之后進(jìn)入主體讀的時(shí)候注意它和 RC 的完成語(yǔ)義差異XRC 的發(fā)送端 QP 與接收端共享接收隊(duì)列完成事件仍然回到發(fā)送端 CQ但接收端資源模型變了。做應(yīng)用適配時(shí)先確認(rèn) verbs 接口和驅(qū)動(dòng)版本是否支持再?zèng)Q定要不要把 RC 改成 XRC。測(cè)試時(shí)可以用對(duì)應(yīng)的 pingpong 工具但不同發(fā)行版的 perftest 子命令名不完全一樣先ibv_xrc_pingpong --help看有沒(méi)有編譯進(jìn)去。3.3 數(shù)據(jù)包頭部逐層拆解LRH/GRH/BTH/RETH/AETH原生 IB 的數(shù)據(jù)包從 LRH 開(kāi)始8 字節(jié)里面有 SL、VL、LID 和鏈路層字段跨子網(wǎng)時(shí)加 GRH40 字節(jié)里面有 SGID、DGID、跳數(shù)限制和流量類別傳輸層從 BTH 開(kāi)始12 字節(jié)里面有 OpCode、P_Key、DestQP、AckReq 和 PSNRDMA Write 會(huì)帶 RETH16 字節(jié)里面有虛擬地址和 rkeyACK 帶 AETH4 字節(jié)里面有 syndrome 和 MSN。RoCEv2 沒(méi)有 LRH以太網(wǎng)/IP/UDP 頭替代了鏈路和網(wǎng)絡(luò)層UDP 目的端口 4791 之后直接是 BTH。抓包時(shí)如果只看到 UDP 而解不出 BTH多半是解析器沒(méi)開(kāi)或者抓包點(diǎn)截?cái)嗔?。頭部長(zhǎng)度關(guān)鍵字段抓包時(shí)看什么LRH8 字節(jié)SL、VL、DLID、SLID原生 IB 鏈路內(nèi)轉(zhuǎn)發(fā)GRH40 字節(jié)SGID、DGID、Hop Limit、TClass跨子網(wǎng)路由BTH12 字節(jié)OpCode、P_Key、DestQP、PSN傳輸操作與隊(duì)列匹配RETH16 字節(jié)VA、rkey、DMALenRDMA Write/Read 遠(yuǎn)端地址AETH4 字節(jié)Syndrome、MSNACK 與完成狀態(tài)DETH8 字節(jié)QPN、Q_KeyUD 數(shù)據(jù)報(bào)ImmDt4 字節(jié)Immediate Data帶立即數(shù)的發(fā)送RoCEv2 的 BTH 解析可以寫(xiě)一個(gè)小腳本把 UDP 4791 的負(fù)載前 12 字節(jié)拿出來(lái)看。字段偏移按規(guī)范第 5 章OpCode 在 byte0P_Key 在 byte2 到 byte3DestQP 在 byte5 到 byte7PSN 在 byte9 到 byte11。不同擴(kuò)展頭會(huì)跟在 BTH 后面但 BTH 本身固定 12 字節(jié)先把這四個(gè)字段抽出來(lái)就能定位大部分問(wèn)題。from scapy.all import rdpcap, UDP, Raw def parse_rocev2(pcap_file): for pkt in rdpcap(pcap_file): # RoCEv2 的約定是 UDP 目的端口 4791 if UDP in pkt and pkt[UDP].dport 4791 and Raw in pkt: bth bytes(pkt[Raw].load)[:12] if len(bth) 12: continue opcode bth[0] pkey int.from_bytes(bth[2:4], big) dest_qp int.from_bytes(bth[5:8], big) psn int.from_bytes(bth[9:12], big) print(fopcode0x{opcode:02x} pkey0x{pkey:04x} fdest_qp0x{dest_qp:06x} psn{psn}) parse_rocev2(roce.pcap)這段腳本只做最粗的字段抽取bth[0]是 OpCode高幾位區(qū)分傳輸類型低幾位區(qū)分具體操作bth[2:4]是 P_Key用來(lái)確認(rèn)分區(qū)是否匹配bth[5:8]是 24 位 DestQP和接收端 QP 號(hào)對(duì)不上就會(huì)丟包bth[9:12]是 24 位 PSN用來(lái)判斷亂序和重傳。腳本沒(méi)有處理 VLAN、IP 分片和擴(kuò)展頭生產(chǎn)抓包建議先用 Wireshark 的 RoCEv2 解析器看一遍再用腳本做批量統(tǒng)計(jì)。3.4 用 tcpdump/Wireshark 驗(yàn)證 RoCEv2 頭部字段抓包點(diǎn)選在業(yè)務(wù)網(wǎng)卡上過(guò)濾器只留 UDP 4791別把整臺(tái)機(jī)器的流量都抓下來(lái)。-s 0抓全包-w直接寫(xiě)文件避免終端輸出拖慢抓包。# 在業(yè)務(wù)網(wǎng)卡上抓 RoCEv2ens1f0 換成實(shí)際網(wǎng)卡名 sudo tcpdump -i ens1f0 -s 0 -w roce.pcap udp port 4791 # 抓完用 Wireshark 打開(kāi)過(guò)濾條件 # udp.port 4791 rocev2-i指定網(wǎng)卡-s 0表示不截?cái)鄒dp port 4791是 BPF 過(guò)濾器。Wireshark 里如果rocev2過(guò)濾條件不生效先看版本是否帶 RoCEv2 解析器或者直接用udp.port 4791看原始負(fù)載。抓到包后重點(diǎn)看三件事OpCode 是否和預(yù)期操作一致DestQP 是否等于接收端 QP 號(hào)PSN 是否連續(xù)。小包正常大包異常時(shí)再看 RETH 里的 DMALen 和路徑 MTU通常能直接看到分片或長(zhǎng)度超限。注意交換機(jī)鏡像口可能把包截?cái)嘧サ降?BTH 后面缺少 RETH 不代表鏈路問(wèn)題先確認(rèn)鏡像口沒(méi)有設(shè)置截?cái)嚅L(zhǎng)度。4. RoCE v1/v2 附錄怎么用從無(wú)損以太網(wǎng)到 IP 可路由4.1 RoCEv1 與 RoCEv2 的封裝差異RoCEv1 把 IB 傳輸層直接套在以太網(wǎng)鏈路層上用 EtherType 0x8915 標(biāo)識(shí)不能跨 IP 網(wǎng)段廣播域就是它的邊界。RoCEv2 把 IB 傳輸層套在 UDP 上目的端口 4791下面走 IPv4 或 IPv6因此可以跨網(wǎng)段路由也可以被 ECMP 哈希。1.4 版把 RoCE-v1 和 RoCE-v2 附錄都補(bǔ)了進(jìn)來(lái)讀的時(shí)候重點(diǎn)看封裝圖、GID 格式和 UDP 端口約定不要把 v1 的 GID 表索引直接套到 v2 上。項(xiàng)目RoCEv1RoCEv2封裝位置以太網(wǎng)鏈路層UDP/IP標(biāo)識(shí)EtherType 0x8915UDP 目的端口 4791跨網(wǎng)段不支持支持 IPv4/IPv6GID 類型鏈路本地IPv4/IPv6 GID常見(jiàn)問(wèn)題廣播域限制ACL、ECMP、分片選型上同一廣播域、追求簡(jiǎn)單封裝的場(chǎng)景可以用 v1跨網(wǎng)段、云環(huán)境、需要 IP 路由的場(chǎng)景用 v2。v2 的代價(jià)是多了 IP 層的分片、ACL 和 ECMP 影響調(diào)優(yōu)時(shí)要同時(shí)看 UDP 端口和 DSCP。查看本機(jī) GID 表時(shí)用ibv_devinfo -v比記命令更直接# 只看 GID 表段落確認(rèn) v1 和 v2 的 index ibv_devinfo -v | sed -n /GID table/,/^$/psed -n /GID table/,/^$/p把 GID 表從輸出里截出來(lái)避免被端口狀態(tài)和鏈路速率刷屏。GID 表里通常會(huì)同時(shí)出現(xiàn)鏈路本地、IPv4 和 IPv6 條目-x或-g填哪個(gè) index取決于你要跑 v1 還是 v2。填錯(cuò)時(shí)常見(jiàn)表現(xiàn)是ib_write_bw連不上但ping正常。4.2 PFC/ECN 與擁塞控制參數(shù)規(guī)范只給邊界調(diào)優(yōu)靠實(shí)測(cè)RoCEv2 的無(wú)損依賴 PFC 和 ECN。PFC 按優(yōu)先級(jí)暫停上游發(fā)送防止交換機(jī)緩存溢出ECN 在擁塞時(shí)給包打標(biāo)記接收端回 CNP發(fā)送端降速。規(guī)范給的是字段和語(yǔ)義邊界具體水線、閾值、優(yōu)先級(jí)映射要按交換機(jī)和網(wǎng)卡實(shí)測(cè)。常見(jiàn)做法是把 RDMA 流量放到一個(gè)獨(dú)立優(yōu)先級(jí)比如 3 或 4交換機(jī)上給這個(gè)優(yōu)先級(jí)開(kāi) PFC同時(shí)開(kāi) ECN閾值從保守值開(kāi)始再按吞吐和時(shí)延調(diào)。PFC 配錯(cuò)會(huì)出現(xiàn)“鏈路 up、小包通、大包卡死”的玄學(xué)現(xiàn)象血淚經(jīng)驗(yàn)是先把 PFC 計(jì)數(shù)器打出來(lái)看不要憑感覺(jué)改水線。參數(shù)作用調(diào)錯(cuò)后的現(xiàn)象PFC 優(yōu)先級(jí)給 RDMA 流量做無(wú)損隊(duì)列優(yōu)先級(jí)不匹配PFC 不生效PFC 水線觸發(fā)暫停的緩存閾值太小頻繁暫停太大容易死鎖ECN 閾值標(biāo)記擁塞的隊(duì)列長(zhǎng)度太低誤標(biāo)記太高不降速DSCP讓交換機(jī)識(shí)別流量類別映射錯(cuò)PFC/ECN 作用不到MTU單包負(fù)載上限兩端不一致大包丟看計(jì)數(shù)器時(shí)用ethtool -S不同驅(qū)動(dòng)的計(jì)數(shù)器名字不一樣抓關(guān)鍵詞比記全名靠譜# 查看 PFC、ECN、CNP 相關(guān)計(jì)數(shù)器 ethtool -S ens1f0 | grep -iE pause|pfc|ecn|cnpethtool -S輸出的是網(wǎng)卡統(tǒng)計(jì)grep只做過(guò)濾??吹絧rioX pause frames持續(xù)增長(zhǎng)說(shuō)明 PFC 在頻繁觸發(fā)看到 ECN 標(biāo)記增長(zhǎng)但吞吐上不去要看 CNP 是否回得去。計(jì)數(shù)器名字因驅(qū)動(dòng)而異別硬套某一種命名先ethtool -S ens1f0 | head看全量字段再過(guò)濾。提示PFC 死鎖是 RoCE 排障里最像“玄學(xué)”的一類問(wèn)題先把不相關(guān)優(yōu)先級(jí)上的 PFC 關(guān)掉只留業(yè)務(wù)優(yōu)先級(jí)能減少互相暫停的鏈路。4.3 一個(gè)最小 RoCEv2 雙機(jī)驗(yàn)證流程驗(yàn)證順序建議固定先鏈路和 IP再 MTU再 GID再 pingpong最后帶寬。每一步只改一個(gè)變量出問(wèn)題能回退。下面是一組可以直接抄的流程網(wǎng)卡名和地址按環(huán)境替換。# 兩端設(shè)置 MTU 和 IP sudo ip link set ens1f0 mtu 4092 up sudo ip addr add 10.10.10.1/24 dev ens1f0 # node-a sudo ip addr add 10.10.10.2/24 dev ens1f0 # node-b # node-a驗(yàn)證路徑 MTU禁止分片 ping -M do -s 4000 10.10.10.2 # node-a服務(wù)端先起 ib_write_bw -d rxe0 -x 3 --report_gbits # node-b客戶端再連 ib_write_bw -d rxe0 -x 3 --report_gbits 10.10.10.1ping -M do -s 4000失敗時(shí)先查兩端 MTU 和交換機(jī) MTU不要急著改 RDMA 參數(shù)。ib_write_bw服務(wù)端先起、客戶端后連-x 3是示例 GID index實(shí)際值從ibv_devinfo -v里取。帶寬結(jié)果受 CPU、PCIe、消息大小和隊(duì)列深度影響先看是否接近線速再看是否抖動(dòng)。驗(yàn)證項(xiàng)命令預(yù)期鏈路與 IPip addr show ens1f0狀態(tài) UP地址正確路徑 MTUping -M do -s 4000不分片通過(guò)GIDibv_devinfo -v找到 v2 對(duì)應(yīng) index建鏈ibv_rc_pingpong兩端完成一次往返帶寬ib_write_bw雙向流量正常無(wú)長(zhǎng)時(shí)間停滯5. 避坑與排查規(guī)范落地時(shí)最容易翻車的五件事5.1 現(xiàn)象鏈路 up 但 RDMA 建鏈?zhǔn)‖F(xiàn)象是網(wǎng)卡燈亮、ip link顯示 UP、ping也通但ib_write_bw或ibv_rc_pingpong一直連不上服務(wù)端看不到連接請(qǐng)求。原因通常不在物理層而在 GID index、P_Key、防火墻或 CM 監(jiān)聽(tīng)。RoCEv2 的 GID 表里同時(shí)有鏈路本地、IPv4、IPv6 條目-x填了 v1 的 index客戶端會(huì)往錯(cuò)誤的地址族發(fā)起連接P_Key 不匹配時(shí)硬件直接丟包抓包只能看到請(qǐng)求沒(méi)有響應(yīng)主機(jī)防火墻把 UDP 4791 或 CM 端口攔了表現(xiàn)也是“ping 通但 RDMA 不通”。解決順序是先用ibv_devinfo -v確認(rèn) GID index 和端口狀態(tài)再用rdma link show確認(rèn)設(shè)備綁定然后臨時(shí)關(guān)掉主機(jī)防火墻做對(duì)照最后抓 UDP 4791 看請(qǐng)求有沒(méi)有到對(duì)端。ibv_rc_pingpong不通時(shí)不要直接改 MTU先看 GID 和防火墻這兩類問(wèn)題占建鏈?zhǔn)〉拇箢^。5.2 現(xiàn)象小包正常大包丟現(xiàn)象是ping小包正常ib_write_bw小消息也能跑一上大消息就掉零或長(zhǎng)時(shí)間停滯。原因最常見(jiàn)的是路徑 MTU 不一致兩端網(wǎng)卡設(shè)了 4092中間交換機(jī)還是 1500小包能過(guò)大包被丟棄或分片其次是 PFC 沒(méi)在業(yè)務(wù)優(yōu)先級(jí)上生效交換機(jī)緩存一滿就丟包RoCEv2 跨 IP 時(shí)還可能遇到 IP 分片和 ACL 對(duì)分片的處理差異。規(guī)范第 5 章的包格式和 RETH 里的 DMALen 能幫你確認(rèn)單包長(zhǎng)度但 MTU 要靠鏈路配置排查。解決時(shí)先用ping -M do -s 4000驗(yàn)證端到端 MTU再逐跳查交換機(jī) MTU 和 PFC 優(yōu)先級(jí)。PFC 計(jì)數(shù)器持續(xù)增長(zhǎng)說(shuō)明暫停幀在起作用但如果只在小包上正常重點(diǎn)還是 MTU 和分片。把兩端和交換機(jī) MTU 統(tǒng)一到同一檔位再?gòu)?fù)測(cè)大包能排掉大部分“小包通大包死”的問(wèn)題。5.3 現(xiàn)象RoCEv2 跨網(wǎng)段不通現(xiàn)象是同網(wǎng)段 RoCEv2 正常一跨網(wǎng)段就建鏈?zhǔn)∽グ吹秸?qǐng)求發(fā)出但沒(méi)有響應(yīng)。原因是 UDP 4791 被 ACL 攔了、ECMP 哈希把雙向流量分到不同路徑、或者路由回程不對(duì)稱也可能是對(duì)端 GID 選成了鏈路本地地址跨網(wǎng)段根本不可達(dá)。RoCEv2 雖然走 IP但它對(duì)丟包和亂序很敏感ACL 放行不等于路徑質(zhì)量夠用。解決時(shí)先在同一網(wǎng)段抓包確認(rèn) BTH 和 DestQP 正常再跨網(wǎng)段抓兩端確認(rèn)請(qǐng)求和響應(yīng)都經(jīng)過(guò)同一對(duì)地址。ACL 要放行 UDP 4791 雙向ECMP 場(chǎng)景下盡量讓同一 QP 的流量走同一路徑或者接受亂序但確認(rèn)重傳能收斂。GID 一定選 IPv4 或 IPv6 對(duì)應(yīng)的 index不要選鏈路本地。5.4 現(xiàn)象Wireshark 解不出 IB 頭現(xiàn)象是抓到 UDP 4791 的包Wireshark 只顯示 UDP 和 Raw沒(méi)有 BTH、RETH 的字段樹(shù)。原因可能是 Wireshark 版本不帶 RoCEv2 解析器、抓包點(diǎn)截?cái)嗔素?fù)載、VLAN 標(biāo)簽導(dǎo)致解析偏移或者包本身是 RoCEv1 但過(guò)濾器用了 v2。還有一種情況是網(wǎng)卡卸載把包頭改寫(xiě)了抓包點(diǎn)看到的是重組后的包字段偏移和線上不一致。解決時(shí)先用udp.port 4791看原始負(fù)載前 12 字節(jié)確認(rèn) BTH 是否存在再升級(jí)或換帶 RoCEv2 解析器的版本抓包點(diǎn)盡量選在主機(jī)業(yè)務(wù)網(wǎng)卡不要選在截?cái)嗟溺R像口。如果 VLAN 存在確認(rèn)解析器能跳過(guò) VLAN 標(biāo)簽。實(shí)在解不出就用 3.3 節(jié)的 Python 腳本按固定偏移抽字段至少能看 OpCode、DestQP 和 PSN。5.5 現(xiàn)象版本對(duì)不上導(dǎo)致字段誤讀現(xiàn)象是照著舊版本文檔查字段抓包結(jié)果和預(yù)期對(duì)不上或者附錄編號(hào)在 1.4 里變了引用找不到。1.4 版修正了早期版本第 9 章的錯(cuò)誤新增了虛擬化和 RoCE 附錄附錄編號(hào)和章節(jié)引用跟 1.2.1 不完全一樣。拿 1.2 的附錄編號(hào)去套 1.4 的正文容易把 RoCEv1 的封裝當(dāng)成 v2或者把 XRC 還當(dāng)成純附錄內(nèi)容。解決時(shí)以 1.4 版的變更條和目錄為準(zhǔn)先確認(rèn)手里文檔的版本號(hào)和發(fā)布日期再查對(duì)應(yīng)章節(jié)。讀舊代碼或舊驅(qū)動(dòng)時(shí)把版本差異表放在旁邊遇到字段語(yǔ)義不確定就回第 5 章包格式和第 3 章傳輸服務(wù)對(duì)照。不要在一個(gè)版本里混用另一個(gè)版本的附錄編號(hào)這是最容易埋坑的地方。6. 把規(guī)范當(dāng)查詢手冊(cè)三個(gè)進(jìn)階用法與一個(gè)驗(yàn)證習(xí)慣6.1 用變更條和附錄定位實(shí)現(xiàn)差異1.4 版的變更條不是給讀者看的裝飾它能告訴你哪些章節(jié)在 1.3 之后動(dòng)過(guò)。做驅(qū)動(dòng)適配或協(xié)議棧升級(jí)時(shí)先看變更條再?zèng)Q定要不要重讀某一章。虛擬化附錄和 RoCE 附錄是 1.4 新增的重點(diǎn)涉及 SR-IOV、虛擬機(jī)直通和 RoCEv2 封裝的實(shí)現(xiàn)優(yōu)先查這兩塊。6.2 從包格式反推硬件寄存器與計(jì)數(shù)器抓到一個(gè)異常包時(shí)不要只盯著“丟包”兩個(gè)字。按 BTH 的 DestQP 找接收 QP按 PSN 看重傳按 RETH 的 DMALen 看長(zhǎng)度再回到網(wǎng)卡計(jì)數(shù)器和交換機(jī)計(jì)數(shù)器找對(duì)應(yīng)項(xiàng)。規(guī)范第 5 章的字段表就是你的字典字段和計(jì)數(shù)器能對(duì)上排障就從猜變成查。6.3 建立自己的“規(guī)范-抓包-計(jì)數(shù)器”對(duì)照表我習(xí)慣在項(xiàng)目里維護(hù)一張小表左邊寫(xiě)規(guī)范章節(jié)和字段中間寫(xiě)抓包過(guò)濾條件右邊寫(xiě)計(jì)數(shù)器名稱。比如 BTH 的 PSN 對(duì)應(yīng) Wireshark 的rocev2.psnPFC 對(duì)應(yīng)ethtool -S里的 pause 計(jì)數(shù)MTU 對(duì)應(yīng)ping -M do。這張表不需要漂亮但每次排障都能省掉重新翻文檔的時(shí)間。規(guī)范位置抓包/命令計(jì)數(shù)器第 5 章 BTHudp.port 4791接收 QP 丟棄第 3 章 QoSDSCP/PFC 過(guò)濾prioX pause第 4 章尋址GID 表端口狀態(tài)RoCEv2 附錄UDP 4791ECN/CNP從那以后我每次上 RDMA 鏈路都強(qiáng)制先跑一遍“MTU、GID、PFC 計(jì)數(shù)器”三件套再談帶寬調(diào)優(yōu)這份 1.4 版卷 1 就放在資料夾里當(dāng)查詢手冊(cè)需要的時(shí)候按第 3 章和第 5 章翻。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取