diff options
author | Jarek Poplawski <jarkao2@gmail.com> | 2008-10-31 03:47:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-10-31 03:47:01 -0400 |
commit | 77be155cba4e163e8bba9fd27222a8b6189ec4f7 (patch) | |
tree | 0819d4c0bb760080aaba8a00060a774205914034 | |
parent | 03c05f0d4bb0c267edf12d614025a40e33c5a6f9 (diff) |
pkt_sched: Add peek emulation for non-work-conserving qdiscs.
This patch adds qdisc_peek_dequeued() wrapper to emulate peek method
with qdisc->dequeue() and storing "peeked" skb in qdisc->gso_skb until
dequeuing. This is mainly for compatibility reasons not to break some
strange configs because peeking is expected for non-work-conserving
parent qdiscs to query work-conserving child qdiscs.
This implementation requires using qdisc_dequeue_peeked() wrapper
instead of directly calling qdisc->dequeue() for all qdiscs ever
querried with qdisc->ops->peek() or qdisc_peek_dequeued().
Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/sch_generic.h | 23 | ||||
-rw-r--r-- | net/sched/sch_atm.c | 4 | ||||
-rw-r--r-- | net/sched/sch_cbq.c | 1 | ||||
-rw-r--r-- | net/sched/sch_hfsc.c | 3 | ||||
-rw-r--r-- | net/sched/sch_htb.c | 1 | ||||
-rw-r--r-- | net/sched/sch_netem.c | 5 | ||||
-rw-r--r-- | net/sched/sch_tbf.c | 3 |
7 files changed, 34 insertions, 6 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index da6839a7ff50..9dcb5bfe094a 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h | |||
@@ -438,6 +438,29 @@ static inline struct sk_buff *qdisc_peek_head(struct Qdisc *sch) | |||
438 | return skb_peek(&sch->q); | 438 | return skb_peek(&sch->q); |
439 | } | 439 | } |
440 | 440 | ||
441 | /* generic pseudo peek method for non-work-conserving qdisc */ | ||
442 | static inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch) | ||
443 | { | ||
444 | /* we can reuse ->gso_skb because peek isn't called for root qdiscs */ | ||
445 | if (!sch->gso_skb) | ||
446 | sch->gso_skb = sch->dequeue(sch); | ||
447 | |||
448 | return sch->gso_skb; | ||
449 | } | ||
450 | |||
451 | /* use instead of qdisc->dequeue() for all qdiscs queried with ->peek() */ | ||
452 | static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch) | ||
453 | { | ||
454 | struct sk_buff *skb = sch->gso_skb; | ||
455 | |||
456 | if (skb) | ||
457 | sch->gso_skb = NULL; | ||
458 | else | ||
459 | skb = sch->dequeue(sch); | ||
460 | |||
461 | return skb; | ||
462 | } | ||
463 | |||
441 | static inline int __qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch, | 464 | static inline int __qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch, |
442 | struct sk_buff_head *list) | 465 | struct sk_buff_head *list) |
443 | { | 466 | { |
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 2ee0c1a8efa9..6eb9a650b63d 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c | |||
@@ -484,7 +484,7 @@ static void sch_atm_dequeue(unsigned long data) | |||
484 | if (!atm_may_send(flow->vcc, skb->truesize)) | 484 | if (!atm_may_send(flow->vcc, skb->truesize)) |
485 | break; | 485 | break; |
486 | 486 | ||
487 | skb = flow->q->dequeue(flow->q); | 487 | skb = qdisc_dequeue_peeked(flow->q); |
488 | if (unlikely(!skb)) | 488 | if (unlikely(!skb)) |
489 | break; | 489 | break; |
490 | 490 | ||
@@ -519,7 +519,7 @@ static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) | |||
519 | 519 | ||
520 | pr_debug("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p); | 520 | pr_debug("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p); |
521 | tasklet_schedule(&p->task); | 521 | tasklet_schedule(&p->task); |
522 | skb = p->link.q->dequeue(p->link.q); | 522 | skb = qdisc_dequeue_peeked(p->link.q); |
523 | if (skb) | 523 | if (skb) |
524 | sch->q.qlen--; | 524 | sch->q.qlen--; |
525 | return skb; | 525 | return skb; |
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 03e389e8d945..63efa70abbea 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -2066,6 +2066,7 @@ static struct Qdisc_ops cbq_qdisc_ops __read_mostly = { | |||
2066 | .priv_size = sizeof(struct cbq_sched_data), | 2066 | .priv_size = sizeof(struct cbq_sched_data), |
2067 | .enqueue = cbq_enqueue, | 2067 | .enqueue = cbq_enqueue, |
2068 | .dequeue = cbq_dequeue, | 2068 | .dequeue = cbq_dequeue, |
2069 | .peek = qdisc_peek_dequeued, | ||
2069 | .requeue = cbq_requeue, | 2070 | .requeue = cbq_requeue, |
2070 | .drop = cbq_drop, | 2071 | .drop = cbq_drop, |
2071 | .init = cbq_init, | 2072 | .init = cbq_init, |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index ddfc40887848..d90b1652f2af 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -1634,7 +1634,7 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1634 | } | 1634 | } |
1635 | } | 1635 | } |
1636 | 1636 | ||
1637 | skb = cl->qdisc->dequeue(cl->qdisc); | 1637 | skb = qdisc_dequeue_peeked(cl->qdisc); |
1638 | if (skb == NULL) { | 1638 | if (skb == NULL) { |
1639 | if (net_ratelimit()) | 1639 | if (net_ratelimit()) |
1640 | printk("HFSC: Non-work-conserving qdisc ?\n"); | 1640 | printk("HFSC: Non-work-conserving qdisc ?\n"); |
@@ -1727,6 +1727,7 @@ static struct Qdisc_ops hfsc_qdisc_ops __read_mostly = { | |||
1727 | .dump = hfsc_dump_qdisc, | 1727 | .dump = hfsc_dump_qdisc, |
1728 | .enqueue = hfsc_enqueue, | 1728 | .enqueue = hfsc_enqueue, |
1729 | .dequeue = hfsc_dequeue, | 1729 | .dequeue = hfsc_dequeue, |
1730 | .peek = qdisc_peek_dequeued, | ||
1730 | .requeue = hfsc_requeue, | 1731 | .requeue = hfsc_requeue, |
1731 | .drop = hfsc_drop, | 1732 | .drop = hfsc_drop, |
1732 | .cl_ops = &hfsc_class_ops, | 1733 | .cl_ops = &hfsc_class_ops, |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index d14f02056ae6..3fda8199713d 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -1565,6 +1565,7 @@ static struct Qdisc_ops htb_qdisc_ops __read_mostly = { | |||
1565 | .priv_size = sizeof(struct htb_sched), | 1565 | .priv_size = sizeof(struct htb_sched), |
1566 | .enqueue = htb_enqueue, | 1566 | .enqueue = htb_enqueue, |
1567 | .dequeue = htb_dequeue, | 1567 | .dequeue = htb_dequeue, |
1568 | .peek = qdisc_peek_dequeued, | ||
1568 | .requeue = htb_requeue, | 1569 | .requeue = htb_requeue, |
1569 | .drop = htb_drop, | 1570 | .drop = htb_drop, |
1570 | .init = htb_init, | 1571 | .init = htb_init, |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 74fbdb52baed..3080bd6ee332 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -290,8 +290,8 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) | |||
290 | 290 | ||
291 | /* if more time remaining? */ | 291 | /* if more time remaining? */ |
292 | if (cb->time_to_send <= now) { | 292 | if (cb->time_to_send <= now) { |
293 | skb = q->qdisc->dequeue(q->qdisc); | 293 | skb = qdisc_dequeue_peeked(q->qdisc); |
294 | if (!skb) | 294 | if (unlikely(!skb)) |
295 | return NULL; | 295 | return NULL; |
296 | 296 | ||
297 | pr_debug("netem_dequeue: return skb=%p\n", skb); | 297 | pr_debug("netem_dequeue: return skb=%p\n", skb); |
@@ -714,6 +714,7 @@ static struct Qdisc_ops netem_qdisc_ops __read_mostly = { | |||
714 | .priv_size = sizeof(struct netem_sched_data), | 714 | .priv_size = sizeof(struct netem_sched_data), |
715 | .enqueue = netem_enqueue, | 715 | .enqueue = netem_enqueue, |
716 | .dequeue = netem_dequeue, | 716 | .dequeue = netem_dequeue, |
717 | .peek = qdisc_peek_dequeued, | ||
717 | .requeue = netem_requeue, | 718 | .requeue = netem_requeue, |
718 | .drop = netem_drop, | 719 | .drop = netem_drop, |
719 | .init = netem_init, | 720 | .init = netem_init, |
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 61fdc77a48d2..435076cf620e 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -192,7 +192,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) | |||
192 | toks -= L2T(q, len); | 192 | toks -= L2T(q, len); |
193 | 193 | ||
194 | if ((toks|ptoks) >= 0) { | 194 | if ((toks|ptoks) >= 0) { |
195 | skb = q->qdisc->dequeue(q->qdisc); | 195 | skb = qdisc_dequeue_peeked(q->qdisc); |
196 | if (unlikely(!skb)) | 196 | if (unlikely(!skb)) |
197 | return NULL; | 197 | return NULL; |
198 | 198 | ||
@@ -467,6 +467,7 @@ static struct Qdisc_ops tbf_qdisc_ops __read_mostly = { | |||
467 | .priv_size = sizeof(struct tbf_sched_data), | 467 | .priv_size = sizeof(struct tbf_sched_data), |
468 | .enqueue = tbf_enqueue, | 468 | .enqueue = tbf_enqueue, |
469 | .dequeue = tbf_dequeue, | 469 | .dequeue = tbf_dequeue, |
470 | .peek = qdisc_peek_dequeued, | ||
470 | .requeue = tbf_requeue, | 471 | .requeue = tbf_requeue, |
471 | .drop = tbf_drop, | 472 | .drop = tbf_drop, |
472 | .init = tbf_init, | 473 | .init = tbf_init, |