日期:2014-05-16 浏览次数:20651 次
7.11 tcindex tcindex是根据skb数据包中的tcindex参数对数据类型进行分类的, 而tcindex的值是在上层设置好的, 代码在net/sched/cls_tcindex.c中定义。 7.11.1 数据结构和过滤器操作结构 // tcindex过滤结果 struct tcindex_filter_result { // 扩展结构 struct tcf_exts exts; // 分类结果 struct tcf_result res; }; // tcindex过滤器 struct tcindex_filter { // 关键字 u16 key; // 过滤结果 struct tcindex_filter_result result; // 链表下一项 struct tcindex_filter *next; }; // tcindex数据结构 struct tcindex_data { // 过滤结果, 完美哈希, 是数组形式 struct tcindex_filter_result *perfect; /* perfect hash; NULL if none */ // 不完美的哈希, 是链表形式 struct tcindex_filter **h; /* imperfect hash; only used if !perfect; NULL if unused */ // 关键字的掩码 u16 mask; /* AND key with mask */ // 偏移数 int shift; /* shift ANDed key to the right */ // 哈希表数量 int hash; /* hash table size; 0 if undefined */ int alloc_hash; /* allocated size */ int fall_through; /* 0: only classify if explicit match */ }; static struct tcf_ext_map tcindex_ext_map = { .police = TCA_TCINDEX_POLICE, .action = TCA_TCINDEX_ACT }; // 操作结构 static struct tcf_proto_ops cls_tcindex_ops = { .next = NULL, .kind = "tcindex", .classify = tcindex_classify, .init = tcindex_init, .destroy = tcindex_destroy, .get = tcindex_get, .put = tcindex_put, .change = tcindex_change, .delete = tcindex_delete, .walk = tcindex_walk, .dump = tcindex_dump, .owner = THIS_MODULE, }; 7.11.2 初始化 static int tcindex_init(struct tcf_proto *tp) { struct tcindex_data *p; DPRINTK("tcindex_init(tp %p)\n",tp); // 分配tcindex数据结构空间 p = kzalloc(sizeof(struct tcindex_data),GFP_KERNEL); if (!p) return -ENOMEM; // 设置基本参数 p->mask = 0xffff; p->hash = DEFAULT_HASH_SIZE; // 64 p->fall_through = 1; // 将其作为TCF_PROTO的规则根节点 tp->root = p; return 0; } 7.11.3 分类 #define PRIV(tp) ((struct tcindex_data *) (tp)->root) static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res) { // TCF_PROTO结构过滤规则根节点即tcindex数据结构 struct tcindex_data *p = PRIV(tp); struct tcindex_filter_result *f; // 根据数据包的tcindex参数计算key: 先掩码掩, 再右移几位 int key = (skb->tc_index & p->mask) >> p->shift; D2PRINTK("tcindex_classify(skb %p,tp %p,res %p),p %p\n",skb,tp,res,p); // 根据key查找过滤结果 f = tcindex_lookup(p, key); if (!f) { if (!p->fall_through) return -1; res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle), key); res->class = 0; D2PRINTK("alg 0x%x\n",res->classid); return 0; } // 找到过滤结果, 赋值给分类结果 *res = f->res; D2PRINTK("map 0x%x\n",res->classid); // 执行TCF配置扩展 return tcf_exts_exec(skb, &f->exts, res); } // 根据key查找过滤结果 static struct tcindex_filter_result * tcindex_lookup(struct tcindex_data *p, u16 key) { struct tcindex_filter *f; if (p->perfect) // 查找perfect数组的第key项 return tcindex_filter_is_set(p->perfect + key) ? p->perfect + key : NULL; else if (p->h) { // 查找非perfect链表 for (f = p->h[key % p->hash]; f; f = f->next) if (f->key == key) return &f->result; } return NULL; } 7.11.4 释放 static void tcindex_destroy(struct tcf_proto *tp) { // TCF_PROTO结构过滤规则根节点即tcindex数据结构 struct tcindex_data *p = PRIV(tp); struct tcf_walker walker; DPRINTK("tcindex_destroy(tp %p),p %p\n",tp,p); // 初始化遍历结构 walker.count = 0; walker.skip = 0; // 释放一个元素 walker.fn = &tcindex_destroy_element; // tcindex遍历删除每个元素 tcindex_walk(tp,&walker); // 释放perfect数组 kfree(p->perfect); // 释放非perfect节点 kfree(p->h); // 释放tcindex数据结构 kfree(p); tp->root = NULL; } static int tcindex_destroy_element(struct tcf_proto *tp, unsigned long arg, struct tcf_walker *walker) { // 释放tcindex过滤结果节点, 操作不加锁 return __tcindex_delete(tp, arg, 0); } static int __tcindex_delete(struct tcf_proto *tp, unsigned long arg, int lock) { // TCF_PROTO结构过滤规则根节点即tcindex数据结构 struct tcindex_data *p = PRIV(tp