Loading

ICSSG千兆发送数据丢失问题分析报告

ICSSG千兆发送数据丢失问题分析

1. 概述

在某轨道交通项目中,基于TI AM6442平台适配ICSSG网卡时,遇到了千兆模式下发送速率低且不稳定的问题。本文档旨在详细分析该问题,并提出解决方案。

2. 问题描述

适配完成后,对ICSSG的百兆和千兆模式分别进行了性能测试。测试结果显示,百兆模式下性能正常,但在千兆模式下,发送速率异常低且不稳定。

通过抓包分析,发现发送时存在一定概率丢失报文中的部分DATA段数据。例如,图1显示第12包的报文头部表明,除去以太网头后包的总长度应为1500字节,但实际包总长仅为1134字节。Wireshark在下一包中提示,之前的报文字段不完整。接收端检测到此现象后,会向发送端发送TCP Dup ACK,要求重发,从而导致发送速度异常。

image

图 1

3 问题分析

3.1是否对协议栈发来的数据处理错误

首先想到的是驱动对协议栈传递的数据处理时发生了错误,之前的适配过程中发现某些情况下lwip会采用链表的形式传递数据,若驱动在合包的时候发生了错误,很吻合数据丢失的现象。目前使用的测试工具为iperf,其中存在选项可以选择是否已链表的形式传递数据,于是将此选项关闭,即发来的数据在存储在一段连续的内存中,再次测试,问题现象没有改变。

为验证数据确实是连续的,在驱动对不连续数据包处理的点进行判断打印,发现并没有进入此分支,至此,对源数据的怀疑打消。
image

3.2 是否是cache一致性造成的

之前适配网卡时,曾发现Enet刷cache的操作在接收数据时并没有生效,导致数据读取错误,同样符合问题现象,于是在发包前对多处进行刷cache操作,将DMA描述符与数据写回内存,再次测试,问题现象没有改变,暂时排除cache的怀疑。
image

3.4是否为Phy状态未有效通知固件

ICSSG的内部处理逻辑依赖PRU固件,百兆下测试收发并无异常,是否为PRU固件依然在百兆模式下工作?于是查找固件中对应位置,在Phy连接后主动打印对应区域的值,发现此值在不同模式下可正确写入并读回,暂时排除该可能。

3.5是否为发送队列溢出导致

虽然发送队列溢出的现象通常为丢包,但此时同样有必要对此进行排查,于是将发送队列由16增大至32,发现问题现象没有变化,排除该可能。
image

3.6该问题是否有规律?

由于之前测试时,只对TCP协议的测试进行了抓包,所以要总结问题规律,需要更多的排查手段。首先,使用ICMP(PING)与UDP分别进行测试,发现ICMP存在超时现象,UDP速率正常,可达200Mb。于是开始抓包分析,ICMP与UDP抓包结果分别为图 2图 3,可以观察到,由于设置了PING超时1包后立即停止,可以观察到抓包记录的最后一包实际上有回复,但包大小与预期的1500并不相符,反而为60,所以request方认为此回复无效,故超时。UDP包也有类似的现象,同样大小为60。

至此,总结出了一个规律为,TCP包丢失数据后总包长随机,而ICMP与UDP包丢失数据后,总包大小大概率为60,而这对问题并没有什么明显的帮助。

继续测试,将PING包大小设置为60以下,发现丢包问题消失了,逐渐增加包大小,发现包总长的极限为64。

对于64字节这个数字,自然联想到了cache,而cache问题也早已验证,于是联想到是不是DMA每次搬移64字节,而DMA尚未搬移完成MAC就将数据发送?

image

图 2

image

图 3

3.7 查看MAC状态

由于之前一直未关注过MAC状态,根据总结的规律,开始对MAC状态进行打印,首先对发送总长进行校验,使用ping发送总长为988的数据(MAC会在帧头与帧尾添加同步码、定界符与CRC校验信息),持续发包直到超时后发现数据增加了1000(988 + 12) * 丢包时的总包数(预期长度) – 1000(丢一包) + 60(包总长) + 12(MAC信息),即MAC统计发送的总长与实际一致,故并不是MAC向Phy传输数据帧时丢失数据。

继续查看其他是否有其他错误信息,发现存在txUnderFlowErr错误,如图 4,且每丢失一次数据,该值增加1,问题便有了新的追踪目标。

image

图 4

3.8什么是txUnderFlowErr

在TI官网的AM65x文档中,对该现象进行了描述,指出“PRU Port Transmit queues should be place in the MSMC memory in order to get maximum throughput from PRUS. Placing in any other memory”,即为了PRU获得最大吞吐量,应该放置PRU传输队列端口在MSMC内存中,放在其他任何内存中都有可能导致下溢(图 5)。

image

图 5

查阅AM64x手册,其中提到PRU传输依靠XFR2V总线,但如何配置该总线的目的地成了新的问题。

image

图 6

3.9 对比Linux提供的固件

至此可以推断出该问题大概率与MAC数存储据的位置有关,而如何修改该位置并不清楚(实际在fw_mem_map头文件中有描述, 但并不清晰),故尝试从Linux中查找是否有可用的固件,对现有固件进行替换, 通过查找设备树,以及用来描述固件内存功能的头文件,发现与现有镜像有少许出入,且AM64x官方开发板提供的镜像中的固件elf文件的二进制值与现有镜像并不吻合,故替换镜像这条路也无法走通。

3.10 向TI官方论坛提问

缩小问题范围后,于是在TI论坛中发帖提问,有人提到了PRU相关内存需要放在MSRAM中,这一点与AM65x文档中提到的一致,并提到了该内存可在sysconfig中配置,结合之前的移植过程,发现部分内存确实有指定section,但之前并不知道该内存段的作用,以为同样是为了内存对齐而设置,故没有在linkcmd链接脚本中实现。结合现象,似乎这就是导致该问题的最终原因。

4 问题验证

通过对比SDK中提供的链接脚本,得到了MSRAM的地址与长度,故对涉及PRU的所有内存都进行了指定,分配到MSRAM所在的区域,再次测试,发送速度为600Mb,符合预期,问题解决。

image

5 结论

该问题是由于PRU的HostPoolMem、HostQueueMem、ScratchMem相关内存没有在MSRAM内存中,导致吞吐量不足,发送时出现下溢问题,最终部分数据丢失。

在进行这类复杂的问题排查时,需要注意及时获取社区和官方支持,同时保持多维度排查,不仅要关注软件层面的协议栈和缓存一致性,还要利用硬件状态寄存器等信息进行深入分析,以便更准确地定位问题。

6 如何修复该问题

修改链接脚本,添加MSRAM内存区域,并将PRU的HostPoolMem、HostQueueMem、ScratchMem,DMA描述符内存池,DMA环内存池全部指定到该内存区域,问题即可解决。

image

posted @ 2023-04-04 09:40  Yangtai  阅读(0)  评论(0)    收藏  举报