Linux网络 IP/TCP校验和、checksum、伪首部相关问题

1、校验和作用

校验和是为防止报文在信道传输出现误码导致报文错误,或者传输过程中间网络设备错误造成报文错误等,并不保证报文被他人恶意篡改。防君子不防小人,而已修改报文内容重新计算校验和是无法检测的。

2、校验内容

网络报文校验和包括3层校验和4层校验,
3层校验:仅校验3层头(网络层ip头,ipv6协议中没有三层校验和,仅指ipv4);
csum(ip头)

4层校验:需要校验 伪头部+4层头+4层负载(应用层负载)。
csum(ip头)+csum(ip负载)=csum(ip头+ip负载)

3、计算方式

校验和的计算方法是统一的,即所有2字节数据的二进制反码求和。内核实现是以四字节求和取反得到校验和。

发送方填充校验和:
将校验和的2byte置0,计算校验和,将计算结果填充到校验和位置。

接收方验证校验和:
验证时按照同样的计算方式,如果计算结果为0则表示校验和正确,否则表示报错已出错。

几个关键点:
1、先取反再求和与先求和再取反结果一致;为了效率内核使用先求和再取反方式计算;
2、按16bit与32bit结果一致;内核使用32bit以减少运算次数;
3、计算过程中二进制溢出进位时,将进位加到低位,循环计算,直到高位为0;
//详细过程可阅读内核源码。反码求和逻辑比较复杂,自行研究。

4、伪首部相关问题

伪首部并非TCP&UDP数据报中实际的有效成分。伪首部是一个虚拟的数据结构,其中的信息是从数据报所在IP分组头的分组头中提取的,既不向下传送也不向上递交,而仅仅是为计算校验和。这样的校验和,既校验了TCP&UDP用户数据的源端口号和目的端口号以及TCP&UDP用户数据报的数据部分,又检验了IP数据报的源IP地址和目的地址。伪报头保证TCP&UDP数据单元到达正确的目的地址。

Q:已经有了ip头校验,为什么还需要在tcp层再次校验ip相关信息?
A:网络报文传输需要进过很多中间网络设备,一般为路由器,rt会操作修改ip头信息(ttl等内容),然后重新计算ip校验和。比如,如果传输过程中由于软硬件异常导致ip头的目的地址错误将报文发送到了非正确的目的地,接收方检查ip头时未发现异常,此时上送到tcp层处理时,如果不检查ip头相关信息就无法检测出此报文是错误的。

Q:伪首部可以直接使用整个ip头吗?
A:不合理,ip头的部分自带经过路由器时会修改变化的,如果使用完整的ip头,中间设备每次都要重新计算tcp层校验和。并且完整的头也增加了计算量。

5、linux内核校验和

计算校验和需要遍历每个字节,对性能影响还是很大的,所以linux对校验和的计算做了很多优化处理
1、按需分多部计算,采用先求和最后取反的计算方式,可以将计算过程分多个步骤,包括报文分片时可以每片单独计算sum,最后再同一相加区分。
2、借助硬件加速,将校验和计算工作留给网卡硬件处理(接收发送都可以),但需要硬件支持此特性。

skb->ip_summed表明L3和L4的计算结果,区分接收和发送:

1、接收过程

skb->csum可能包含L4一部分校验和;
skb->ip_summed字段代表:设备驱动告诉L4软件当前校验和的状态,各取值含义如下:

(1) CHECKSUM_NONE:
skb->csum中的校验和无效,可能是硬件没有提供校验和(硬件不支持、未开启此功能等),此时将ip_summed设为CHECKSUM_NONE,让L4软件层重新校验;

(2) CHECKSUM_COMPLETE:
硬件已经校验了L4报头和其payload部分,并且校验和保存在了skb->csum中,L4软件只需要再计算伪报头然后检查校验结果即可。硬件计算稍复杂的伪头部比较好性能,因为伪头部需要提取ip头的信息。
伪头部包含ip信息、报文长度信息等,需要解析提取一些字段,此类工作对硬件来说比较复杂, 所以伪首部仍然交由软件计算。

(3) CHECKSUM_UNNECESSARY:
硬件已经进行了完整的校验,无需软件再进行检查,L4收到数据包后如果检查ip_summed是这种情况,就可以跳过校验过程;

(4) CHECKSUM_PARTIAL:
虚拟化环境同宿主机不同vm通信时收包会有此种情况(如virtio网卡),此时认为数据虽然未校验,但认为可靠,不过tcp头的校验和字段是错误的。tcp协议栈检查校验和时此种情况不会检查。

 * CHECKSUM_PARTIAL:
 *
 *   A checksum is set up to be offloaded to a device as described in the
 *   output description for CHECKSUM_PARTIAL. This may occur on a packet
 *   received directly from another Linux OS, e.g., a virtualized Linux kernel
 *   on the same host, or it may be set in the input path in GRO or remote
 *   checksum offload. For the purposes of checksum verification, the checksum
 *   referred to by skb->csum_start + skb->csum_offset and any preceding
 *   checksums in the packet are considered verified. Any checksums in the
 *   packet that are after the checksum being offloaded are not considered to
 *   be verified.

2、发送过程

skb->ip_summed字段包含了L4软件告诉设备驱动程序当前校验和的状态,各取值含义如下:
(1) CHECKSUM_NONE:L4软件已经进行了校验,硬件无需做任何事情;

(2) CHECKSUM_PARTIAL:L4软件计算了伪报头,并且将值保存在了tcp/udp首部的check字段中,硬件需要计算其余部分的校验和。硬件适合做简单的++操作,伪头部稍复杂交给cpu。
(对应网卡驱动程序会设置描述符相应字段,硬件来处理)

参考:
https://blog.csdn.net/qy532846454/article/details/7010852
https://blog.csdn.net/weixin_39631017/article/details/111845098
https://blog.csdn.net/zhangwenxinzck/article/details/107574202
https://blog.csdn.net/weixin_29159127/article/details/116691805

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值