X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fsched%2Fsch_htb.c;h=65797b3306cccb7c6c066b87f904ac3750df21ec;hb=052710fcf296f48df03c0e248eface251a7ab22c;hp=d07dfd8b5cf03f75ede572ef52abc89f4fd08ef0;hpb=a91482bdcc2e0f6035702e46f1b99043a0893346;p=linux-2.6.git diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index d07dfd8b5..65797b330 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -76,7 +76,7 @@ #define HTB_HYSTERESIS 1/* whether to use mode hysteresis for speedup */ #define HTB_QLOCK(S) spin_lock_bh(&(S)->dev->queue_lock) #define HTB_QUNLOCK(S) spin_unlock_bh(&(S)->dev->queue_lock) -#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */ +#define HTB_VER 0x30010 /* major must be matched with number suplied by TC as version */ #if HTB_VER >> 16 != TC_HTB_PROTOVER #error "Mismatched sch_htb.c and pkt_sch.h" @@ -172,11 +172,6 @@ struct htb_class struct htb_class_inner { struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */ struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */ - /* When class changes from state 1->2 and disconnects from - parent's feed then we lost ptr value and start from the - first child again. Here we store classid of the - last valid ptr (used when ptr is NULL). */ - u32 last_ptr_id[TC_HTB_NUMPRIO]; } inner; } un; struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ @@ -223,7 +218,6 @@ struct htb_sched struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; int row_mask[TC_HTB_MAXDEPTH]; struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; - u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; /* self wait list - roots of wait PQs per row */ struct rb_root wait_pq[TC_HTB_MAXDEPTH]; @@ -273,7 +267,7 @@ static __inline__ int htb_hash(u32 h) /* find class in global hash table using given handle */ static __inline__ struct htb_class *htb_find(u32 handle, struct Qdisc *sch) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; struct list_head *p; if (TC_H_MAJ(handle) != sch->handle) return NULL; @@ -306,7 +300,7 @@ static inline u32 htb_classid(struct htb_class *cl) static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; struct htb_class *cl; struct tcf_result res; struct tcf_proto *tcf; @@ -598,13 +592,8 @@ static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl) int prio = ffz(~m); m &= ~(1 << prio); - if (p->un.inner.ptr[prio] == cl->node+prio) { - /* we are removing child which is pointed to from - parent feed - forget the pointer but remember - classid */ - p->un.inner.last_ptr_id[prio] = cl->classid; - p->un.inner.ptr[prio] = NULL; - } + if (p->un.inner.ptr[prio] == cl->node+prio) + htb_next_rb_node(p->un.inner.ptr + prio); htb_safe_rb_erase(cl->node + prio,p->un.inner.feed + prio); @@ -723,7 +712,7 @@ htb_deactivate(struct htb_sched *q,struct htb_class *cl) static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) { int ret = NET_XMIT_SUCCESS; - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; struct htb_class *cl = htb_classify(skb,sch,&ret); @@ -770,7 +759,7 @@ 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) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; int ret = NET_XMIT_SUCCESS; struct htb_class *cl = htb_classify(skb,sch, &ret); struct sk_buff *tskb; @@ -811,7 +800,7 @@ static void htb_timer(unsigned long arg) static void htb_rate_timer(unsigned long arg) { struct Qdisc *sch = (struct Qdisc*)arg; - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; struct list_head *p; /* lock queue so that we can muck with it */ @@ -867,13 +856,8 @@ static void htb_charge_class(struct htb_sched *q,struct htb_class *cl, if (net_ratelimit()) printk(KERN_ERR "HTB: bad diff in charge, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n", cl->classid, diff, -#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY - q->now.tv_sec * 1000000ULL + q->now.tv_usec, - cl->t_c.tv_sec * 1000000ULL + cl->t_c.tv_usec, -#else (unsigned long long) q->now, (unsigned long long) cl->t_c, -#endif q->jiffies); diff = 1000; } @@ -943,13 +927,8 @@ static long htb_do_events(struct htb_sched *q,int level) if (net_ratelimit()) printk(KERN_ERR "HTB: bad diff in events, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n", cl->classid, diff, -#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY - q->now.tv_sec * 1000000ULL + q->now.tv_usec, - cl->t_c.tv_sec * 1000000ULL + cl->t_c.tv_usec, -#else (unsigned long long) q->now, (unsigned long long) cl->t_c, -#endif q->jiffies); diff = 1000; } @@ -963,56 +942,25 @@ static long htb_do_events(struct htb_sched *q,int level) return HZ/10; } -/* Returns class->node+prio from id-tree where classe's id is >= id. NULL - is no such one exists. */ -static struct rb_node * -htb_id_find_next_upper(int prio,struct rb_node *n,u32 id) -{ - struct rb_node *r = NULL; - while (n) { - struct htb_class *cl = rb_entry(n,struct htb_class,node[prio]); - if (id == cl->classid) return n; - - if (id > cl->classid) { - n = n->rb_right; - } else { - r = n; - n = n->rb_left; - } - } - return r; -} - /** * htb_lookup_leaf - returns next leaf class in DRR order * * Find leaf where current feed pointers points to. */ static struct htb_class * -htb_lookup_leaf(HTB_ARGQ struct rb_root *tree,int prio,struct rb_node **pptr,u32 *pid) +htb_lookup_leaf(struct rb_root *tree,int prio,struct rb_node **pptr) { int i; struct { struct rb_node *root; struct rb_node **pptr; - u32 *pid; } stk[TC_HTB_MAXDEPTH],*sp = stk; BUG_TRAP(tree->rb_node); sp->root = tree->rb_node; sp->pptr = pptr; - sp->pid = pid; for (i = 0; i < 65535; i++) { - HTB_DBG(4,2,"htb_lleaf ptr=%p pid=%X\n",*sp->pptr,*sp->pid); - - if (!*sp->pptr && *sp->pid) { - /* ptr was invalidated but id is valid - try to recover - the original or next ptr */ - *sp->pptr = htb_id_find_next_upper(prio,sp->root,*sp->pid); - } - *sp->pid = 0; /* ptr is valid now so that remove this hint as it - can become out of date quickly */ if (!*sp->pptr) { /* we are at right end; rewind & go up */ *sp->pptr = sp->root; while ((*sp->pptr)->rb_left) @@ -1030,7 +978,6 @@ htb_lookup_leaf(HTB_ARGQ struct rb_root *tree,int prio,struct rb_node **pptr,u32 return cl; (++sp)->root = cl->un.inner.feed[prio].rb_node; sp->pptr = cl->un.inner.ptr+prio; - sp->pid = cl->un.inner.last_ptr_id+prio; } } BUG_TRAP(0); @@ -1045,8 +992,7 @@ htb_dequeue_tree(struct htb_sched *q,int prio,int level) struct sk_buff *skb = NULL; struct htb_class *cl,*start; /* look initial class up in the row */ - start = cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio, - q->ptr[level]+prio,q->last_ptr_id[level]+prio); + start = cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio); do { next: @@ -1067,9 +1013,8 @@ next: if ((q->row_mask[level] & (1 << prio)) == 0) return NULL; - next = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio, - prio,q->ptr[level]+prio,q->last_ptr_id[level]+prio); - + next = htb_lookup_leaf (q->row[level]+prio, + prio,q->ptr[level]+prio); if (cl == start) /* fix start if we just deleted it */ start = next; cl = next; @@ -1084,9 +1029,7 @@ next: } q->nwc_hit++; htb_next_rb_node((level?cl->parent->un.inner.ptr:q->ptr[0])+prio); - cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,q->ptr[level]+prio, - q->last_ptr_id[level]+prio); - + cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio); } while (cl != start); if (likely(skb != NULL)) { @@ -1107,7 +1050,7 @@ next: static void htb_delay_by(struct Qdisc *sch,long delay) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; if (delay <= 0) delay = 1; if (unlikely(delay > 5*HZ)) { if (net_ratelimit()) @@ -1124,7 +1067,7 @@ static void htb_delay_by(struct Qdisc *sch,long delay) static struct sk_buff *htb_dequeue(struct Qdisc *sch) { struct sk_buff *skb = NULL; - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; int level; long min_delay; #ifdef HTB_DEBUG @@ -1194,7 +1137,7 @@ fin: /* try to drop from each class (by prio) until one succeed */ static unsigned int htb_drop(struct Qdisc* sch) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; int prio; for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) { @@ -1219,7 +1162,7 @@ static unsigned int htb_drop(struct Qdisc* sch) /* always caled under BH & queue lock */ static void htb_reset(struct Qdisc* sch) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; int i; HTB_DBG(0,1,"htb_reset sch=%p, handle=%X\n",sch,sch->handle); @@ -1257,7 +1200,7 @@ static void htb_reset(struct Qdisc* sch) static int htb_init(struct Qdisc *sch, struct rtattr *opt) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched*)sch->data; struct rtattr *tb[TCA_HTB_INIT]; struct tc_htb_glob *gopt; int i; @@ -1312,7 +1255,7 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt) static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched*)sch->data; unsigned char *b = skb->tail; struct rtattr *rta; struct tc_htb_glob gopt; @@ -1347,7 +1290,7 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, struct tcmsg *tcm) { #ifdef HTB_DEBUG - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched*)sch->data; #endif struct htb_class *cl = (struct htb_class*)arg; unsigned char *b = skb->tail; @@ -1405,7 +1348,7 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, sch_tree_lock(sch); if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) { if (cl->prio_activity) - htb_deactivate (qdisc_priv(sch),cl); + htb_deactivate ((struct htb_sched*)sch->data,cl); /* TODO: is it correct ? Why CBQ doesn't do it ? */ sch->q.qlen -= (*old)->q.qlen; @@ -1426,7 +1369,7 @@ static struct Qdisc * htb_leaf(struct Qdisc *sch, unsigned long arg) static unsigned long htb_get(struct Qdisc *sch, u32 classid) { #ifdef HTB_DEBUG - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; #endif struct htb_class *cl = htb_find(classid,sch); HTB_DBG(0,1,"htb_get clid=%X q=%p cl=%p ref=%d\n",classid,q,cl,cl?cl->refcnt:0); @@ -1447,7 +1390,7 @@ static void htb_destroy_filters(struct tcf_proto **fl) static void htb_destroy_class(struct Qdisc* sch,struct htb_class *cl) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; HTB_DBG(0,1,"htb_destrycls clid=%X ref=%d\n", cl?cl->classid:0,cl?cl->refcnt:0); if (!cl->level) { BUG_TRAP(cl->un.leaf.q); @@ -1482,7 +1425,7 @@ static void htb_destroy_class(struct Qdisc* sch,struct htb_class *cl) /* always caled under BH & queue lock */ static void htb_destroy(struct Qdisc* sch) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; HTB_DBG(0,1,"htb_destroy q=%p\n",q); del_timer_sync (&q->timer); @@ -1504,7 +1447,7 @@ static void htb_destroy(struct Qdisc* sch) static int htb_delete(struct Qdisc *sch, unsigned long arg) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; struct htb_class *cl = (struct htb_class*)arg; HTB_DBG(0,1,"htb_delete q=%p cl=%X ref=%d\n",q,cl?cl->classid:0,cl?cl->refcnt:0); @@ -1531,7 +1474,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) static void htb_put(struct Qdisc *sch, unsigned long arg) { #ifdef HTB_DEBUG - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; #endif struct htb_class *cl = (struct htb_class*)arg; HTB_DBG(0,1,"htb_put q=%p cl=%X ref=%d\n",q,cl?cl->classid:0,cl?cl->refcnt:0); @@ -1544,7 +1487,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **tca, unsigned long *arg) { int err = -EINVAL; - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; struct htb_class *cl = (struct htb_class*)*arg,*parent; struct rtattr *opt = tca[TCA_OPTIONS-1]; struct qdisc_rate_table *rtab = NULL, *ctab = NULL; @@ -1670,7 +1613,7 @@ failure: static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; struct htb_class *cl = (struct htb_class *)arg; struct tcf_proto **fl = cl ? &cl->filter_list : &q->filter_list; HTB_DBG(0,2,"htb_tcf q=%p clid=%X fref=%d fl=%p\n",q,cl?cl->classid:0,cl?cl->filter_cnt:q->filter_cnt,*fl); @@ -1680,7 +1623,7 @@ static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg) static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent, u32 classid) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; struct htb_class *cl = htb_find (classid,sch); HTB_DBG(0,2,"htb_bind q=%p clid=%X cl=%p fref=%d\n",q,classid,cl,cl?cl->filter_cnt:q->filter_cnt); /*if (cl && !cl->level) return 0; @@ -1701,7 +1644,7 @@ static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent, static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; struct htb_class *cl = (struct htb_class *)arg; HTB_DBG(0,2,"htb_unbind q=%p cl=%p fref=%d\n",q,cl,cl?cl->filter_cnt:q->filter_cnt); if (cl) @@ -1712,7 +1655,7 @@ static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg) static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg) { - struct htb_sched *q = qdisc_priv(sch); + struct htb_sched *q = (struct htb_sched *)sch->data; int i; if (arg->stop)