X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=net%2Fsched%2Fsch_htb.c;h=5bc1ed4901800af63fc1255ba1f5eecbbe8368de;hb=59b1c82500bb5d658891bc8e8a2308b76d58a4de;hp=69fac320f8bcdb1eeeabb946bdc44ae41716621e;hpb=4b3550ef530cfc153fa91f0b37cbda448bad11c6;p=linux-2.6-omap-h63xx.git diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 69fac320f8b..5bc1ed49018 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -609,14 +609,14 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) /* TODO: requeuing packet charges it to policers again !! */ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) { + int ret; struct htb_sched *q = qdisc_priv(sch); - int ret = NET_XMIT_SUCCESS; struct htb_class *cl = htb_classify(skb, sch, &ret); struct sk_buff *tskb; - if (cl == HTB_DIRECT || !cl) { + if (cl == HTB_DIRECT) { /* enqueue to helper queue */ - if (q->direct_queue.qlen < q->direct_qlen && cl) { + if (q->direct_queue.qlen < q->direct_qlen) { __skb_queue_head(&q->direct_queue, skb); } else { __skb_queue_head(&q->direct_queue, skb); @@ -625,6 +625,13 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) sch->qstats.drops++; return NET_XMIT_CN; } +#ifdef CONFIG_NET_CLS_ACT + } else if (!cl) { + if (ret == NET_XMIT_BYPASS) + sch->qstats.drops++; + kfree_skb(skb); + return ret; +#endif } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) { sch->qstats.drops++; @@ -704,9 +711,11 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, */ static psched_time_t htb_do_events(struct htb_sched *q, int level) { - int i; - - for (i = 0; i < 500; i++) { + /* don't run for longer than 2 jiffies; 2 is used instead of + 1 to simplify things when jiffy is going to be incremented + too soon */ + unsigned long stop_at = jiffies + 2; + while (time_before(jiffies, stop_at)) { struct htb_class *cl; long diff; struct rb_node *p = rb_first(&q->wait_pq[level]); @@ -724,9 +733,8 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level) if (cl->cmode != HTB_CAN_SEND) htb_add_to_wait_tree(q, cl, diff); } - if (net_ratelimit()) - printk(KERN_WARNING "htb: too many events !\n"); - return q->now + PSCHED_TICKS_PER_SEC / 10; + /* too much load - let's continue on next jiffie */ + return q->now + PSCHED_TICKS_PER_SEC / HZ; } /* Returns class->node+prio from id-tree where classe's id is >= id. NULL @@ -992,6 +1000,13 @@ static void htb_reset(struct Qdisc *sch) INIT_LIST_HEAD(q->drops + i); } +static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = { + [TCA_HTB_PARMS] = { .len = sizeof(struct tc_htb_opt) }, + [TCA_HTB_INIT] = { .len = sizeof(struct tc_htb_glob) }, + [TCA_HTB_CTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, + [TCA_HTB_RTAB] = { .type = NLA_BINARY, .len = TC_RTAB_SIZE }, +}; + static int htb_init(struct Qdisc *sch, struct nlattr *opt) { struct htb_sched *q = qdisc_priv(sch); @@ -1003,12 +1018,11 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt) if (!opt) return -EINVAL; - err = nla_parse_nested(tb, TCA_HTB_INIT, opt, NULL); + err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy); if (err < 0) return err; - if (tb[TCA_HTB_INIT] == NULL || - nla_len(tb[TCA_HTB_INIT]) < sizeof(*gopt)) { + if (tb[TCA_HTB_INIT] == NULL) { printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n"); return -EINVAL; } @@ -1183,12 +1197,16 @@ static inline int htb_parent_last_child(struct htb_class *cl) return 1; } -static void htb_parent_to_leaf(struct htb_class *cl, struct Qdisc *new_q) +static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl, + struct Qdisc *new_q) { struct htb_class *parent = cl->parent; BUG_TRAP(!cl->level && cl->un.leaf.q && !cl->prio_activity); + if (parent->cmode != HTB_CAN_SEND) + htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level); + parent->level = 0; memset(&parent->un.inner, 0, sizeof(parent->un.inner)); INIT_LIST_HEAD(&parent->un.leaf.drop_list); @@ -1286,7 +1304,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) htb_deactivate(q, cl); if (last_child) - htb_parent_to_leaf(cl, new_q); + htb_parent_to_leaf(q, cl, new_q); if (--cl->refcnt == 0) htb_destroy_class(sch, cl); @@ -1319,13 +1337,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, if (!opt) goto failure; - err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, NULL); + err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy); if (err < 0) goto failure; err = -EINVAL; - if (tb[TCA_HTB_PARMS] == NULL || - nla_len(tb[TCA_HTB_PARMS]) < sizeof(*hopt)) + if (tb[TCA_HTB_PARMS] == NULL) goto failure; parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);