linux kernel.shmall

一、引言 1、linux kernel中要保证IP/TCP/UDP数据的正确性,就要对数据进行校验。校验方法,简单来说,就是对要计算的数据,以16bit为单元进行累加,取反。 2、由于目前很多网卡设备是支持对L4层(传输层 tcp/udp层)数据包进行checksum的计算和验证的,

一、引言

1、linux kernel中要保证IP/TCP/UDP数据的正确性,就要对数据进行校验。校验方法,简单来说,就是对要计算的数据,以16bit为单元进行累加,取反。
2、由于目前很多网卡设备是支持对L4层(传输层 tcp/udp层)数据包进行checksum的计算和验证的,所以在L4协议软件的实现中,会根据网卡的支持情况作不同的处理,为此内核在struct sk_buff结构和struct net_device中增加了校验和相关的参数,如下:

二、struct sk_buff 结构

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,可取四个标志,而且在发送和接收时的含义还有所不同。

1、接收过程

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软件只需要再计算伪报头然后检查校验结果即可。

2、发送过程

skb->ip_summed字段包含了L4软件告诉设备驱动程序当前校验和的状态,各取值含义如下:
(1) CHECKSUM_NONE:L4软件已经进行了校验,硬件无需做任何事情;
(2) CHECKSUM_PARTIAL:L4软件计算了伪报头,并且将值保存在了tcp/udp首部的check字段中,硬件需要计算其余部分的校验和。

三、struct net_device 结构

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/

知秋君
上一篇 2024-07-04 21:02
下一篇 2024-07-04 20:36

相关推荐