在ip_local_deliver中,如果检测到是分片包,则需要将报文进行重组。其所有的分片被重新组合后才能提交到上层协议,每一个被重新组合的数据包文用ipq结构实例来表示
struct ipq { struct inet_frag_queue q; u32 user;//分片来源 __be32 saddr;//原地址 __be32 daddr;//目的地址 __be16 id;//ip报文序列号 u8 protocol;//上层协议号 //这四个字段来自ip首部是为了确定来自哪个ip数据报文 u8 ecn; /* RFC3168 support */ u16 max_df_size; /* largest frag with DF set seen */ int iif; int vif; /* L3 master device index */ unsigned int rid;//已收到的分片计数器 struct inet_peer *peer;//记录发送方信息 //通过rid peer 可以防止Dos攻击 };
网络空间分段管理结构
struct inet_frags { struct inet_frag_bucket hash[INETFRAGS_HASHSZ];//哈希队列 struct work_struct frags_work;//工作队列 unsigned int next_bucket; unsigned long last_rebuild_jiffies; bool rebuild; /* The first call to hashfn is responsible to initialize * rnd. This is best done with net_get_random_once. * * rnd_seqlock is used to let hash insertion detect * when it needs to re-lookup the hash chain to use. */ u32 rnd;//随机数 seqlock_t rnd_seqlock;// int qsize;//队列长度 unsigned int (*hashfn)(const struct inet_frag_queue *); bool (*match)(const struct inet_frag_queue *q, const void *arg);//分段队列匹配函数 void (*constructor)(struct inet_frag_queue *q, const void *arg); void (*destructor)(struct inet_frag_queue *); void (*frag_expire)(unsigned long data);//队列过期处理函数 struct kmem_cache *frags_cachep; const char *frags_cache_name; };
struct netns_frags { /* The percpu_counter "mem" need to be cacheline aligned. * mem.count must not share cacheline with other writers */ struct percpu_counter mem ____cacheline_aligned_in_smp; /* sysctls */ int timeout;超时时间 int high_thresh;内存使用上限 int low_thresh;内存使用下限 int max_dist; };