日期:2014-05-16 浏览次数:20756 次
5.14 CBQ(Class Based Queueing, 基于类别的排队) CBQ(Class-Based Queueing discipline)是个经典的基于分类的流控算法,比较复杂, 具体算法基础也是TBF, 也是根据令牌情况决定是否发送数据包。CBQ在HTB出现后一般用得就少了, 其实对于分类的类别操作和HTB也差不多, 所以只简要介绍一下入队和出队操作过程, 其他处理过程不再详细分析了。 5.14.1 CBQ相关结构定义 // CBQ流控结构 static struct Qdisc_ops cbq_qdisc_ops = { .next = NULL, .cl_ops = &cbq_class_ops, .id = "cbq", // 私有数据是一个用于CBQ调度的数据结构struct cbq_sched_data .priv_size = sizeof(struct cbq_sched_data), .enqueue = cbq_enqueue, .dequeue = cbq_dequeue, .requeue = cbq_requeue, .drop = cbq_drop, .init = cbq_init, .reset = cbq_reset, .destroy = cbq_destroy, .change = NULL, .dump = cbq_dump, .dump_stats = cbq_dump_stats, .owner = THIS_MODULE, }; // CBQ类别操作结构 static struct Qdisc_class_ops cbq_class_ops = { .graft = cbq_graft, .leaf = cbq_leaf, .get = cbq_get, .put = cbq_put, .change = cbq_change_class, .delete = cbq_delete, .walk = cbq_walk, .tcf_chain = cbq_find_tcf, .bind_tcf = cbq_bind_filter, .unbind_tcf = cbq_unbind_filter, .dump = cbq_dump_class, .dump_stats = cbq_dump_class_stats, }; // CBQ调度数据, 是作为CBQ调度算法的Qdisc的私有数据 struct cbq_sched_data { // 类别HASH表, 16个链表 struct cbq_class *classes[16]; /* Hash table of all classes */ int nclasses[TC_CBQ_MAXPRIO+1]; unsigned quanta[TC_CBQ_MAXPRIO+1]; struct cbq_class link; unsigned activemask; // 活动的CBQ类别链表, 最多8+1个, 按类别优先权区分 struct cbq_class *active[TC_CBQ_MAXPRIO+1]; /* List of all classes with backlog */ #ifdef CONFIG_NET_CLS_POLICE // 接收用的CBQ类别结构 struct cbq_class *rx_class; #endif // 发送用的CBQ类别结构 struct cbq_class *tx_class; // 借带宽时的CBQ类别结构 struct cbq_class *tx_borrowed; int tx_len; psched_time_t now; /* Cached timestamp */ psched_time_t now_rt; /* Cached real time */ unsigned pmask; struct timer_list delay_timer; struct timer_list wd_timer; /* Watchdog timer, started when CBQ has backlog, but cannot transmit just now */ long wd_expires; int toplevel; u32 hgenerator; }; // CBQ类别结构 struct cbq_class { // 链表下一项 struct cbq_class *next; /* hash table link */ // backlog中的下一个活动的类别结构 struct cbq_class *next_alive; /* next class with backlog in this priority band */ /* Parameters */ // 类型ID值 u32 classid; // 正常情况下的优先权值 unsigned char priority; /* class priority */ // 流量超过限制值后使用的优先权值 unsigned char priority2; /* priority to be used after overlimit */ // unsigned char ewma_log; /* time constant for idle time calculation */ // ovl策略 unsigned char ovl_strategy; #ifdef CONFIG_NET_CLS_POLICE unsigned char police; #endif // 缺省 u32 defmap; /* Link-sharing scheduler parameters */ long maxidle; /* Class parameters: see below. */ long offtime; long minidle; u32 avpkt; // 流量表指针 struct qdisc_rate_table *R_tab; /* Overlimit strategy parameters */ // 超过限制时的处理函数 void (*overlimit)(struct cbq_class *cl); long penalty; /* General scheduler (WRR) parameters */ long allot; long quantum; /* Allotment per WRR round */ long weight; /* Relative allotment: see below */ // 指向当前Qdisc结构 struct Qdisc *qdisc; /* Ptr to CBQ discipline */ struct cbq_class *split; /* Ptr to split node */ struct cbq_class *share; /* Ptr to LS parent in the class tree */ struct cbq_class *tparent; /* Ptr to tree parent in the class tree */ struct cbq_class *borrow; /* NULL if class is bandwidth limited; parent otherwise */ struct cbq_class *sibling; /* Sibling chain */ struct cbq_class *children; /* Pointer to children chain */ // 内部流控节点, 实际通过该Qdisc完成流控操作 struct Qdisc *q; /* Elementary queueing discipline */ /* Variables */ unsigned char cpriority; /* Effective priority */ unsigned char delayed; unsigned char level; /* level of the class in hierarchy: 0 for leaf classes, and maximal level of children + 1 for nodes. */ psched_time_