linux TCP/IP协议栈 ---ip_defrag() inet_frag_find
- /* Process an incoming IP datagram fragment. */
- int ip_defrag(struct sk_buff *skb, u32 user)
- {
- struct ipq *qp;
- IP_INC_STATS_BH(IPSTATS_MIB_REASMREQDS);
- /* Start by cleaning up the memory. */
- /*
- * 首先检查所有IP分片所消耗的内存是否大于系统允许的最高阀值,如果是,则调用
- * ip_evictor()丢弃未完全到达的IP分片,从最旧的分片开始释放。此举一来是为了节
- * 约内存,二来是未了防止黑客的恶意攻击。使分片在系统中累计,降低系统性能。
- */
- if (atomic_read(&ip4_frags.mem) > ip4_frags_ctl.high_thresh)
- ip_evictor();
- /* Lookup (or create) queue header */
- /* 如果该分片是数据报的第一个分片,则ip_find返回一个新的队列来搜集分片,否则
- * 返回其所属于的分片队列。 */
- if ((qp = ip_find(ip_hdr(skb), user)) != NULL) {
- int ret;
- spin_lock(&qp->q.lock);
- /* 将该分片加入到队列中,重组分片队列,如果所有的包都收到了,则该函数
- * 负责重组IP包 */
- ret = ip_frag_queue(qp, skb);
- spin_unlock(&qp->q.lock);
- ipq_put(qp); /* 引用计数减1 */
- return ret;
- }
- IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
- kfree_skb(skb);
- return -ENOMEM;
- }
- struct inet_frag_queue *inet_frag_find(struct inet_frags *f, void *key,
- unsigned int hash)
- {
- struct inet_frag_queue *q;
- struct hlist_node *n;
- /* f->lock是读写锁,先搜索是否存在该IP分段所属的队列 */
- read_lock(&f->lock);
- hlist_for_each_entry(q, n, &f->hash[hash], list) { /* 扫描该HASH槽中所有节点 */
- /* f->match中match字段在ipfrag_init中初始化为ip4_frag_match函数。*/
- /* 对比分片队列中的散列字段和user是否和key相等,key指向的是struct ip4_create_arg
- * 结构,包含IP头部和user字段。 */
- if (f->match(q, key)) {
- atomic_inc(&q->refcnt); /* 若找到,则增加该队列引用计数。 */
- read_unlock(&f->lock);
- return q; /* 返回该队列 */
- }
- }
- read_unlock(&f->lock);
- /* 该分片是第一个IP分片,创建一个新的分片队列并添加到合适的HASH队列 */
- return inet_frag_create(f, key, hash);
- }
没有评论:
发表评论