⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 200-sched_esfq.patch

📁 Linux Home Server 是专门为家庭和SOHO/SMB 设计的高性价比的ISCSI 存储服务器, 具有如下的特色: 强大的iscsi 存储服务器软件; 混合iscsi 和NAS 服务;
💻 PATCH
📖 第 1 页 / 共 2 页
字号:
+	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 + -