一、复现场景
这个问题是做 SIL 维护软件时遇到的。一个板卡给另外一个板卡发送 UDP 报文。发送端板卡和接收端板卡都有三个 UDP 套接字。此时都能正常收发,但是当接收端板卡有两个套接字不 recvfrom 接收数据,导致另外一个套接字也收不到数据。用 tcpdump 抓包能抓到数据。
二、分析流程
一开始我和大家一样,疯狂加打印。最后定位到协议栈里面recv_udp函数申请netbuf那退出了,并没有按正常逻辑往下走。这个时候就需要梳理一下网卡接收数据上传的逻辑了。
网卡接收到数据,协议栈会根据不同报文类型调用不同的input任务处理。udp_input 任务最终调用 recv_udp,在这个函数中申请 netbuf,将网卡收到的数据放到 recvmbox 消息队列里,应用程序再从消息队列里面拿数据。所以当一个板卡发 UDP 报文另一个板卡收 UDP 报文,UDP 能够正常通信。
但消息队列最大长度是 512,netbu f最大数量是 1024个。所以当有两个 UDP 套接字不收数,netbuf 就会被占满导致其他套接字收不到数据。
三、解决方法
1、修改应用程序代码,一直 recvfrom 收数据,netbuf 用完即释放。
2、修改 base,将 netbuf 数量改大或者消息队列长度改小(消息队列长度改小如果接收速度慢可能会丢数)。
修改 netbuf 的头文件在 libsylixos/SylixOS/config/net/ 目录下的 net_perf_cfg.h。第 34 行 LW_CFG_LWIP_MSG_SIZG 为一个套接字最大的消息队列长度,第39行 LW_CFG_LWIP_NUM_NETBUF 为系统总的 netbuf 数量。