📄 200-sched_esfq.patch
字号:
+ n = q->dep[x].next;+ p = q->dep[x].prev;+ q->dep[p].next = n;+ q->dep[n].prev = p;+ d = q->qs[x].qlen;+ if (q->max_depth < d)+ q->max_depth = d;++ esfq_link(q, x);+}++static unsigned int esfq_drop(struct Qdisc *sch)+{+ struct esfq_sched_data *q = qdisc_priv(sch);+ esfq_index d = q->max_depth;+ struct sk_buff *skb;+ unsigned int len;++ /* Queue is full! Find the longest slot and+ drop a packet from it */++ if (d > 1) {+ esfq_index x = q->dep[d+q->depth].next;+ skb = q->qs[x].prev;+ len = skb->len;+ __skb_unlink(skb, &q->qs[x]);+ kfree_skb(skb);+ esfq_dec(q, x);+ sch->q.qlen--;+ sch->qstats.drops++;+ sch->qstats.backlog -= len;+ return len;+ }++ if (d == 1) {+ /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */+ d = q->next[q->tail];+ q->next[q->tail] = q->next[d];+ q->allot[q->next[d]] += q->quantum;+ skb = q->qs[d].prev;+ len = skb->len;+ __skb_unlink(skb, &q->qs[d]);+ kfree_skb(skb);+ esfq_dec(q, d);+ sch->q.qlen--;+ q->ht[q->hash[d]] = q->depth;+ sch->qstats.drops++;+ sch->qstats.backlog -= len;+ return len;+ }++ return 0;+}++static int+esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)+{+ struct esfq_sched_data *q = qdisc_priv(sch);+ unsigned hash = esfq_hash(q, skb);+ unsigned depth = q->depth;+ esfq_index x;++ x = q->ht[hash];+ if (x == depth) {+ q->ht[hash] = x = q->dep[depth].next;+ q->hash[x] = hash;+ }+ sch->qstats.backlog += skb->len;+ __skb_queue_tail(&q->qs[x], skb);+ esfq_inc(q, x);+ if (q->qs[x].qlen == 1) { /* The flow is new */+ if (q->tail == depth) { /* It is the first flow */+ q->tail = x;+ q->next[x] = x;+ q->allot[x] = q->quantum;+ } else {+ q->next[x] = q->next[q->tail];+ q->next[q->tail] = x;+ q->tail = x;+ }+ }+ if (++sch->q.qlen < q->limit-1) {+ sch->bstats.bytes += skb->len;+ sch->bstats.packets++;+ return 0;+ }++ esfq_drop(sch);+ return NET_XMIT_CN;+}++static int+esfq_requeue(struct sk_buff *skb, struct Qdisc* sch)+{+ struct esfq_sched_data *q = qdisc_priv(sch);+ unsigned hash = esfq_hash(q, skb);+ unsigned depth = q->depth;+ esfq_index x;++ x = q->ht[hash];+ if (x == depth) {+ q->ht[hash] = x = q->dep[depth].next;+ q->hash[x] = hash;+ }+ sch->qstats.backlog += skb->len;+ __skb_queue_head(&q->qs[x], skb);+ esfq_inc(q, x);+ if (q->qs[x].qlen == 1) { /* The flow is new */+ if (q->tail == depth) { /* It is the first flow */+ q->tail = x;+ q->next[x] = x;+ q->allot[x] = q->quantum;+ } else {+ q->next[x] = q->next[q->tail];+ q->next[q->tail] = x;+ q->tail = x;+ }+ }+ if (++sch->q.qlen < q->limit - 1) {+ sch->qstats.requeues++;+ return 0;+ }++ sch->qstats.drops++;+ esfq_drop(sch);+ return NET_XMIT_CN;+}+++++static struct sk_buff *+esfq_dequeue(struct Qdisc* sch)+{+ struct esfq_sched_data *q = qdisc_priv(sch);+ struct sk_buff *skb;+ unsigned depth = q->depth;+ esfq_index a, old_a;++ /* No active slots */+ if (q->tail == depth)+ return NULL;+ + a = old_a = q->next[q->tail];+ + /* Grab packet */+ skb = __skb_dequeue(&q->qs[a]);+ esfq_dec(q, a);+ sch->q.qlen--;+ sch->qstats.backlog -= skb->len;+ + /* Is the slot empty? */+ if (q->qs[a].qlen == 0) {+ q->ht[q->hash[a]] = depth;+ a = q->next[a];+ if (a == old_a) {+ q->tail = depth;+ return skb;+ }+ q->next[q->tail] = a;+ q->allot[a] += q->quantum;+ } else if ((q->allot[a] -= skb->len) <= 0) {+ q->tail = a;+ a = q->next[a];+ q->allot[a] += q->quantum;+ }+ + return skb;+}++static void+esfq_reset(struct Qdisc* sch)+{+ struct sk_buff *skb;++ while ((skb = esfq_dequeue(sch)) != NULL)+ kfree_skb(skb);+}++static void esfq_perturbation(unsigned long arg)+{+ struct Qdisc *sch = (struct Qdisc*)arg;+ struct esfq_sched_data *q = qdisc_priv(sch);++ q->perturbation = net_random()&0x1F;++ if (q->perturb_period) {+ q->perturb_timer.expires = jiffies + q->perturb_period;+ add_timer(&q->perturb_timer);+ }+}++static int esfq_change(struct Qdisc *sch, struct rtattr *opt)+{+ struct esfq_sched_data *q = qdisc_priv(sch);+ struct tc_esfq_qopt *ctl = RTA_DATA(opt);+ int old_perturb = q->perturb_period;+ + if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))+ return -EINVAL;+ + sch_tree_lock(sch);+ q->quantum = ctl->quantum ? : psched_mtu(sch->dev);+ q->perturb_period = ctl->perturb_period*HZ;+// q->hash_divisor = ctl->divisor;+// q->tail = q->limit = q->depth = ctl->flows;+ + if (ctl->limit)+ q->limit = min_t(u32, ctl->limit, q->depth);+ + if (ctl->hash_kind) {+ q->hash_kind = ctl->hash_kind;+ if (q->hash_kind != TCA_SFQ_HASH_CLASSIC)+ q->perturb_period = 0;+ }+ + // is sch_tree_lock enough to do this ?+ while (sch->q.qlen >= q->limit-1)+ esfq_drop(sch);+ + if (old_perturb)+ del_timer(&q->perturb_timer);+ if (q->perturb_period) {+ q->perturb_timer.expires = jiffies + q->perturb_period;+ add_timer(&q->perturb_timer);+ } else {+ q->perturbation = 0;+ }+ sch_tree_unlock(sch);+ return 0;+}++static int esfq_init(struct Qdisc *sch, struct rtattr *opt)+{+ struct esfq_sched_data *q = qdisc_priv(sch);+ struct tc_esfq_qopt *ctl;+ esfq_index p = ~0U/2;+ int i;+ + if (opt && opt->rta_len < RTA_LENGTH(sizeof(*ctl)))+ return -EINVAL;++ init_timer(&q->perturb_timer);+ q->perturb_timer.data = (unsigned long)sch;+ q->perturb_timer.function = esfq_perturbation;+ q->perturbation = 0;+ q->hash_kind = TCA_SFQ_HASH_CLASSIC;+ q->max_depth = 0;+ q->dyn_min = ~0U; /* maximum value for this type */+ q->dyn_max = 0; /* dyn_min/dyn_max will be set properly upon first packet */+ if (opt == NULL) {+ q->quantum = psched_mtu(sch->dev);+ q->perturb_period = 0;+ q->hash_divisor = 1024;+ q->tail = q->limit = q->depth = 128;+ + } else {+ ctl = RTA_DATA(opt);+ q->quantum = ctl->quantum ? : psched_mtu(sch->dev);+ q->perturb_period = ctl->perturb_period*HZ;+ q->hash_divisor = ctl->divisor ? : 1024;+ q->tail = q->limit = q->depth = ctl->flows ? : 128;+ + if ( q->depth > p - 1 )+ return -EINVAL;+ + if (ctl->limit)+ q->limit = min_t(u32, ctl->limit, q->depth);+ + if (ctl->hash_kind) {+ q->hash_kind = ctl->hash_kind;+ }+ + if (q->perturb_period) {+ q->perturb_timer.expires = jiffies + q->perturb_period;+ add_timer(&q->perturb_timer);+ }+ }+ + q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);+ if (!q->ht)+ goto err_case;+ + q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);+ if (!q->dep)+ goto err_case;+ q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);+ if (!q->next)+ goto err_case;+ + q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);+ if (!q->allot)+ goto err_case;+ q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);+ if (!q->hash)+ goto err_case;+ q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);+ if (!q->qs)+ goto err_case;+ + for (i=0; i< q->hash_divisor; i++)+ q->ht[i] = q->depth;+ for (i=0; i<q->depth; i++) {+ skb_queue_head_init(&q->qs[i]);+ q->dep[i+q->depth].next = i+q->depth;+ q->dep[i+q->depth].prev = i+q->depth;+ }+ + for (i=0; i<q->depth; i++)+ esfq_link(q, i);+ return 0;+err_case:+ del_timer(&q->perturb_timer);+ if (q->ht)+ kfree(q->ht);+ if (q->dep)+ kfree(q->dep);+ if (q->next)+ kfree(q->next);+ if (q->allot)+ kfree(q->allot);+ if (q->hash)+ kfree(q->hash);+ if (q->qs)+ kfree(q->qs);+ return -ENOBUFS;+}++static void esfq_destroy(struct Qdisc *sch)+{+ struct esfq_sched_data *q = qdisc_priv(sch);+ del_timer(&q->perturb_timer);+ if(q->ht)+ kfree(q->ht);+ if(q->dep)+ kfree(q->dep);+ if(q->next)+ kfree(q->next);+ if(q->allot)+ kfree(q->allot);+ if(q->hash)+ kfree(q->hash);+ if(q->qs)+ kfree(q->qs);+}++static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)+{+ struct esfq_sched_data *q = qdisc_priv(sch);+ unsigned char *b = skb->tail;+ struct tc_esfq_qopt opt;++ opt.quantum = q->quantum;+ opt.perturb_period = q->perturb_period/HZ;++ opt.limit = q->limit;+ opt.divisor = q->hash_divisor;+ opt.flows = q->depth;+ opt.hash_kind = q->hash_kind;++ RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);++ return skb->len;++rtattr_failure:+ skb_trim(skb, b - skb->data);+ return -1;+}++static struct Qdisc_ops esfq_qdisc_ops =+{+ .next = NULL,+ .cl_ops = NULL,+ .id = "esfq",+ .priv_size = sizeof(struct esfq_sched_data),+ .enqueue = esfq_enqueue,+ .dequeue = esfq_dequeue,+ .requeue = esfq_requeue,+ .drop = esfq_drop,+ .init = esfq_init,+ .reset = esfq_reset,+ .destroy = esfq_destroy,+ .change = NULL, /* esfq_change - needs more work */+ .dump = esfq_dump,+ .owner = THIS_MODULE,+};++static int __init esfq_module_init(void)+{+ return register_qdisc(&esfq_qdisc_ops);+}+static void __exit esfq_module_exit(void) +{+ unregister_qdisc(&esfq_qdisc_ops);+}+module_init(esfq_module_init)+module_exit(esfq_module_exit)+MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -