如果您在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 |