Chinaunix首页 | 论坛 | 博客
  • 博客访问: 825408
  • 博文数量: 264
  • 博客积分: 592
  • 博客等级: 中士
  • 技术积分: 1574
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-24 22:02
文章分类

全部博文(264)

文章存档

2019年(2)

2018年(1)

2017年(1)

2016年(4)

2015年(14)

2014年(57)

2013年(88)

2012年(97)

分类: LINUX

2014-02-12 15:51:13

转:http://blog.csdn.net/nerdx/article/details/12656987
  1. //  为分片确定正确的ipq结构  
  2. //      通过5元组定位ipq,成功后,递增ipq引用计数,返回ipq  
  3. //  定位5元组   
  4. //      1. 可通过ip报文获取  
  5. //      2.user 通过ip_defrag给出,指出重组是由谁发起的,最常见的时IP_DEFRAG_LOCAL_DELIVER,当重组的入口分包要传递给本地时  
  6. //  ipq中所有分片最迟完成重组的时间为30HZ  
  7. 1.1 static inline struct ipq *ip_find(struct iphdr *iph, u32 user)  
  8. {  
  9.     //定位4元组  
  10.     __u16 id = iph->id;  
  11.     __u32 saddr = iph->saddr;  
  12.     __u32 daddr = iph->daddr;  
  13.     __u8 protocol = iph->protocol;  
  14.     //对4元组进行hash  
  15.     unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);  
  16.     struct ipq *qp;  
  17.   
  18.     read_lock(&ipfrag_lock);  
  19.     //选择正确的bucket  
  20.     for(qp = ipq_hash[hash]; qp; qp = qp->next) {  
  21.         if(qp->id == id      &&  
  22.            qp->saddr == saddr    &&  
  23.            qp->daddr == daddr    &&  
  24.            qp->protocol == protocol &&  
  25.            qp->user == user) {  
  26.             atomic_inc(&qp->refcnt);  
  27.             read_unlock(&ipfrag_lock);  
  28.             return qp;  
  29.         }  
  30.     }  
  31.     read_unlock(&ipfrag_lock);  
  32.     //该4元组的第一个分片,创建新的ipq  
  33.     return ip_frag_create(hash, iph, user);  
  34. }  
  35.   
  36. //调用路径:ip_find->ip_frag_create  
  37. //  新ip分片到达时,根据5元组创建一个ipq  
  38. 1.2 static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)  
  39. {  
  40.     struct ipq *qp;  
  41.   
  42.     if ((qp = frag_alloc_queue()) == NULL)//SLAB缓存  
  43.         goto out_nomem;  
  44.     //5元组  
  45.     qp->protocol = iph->protocol;  
  46.     qp->last_in = 0;  
  47.     qp->id = iph->id;  
  48.     qp->saddr = iph->saddr;  
  49.     qp->daddr = iph->daddr;  
  50.     //重组的发起者  
  51.     qp->user = user;  
  52.     //新ipq还没有任何分片与之关联  
  53.     qp->len = 0;  
  54.     qp->meat = 0;  
  55.     qp->fragments = NULL;  
  56.     qp->iif = 0;//入口设备  
  57.   
  58.     init_timer(&qp->timer);//定时器,当一定时间范围内,重组没有完成,则释放与之关联的内存  
  59.     qp->timer.data = (unsigned long) qp;   
  60.     qp->timer.function = ip_expire;        
  61.     spin_lock_init(&qp->lock);  
  62.     atomic_set(&qp->refcnt, 1);  
  63.   
  64.     return ip_frag_intern(hash, qp);//将ipq插入到hash表中  
  65.   
  66. out_nomem:  
  67.     NETDEBUG(if (net_ratelimit()) printk(KERN_ERR "ip_frag_create: no memory left !\n"));  
  68.     return NULL;  
  69. }  
  70.   
  71. //  将ipq插入到hash表中  
  72. //  调用路径:ip_frag_create->ip_frag_intern  
  73. //  函数主要任务:  
  74. //      1.修改定时器的到期时间,在一段时间内没有接收到新的分片,则释放所有接收到的分片。  
  75. //      2.将ipq插入到hash表  
  76. //      3.将ipq插入到lru链表  
  77. 1.3 static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)  
  78. {  
  79.     struct ipq *qp;  
  80.   
  81.     write_lock(&ipfrag_lock);  
  82.   
  83.     qp = qp_in;  
  84.     //sysctl_ipfrag_time = 30HZ  
  85.     if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time))//ipq所有封包延迟定时器  
  86.         atomic_inc(&qp->refcnt);//增加引用计数,表示定时器对其的引用  
  87.   
  88.     //表示hash表对其的引用  
  89.     atomic_inc(&qp->refcnt);  
  90.     if((qp->next = ipq_hash[hash]) != NULL)  
  91.         qp->next->pprev = &qp->next;  
  92.     ipq_hash[hash] = qp;//将ipq插入到hash表中  
  93.     qp->pprev = &ipq_hash[hash];  
  94.     //将新加入的ipq加入到lru尾  
  95.     INIT_LIST_HEAD(&qp->lru_list);  
  96.     list_add_tail(&qp->lru_list, &ipq_lru_list);  
  97.     ip_frag_nqueues++;  
  98.     write_unlock(&ipfrag_lock);  
  99.     return qp;  
  100. }  
  101.   
  102. //ipq中所有分片的到期时间  
  103. //接收到的ip分片不能永久的存在内存中,如果在一定时间范围内,没有为其完成重组,则需要释放所有分片占用的内存   
  104. //  1.删除定时器  
  105. //  2.从hash表中unlink  
  106. //  3.使用分片的入口设备向发送方发送icmp消息,告诉对方过期  
  107. //  4.释放ipq中的所有分片,释放ipq结构  
  108. 1.4 static void ip_expire(unsigned long arg)  
  109. {  
  110.     struct ipq *qp = (struct ipq *) arg;  
  111.   
  112.     spin_lock(&qp->lock);  
  113.   
  114.     if (qp->last_in & COMPLETE)  
  115.         goto out;  
  116.     //删除定时器,从ipq hash表中unlink  
  117.     ipq_kill(qp);  
  118.   
  119.     if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) {  
  120.         struct sk_buff *head = qp->fragments;  
  121.         if ((head->dev = dev_get_by_index(qp->iif)) != NULL) {  
  122.             icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);//发送ICMP消息  
  123.             dev_put(head->dev);  
  124.         }  
  125.     }  
  126. out:  
  127.     spin_unlock(&qp->lock);  
  128.     ipq_put(qp, NULL);//释放与ipq关联的所有分片,释放ipq结构  
  129. }  
阅读(996) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~