lwip中ip层的实现浅析

来源:互联网 发布:windows whistler 2257 编辑:程序博客网 时间:2024/05/19 13:24

以下部分来源2001版<lwip协议栈的设计与实现>,可能已经不适用于当前版本的lwip,但是作用于参考足够了~

--------------------------------------------------------

LwIP 仅实现了 IP 层大部分的基本功能,能够发送、接收以及转发信息包,但是不能接 收和发送 IP 分片包,也不能处理携带 IP 参数选项的信息包。不过对大多数的应用来说,这 不会引起任何问题。 

1 接收信息包  
    对到达的 IP  信息包,由网络设备驱动调用 ip_input()函数开始处理。在这里完成对 IP 版本字段及包头长度的初始完整性检查,同时还要计算和验证包头校验和。协议栈假定代理 会重新组合 IP 分片包为一个完整的包,因此它会把收到的 IP 分片包直接丢掉。同样,信息 包携带的 IP 参数选项也被认为已经由代理处理过,这些内容会被删掉。 
    接下来,函数检查目的地址是否与网络接口的 IP 地址相符以确定信息包是否到达预定 主机。网络接口在链表中被排序并且采用了线性检索。因为预计接口的数量比较少,所以没 有实现比线性检索更好的检索策略。 
    如果一个到达的信息包被发现已经到达了目的主机,则由协议字段来决定信息包应该传 送到哪一个上层协议。 

2 发送信息包  

    外发的信息包由 ip_output()函数处理,该函数使用 ip_route()函数查找适当的网络接口来 传送信息包。当外发的网络接口确定后,信息包传给以外发网络接口为参数的 ip_output_if() 函数。在这里,所有的 IP 包头字段被填充,并且计算 IP 包头校验和。IP 信息包的源及目标 地址作为参数被传递给 ip_output_if()函数。源 IP 地址可以被忽略,不过在这种情况下外发 网络接口的IP 地址会作为 IP 信息包的源 IP 地址被使用。 
    ip_route()函数通过线性检索网络接口链表找到适当的网络接口。在检索期间,用网络接 口的网络掩码对 IP 信息包的目标地址进行掩码运算。如果经掩码运算的目标地址等与同样经掩码运算的接口 IP  地址(即网络地址相等,同在一个子网中,译者注),则选择这个接口。如 果没有找到匹配的,则使用缺省网络接口。缺省网络接口在启动时或运行时由人工操作进行 配置(注意运行期间人工配置需要一个能配置协议栈的应用程序,LwIP 不包含这样的程序)。 如果缺省网络接口的地址不匹配目的 IP 地址,则网络接口结构体(图 5 )的gw 字段被选择 作为链路层帧的目的MAC地址(注意,在这种情况下,IP 信息包的目标地址与链路层帧的目标地址是不同的)。路由的基本形式掩盖这样一个事实:一个网络可能拥有很多路由器依附 它。不过对于最基本的情况,一个本地网络只拥有一个路由器进行路由工作。 
    因为传输层协议 UDP  与 TCP 在计算传输层校验和的时候需要拥有目标 IP 地址,因此在有些情况下,信息包被传递给 IP 层之前必须确定外发网络接口。这可以让传输层函数直接调用 ip_route()函数做到,因为在信息包到达 IP 层时已经知道了外发网络接口,因此就没 有必要再检索网络接口链表,而是让那些协议改为直接调用 ip_output_if()函数。因为这个函 数将网络接口作为参数,从而避免了对外发接口的检索。 

3 转发信息包  

    如果没有网络接口的地址与到达的信息包的目标地址相同,信息包应该被转发。这项工 作由 ip_forward()函数完成。在这里,TTL 字段值被减少(Time To Live的简写,生存时间的意 思,译者注),当减为 0 的时候,将会给 IP 信息包的最初发送者发送 ICMP错误信息,并抛弃 该信息包。因为 IP 包头被改变,因此需要调整 IP 包头校验和。不过,不必重新计算完整的 校验和,因为可以使用简单的算法调整原始 IP 校验和。最后,信息包被转发到适当的网络 接口。查找适当的网络接口的算法与发送信息包使用的算法相同。  

4 ICMP处理  

    ICMP 处理相当简单。ip_input()函数收到的 ICMP  信息包被移交给 icmp_input()函数对 ICMP 包头解码,然后进行适当的动作。某些 ICMP 消息被传递给上层协议,由传输层的特 定函数处理。ICMP目标不可到达消息可以由传输层发送,特别是通过 UDP ,使用 icmp_dest_unreach()函数完成这项工作。 

    用 ICMP ECHO 消息来探测网络被广泛的使用,因而 ICMP 回显处理性能最优。实际处 理被放置在 icmp_input()函数,由交换到达包的源与目的 IP 地址,改变 ICMP 类型为回显应 答以及调整 ICMP 校验和组成。然后,信息包被回传给 IP 层传送。

--------------------------------------------------------

关于上述部分,需要确定一个原则:报文在经由路由或者转发的时候,其src-IP 和 dst-IP是不会变化的,src-MAC 和 dst-MAC则会经常变化(变化为switch或router的mac)

--------------------------------------------------------

"首部检验和字段是根据I P首部计算的检验和码。它不对首部后面的数据进行计算。 I C M P 、 I G M P 、U D P和T C P在它们各自的首部中均含有同时覆盖首部和数据检验和码。 

    为了计算一份数据报的 I P检验和,首先把检验和字段置为 0 。然后,对首部中每个 16 bit 进行二进制反码求和(整个首部看成是由一串 16 bit的字组成),结果存在检验和字段中。当收到一份I P数据报后,同样对首部中每个 16 bit进行二进制反码的求和。由于接收方在计算过 程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错, 那么接收方计算的结果应该为全 1。如果结果不是全1  (即检验和错误),那么I P就丢弃收到的 数据报。但是不生成差错报文,由上层去发现丢失的数据报并进行重传。 

    I C M P 、I G M P 、U D P和T C P都采用相同的检验和算法,尽管 T C P和U D P 除了本身的首部和 数据外,在I P首部中还包含不同的字段。在RFC 1071[Braden, Borman and Patridge 1988] 中有 关于如何计算I n t e r n e t检验和的实现技术。由于路由器经常只修改 T T L字段(减 1),因此当路 由器转发一份报文时可以增加它的检验和,而不需要对  I P 整个首部进行重新计算。 R F C 1141[Mallory and Kullberg 1990]为此给出了一个很有效的方法。 但是,标准的BSD实现在转发数据报时并不是采用这种增加的办法。"   (tcp/ip 详解卷1)

来看看lwip中关于ip校验和的实现:(二进制反码求和 百度一下你就知道)

u16_tinet_chksum(void *dataptr, u16_t len){  u32_t acc, sum;  acc = chksum(dataptr, len);  sum = (acc & 0xffff) + (acc >> 16);  sum += (sum >> 16);  return ~(sum & 0xffff);}u16_tinet_chksum(void *dataptr, u16_t len){  u32_t acc, sum;  acc = chksum(dataptr, len);  sum = (acc & 0xffff) + (acc >> 16);  sum += (sum >> 16);  return ~(sum & 0xffff);}

原创粉丝点击