加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内核分析 - 网络[十三]:校验和

发布时间:2016-10-16 06:10:02 所属栏目: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的值就可以保证两者相等原因。

Linux内核分析 - 网络[十三]:校验和

保证计算的长度是偶数字节

长度对齐理由很简单,累加是 以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;     
}

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读