[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20070511.010030.06784245.taka@valinux.co.jp>
Date: Fri, 11 May 2007 01:00:30 +0900 (JST)
From: Hirokazu Takahashi <taka@...inux.co.jp>
To: netdev@...r.kernel.org
Subject: [PATCH] tbf scheduler: TSO support
Hi,
TBF --- Simple Token Bucket Filter --- packet scheduler doesn't
work correctly with TSO on that it slows down to send out packets.
TSO packets will be discarded since the size can be larger than
the scheduler expects. But it won't cause serious problems
because the retransmitted packets can be passed.
So I made the scheduler allow to pass TSO packets:
- tbf_enqueue() accepts packets with any size if the netdevice
has TSO ability.
- tbf_dequeue() can handle the packets whose size is larger than
the bucket, which keeps tokens.
Any packet, which may be TSO packet, can be sent if the bucket is
full of tokens. this may lead that the number of tokens in
the bucket turns into negative value, which means kind of debt.
But we don't have to mind it because this will be filled up
with tokens in a short time and it will turns into positive value
again.
I'm not sure if this approach is the best. I appreciate any comments.
Thank you.
Signed-off-by: Hirokazu Takahashi <taka@...inux.co.jp>
--- linux-2.6.21/net/sched/sch_tbf.c.ORG 2007-05-08 20:59:28.000000000 +0900
+++ linux-2.6.21/net/sched/sch_tbf.c 2007-05-10 16:12:54.000000000 +0900
@@ -139,7 +139,7 @@ static int tbf_enqueue(struct sk_buff *s
struct tbf_sched_data *q = qdisc_priv(sch);
int ret;
- if (skb->len > q->max_size) {
+ if (skb->len > q->max_size && !(sch->dev->features & NETIF_F_GSO_MASK)) {
sch->qstats.drops++;
#ifdef CONFIG_NET_CLS_POLICE
if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
@@ -197,6 +197,7 @@ static struct sk_buff *tbf_dequeue(struc
{
struct tbf_sched_data *q = qdisc_priv(sch);
struct sk_buff *skb;
+ int full = 0;
skb = q->qdisc->dequeue(q->qdisc);
@@ -204,7 +205,8 @@ static struct sk_buff *tbf_dequeue(struc
psched_time_t now;
long toks, delay;
long ptoks = 0;
- unsigned int len = skb->len;
+ unsigned int len;
+ int n;
PSCHED_GET_TIME(now);
@@ -212,16 +214,26 @@ static struct sk_buff *tbf_dequeue(struc
if (q->P_tab) {
ptoks = toks + q->ptokens;
- if (ptoks > (long)q->mtu)
+ if (ptoks >= (long)q->mtu) {
ptoks = q->mtu;
- ptoks -= L2T_P(q, len);
+ full = 1;
+ }
+ for (len = skb->len; len > 0; len -= n) {
+ n = min(q->max_size, len);
+ ptoks -= L2T_P(q, n);
+ }
}
toks += q->tokens;
- if (toks > (long)q->buffer)
+ if (toks >= (long)q->buffer) {
toks = q->buffer;
- toks -= L2T(q, len);
+ full = 1;
+ }
+ for (len = skb->len; len > 0; len -= n) {
+ n = min(q->max_size, len);
+ toks -= L2T(q, n);
+ }
- if ((toks|ptoks) >= 0) {
+ if ((toks|ptoks) >= 0 || full) {
q->t_c = now;
q->tokens = toks;
q->ptokens = ptoks;
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists