Commit c10c32d3 authored by Martin Devera's avatar Martin Devera Committed by Stephen Hemminger

[PKT_SCHED]: Fix borrowing fairness in htb.

parent 54ab147e
......@@ -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 0x30010 /* major must be matched with number suplied by TC as version */
#define HTB_VER 0x30011 /* 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,6 +172,11 @@ 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 */
......@@ -218,6 +223,7 @@ 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];
......@@ -592,8 +598,13 @@ 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)
htb_next_rb_node(p->un.inner.ptr + 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;
}
htb_safe_rb_erase(cl->node + prio,p->un.inner.feed + prio);
......@@ -952,25 +963,56 @@ 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(struct rb_root *tree,int prio,struct rb_node **pptr)
htb_lookup_leaf(HTB_ARGQ struct rb_root *tree,int prio,struct rb_node **pptr,u32 *pid)
{
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)
......@@ -988,6 +1030,7 @@ htb_lookup_leaf(struct rb_root *tree,int prio,struct rb_node **pptr)
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);
......@@ -1002,7 +1045,8 @@ 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 (q->row[level]+prio,prio,q->ptr[level]+prio);
start = cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,
q->ptr[level]+prio,q->last_ptr_id[level]+prio);
do {
next:
......@@ -1023,8 +1067,9 @@ htb_dequeue_tree(struct htb_sched *q,int prio,int level)
if ((q->row_mask[level] & (1 << prio)) == 0)
return NULL;
next = htb_lookup_leaf (q->row[level]+prio,
prio,q->ptr[level]+prio);
next = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,
prio,q->ptr[level]+prio,q->last_ptr_id[level]+prio);
if (cl == start) /* fix start if we just deleted it */
start = next;
cl = next;
......@@ -1039,7 +1084,9 @@ htb_dequeue_tree(struct htb_sched *q,int prio,int level)
}
q->nwc_hit++;
htb_next_rb_node((level?cl->parent->un.inner.ptr:q->ptr[0])+prio);
cl = htb_lookup_leaf (q->row[level]+prio,prio,q->ptr[level]+prio);
cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,q->ptr[level]+prio,
q->last_ptr_id[level]+prio);
} while (cl != start);
if (likely(skb != NULL)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment