赞
踩
1、linux kernel中要保证IP/TCP/UDP数据的正确性,就要对数据进行校验。校验方法,简单来说,就是对要计算的数据,以16bit为单元进行累加,取反。
2、由于目前很多网卡设备是支持对L4层(传输层 tcp/udp层)数据包进行checksum的计算和验证的,所以在L4协议软件的实现中,会根据网卡的支持情况作不同的处理,为此内核在struct sk_buff结构和struct net_device中增加了校验和相关的参数,如下:
struct sk_buff 中与checksum有关的字段如下:
struct sk_buff
{
...
__u8 ip_summed:2;
...
union {
__wsum csum;
struct {
__u16 csum_start;
__u16 csum_offset;
};
};
...
}
#define CHECKSUM_NONE 0
#define CHECKSUM_UNNECESSARY 1
#define CHECKSUM_COMPLETE 2
#define CHECKSUM_PARTIAL 3
上述联合体中哪个成员有效取决于ip_summed的值,ip_summed共两个bit,可取四个标志,而且在发送和接收时的含义还有所不同。
skb->csum可能包含L4一部分校验和;
skb->ip_summed字段代表:设备驱动告诉L4, 软件当前校验和的状态,各取值含义如下:
(1) CHECKSUM_NONE:
skb->csum中的校验和无效,可能是硬件没有提供校验和,可能是硬件不支持,也可能是硬件校验出错但是并未丢弃数据包,此时将ip_summed设为CHECKSUM_NONE,让L4软件重新校验;
(2) CHECKSUM_UNNECESSARY:
硬件已经进行了完整的校验,无需软件再进行检查,L4收到数据包后如果检查ip_summed是这种情况,就可以跳过校验过程;
(3) CHECKSUM_COMPLETE:
硬件已经校验了L4报头和其payload部分,并且校验和保存在了skb->csum中,L4软件只需要再计算伪报头然后检查校验结果即可。
skb->ip_summed字段包含了L4软件告诉设备驱动程序当前校验和的状态,各取值含义如下:
(1) CHECKSUM_NONE:L4软件已经进行了校验,硬件无需做任何事情;
(2) CHECKSUM_PARTIAL:L4软件计算了伪报头,并且将值保存在了tcp/udp首部的check字段中,硬件需要计算其余部分的校验和。
net_device结构中的feature字段中定义了如下和校验和相关的字段,这些字段表明了硬件计算校验和的能力。
NETIF_F_NO_CSUM:该设备非常可靠,无需L4执行任何校验,环回设备一般设置该标记
NETIF_F_IP_CSUM:设备可以对基于IPv4的TCP和UDP数据包进行校验
NETIF_F_IPV6_CSUM:设备可以对基于IPv6的TCP和UDP数据包进行校验
NETIF_F_HW_CSUM: 设备可以对任何L4协议的数据包进行校验
(1)UDP之数据报校验和:https://blog.csdn.net/xiaoyu_750516366/article/details/83422212
(2)Checksum in Linux Kernel:http://hustcat.github.io/checksum-in-kernel/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。