diff options
Diffstat (limited to 'net/sched/sch_hfsc.c')
-rw-r--r-- | net/sched/sch_hfsc.c | 64 |
1 files changed, 25 insertions, 39 deletions
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index c1e77da8cd0..45c31b1a4e1 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -184,7 +184,6 @@ struct hfsc_sched | |||
184 | struct rb_root eligible; /* eligible tree */ | 184 | struct rb_root eligible; /* eligible tree */ |
185 | struct list_head droplist; /* active leaf class list (for | 185 | struct list_head droplist; /* active leaf class list (for |
186 | dropping) */ | 186 | dropping) */ |
187 | struct sk_buff_head requeue; /* requeued packet */ | ||
188 | struct qdisc_watchdog watchdog; /* watchdog timer */ | 187 | struct qdisc_watchdog watchdog; /* watchdog timer */ |
189 | }; | 188 | }; |
190 | 189 | ||
@@ -880,28 +879,20 @@ set_passive(struct hfsc_class *cl) | |||
880 | */ | 879 | */ |
881 | } | 880 | } |
882 | 881 | ||
883 | /* | ||
884 | * hack to get length of first packet in queue. | ||
885 | */ | ||
886 | static unsigned int | 882 | static unsigned int |
887 | qdisc_peek_len(struct Qdisc *sch) | 883 | qdisc_peek_len(struct Qdisc *sch) |
888 | { | 884 | { |
889 | struct sk_buff *skb; | 885 | struct sk_buff *skb; |
890 | unsigned int len; | 886 | unsigned int len; |
891 | 887 | ||
892 | skb = sch->dequeue(sch); | 888 | skb = sch->ops->peek(sch); |
893 | if (skb == NULL) { | 889 | if (skb == NULL) { |
894 | if (net_ratelimit()) | 890 | if (net_ratelimit()) |
895 | printk("qdisc_peek_len: non work-conserving qdisc ?\n"); | 891 | printk("qdisc_peek_len: non work-conserving qdisc ?\n"); |
896 | return 0; | 892 | return 0; |
897 | } | 893 | } |
898 | len = qdisc_pkt_len(skb); | 894 | len = qdisc_pkt_len(skb); |
899 | if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) { | 895 | |
900 | if (net_ratelimit()) | ||
901 | printk("qdisc_peek_len: failed to requeue\n"); | ||
902 | qdisc_tree_decrease_qlen(sch, 1); | ||
903 | return 0; | ||
904 | } | ||
905 | return len; | 896 | return len; |
906 | } | 897 | } |
907 | 898 | ||
@@ -1027,6 +1018,14 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1027 | } | 1018 | } |
1028 | cur_time = psched_get_time(); | 1019 | cur_time = psched_get_time(); |
1029 | 1020 | ||
1021 | if (tca[TCA_RATE]) { | ||
1022 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
1023 | qdisc_root_sleeping_lock(sch), | ||
1024 | tca[TCA_RATE]); | ||
1025 | if (err) | ||
1026 | return err; | ||
1027 | } | ||
1028 | |||
1030 | sch_tree_lock(sch); | 1029 | sch_tree_lock(sch); |
1031 | if (rsc != NULL) | 1030 | if (rsc != NULL) |
1032 | hfsc_change_rsc(cl, rsc, cur_time); | 1031 | hfsc_change_rsc(cl, rsc, cur_time); |
@@ -1043,10 +1042,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1043 | } | 1042 | } |
1044 | sch_tree_unlock(sch); | 1043 | sch_tree_unlock(sch); |
1045 | 1044 | ||
1046 | if (tca[TCA_RATE]) | ||
1047 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
1048 | qdisc_root_sleeping_lock(sch), | ||
1049 | tca[TCA_RATE]); | ||
1050 | return 0; | 1045 | return 0; |
1051 | } | 1046 | } |
1052 | 1047 | ||
@@ -1072,6 +1067,16 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1072 | if (cl == NULL) | 1067 | if (cl == NULL) |
1073 | return -ENOBUFS; | 1068 | return -ENOBUFS; |
1074 | 1069 | ||
1070 | if (tca[TCA_RATE]) { | ||
1071 | err = gen_new_estimator(&cl->bstats, &cl->rate_est, | ||
1072 | qdisc_root_sleeping_lock(sch), | ||
1073 | tca[TCA_RATE]); | ||
1074 | if (err) { | ||
1075 | kfree(cl); | ||
1076 | return err; | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1075 | if (rsc != NULL) | 1080 | if (rsc != NULL) |
1076 | hfsc_change_rsc(cl, rsc, 0); | 1081 | hfsc_change_rsc(cl, rsc, 0); |
1077 | if (fsc != NULL) | 1082 | if (fsc != NULL) |
@@ -1102,9 +1107,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1102 | 1107 | ||
1103 | qdisc_class_hash_grow(sch, &q->clhash); | 1108 | qdisc_class_hash_grow(sch, &q->clhash); |
1104 | 1109 | ||
1105 | if (tca[TCA_RATE]) | ||
1106 | gen_new_estimator(&cl->bstats, &cl->rate_est, | ||
1107 | qdisc_root_sleeping_lock(sch), tca[TCA_RATE]); | ||
1108 | *arg = (unsigned long)cl; | 1110 | *arg = (unsigned long)cl; |
1109 | return 0; | 1111 | return 0; |
1110 | } | 1112 | } |
@@ -1211,7 +1213,8 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | |||
1211 | 1213 | ||
1212 | sch_tree_lock(sch); | 1214 | sch_tree_lock(sch); |
1213 | hfsc_purge_queue(sch, cl); | 1215 | hfsc_purge_queue(sch, cl); |
1214 | *old = xchg(&cl->qdisc, new); | 1216 | *old = cl->qdisc; |
1217 | cl->qdisc = new; | ||
1215 | sch_tree_unlock(sch); | 1218 | sch_tree_unlock(sch); |
1216 | return 0; | 1219 | return 0; |
1217 | } | 1220 | } |
@@ -1440,7 +1443,6 @@ hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt) | |||
1440 | return err; | 1443 | return err; |
1441 | q->eligible = RB_ROOT; | 1444 | q->eligible = RB_ROOT; |
1442 | INIT_LIST_HEAD(&q->droplist); | 1445 | INIT_LIST_HEAD(&q->droplist); |
1443 | skb_queue_head_init(&q->requeue); | ||
1444 | 1446 | ||
1445 | q->root.cl_common.classid = sch->handle; | 1447 | q->root.cl_common.classid = sch->handle; |
1446 | q->root.refcnt = 1; | 1448 | q->root.refcnt = 1; |
@@ -1525,7 +1527,6 @@ hfsc_reset_qdisc(struct Qdisc *sch) | |||
1525 | hlist_for_each_entry(cl, n, &q->clhash.hash[i], cl_common.hnode) | 1527 | hlist_for_each_entry(cl, n, &q->clhash.hash[i], cl_common.hnode) |
1526 | hfsc_reset_class(cl); | 1528 | hfsc_reset_class(cl); |
1527 | } | 1529 | } |
1528 | __skb_queue_purge(&q->requeue); | ||
1529 | q->eligible = RB_ROOT; | 1530 | q->eligible = RB_ROOT; |
1530 | INIT_LIST_HEAD(&q->droplist); | 1531 | INIT_LIST_HEAD(&q->droplist); |
1531 | qdisc_watchdog_cancel(&q->watchdog); | 1532 | qdisc_watchdog_cancel(&q->watchdog); |
@@ -1550,7 +1551,6 @@ hfsc_destroy_qdisc(struct Qdisc *sch) | |||
1550 | hfsc_destroy_class(sch, cl); | 1551 | hfsc_destroy_class(sch, cl); |
1551 | } | 1552 | } |
1552 | qdisc_class_hash_destroy(&q->clhash); | 1553 | qdisc_class_hash_destroy(&q->clhash); |
1553 | __skb_queue_purge(&q->requeue); | ||
1554 | qdisc_watchdog_cancel(&q->watchdog); | 1554 | qdisc_watchdog_cancel(&q->watchdog); |
1555 | } | 1555 | } |
1556 | 1556 | ||
@@ -1574,7 +1574,7 @@ static int | |||
1574 | hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch) | 1574 | hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
1575 | { | 1575 | { |
1576 | struct hfsc_class *cl; | 1576 | struct hfsc_class *cl; |
1577 | int err; | 1577 | int uninitialized_var(err); |
1578 | 1578 | ||
1579 | cl = hfsc_classify(skb, sch, &err); | 1579 | cl = hfsc_classify(skb, sch, &err); |
1580 | if (cl == NULL) { | 1580 | if (cl == NULL) { |
@@ -1617,8 +1617,6 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1617 | 1617 | ||
1618 | if (sch->q.qlen == 0) | 1618 | if (sch->q.qlen == 0) |
1619 | return NULL; | 1619 | return NULL; |
1620 | if ((skb = __skb_dequeue(&q->requeue))) | ||
1621 | goto out; | ||
1622 | 1620 | ||
1623 | cur_time = psched_get_time(); | 1621 | cur_time = psched_get_time(); |
1624 | 1622 | ||
@@ -1642,7 +1640,7 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1642 | } | 1640 | } |
1643 | } | 1641 | } |
1644 | 1642 | ||
1645 | skb = cl->qdisc->dequeue(cl->qdisc); | 1643 | skb = qdisc_dequeue_peeked(cl->qdisc); |
1646 | if (skb == NULL) { | 1644 | if (skb == NULL) { |
1647 | if (net_ratelimit()) | 1645 | if (net_ratelimit()) |
1648 | printk("HFSC: Non-work-conserving qdisc ?\n"); | 1646 | printk("HFSC: Non-work-conserving qdisc ?\n"); |
@@ -1667,24 +1665,12 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1667 | set_passive(cl); | 1665 | set_passive(cl); |
1668 | } | 1666 | } |
1669 | 1667 | ||
1670 | out: | ||
1671 | sch->flags &= ~TCQ_F_THROTTLED; | 1668 | sch->flags &= ~TCQ_F_THROTTLED; |
1672 | sch->q.qlen--; | 1669 | sch->q.qlen--; |
1673 | 1670 | ||
1674 | return skb; | 1671 | return skb; |
1675 | } | 1672 | } |
1676 | 1673 | ||
1677 | static int | ||
1678 | hfsc_requeue(struct sk_buff *skb, struct Qdisc *sch) | ||
1679 | { | ||
1680 | struct hfsc_sched *q = qdisc_priv(sch); | ||
1681 | |||
1682 | __skb_queue_head(&q->requeue, skb); | ||
1683 | sch->q.qlen++; | ||
1684 | sch->qstats.requeues++; | ||
1685 | return NET_XMIT_SUCCESS; | ||
1686 | } | ||
1687 | |||
1688 | static unsigned int | 1674 | static unsigned int |
1689 | hfsc_drop(struct Qdisc *sch) | 1675 | hfsc_drop(struct Qdisc *sch) |
1690 | { | 1676 | { |
@@ -1735,7 +1721,7 @@ static struct Qdisc_ops hfsc_qdisc_ops __read_mostly = { | |||
1735 | .dump = hfsc_dump_qdisc, | 1721 | .dump = hfsc_dump_qdisc, |
1736 | .enqueue = hfsc_enqueue, | 1722 | .enqueue = hfsc_enqueue, |
1737 | .dequeue = hfsc_dequeue, | 1723 | .dequeue = hfsc_dequeue, |
1738 | .requeue = hfsc_requeue, | 1724 | .peek = qdisc_peek_dequeued, |
1739 | .drop = hfsc_drop, | 1725 | .drop = hfsc_drop, |
1740 | .cl_ops = &hfsc_class_ops, | 1726 | .cl_ops = &hfsc_class_ops, |
1741 | .priv_size = sizeof(struct hfsc_sched), | 1727 | .priv_size = sizeof(struct hfsc_sched), |