Linux内核分析 - 网络[十三]:校验和
发布时间:2016-10-08 04:33:34 所属栏目:Linux 来源:站长网
导读:副标题#e# 内核版本:2.6.34 报文的IP校验和、ICMP校验和、TCP/UDP校验和使用相同的算法,在RFC1071中定义,网上这方面的 资料和例子很多,就不解释算法流程了,而是侧重于在实现的变化和技巧。 The checksum algorithm is simply to add up all the 16-bit
|
还是以例子说明,一个5字节 的buff,起始地址addr(1)=0x1,下面是传统计算和从偶数地址开始计算的对比,要注意的是累加进程中是循环进位的,即溢出 的进位会加到最低位。因此,无论哪种方法,1,3,5累加进位会加到2+4中,而2,4累加进位会加到1+3+5中,这也是最后调换前后 8bit的值就可以保证两者相等原因。
保证计算的长度是偶数字节 长度对齐理由很简单,累加是 以16bit为单位的,因此主体部分只计算偶数字节,如果有多余的一个字节len & 1,则进行如下处理。 if (len & 1) #ifdef __LITTLE_ENDIAN result += *buff; #else result += (*buff << 8); #endif 最后是计算的主体部分,可以看到,它并不是单纯的16bit累加,而是用32bit累加do-while循环。当然,为了 进行32bit累加,要将起始地址处理成32bit对齐,长度也要处理成32bit对齐。
count = len >> 1; /* nr of 16-bit words.. */
if (count) {
if (2 & (unsigned long) buff) {
result += *(unsigned short *) buff;
count--;
len -= 2;
buff += 2;
}
count >>= 1; /* nr of 32-bit words.. */
if (count) {
unsigned int carry = 0;
do {
unsigned int w = *(unsigned int *) buff;
count--;
buff += 4;
result += carry;
result += w;
carry = (w > result);
} while (count);
result += carry;
result = (result & 0xffff) + (result >> 16);
}
if (len & 2) {
result += *(unsigned short *) buff;
buff += 2;
}
}
csum_fold() 校验和取反 取反操作很简单,~sum
static inline __sum16 csum_fold(__wsum csum)
{
u32 sum = (__force u32)csum;
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
return (__force __sum16)~sum;
}(编辑:宣城站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

![Linux内核分析 - 网络[十三]:校验和](http://img16.aspzz.cn/uploads/allimg/c160921/14J4632IQ430-31349.gif)

