diff options
Diffstat (limited to 'net/sched/sch_htb.c')
-rw-r--r-- | net/sched/sch_htb.c | 171 |
1 files changed, 70 insertions, 101 deletions
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index d14f02056ae6..5070643ce534 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -84,12 +84,12 @@ struct htb_class { | |||
84 | unsigned int children; | 84 | unsigned int children; |
85 | struct htb_class *parent; /* parent class */ | 85 | struct htb_class *parent; /* parent class */ |
86 | 86 | ||
87 | int prio; /* these two are used only by leaves... */ | ||
88 | int quantum; /* but stored for parent-to-leaf return */ | ||
89 | |||
87 | union { | 90 | union { |
88 | struct htb_class_leaf { | 91 | struct htb_class_leaf { |
89 | struct Qdisc *q; | 92 | struct Qdisc *q; |
90 | int prio; | ||
91 | int aprio; | ||
92 | int quantum; | ||
93 | int deficit[TC_HTB_MAXDEPTH]; | 93 | int deficit[TC_HTB_MAXDEPTH]; |
94 | struct list_head drop_list; | 94 | struct list_head drop_list; |
95 | } leaf; | 95 | } leaf; |
@@ -123,19 +123,8 @@ struct htb_class { | |||
123 | psched_tdiff_t mbuffer; /* max wait time */ | 123 | psched_tdiff_t mbuffer; /* max wait time */ |
124 | long tokens, ctokens; /* current number of tokens */ | 124 | long tokens, ctokens; /* current number of tokens */ |
125 | psched_time_t t_c; /* checkpoint time */ | 125 | psched_time_t t_c; /* checkpoint time */ |
126 | |||
127 | int prio; /* For parent to leaf return possible here */ | ||
128 | int quantum; /* we do backup. Finally full replacement */ | ||
129 | /* of un.leaf originals should be done. */ | ||
130 | }; | 126 | }; |
131 | 127 | ||
132 | static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate, | ||
133 | int size) | ||
134 | { | ||
135 | long result = qdisc_l2t(rate, size); | ||
136 | return result; | ||
137 | } | ||
138 | |||
139 | struct htb_sched { | 128 | struct htb_sched { |
140 | struct Qdisc_class_hash clhash; | 129 | struct Qdisc_class_hash clhash; |
141 | struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */ | 130 | struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */ |
@@ -152,9 +141,6 @@ struct htb_sched { | |||
152 | /* time of nearest event per level (row) */ | 141 | /* time of nearest event per level (row) */ |
153 | psched_time_t near_ev_cache[TC_HTB_MAXDEPTH]; | 142 | psched_time_t near_ev_cache[TC_HTB_MAXDEPTH]; |
154 | 143 | ||
155 | /* whether we hit non-work conserving class during this dequeue; we use */ | ||
156 | int nwc_hit; /* this to disable mindelay complaint in dequeue */ | ||
157 | |||
158 | int defcls; /* class where unclassified flows go to */ | 144 | int defcls; /* class where unclassified flows go to */ |
159 | 145 | ||
160 | /* filters for qdisc itself */ | 146 | /* filters for qdisc itself */ |
@@ -527,10 +513,10 @@ static inline void htb_activate(struct htb_sched *q, struct htb_class *cl) | |||
527 | WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen); | 513 | WARN_ON(cl->level || !cl->un.leaf.q || !cl->un.leaf.q->q.qlen); |
528 | 514 | ||
529 | if (!cl->prio_activity) { | 515 | if (!cl->prio_activity) { |
530 | cl->prio_activity = 1 << (cl->un.leaf.aprio = cl->un.leaf.prio); | 516 | cl->prio_activity = 1 << cl->prio; |
531 | htb_activate_prios(q, cl); | 517 | htb_activate_prios(q, cl); |
532 | list_add_tail(&cl->un.leaf.drop_list, | 518 | list_add_tail(&cl->un.leaf.drop_list, |
533 | q->drops + cl->un.leaf.aprio); | 519 | q->drops + cl->prio); |
534 | } | 520 | } |
535 | } | 521 | } |
536 | 522 | ||
@@ -551,7 +537,7 @@ static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl) | |||
551 | 537 | ||
552 | static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | 538 | static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
553 | { | 539 | { |
554 | int ret; | 540 | int uninitialized_var(ret); |
555 | struct htb_sched *q = qdisc_priv(sch); | 541 | struct htb_sched *q = qdisc_priv(sch); |
556 | struct htb_class *cl = htb_classify(skb, sch, &ret); | 542 | struct htb_class *cl = htb_classify(skb, sch, &ret); |
557 | 543 | ||
@@ -591,45 +577,30 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
591 | return NET_XMIT_SUCCESS; | 577 | return NET_XMIT_SUCCESS; |
592 | } | 578 | } |
593 | 579 | ||
594 | /* TODO: requeuing packet charges it to policers again !! */ | 580 | static inline void htb_accnt_tokens(struct htb_class *cl, int bytes, long diff) |
595 | static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) | ||
596 | { | 581 | { |
597 | int ret; | 582 | long toks = diff + cl->tokens; |
598 | struct htb_sched *q = qdisc_priv(sch); | ||
599 | struct htb_class *cl = htb_classify(skb, sch, &ret); | ||
600 | struct sk_buff *tskb; | ||
601 | 583 | ||
602 | if (cl == HTB_DIRECT) { | 584 | if (toks > cl->buffer) |
603 | /* enqueue to helper queue */ | 585 | toks = cl->buffer; |
604 | if (q->direct_queue.qlen < q->direct_qlen) { | 586 | toks -= (long) qdisc_l2t(cl->rate, bytes); |
605 | __skb_queue_head(&q->direct_queue, skb); | 587 | if (toks <= -cl->mbuffer) |
606 | } else { | 588 | toks = 1 - cl->mbuffer; |
607 | __skb_queue_head(&q->direct_queue, skb); | ||
608 | tskb = __skb_dequeue_tail(&q->direct_queue); | ||
609 | kfree_skb(tskb); | ||
610 | sch->qstats.drops++; | ||
611 | return NET_XMIT_CN; | ||
612 | } | ||
613 | #ifdef CONFIG_NET_CLS_ACT | ||
614 | } else if (!cl) { | ||
615 | if (ret & __NET_XMIT_BYPASS) | ||
616 | sch->qstats.drops++; | ||
617 | kfree_skb(skb); | ||
618 | return ret; | ||
619 | #endif | ||
620 | } else if ((ret = cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q)) != | ||
621 | NET_XMIT_SUCCESS) { | ||
622 | if (net_xmit_drop_count(ret)) { | ||
623 | sch->qstats.drops++; | ||
624 | cl->qstats.drops++; | ||
625 | } | ||
626 | return ret; | ||
627 | } else | ||
628 | htb_activate(q, cl); | ||
629 | 589 | ||
630 | sch->q.qlen++; | 590 | cl->tokens = toks; |
631 | sch->qstats.requeues++; | 591 | } |
632 | return NET_XMIT_SUCCESS; | 592 | |
593 | static inline void htb_accnt_ctokens(struct htb_class *cl, int bytes, long diff) | ||
594 | { | ||
595 | long toks = diff + cl->ctokens; | ||
596 | |||
597 | if (toks > cl->cbuffer) | ||
598 | toks = cl->cbuffer; | ||
599 | toks -= (long) qdisc_l2t(cl->ceil, bytes); | ||
600 | if (toks <= -cl->mbuffer) | ||
601 | toks = 1 - cl->mbuffer; | ||
602 | |||
603 | cl->ctokens = toks; | ||
633 | } | 604 | } |
634 | 605 | ||
635 | /** | 606 | /** |
@@ -647,26 +618,20 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, | |||
647 | int level, struct sk_buff *skb) | 618 | int level, struct sk_buff *skb) |
648 | { | 619 | { |
649 | int bytes = qdisc_pkt_len(skb); | 620 | int bytes = qdisc_pkt_len(skb); |
650 | long toks, diff; | ||
651 | enum htb_cmode old_mode; | 621 | enum htb_cmode old_mode; |
652 | 622 | long diff; | |
653 | #define HTB_ACCNT(T,B,R) toks = diff + cl->T; \ | ||
654 | if (toks > cl->B) toks = cl->B; \ | ||
655 | toks -= L2T(cl, cl->R, bytes); \ | ||
656 | if (toks <= -cl->mbuffer) toks = 1-cl->mbuffer; \ | ||
657 | cl->T = toks | ||
658 | 623 | ||
659 | while (cl) { | 624 | while (cl) { |
660 | diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer); | 625 | diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer); |
661 | if (cl->level >= level) { | 626 | if (cl->level >= level) { |
662 | if (cl->level == level) | 627 | if (cl->level == level) |
663 | cl->xstats.lends++; | 628 | cl->xstats.lends++; |
664 | HTB_ACCNT(tokens, buffer, rate); | 629 | htb_accnt_tokens(cl, bytes, diff); |
665 | } else { | 630 | } else { |
666 | cl->xstats.borrows++; | 631 | cl->xstats.borrows++; |
667 | cl->tokens += diff; /* we moved t_c; update tokens */ | 632 | cl->tokens += diff; /* we moved t_c; update tokens */ |
668 | } | 633 | } |
669 | HTB_ACCNT(ctokens, cbuffer, ceil); | 634 | htb_accnt_ctokens(cl, bytes, diff); |
670 | cl->t_c = q->now; | 635 | cl->t_c = q->now; |
671 | 636 | ||
672 | old_mode = cl->cmode; | 637 | old_mode = cl->cmode; |
@@ -733,14 +698,14 @@ static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n, | |||
733 | while (n) { | 698 | while (n) { |
734 | struct htb_class *cl = | 699 | struct htb_class *cl = |
735 | rb_entry(n, struct htb_class, node[prio]); | 700 | rb_entry(n, struct htb_class, node[prio]); |
736 | if (id == cl->common.classid) | ||
737 | return n; | ||
738 | 701 | ||
739 | if (id > cl->common.classid) { | 702 | if (id > cl->common.classid) { |
740 | n = n->rb_right; | 703 | n = n->rb_right; |
741 | } else { | 704 | } else if (id < cl->common.classid) { |
742 | r = n; | 705 | r = n; |
743 | n = n->rb_left; | 706 | n = n->rb_left; |
707 | } else { | ||
708 | return n; | ||
744 | } | 709 | } |
745 | } | 710 | } |
746 | return r; | 711 | return r; |
@@ -761,7 +726,7 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio, | |||
761 | u32 *pid; | 726 | u32 *pid; |
762 | } stk[TC_HTB_MAXDEPTH], *sp = stk; | 727 | } stk[TC_HTB_MAXDEPTH], *sp = stk; |
763 | 728 | ||
764 | WARN_ON(!tree->rb_node); | 729 | BUG_ON(!tree->rb_node); |
765 | sp->root = tree->rb_node; | 730 | sp->root = tree->rb_node; |
766 | sp->pptr = pptr; | 731 | sp->pptr = pptr; |
767 | sp->pid = pid; | 732 | sp->pid = pid; |
@@ -781,9 +746,10 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio, | |||
781 | *sp->pptr = (*sp->pptr)->rb_left; | 746 | *sp->pptr = (*sp->pptr)->rb_left; |
782 | if (sp > stk) { | 747 | if (sp > stk) { |
783 | sp--; | 748 | sp--; |
784 | WARN_ON(!*sp->pptr); | 749 | if (!*sp->pptr) { |
785 | if (!*sp->pptr) | 750 | WARN_ON(1); |
786 | return NULL; | 751 | return NULL; |
752 | } | ||
787 | htb_next_rb_node(sp->pptr); | 753 | htb_next_rb_node(sp->pptr); |
788 | } | 754 | } |
789 | } else { | 755 | } else { |
@@ -814,8 +780,7 @@ static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio, | |||
814 | 780 | ||
815 | do { | 781 | do { |
816 | next: | 782 | next: |
817 | WARN_ON(!cl); | 783 | if (unlikely(!cl)) |
818 | if (!cl) | ||
819 | return NULL; | 784 | return NULL; |
820 | 785 | ||
821 | /* class can be empty - it is unlikely but can be true if leaf | 786 | /* class can be empty - it is unlikely but can be true if leaf |
@@ -849,7 +814,7 @@ next: | |||
849 | cl->common.classid); | 814 | cl->common.classid); |
850 | cl->warned = 1; | 815 | cl->warned = 1; |
851 | } | 816 | } |
852 | q->nwc_hit++; | 817 | |
853 | htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> | 818 | htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> |
854 | ptr[0]) + prio); | 819 | ptr[0]) + prio); |
855 | cl = htb_lookup_leaf(q->row[level] + prio, prio, | 820 | cl = htb_lookup_leaf(q->row[level] + prio, prio, |
@@ -861,7 +826,7 @@ next: | |||
861 | if (likely(skb != NULL)) { | 826 | if (likely(skb != NULL)) { |
862 | cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb); | 827 | cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb); |
863 | if (cl->un.leaf.deficit[level] < 0) { | 828 | if (cl->un.leaf.deficit[level] < 0) { |
864 | cl->un.leaf.deficit[level] += cl->un.leaf.quantum; | 829 | cl->un.leaf.deficit[level] += cl->quantum; |
865 | htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> | 830 | htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> |
866 | ptr[0]) + prio); | 831 | ptr[0]) + prio); |
867 | } | 832 | } |
@@ -894,7 +859,7 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) | |||
894 | q->now = psched_get_time(); | 859 | q->now = psched_get_time(); |
895 | 860 | ||
896 | next_event = q->now + 5 * PSCHED_TICKS_PER_SEC; | 861 | next_event = q->now + 5 * PSCHED_TICKS_PER_SEC; |
897 | q->nwc_hit = 0; | 862 | |
898 | for (level = 0; level < TC_HTB_MAXDEPTH; level++) { | 863 | for (level = 0; level < TC_HTB_MAXDEPTH; level++) { |
899 | /* common case optimization - skip event handler quickly */ | 864 | /* common case optimization - skip event handler quickly */ |
900 | int m; | 865 | int m; |
@@ -1095,8 +1060,8 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, | |||
1095 | opt.buffer = cl->buffer; | 1060 | opt.buffer = cl->buffer; |
1096 | opt.ceil = cl->ceil->rate; | 1061 | opt.ceil = cl->ceil->rate; |
1097 | opt.cbuffer = cl->cbuffer; | 1062 | opt.cbuffer = cl->cbuffer; |
1098 | opt.quantum = cl->un.leaf.quantum; | 1063 | opt.quantum = cl->quantum; |
1099 | opt.prio = cl->un.leaf.prio; | 1064 | opt.prio = cl->prio; |
1100 | opt.level = cl->level; | 1065 | opt.level = cl->level; |
1101 | NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt); | 1066 | NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt); |
1102 | 1067 | ||
@@ -1141,7 +1106,9 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | |||
1141 | == NULL) | 1106 | == NULL) |
1142 | return -ENOBUFS; | 1107 | return -ENOBUFS; |
1143 | sch_tree_lock(sch); | 1108 | sch_tree_lock(sch); |
1144 | if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) { | 1109 | *old = cl->un.leaf.q; |
1110 | cl->un.leaf.q = new; | ||
1111 | if (*old != NULL) { | ||
1145 | qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); | 1112 | qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); |
1146 | qdisc_reset(*old); | 1113 | qdisc_reset(*old); |
1147 | } | 1114 | } |
@@ -1198,8 +1165,6 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl, | |||
1198 | memset(&parent->un.inner, 0, sizeof(parent->un.inner)); | 1165 | memset(&parent->un.inner, 0, sizeof(parent->un.inner)); |
1199 | INIT_LIST_HEAD(&parent->un.leaf.drop_list); | 1166 | INIT_LIST_HEAD(&parent->un.leaf.drop_list); |
1200 | parent->un.leaf.q = new_q ? new_q : &noop_qdisc; | 1167 | parent->un.leaf.q = new_q ? new_q : &noop_qdisc; |
1201 | parent->un.leaf.quantum = parent->quantum; | ||
1202 | parent->un.leaf.prio = parent->prio; | ||
1203 | parent->tokens = parent->buffer; | 1168 | parent->tokens = parent->buffer; |
1204 | parent->ctokens = parent->cbuffer; | 1169 | parent->ctokens = parent->cbuffer; |
1205 | parent->t_c = psched_get_time(); | 1170 | parent->t_c = psched_get_time(); |
@@ -1371,9 +1336,14 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1371 | if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL) | 1336 | if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL) |
1372 | goto failure; | 1337 | goto failure; |
1373 | 1338 | ||
1374 | gen_new_estimator(&cl->bstats, &cl->rate_est, | 1339 | err = gen_new_estimator(&cl->bstats, &cl->rate_est, |
1375 | qdisc_root_sleeping_lock(sch), | 1340 | qdisc_root_sleeping_lock(sch), |
1376 | tca[TCA_RATE] ? : &est.nla); | 1341 | tca[TCA_RATE] ? : &est.nla); |
1342 | if (err) { | ||
1343 | kfree(cl); | ||
1344 | goto failure; | ||
1345 | } | ||
1346 | |||
1377 | cl->refcnt = 1; | 1347 | cl->refcnt = 1; |
1378 | cl->children = 0; | 1348 | cl->children = 0; |
1379 | INIT_LIST_HEAD(&cl->un.leaf.drop_list); | 1349 | INIT_LIST_HEAD(&cl->un.leaf.drop_list); |
@@ -1425,37 +1395,36 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1425 | if (parent) | 1395 | if (parent) |
1426 | parent->children++; | 1396 | parent->children++; |
1427 | } else { | 1397 | } else { |
1428 | if (tca[TCA_RATE]) | 1398 | if (tca[TCA_RATE]) { |
1429 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | 1399 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, |
1430 | qdisc_root_sleeping_lock(sch), | 1400 | qdisc_root_sleeping_lock(sch), |
1431 | tca[TCA_RATE]); | 1401 | tca[TCA_RATE]); |
1402 | if (err) | ||
1403 | return err; | ||
1404 | } | ||
1432 | sch_tree_lock(sch); | 1405 | sch_tree_lock(sch); |
1433 | } | 1406 | } |
1434 | 1407 | ||
1435 | /* it used to be a nasty bug here, we have to check that node | 1408 | /* it used to be a nasty bug here, we have to check that node |
1436 | is really leaf before changing cl->un.leaf ! */ | 1409 | is really leaf before changing cl->un.leaf ! */ |
1437 | if (!cl->level) { | 1410 | if (!cl->level) { |
1438 | cl->un.leaf.quantum = rtab->rate.rate / q->rate2quantum; | 1411 | cl->quantum = rtab->rate.rate / q->rate2quantum; |
1439 | if (!hopt->quantum && cl->un.leaf.quantum < 1000) { | 1412 | if (!hopt->quantum && cl->quantum < 1000) { |
1440 | printk(KERN_WARNING | 1413 | printk(KERN_WARNING |
1441 | "HTB: quantum of class %X is small. Consider r2q change.\n", | 1414 | "HTB: quantum of class %X is small. Consider r2q change.\n", |
1442 | cl->common.classid); | 1415 | cl->common.classid); |
1443 | cl->un.leaf.quantum = 1000; | 1416 | cl->quantum = 1000; |
1444 | } | 1417 | } |
1445 | if (!hopt->quantum && cl->un.leaf.quantum > 200000) { | 1418 | if (!hopt->quantum && cl->quantum > 200000) { |
1446 | printk(KERN_WARNING | 1419 | printk(KERN_WARNING |
1447 | "HTB: quantum of class %X is big. Consider r2q change.\n", | 1420 | "HTB: quantum of class %X is big. Consider r2q change.\n", |
1448 | cl->common.classid); | 1421 | cl->common.classid); |
1449 | cl->un.leaf.quantum = 200000; | 1422 | cl->quantum = 200000; |
1450 | } | 1423 | } |
1451 | if (hopt->quantum) | 1424 | if (hopt->quantum) |
1452 | cl->un.leaf.quantum = hopt->quantum; | 1425 | cl->quantum = hopt->quantum; |
1453 | if ((cl->un.leaf.prio = hopt->prio) >= TC_HTB_NUMPRIO) | 1426 | if ((cl->prio = hopt->prio) >= TC_HTB_NUMPRIO) |
1454 | cl->un.leaf.prio = TC_HTB_NUMPRIO - 1; | 1427 | cl->prio = TC_HTB_NUMPRIO - 1; |
1455 | |||
1456 | /* backup for htb_parent_to_leaf */ | ||
1457 | cl->quantum = cl->un.leaf.quantum; | ||
1458 | cl->prio = cl->un.leaf.prio; | ||
1459 | } | 1428 | } |
1460 | 1429 | ||
1461 | cl->buffer = hopt->buffer; | 1430 | cl->buffer = hopt->buffer; |
@@ -1565,7 +1534,7 @@ static struct Qdisc_ops htb_qdisc_ops __read_mostly = { | |||
1565 | .priv_size = sizeof(struct htb_sched), | 1534 | .priv_size = sizeof(struct htb_sched), |
1566 | .enqueue = htb_enqueue, | 1535 | .enqueue = htb_enqueue, |
1567 | .dequeue = htb_dequeue, | 1536 | .dequeue = htb_dequeue, |
1568 | .requeue = htb_requeue, | 1537 | .peek = qdisc_peek_dequeued, |
1569 | .drop = htb_drop, | 1538 | .drop = htb_drop, |
1570 | .init = htb_init, | 1539 | .init = htb_init, |
1571 | .reset = htb_reset, | 1540 | .reset = htb_reset, |