Linux内核中游量控制(21)

Linux内核中游量控制(21)

Linux内核中流量控制(21)

本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn: yfydz_no1@hotmail.com
来源:http://yfydz.cublog.cn

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

Linux内核中游量控制(21)

相关文章:

你感兴趣的文章:

标签云: