免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2275 | 回复: 5
打印 上一主题 下一主题

增量式修改检验和(IP, TCP, UDP)算法的研究和实现 [复制链接]

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-08-26 13:43 |只看该作者 |倒序浏览
/*
* Author: Godbach
* E-mail:nylzhaowei@163.com
* 本文可以自由转载,但请标明出处,并保证本文的完整性。
*/
对于数据包中检验和的计算,很多讲TCP/IP协议的书中都讲过,RFC1071是讨论计算检验和的文档。传统的计算方法都是需要将整个数据报文的数据(IP报文是计算IP头部的数据)进行反码求和。

但在实际的应用中,存在对收到的数据包进行修改若干个地方,并回送至发送方或者转发的情况。这个时候,就涉及的重新计算数据包的检验和。最常见的可能就是,将收到的数据包的TTL字段减1,并转发的情况。如果仍旧按照传统的计算检验和的方式进行计算,特别是当数据包长度很大时,为了重新计算校验和而将整个数据包的数据遍历一边,反码求和,效率肯定比较低。

一、增量修改检验和的实现

解决的方法就是采用增量式修改检验和的方法。该方法是由RFC1141提出的。这里进行以下简单的变通,将增量式修改检验和的公式列出来:
HC -- 数据包中旧的检验和
HC'-- 数据包中新的检验和
m  -- 数据包中某个域(16-bit字)修改前的值
m' -- 数据包中某个域(16-bit字)修改后的值

那么,修改某个域之后的校验和HC'与HC,m 和m'的关系如下:
    HC' = HC + m + ~m'        (公式1)

具体实现的C代码如下:
/*implemented according with RFC 1071 and 1141*/

static  unsigned short csum_incremental_update(unsigned short old_csum,

                unsigned short old_field,

                unsigned short new_field)

{

    unsigned long csum = old_csum + old_field + (~new_field & 0xFFFF);

    csum = (csum >> 16) + (csum & 0xFFFF);

    csum +=  (csum >> 16);

    return csum;

}

这个时候,如果修改了IP头部的TTL值,将取修改前的TTL域所在的16-bit字的值为old_field, 修改后的为new_field, 并取出就得检验和old_csum,通过调用该函数即可计算出新的检验和。
当然该函数每次只能计算一个16-bit字,如果对数据包中修改了过多的16-bit字,那么它的性能将会如何呢。

用TCP数据包做测试。而且该TCP数据包为三次握手时的数据包,仅有头部,没有数据部分。对该数据包修改了8个不同的16-bit字,调用该函数8次所需的时间仍旧不到传统计算方法的一半。可见,效果适合明显的。

二、增量修改检验和的完善
1.RFC1071和1141所提出的增量式修改检验有一个BUG,就是按照公式1计算新的检验和时,有可能出现计算结果为0xFFFF的情形,可以参看 RFC1624给出的例子。如果检验和为0xFFFF,则意味着数据包中所有部分相加的结果为0x0000。这是不可能的。因此,RFC1624提出了对这个BUG的改进方法,见公式2:
    HC' = ~(~HC + ~m + m')        (公式2)
公式2先对旧的检验和和某个域的值取反,加上新的域值之后,将整体的和再次取反得出新的检验和。
具体实现的C代码如下:
/*implemented according with RFC 1624, modified the algorithm from RFC 1071 and 1141*/

static  unsigned short csum_incremental_update_modified(unsigned short old_csum,

                unsigned short old_field,

                unsigned short new_field)

{

    unsigned long csum = (~old_csum & 0xFFFF) + (~old_field & 0xFFFF) + new_field ;

    csum = (csum >> 16) + (csum & 0xFFFF);

    csum +=  (csum >> 16);

    return ~csum;

}

该方法和公式1给出的方法很明显多出了两次取反操作,在效率上并没有公式1的高,这个也经过了实际的测试。
2. 对此,RFC1624又给出了另外一个方法既可以保证修正RFC1071和RFC1141的BUG,又可以保证执行的效率,见公式3:
    HC' = HC - ~m - m'        (公式3)
公式3采用减法操作代替公示2中的加法操作。
具体实现的AT&T汇编代码如下:
/*incremental update IP ,TCP, UDP checksum,
implemented in Assembly according with RFC 1624, used subtraction to update checksum*/

static inline unsigned short csum_incremental_update(unsigned short old_csum,
                                unsigned short old_field,
                                unsigned short new_field)
{
    __asm__ __volatile__(
        "notw %1; \n"
        "subw %1, %0; \n"   
        "sbbw %2, %0; \n"
        "sbbw $0, %0; \n"
        :"=r" (old_csum)
        :"r"(old_field), "r"(new_field), "0"(old_csum));
    return old_csum;
}

经过实际测试,公式3的效率比公式2的效率高了很多,基本上和公示1的效率接近。

以上就是本人关于增量式修改检验和的研究和实现。不妥之处,请多指点。

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
2 [报告]
发表于 2008-08-26 14:06 |只看该作者
写得不错,学习了!

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
3 [报告]
发表于 2008-08-26 14:12 |只看该作者
原帖由 dreamice 于 2008-8-26 14:06 发表
写得不错,学习了!


最近没怎么见到你,比较忙吗

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
4 [报告]
发表于 2008-08-26 14:35 |只看该作者
原帖由 Godbach 于 2008-8-26 14:12 发表


最近没怎么见到你,比较忙吗


都在的,任务比较多。我隐身
这里好想不准灌水哦 ,还是讨论技术问题。

论坛徽章:
0
5 [报告]
发表于 2008-08-26 14:37 |只看该作者
学习了!谢谢。            

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
6 [报告]
发表于 2008-08-26 14:47 |只看该作者
原帖由 scutan 于 2008-8-26 14:37 发表
学习了!谢谢。            


大家都在啊。 本来已经贴在C版了,没有人气,还是拿到内核版有需要的一起研究
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP