如果您在Alibaba Cloud Linux 3系統中啟用了共用記憶體通訊SMC(Shared Memory Communication),且使用過程中遇到無法正常通訊、部分連接埠不可用、對比TCP沒有應用效能提升等問題,可以參考本文提供的方案進行排查並解決。
啟用SMC後應用效能對比TCP沒有提升
問題描述
使用SMC加速應用TCP串連之後,應用的效能與直接使用TCP對比並沒有提升。
問題原因及解決方案
啟用SMC後無法正常通訊
問題描述
使用Alibaba Cloud Linux 3開啟SMC之後,訪問某些地址(例如某些公網服務)不通,但是可以ping通。關閉SMC之後恢複正常。
問題原因
某些伺服器實現上沒有嚴格准守TCP規範,在處理TCP options時,可能重放TCP options,導致SMC協議識別出現問題。
說明 A TCP implementation MUST (MUST-6) ignore without error any TCP Option it does not implement, assuming that the option has a length field. 更多資訊,請參見RFC 9293。
如果用於表徵支援SMC的TCP option被重放,就會使得本端誤認為對端服務具備SMC能力,引起握手錯誤,導致請求(例如curl)失敗,而ping(ICMP協議)成功的現象。
您可以通過check_tcpoption_replay.py工具診斷此類問題:
單擊check_tcpoption_replay.py查看指令碼內容
from scapy.all import *
import time
import argparse
# Set up command line arguments
parser = argparse.ArgumentParser(description='Check if the server replays with the same TCP option.')
parser.add_argument('-i', '--ip', required=True, help='Target IP address')
parser.add_argument('-p', '--port', required=True, type=int, help='Target port number')
parser.add_argument('-v', '--verbose', action='store_true', help='Print verbose output')
args = parser.parse_args()
# Target IP and port
target_ip = args.ip # Get target IP from command line arguments
target_port = args.port # Get target port from command line arguments
verbose = args.verbose # Get verbose flag from command line arguments
# Create a TCP SYN packet that includes a special TCP Option
ip = IP(dst=target_ip)
syn = TCP(sport=RandShort(), dport=target_port, flags='S', options=[(254, b'xxxx')])
syn_ack_pkt = sr1(ip/syn, timeout=1, verbose=verbose)
# Check if the returned packet is a TCP SYN-ACK
if syn_ack_pkt and TCP in syn_ack_pkt and syn_ack_pkt[TCP].flags & 18: # SYN-ACK flags
# Check for the special TCP Option
if any(opt[0] == 254 and opt[1] == b'xxxx' for opt in syn_ack_pkt[TCP].options):
print("The server has replayed the TCP option")
else:
print("The server did not replay the TCP option")
else:
print("Failed to receive SYN-ACK, please make sure the IP and port are correct")
sys.exit(1)
# Complete the TCP handshake
if syn_ack_pkt:
ack = TCP(sport=syn_ack_pkt[TCP].dport, dport=target_port, flags='A', seq=syn_ack_pkt[TCP].ack, ack=syn_ack_pkt[TCP].seq + 1)
send(ip/ack, verbose=verbose)
# Wait for 1 second before disconnecting
time.sleep(1)
# Send TCP FIN to close the connection
if syn_ack_pkt:
fin = TCP(sport=syn_ack_pkt[TCP].dport, dport=target_port, flags='FA', seq=syn_ack_pkt[TCP].ack, ack=syn_ack_pkt[TCP].seq + 1)
last_ack_pkt = sr1(ip/fin, timeout=1, verbose=verbose)
# Complete the four-way handshake
if last_ack_pkt and TCP in last_ack_pkt and last_ack_pkt[TCP].flags & 16: # ACK flag
last_ack = TCP(sport=syn_ack_pkt[TCP].dport, dport=target_port, flags='A', seq=last_ack_pkt[TCP].ack, ack=last_ack_pkt[TCP].seq + 1)
send(ip/last_ack, verbose=verbose)
安裝Python 3和scapy庫。
yum install python3 -y
python3 -m pip install scapy
運行check_tcpoption_replay.py工具。
python3 check_tcpoption_replay.py -i <服務端IP> -p <服務端port>
如果服務端存在重放問題則輸出The server has replayed the TCP option
,否則輸出The server did not replay the TCP option
。
解決方案
對於重放SMC TCP option的非預期現象,由於是網路中間節點或對端的錯誤行為,無法從根本上避免,建議避免在訪問這類服務時使用SMC。
通過smc_run啟用SMC無效
問題描述
根據 共用記憶體通訊(SMC)使用說明通過smc_run ./foo
在應用程式維度啟用SMC後,使用smcr l
觀察發現沒有成功建立的link group,使用smcss -a
也看不到串連或是看到一側串連出現回退。
問題原因
smc_run
透明啟用SMC的原理是通過LD_PRELOAD將smc-tools中提供的動態連結程式庫優先於其他庫之前載入,在優先載入的動態連結程式庫的socket(2)中對socket的family和protocol進行修改。因此,若應用程式並非通過動態方式連結(如靜態連結),則smc_run
無法成功透明啟用SMC。
解決方案
根據共用記憶體通訊(SMC)使用說明提供的sysctl net.smc.tcp2smc
啟用SMC。
啟用SMC後導致部分連接埠不可用
問題描述
載入SMC後,65500後的16個連接埠(即65500~65515)不可用,bind(2)這些連接埠會導致返回EADDRINUSE
。
問題原因
由於SMC-R+eRDMA實現方式的特殊性,SMC模組將會佔用ERI所在net namespace下65500開始的16個連接埠作為OOB建連的預留連接埠,在dmesg中可以查看到如下提示資訊:
smc: smc: load SMC module with reserve_mode
NET: Registered protocol family 43
smc: netns <netns ID> reserved ports [65500 ~ 65515] for eRDMA OOB
smc: adding ib device erdma_0 with port count 1
smc: ib device erdma_0 port 1 has pnetid
如果連接埠佔用失敗則SMC模組無法使用eRDMA裝置。
解決方案
卸載SMC模組後將會釋放這些連接埠。卸載方法請參見使用說明。
啟用SMC後回退無法使用RDMA加速
問題描述
啟用SMC並替換應用的TCP串連,此時運行smcss -a
命令可以看到建立的串連已經自動回退(fallback)到TCP。
問題原因
SMC建立串連時,如果發生異常會自動回退到TCP串連,此時SMC串連仍然可以正常通訊,但是無法享受RDMA帶來的效能提升。SMC發生回退時會提供回退原因編號,根據回退編號可以協助分析和定位問題。
解決方案
運行smcss -a
命令,查看SMC串連的回退編號。
返回結果樣本:
State UID Inode Local Address Peer Address Intf Mode
ACTIVE 00000 0156721 192.168.99.21:60188 192.168.99.22:8090 0000 TCP 0x03010000
ACTIVE 00000 1202539 172.16.4.189:44780 172.16.4.190:1811 0000 SMCR
其中第一條記錄Mode列為TCP,意味著該SMC串連回退到TCP,同時回退編號為0x03010000。第二條記錄Mode列為SMCR,則說明已經正常建立SMC-R串連。如果Mode列顯示的回退編號為兩個(例如0x05000000/0x03030001),其中第一個回退編號為本地的回退原因,第二個回退編號為對端的回退原因,通常是由於對端回退導致了本機無法正常建立SMC串連而回退。
根據回退編號,從下表中查看可能的原因和解決方案。
啟用SMC後回退無法使用RDMA加速的原因和解決方案
回退原因編號 | 說明 | 可能原因和解決方案 |
0x01010000 | 機器記憶體不足,導致資源建立失敗。 | |
0x02010000 | 通過CLC或者LLC握手時,等待RDMA鏈路確認逾時。 | |
0x02020000 | 通過LLC建立link逾時。 | 預留欄位,當前未使用。 |
0x03000000 | 配置錯誤,無法擷取正確的IP地址。 | |
0x03010000 | 對端不支援或未使用SMC。 | |
0x03020000 | 不支援IPSec。 | |
0x03030000 | 未找到可用的SMC-D或SMC-R裝置。 | 原因3:如果啟用RDMA裝置的獨佔模式,SMC只會在當前建立socket的net namespace中尋找RDMA裝置。 解決方案3:執行rdma system 命令,如果返回的結果中包含netns exclusive 則說明為獨佔模式。如果需要在某個netns中使用該RDMA裝置,請執行命令rdma dev set <RDMA 裝置名稱> netns <NETNS 名> ,將RDMA裝置移至該netns。如果RDMA裝置為RoCE和iWARP,請將所需的乙太網路裝置也一併移動到該netns。
|
0x03030001 | 未找到可用的SMC-D裝置。 | 當前雲情境暫未提供可用的SMC-D裝置,如出現該錯誤請聯絡阿里雲支援人員。 |
0x03030002 | 未找到可用的SMC-R裝置。 | 原因3:如果啟用RDMA裝置的獨佔模式,SMC只會在當前建立socket的net namespace中尋找RDMA裝置。 解決方案3:執行rdma system 命令,如果返回的結果中包含netns exclusive 則說明為獨佔模式。如果需要在某個netns中使用該RDMA裝置,請執行命令rdma dev set <RDMA 裝置名稱> netns <NETNS 名> ,將RDMA裝置移至該netns。如果RDMA裝置為RoCE和iWARP,請將所需的乙太網路裝置也一併移動到該netns。
|
0x03030003 | SMC-D裝置不支援ISMv2協議。 | 當前雲情境暫未提供可用的SMC-D裝置,如出現該錯誤請聯絡阿里雲支援人員。 |
0x03030004 | 對端不支援SMCv2協議的拓展。 | 原因:本地啟用了SMC v2協議,但對端不支援SMC v2協議。SMC協議棧通過底層裝置能力自動選擇使用SMC v1或SMC v2協議。在使用阿里雲eRDMA和RoCE v2的情境下,將使用SMC v2協議。 解決方案:保證通訊兩端所有RDMA裝置類型相同,則兩端SMC協議版本相同。可通過smcr d 查看SMC-R所用裝置,在type 一欄中可以看到裝置類型,如RoCE_Express、RoCE_Express2、或0x107f(即阿里雲eRDMA)。
|
0x03030005 | 對端不支援SMC-Dv2協議的拓展。 | 當前雲情境暫未提供可用的SMC-D裝置,如出現該錯誤請聯絡阿里雲支援人員。 |
0x03030006 | 對端缺失SEID。 | 預留欄位,當前未使用。 |
0x03030007 | 未找到可用的SMC-D v2裝置。 | 當前雲情境暫未提供可用的SMC-D裝置,如出現該錯誤請聯絡阿里雲支援人員。 |
0x03030008 | 對端缺少UEID。 | |
0x03030009 | 本地和對端協商SMC版本失敗。 | |
0x0303000a | LGR可容納串連數量協商失敗。 | |
0x0303000b | LGR可容納link數量協商失敗。 | |
0x0303000c | 本地與對端協商SMC vendor特性失敗。 | 原因:兩側協商SMC vendor特性的結果在CLC握手過程中發生變化。 解決方案:首先確認兩端OS發行版一致;其次通過uname -r 命令確認核心版本,若核心版本為5.10.134-015 ,則確保在建連過程中不要主動修改sysctl net.smc.vendor_exp_options 的值,若核心版本大於等於5.10.134-016 ,則確保在建連過程中不要主動修改sysctl net.smc.experiment_vendor_options 的值。
|
0x03040000 | 本地和對端的SMC裝置模式不匹配 (SMC-D 或 SMC-R)。 | 當前雲情境暫未提供可用的SMC-D裝置,如出現該錯誤請聯絡阿里雲支援人員。 |
0x03050000 | 對端RMBE中包含eyecatcher非法欄位。 | 預留欄位,Linux實現中未使用。 |
0x03060000 | 串連使用了不支援MSG_FASTOPEN。 | |
0x03070000 | 本地和對端的IP首碼/子網不匹配。 | |
0x03080000 | 擷取裝置VLAN ID失敗。 | |
0x03090000 | ISM裝置註冊VLAN ID失敗。 | 當前雲情境暫未提供可用的SMC-D裝置,如出現該錯誤請聯絡阿里雲支援人員。 |
0x030a0000 | LGR中無可用SMC-R RDMA鏈路。 | |
0x030b0000 | 用戶端找不到服務端提供的RDMA鏈路。 | |
0x030c0000 | 協商SMC版本失敗。 | 原因:通訊兩端SMC版本協商結果超出可接受範圍。 解決方案:確認兩端OS發行版一致。
|
0x030d0000 | SMC-D DMB數量超越上限。 | 當前雲情境暫未提供可用的SMC-D裝置,如出現該錯誤請聯絡阿里雲支援人員。 |
0x030e0000 | SMC-R v2串連對端不可達。 | |
0x030f0000 | SMC-R v2串連非直連標誌位設定錯誤。 | |
0x04000000 | 服務端和用戶端複用LGR錯誤。 | |
0x05000000 | 握手過程中對端拒絕。 | |
0x09990000 | RDMA相關資源建立錯誤。 | |
0x09990001 | RDMA rtoken增加失敗。 | SMC協議棧錯誤,如出現該錯誤請聯絡阿里雲支援人員。 |
0x09990002 | 初始化RDMA QP資源失敗。 | |
0x09990003 | RDMA記憶體註冊(MR)失敗。 | 原因:使用RDMA通訊時,需要註冊記憶體地區用以RDMA網卡訪問和寫入資料,如果使用的MR數量或者大小超過了RDMA裝置的規格,則會報錯。 解決方案:執行smcr d 命令,找到SMC所使用的RDMA裝置名稱。再執行ibv_devinfo -d <RDMA 裝置名稱> -v | grep max_mr ,其中 max_mr 為RDMA裝置支援的最多MR數量,max_mr_size 為 RDMA裝置支援的最大MR大小;通常情況下為MR的數量達到瓶頸,此時請減少SMC的串連數量。
|
0x09990004 | SMC流控所需的credit初始化失敗。 | |
啟用SMC後常見網路營運工具的資料與預期不符
問題描述
使用Alibaba Cloud Linux 3開啟SMC-R之後,常見的網路分析工具tcpdump、Wireshark等,網路監控工具ss(Socket Statistics)、netstat等,觀察到的網路流量與預期不符或無法觀察到預期流量。
問題原因
這是因為SMC-R是基於RDMA的網路通訊技術,目前常見的網路營運工具只能分析或監控TCP流量,無法識別RDMA的網路資料報文。這會導致實際的網路資料和網路營運工具中顯示的資料不匹配。
解決方案
可以嘗試使用RDMA相關的營運工具進行資料分析或監控。更多資訊,請參見監測和診斷eRDMA。
在GPU或SCC執行個體上載入SMC模組不可用
問題描述
在GPU或SCC執行個體上載入SMC模組,模組不可用。
問題原因
這類執行個體中安裝了Mellanox廠商版本OFED驅動,預設載入的是OFED中的SMC模組,不具備實際功能。且由於安裝Mellanox OFED驅動後RDMA相關函數的符號發生變化,載入核心內建的SMC模組會出現Unknow symbol
錯誤而無法載入成功。
解決方案
目前Alibaba Cloud Linux 3 SMC模組不支援在GPU或SCC等執行個體中使用。
啟用SMC後setsockopt/getsockopt部分SOL_SOCKET或SOL_TCP層選項效果與預期不符
問題描述
啟用SMC並替換應用的TCP串連後,原本作用於TCP串連的部分SOL_SOCKET或SOL_TCP層選項通過setsockopt或getsockopt設定失敗,或設定成功但無法起到預期效果。
問題原因
使用SMC替換TCP協議棧後,資料路徑上基於共用記憶體完成通訊,協議棧設計和資料傳遞方式都與TCP有著很大的不同。因此,部分SOL_SOCKET或SOL_TCP層選項不再適用。
解決方案
對照下表查看Alibaba Cloud Linux 3中SMC對SOL_SOCKET或SOL_TCP層選項的支援情況。
SMC對SOL_SOCKET或SOL_TCP層選項的支援情況可以分為以下3種類型:
Y:支援,設定/擷取選項返回成功,並且能夠達到預期效果。
M:不支援,設定/擷取返回成功,但由於SMC與TCP設計的不同,無法達到預期效果。
N:不支援,設定/擷取返回失敗,回退到TCP(回退原因編號:0x03060000或0x03010001)。
SOL_SOCKET層選項
OPTIONS | SMC支援情況 |
SO_DEBUG | Y |
SO_REUSEADDR | Y |
SO_TYPE | Y |
SO_ERROR | Y |
SO_DONTROUTE | M |
SO_BROADCAST | M |
SO_SNDBUF | Y |
SO_RCVBUF | Y |
SO_SNDBUFFORCE | Y |
SO_RCVBUFFORCE | Y |
SO_KEEPALIVE | M |
SO_OOBINLINE | M |
SO_NO_CHECK | M |
SO_PRIORITY | M |
SO_LINGER | Y |
SO_BSDCOMPAT | M |
SO_REUSEPORT | Y |
SO_PASSCRED | M |
SO_PEERCRED | M |
SO_RCVLOWAT | M |
SO_SNDLOWAT | M |
SO_RCVTIMEO_OLD | Y |
SO_SNDTIMEO_OLD | Y |
SO_SECURITY_AUTHENTICATION | N |
SO_SECURITY_ENCRYPTION_TRANSPORT | N |
SO_SECURITY_ENCRYPTION_NETWORK | N |
SO_BINDTODEVICE | N |
SO_ATTACH_FILTER | M |
SO_DETACH_FILTER | M |
SO_PEERNAME | Y |
SO_ACCEPTCONN | M |
SO_PEERSEC | N |
SO_PASSSEC | M |
SO_MARK | M |
SO_PROTOCOL | Y |
SO_DOMAIN | Y |
SO_RXQ_OVFL | M |
SO_WIFI_STATUS | M |
SO_PEEK_OFF | N |
SO_NOFCS | M |
SO_LOCK_FILTER | Y |
SO_SELECT_ERR_QUEUE | M |
SO_BUSY_POLL | M |
SO_MAX_PACING_RATE | M |
SO_BPF_EXTENSIONS | Y |
SO_INCOMING_CPU | M |
SO_ATTACH_BPF | M |
SO_ATTACH_REUSEPORT_CBPF | M |
SO_ATTACH_REUSEPORT_EBPF | N |
SO_CNX_ADVICE | M |
SO_MEMINFO | M |
SO_INCOMING_NAPI_ID | M |
SO_COOKIE | Y |
SO_PEERGROUPS | N |
SO_ZEROCOPY | N |
SO_TXTIME | M |
SO_BINDTOIFINDEX | N |
SO_TIMESTAMP_OLD | M |
SO_TIMESTAMPNS_OLD | M |
SO_TIMESTAMPING_OLD | M |
SO_TIMESTAMP_NEW | M |
SO_TIMESTAMPNS_NEW | M |
SO_TIMESTAMPING_NEW | M |
SO_RCVTIMEO_NEW | Y |
SO_SNDTIMEO_NEW | Y |
SO_DETACH_REUSEPORT_BPF | N |
SOL_TCP層選項
OPTIONS | SMC支援情況 |
TCP_NODELAY | Y |
TCP_MAXSEG | M |
TCP_CORK | Y |
TCP_KEEPIDLE | M |
TCP_KEEPINTVL | M |
TCP_KEEPCNT | M |
TCP_SYNCNT | M |
TCP_LINGER2 | M |
TCP_DEFER_ACCEPT | Y |
TCP_WINDOW_CLAMP | M |
TCP_INFO | M |
TCP_QUICKACK | M |
TCP_CONGESTION | M |
TCP_MD5SIG | Y |
TCP_THIN_LINEAR_TIMEOUTS | M |
TCP_THIN_DUPACK | M |
TCP_USER_TIMEOUT | M |
TCP_REPAIR | M |
TCP_REPAIR_QUEUE | M |
TCP_QUEUE_SEQ | M |
TCP_REPAIR_OPTIONS | M |
TCP_FASTOPEN | N |
TCP_TIMESTAMP | M |
TCP_NOTSENT_LOWAT | M |
TCP_CC_INFO | M |
TCP_SAVE_SYN | Y |
TCP_SAVED_SYN | Y |
TCP_REPAIR_WINDOW | M |
TCP_FASTOPEN_CONNECT | N |
TCP_ULP | N |
TCP_MD5SIG_EXT | Y |
TCP_FASTOPEN_KEY | N |
TCP_FASTOPEN_NO_COOKIE | N |
TCP_ZEROCOPY_RECEIVE | N |
TCP_CM_INQ/TCP_INQ | M |
TCP_TX_DELAY | M |