X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fsched%2Fsch_sfq.c;h=e057768f68b4806a1155e367fbf77ba5e00d2fc4;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=acf2666ad7486f3c9f39acdf9315828d8446d6dd;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index acf2666ad..e057768f6 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -144,6 +144,8 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) && (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP || + iph->protocol == IPPROTO_SCTP || + iph->protocol == IPPROTO_DCCP || iph->protocol == IPPROTO_ESP)) h2 ^= *(((u32*)iph) + iph->ihl); break; @@ -155,6 +157,8 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) h2 = iph->saddr.s6_addr32[3]^iph->nexthdr; if (iph->nexthdr == IPPROTO_TCP || iph->nexthdr == IPPROTO_UDP || + iph->nexthdr == IPPROTO_SCTP || + iph->nexthdr == IPPROTO_DCCP || iph->nexthdr == IPPROTO_ESP) h2 ^= *(u32*)&iph[1]; break; @@ -211,7 +215,7 @@ static inline void sfq_inc(struct sfq_sched_data *q, sfq_index x) static unsigned int sfq_drop(struct Qdisc *sch) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); sfq_index d = q->max_depth; struct sk_buff *skb; unsigned int len; @@ -227,7 +231,8 @@ static unsigned int sfq_drop(struct Qdisc *sch) kfree_skb(skb); sfq_dec(q, x); sch->q.qlen--; - sch->stats.drops++; + sch->qstats.drops++; + sch->qstats.backlog -= len; return len; } @@ -243,7 +248,8 @@ static unsigned int sfq_drop(struct Qdisc *sch) sfq_dec(q, d); sch->q.qlen--; q->ht[q->hash[d]] = SFQ_DEPTH; - sch->stats.drops++; + sch->qstats.drops++; + sch->qstats.backlog -= len; return len; } @@ -253,7 +259,7 @@ static unsigned int sfq_drop(struct Qdisc *sch) static int sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); unsigned hash = sfq_hash(q, skb); sfq_index x; @@ -262,6 +268,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) q->ht[hash] = x = q->dep[SFQ_DEPTH].next; q->hash[x] = hash; } + sch->qstats.backlog += skb->len; __skb_queue_tail(&q->qs[x], skb); sfq_inc(q, x); if (q->qs[x].qlen == 1) { /* The flow is new */ @@ -276,8 +283,8 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) } } if (++sch->q.qlen < q->limit-1) { - sch->stats.bytes += skb->len; - sch->stats.packets++; + sch->bstats.bytes += skb->len; + sch->bstats.packets++; return 0; } @@ -288,7 +295,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) static int sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); unsigned hash = sfq_hash(q, skb); sfq_index x; @@ -297,6 +304,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) q->ht[hash] = x = q->dep[SFQ_DEPTH].next; q->hash[x] = hash; } + sch->qstats.backlog += skb->len; __skb_queue_head(&q->qs[x], skb); sfq_inc(q, x); if (q->qs[x].qlen == 1) { /* The flow is new */ @@ -310,10 +318,12 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) q->tail = x; } } - if (++sch->q.qlen < q->limit - 1) + if (++sch->q.qlen < q->limit - 1) { + sch->qstats.requeues++; return 0; + } - sch->stats.drops++; + sch->qstats.drops++; sfq_drop(sch); return NET_XMIT_CN; } @@ -324,7 +334,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) static struct sk_buff * sfq_dequeue(struct Qdisc* sch) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); struct sk_buff *skb; sfq_index a, old_a; @@ -338,6 +348,7 @@ sfq_dequeue(struct Qdisc* sch) skb = __skb_dequeue(&q->qs[a]); sfq_dec(q, a); sch->q.qlen--; + sch->qstats.backlog -= skb->len; /* Is the slot empty? */ if (q->qs[a].qlen == 0) { @@ -369,10 +380,9 @@ sfq_reset(struct Qdisc* sch) static void sfq_perturbation(unsigned long arg) { struct Qdisc *sch = (struct Qdisc*)arg; - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); q->perturbation = net_random()&0x1F; - q->perturb_timer.expires = jiffies + q->perturb_period; if (q->perturb_period) { q->perturb_timer.expires = jiffies + q->perturb_period; @@ -382,7 +392,7 @@ static void sfq_perturbation(unsigned long arg) static int sfq_change(struct Qdisc *sch, struct rtattr *opt) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); struct tc_sfq_qopt *ctl = RTA_DATA(opt); if (opt->rta_len < RTA_LENGTH(sizeof(*ctl))) @@ -408,7 +418,7 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt) static int sfq_init(struct Qdisc *sch, struct rtattr *opt) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); int i; init_timer(&q->perturb_timer); @@ -440,13 +450,13 @@ static int sfq_init(struct Qdisc *sch, struct rtattr *opt) static void sfq_destroy(struct Qdisc *sch) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); del_timer(&q->perturb_timer); } static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; + struct sfq_sched_data *q = qdisc_priv(sch); unsigned char *b = skb->tail; struct tc_sfq_qopt opt;