aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarek Poplawski <jarkao2@gmail.com>2008-10-31 03:47:01 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-31 03:47:01 -0400
commit77be155cba4e163e8bba9fd27222a8b6189ec4f7 (patch)
tree0819d4c0bb760080aaba8a00060a774205914034
parent03c05f0d4bb0c267edf12d614025a40e33c5a6f9 (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.h23
-rw-r--r--net/sched/sch_atm.c4
-rw-r--r--net/sched/sch_cbq.c1
-rw-r--r--net/sched/sch_hfsc.c3
-rw-r--r--net/sched/sch_htb.c1
-rw-r--r--net/sched/sch_netem.c5
-rw-r--r--net/sched/sch_tbf.c3
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 */
442static 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() */
452static 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
441static inline int __qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch, 464static 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,