记录一次checksum校验失败导致丢包的问题

开始之前先附上 络模型的图,此次问题的重点出在运输层、 络层、数据链路层。
协议栈应用:lwip_1.4.1

普通的 IP 头部长度为20 个字节,不包含IP 选项字段。
版本 (Version)字段标明了IP 协议的版本 ,目前的协议版本 为4。下一代IP 协议的版本 为6。
文长度指 IP 包头部长度,占4 位。
8 位的服务类型(TOS,Type of Service)字段包括一个3 位的优先权字段(COS,Class of Service),4 位TOS 字段和1 位未用位。4 位TOS 分别代表最小时延、最大吞吐量、最高可靠性和最小费用。
总长度(Total length)是整个IP 数据 长度,包括数据部分。
标识符(Identification)字段唯一地标识主机发送的每一份数据 。通常每发送一份 文它的值就会加1.
生存时间(TTL,Time to Live)字段设置了数据包可以经过的路由器数目。一旦经过一个路由器,TTL 值就会减1,当该字段值为0 时,数据包将被丢弃。
协议字段确定在数据包内传送的上层协议,和端口 类似,IP 协议用协议 区分上层协议。TCP 协议的协议 为6,UDP 协议的协议 为17。
头校验和(Head checksum)字段计算IP 头部的校验和,检查 文头部的完整性。源IP 地址和目的IP 地址字段标识数据包的源端设备和目的端设备。

3.手动计算wireshark中的checksum值,发现checksum值是正确的,计算方法在另外一篇博文中:
https://blog.csdn.net/zhaozhiyuan111/article/details/97640966
发现程式中的TTL默认为255(在lwip配置文件lwipopt.h中),修改为64,无进展,卡死。

兴高采烈的去lwip udp.c中的相应位置:
udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
去修改,发现怎么改抓包看到的checksum值都不变。

7.问题指向了checksum是否是由硬件校验生成,导致软件修改无果。
最终发现确实如此,在数据包的实际传输tivaif_transmit函数中,配置了 卡的状态为DES0_TX_CTRL_IP_ALL_CKHSUMS,修改为DES0_TX_CTRL_NO_CHKSUM,问题完美解决。

总结:udp在发送数据时会因为包头中的checksum值不对而丢包,一般为了提高CPU的工作效率,都会默认为checksum的校验方式为硬件校验,导致在超过MTU值限制时,硬件 卡自动生成的checksum值出错,改为软件校验可以解决此问题。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年7月2日
下一篇 2019年7月2日

相关推荐