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