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

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

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

普通的 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,无进展,卡死。

4.上网查到wireshark可以自动校验checksum,默认不打开。
设置方式:编辑—-首选项—-协议—-udp—-勾选Validata the UDP checksum if possible

记录一次checksum校验失败导致丢包的问题
6.在lwipopt.h中打开了传输层与网络层的checksum定义CHECKSUM_GEN_IP和CHECKSUM_GEN_UDP(意味着发送时采用软件计算checksum):

兴高采烈的去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值出错,改为软件校验可以解决此问题。

来源:Black_黑色

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

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

相关推荐