diff options
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/sch_netem.c | 87 |
1 files changed, 79 insertions, 8 deletions
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 289febd3ccac..f176890eeef0 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -238,14 +238,15 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
238 | ret = NET_XMIT_SUCCESS; | 238 | ret = NET_XMIT_SUCCESS; |
239 | } | 239 | } |
240 | 240 | ||
241 | if (likely(ret == NET_XMIT_SUCCESS)) { | 241 | if (ret != NET_XMIT_SUCCESS) { |
242 | sch->q.qlen++; | 242 | if (net_xmit_drop_count(ret)) { |
243 | } else if (net_xmit_drop_count(ret)) { | 243 | sch->qstats.drops++; |
244 | sch->qstats.drops++; | 244 | return ret; |
245 | } | ||
245 | } | 246 | } |
246 | 247 | ||
247 | pr_debug("netem: enqueue ret %d\n", ret); | 248 | sch->q.qlen++; |
248 | return ret; | 249 | return NET_XMIT_SUCCESS; |
249 | } | 250 | } |
250 | 251 | ||
251 | static unsigned int netem_drop(struct Qdisc *sch) | 252 | static unsigned int netem_drop(struct Qdisc *sch) |
@@ -287,9 +288,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch) | |||
287 | if (G_TC_FROM(skb->tc_verd) & AT_INGRESS) | 288 | if (G_TC_FROM(skb->tc_verd) & AT_INGRESS) |
288 | skb->tstamp.tv64 = 0; | 289 | skb->tstamp.tv64 = 0; |
289 | #endif | 290 | #endif |
290 | pr_debug("netem_dequeue: return skb=%p\n", skb); | 291 | |
291 | qdisc_bstats_update(sch, skb); | ||
292 | sch->q.qlen--; | 292 | sch->q.qlen--; |
293 | qdisc_unthrottled(sch); | ||
294 | qdisc_bstats_update(sch, skb); | ||
293 | return skb; | 295 | return skb; |
294 | } | 296 | } |
295 | 297 | ||
@@ -610,8 +612,77 @@ nla_put_failure: | |||
610 | return -1; | 612 | return -1; |
611 | } | 613 | } |
612 | 614 | ||
615 | static int netem_dump_class(struct Qdisc *sch, unsigned long cl, | ||
616 | struct sk_buff *skb, struct tcmsg *tcm) | ||
617 | { | ||
618 | struct netem_sched_data *q = qdisc_priv(sch); | ||
619 | |||
620 | if (cl != 1) /* only one class */ | ||
621 | return -ENOENT; | ||
622 | |||
623 | tcm->tcm_handle |= TC_H_MIN(1); | ||
624 | tcm->tcm_info = q->qdisc->handle; | ||
625 | |||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | ||
630 | struct Qdisc **old) | ||
631 | { | ||
632 | struct netem_sched_data *q = qdisc_priv(sch); | ||
633 | |||
634 | if (new == NULL) | ||
635 | new = &noop_qdisc; | ||
636 | |||
637 | sch_tree_lock(sch); | ||
638 | *old = q->qdisc; | ||
639 | q->qdisc = new; | ||
640 | qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); | ||
641 | qdisc_reset(*old); | ||
642 | sch_tree_unlock(sch); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg) | ||
648 | { | ||
649 | struct netem_sched_data *q = qdisc_priv(sch); | ||
650 | return q->qdisc; | ||
651 | } | ||
652 | |||
653 | static unsigned long netem_get(struct Qdisc *sch, u32 classid) | ||
654 | { | ||
655 | return 1; | ||
656 | } | ||
657 | |||
658 | static void netem_put(struct Qdisc *sch, unsigned long arg) | ||
659 | { | ||
660 | } | ||
661 | |||
662 | static void netem_walk(struct Qdisc *sch, struct qdisc_walker *walker) | ||
663 | { | ||
664 | if (!walker->stop) { | ||
665 | if (walker->count >= walker->skip) | ||
666 | if (walker->fn(sch, 1, walker) < 0) { | ||
667 | walker->stop = 1; | ||
668 | return; | ||
669 | } | ||
670 | walker->count++; | ||
671 | } | ||
672 | } | ||
673 | |||
674 | static const struct Qdisc_class_ops netem_class_ops = { | ||
675 | .graft = netem_graft, | ||
676 | .leaf = netem_leaf, | ||
677 | .get = netem_get, | ||
678 | .put = netem_put, | ||
679 | .walk = netem_walk, | ||
680 | .dump = netem_dump_class, | ||
681 | }; | ||
682 | |||
613 | static struct Qdisc_ops netem_qdisc_ops __read_mostly = { | 683 | static struct Qdisc_ops netem_qdisc_ops __read_mostly = { |
614 | .id = "netem", | 684 | .id = "netem", |
685 | .cl_ops = &netem_class_ops, | ||
615 | .priv_size = sizeof(struct netem_sched_data), | 686 | .priv_size = sizeof(struct netem_sched_data), |
616 | .enqueue = netem_enqueue, | 687 | .enqueue = netem_enqueue, |
617 | .dequeue = netem_dequeue, | 688 | .dequeue = netem_dequeue, |