日期:2014-05-16 浏览次数:20721 次
7.12 route route分类是根据数据包的路由信息进行分类的, 路由信息中会带tclassid参数用于分类, 代码在net/sched/cls_route.c中定义, 只支持IPV4。 7.12.1 数据结构和过滤器操作结构 // route 快速映射结构, 相当于分类结果的cache struct route4_fastmap { struct route4_filter *filter; u32 id; int iif; }; // route头结构 struct route4_head { // 16个快速映射结构 struct route4_fastmap fastmap[16]; // 257个bucket链表 struct route4_bucket *table[256+1]; }; struct route4_bucket { /* 16 FROM buckets + 16 IIF buckets + 1 wildcard bucket */ struct route4_filter *ht[16+16+1]; }; // route过滤器结构 struct route4_filter { // 链表中的下一项 struct route4_filter *next; // ID u32 id; // 网卡索引号 int iif; // 分类结构 struct tcf_result res; // TCF扩展 struct tcf_exts exts; // 句柄 u32 handle; // 所在的bucket struct route4_bucket *bkt; }; #define ROUTE4_FAILURE ((struct route4_filter*)(-1L)) static struct tcf_ext_map route_ext_map = { .police = TCA_ROUTE4_POLICE, .action = TCA_ROUTE4_ACT }; static struct tcf_ext_map tcindex_ext_map = { .police = TCA_TCINDEX_POLICE, .action = TCA_TCINDEX_ACT }; // 分类操作结构 static struct tcf_proto_ops cls_route4_ops = { .next = NULL, .kind = "route", .classify = route4_classify, .init = route4_init, .destroy = route4_destroy, .get = route4_get, .put = route4_put, .change = route4_change, .delete = route4_delete, .walk = route4_walk, .dump = route4_dump, .owner = THIS_MODULE, }; 7.12.2 一些哈希函数 // 快速映射表位置哈希 static __inline__ int route4_fastmap_hash(u32 id, int iif) { // 取ID的低4位, 结果在0~15之间 return id&0xF; } // 进入方向路由哈希 static __inline__ int route4_hash_to(u32 id) { // 取ID的低8位, 结果在0~255之间 return id&0xFF; } // 来源方向路由哈希 static __inline__ int route4_hash_from(u32 id) { // 取ID的16~19位, 结果在0~15之间 return (id>>16)&0xF; } // 网卡索引号哈希 static __inline__ int route4_hash_iif(int iif) { // 取网卡索引号的16~19位再加16, 结果在16~31之间 return 16 + ((iif>>16)&0xF); } // 外卡哈希, 返回外卡哈希表号:32 static __inline__ int route4_hash_wild(void) { return 32; } // 插入哈希, 从哈希表中删除时计算 static inline u32 to_hash(u32 id) { // 取低8位 u32 h = id&0xFF; // 第15位为1的话哈希值增加256 if (id&0x8000) h += 256; // 结果范围应该是0~511 return h; } // 来源哈希, 插入哈希表时计算 static inline u32 from_hash(u32 id) { // 高16位清零 id &= 0xFFFF; // 低16位全1的话返回32, 外卡值 if (id == 0xFFFF) return 32; // 如果第15位为0 if (!(id & 0x8000)) { // 超过255的话返回256 if (id > 255) return 256; // 否则返回低4位, 范围为0~15 return id&0xF; } // 第15位为1 // 返回低4位加16, 范围为16~31 return 16 + (id&0xF); } 7.12.3 初始化 // 空函数 static int route4_init(struct tcf_proto *tp) { return 0; } 7.12.4 分类 // 分类结果处理宏 #define ROUTE4_APPLY_RESULT() \ { \ // 要返回的分类结果 *res = f->res; \ if (tcf_exts_is_available(&f->exts)) { \ // 执行TCF扩展操作 int r = tcf_exts_exec(skb, &f->exts, res); \ if (r < 0) { \ // 操作失败, 不需要将结果进cache, 继续循环 dont_cache = 1; \ continue; \ } \ return r; \ } else if (!dont_cache) \ // 将结果进cache, route4_set_fastmap(head, id, iif, f); \ return 0; \ } static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res) { // route头节点 struct route4_head *head = (struct route4_head*)tp->root; struct dst_entry *dst; struct route4_bucket *b; struct route4_filter *f; u32 id, h; int iif, dont_cache = 0; // 如果数据包路由项为空, 分类失败 if ((dst = skb->dst) == NULL) goto failure; // 类别ID id = dst->tclassid; // 如果头节点空, 用老方法分类 if (head == NULL) goto old_method; // 网卡索引号 iif = ((struct rtable*)dst)->fl.iif; // 根据ID和网卡索引号计算快速映射哈希值 h = route4_fastmap_hash(id, iif); // 如果快速映射表中元素和此ID和网卡匹配, 而且过滤结构有效 if (id == head->fastmap[h].id && iif == head->fastmap[h].iif && (f = head->fastmap[h].filter) != NULL) { // 如果是错误分类, 返回失败 if (f == ROUTE4_FAILURE) goto failure; // 否则返回分类结构, 分类成功 *res = f->res; r