Chinaunix首页 | 论坛 | 博客
  • 博客访问: 378716
  • 博文数量: 56
  • 博客积分: 1449
  • 博客等级: 中尉
  • 技术积分: 822
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-08 10:24
文章分类

全部博文(56)

文章存档

2014年(7)

2012年(13)

2011年(10)

2010年(26)

分类: LINUX

2012-05-23 16:54:29

数据包从外界进入到协议栈的IP层的入口的ip_rcv函数。

ip_rcv:

1. 它首先判断包的类型,如果是去往其他主机的包,则直接丢弃。

2. skb是共享的,则创建一个新的sk_buff结构,并拷贝skb。数据缓冲区依然保持共享。

3. 确保最小的IP头部已经在线性数据缓冲区中,即在skb->data所指向的内存中。否则需要从skb_shinfo(skb)->frags[]中拷贝。可能有些驱动把数据放入了非线性区域。这种情形是相当少的。

4. IP头部的各个字段进行严格检查,看其是否合法,若非法,则丢弃该包。

5. 3,只不过这次要确保实际IP头部在线性数据缓冲区中。

6. 验证IP头部校验和及skb和头部的长度有效性。

7. 由于L2层可能会对包进行padding,将skb的数据缓冲区调整为IP头部指定的确切长度。

8. 调用ip_rcv_finish

ip_rcv->ip_rcv_finish:

1. 若该包的路由信息为空,则调用ip_route_input获取路由信息,路由信息在skb->dst字段中。

2. IP头部大于20字节,则调用ip_rcv_options处理选项。

3. 实质调用skb->dst.input()。若递交到本地则是ip_local_deliver,若转发则是ip_forward

ip_rcv->ip_rcv_finish->ip_local_deliver:

1. 如果该skb是一个分段IP包,则调用ip_defrag进行IP分段包重组。

2. 调用ip_local_deliver_finish

ip_rcv->ip_rcv_finish->ip_local_deliver_finish:

最简单的情形下,该函数根据IP头部的协议字段找到处理该协议的上层协议处理入口并调用。数据包离开IP层。

IP分片重组

ip_rcv->ip_rcv_finish->ip_local_deliver->ip_defrag:

1. 检查IP分片所消耗的内存是否大于系统设置的最高阀值,若是,则调用ip_evictor函数开始清理分片,从最旧的开始清理,直至达到系统设置的最低阀值。

2. 调用ip_find找到该分片的分片等待队列。若其是第一个达到的分片,则会分配一个分片等待队列。

3. 调用ip_frag_queue将该分片加入到其所属分片等待队列,对所有分片进行重组,消除可能存在的重叠。ip_frag_reasm负责对所有分片到达时对分片进行重组。

ip_rcv->ip_rcv_finish->ip_local_deliver->ip_defrag->ip_find:

设置好inet_frag_find所需的参数并调用它,进行实质性的工作由这个函数完成。

ip_rcv->ip_rcv_finish->ip_local_deliver->ip_defrag->ip_find->inet_frag_find:

扫描哈希槽队列中是否有容纳该分片的分片等待队列,若找到则返回该队列,否则调用inet_frag_create创建一个分片等待队列。

ip_rcv->ip_rcv_finish->ip_local_deliver->ip_defrag->ip_find->inet_frag_find->inet_ftag_create:

1. 调用inet_frag_alloc创建一个新的分片等待队列,并进行初始化。

2. 调用inet_frag_intern将该队列加入到哈希表中并加入的lru_list链表中。 

阅读(4333) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~