diff -rubB /usr/src/linux-2.2.16/net/sched/sch_sfq.c gatek/net/sched/sch_sfq.c --- /usr/src/linux-2.2.16/net/sched/sch_sfq.c Sun Apr 25 02:51:48 1999 +++ gatek/net/sched/sch_sfq.c Sun Sep 24 15:45:50 2000 @@ -111,6 +111,8 @@ int perturbation; sfq_index tail; /* Index of current slot in round */ sfq_index max_depth; /* Maximal depth */ + short flows; /* Num of flows */ + short max_flows; /* Max num of flows */ sfq_index ht[SFQ_HASH_DIVISOR]; /* Hash table */ sfq_index next[SFQ_DEPTH]; /* Active slots link */ @@ -265,6 +267,7 @@ __skb_queue_tail(&q->qs[x], skb); sfq_inc(q, x); if (q->qs[x].qlen == 1) { /* The flow is new */ + if (++q->flows > q->max_flows) q->max_flows = q->flows; if (q->tail == SFQ_DEPTH) { /* It is the first flow */ q->tail = x; q->next[x] = x; @@ -276,11 +279,13 @@ } } if (++sch->q.qlen < SFQ_DEPTH-1) { + // arbitrary hack to limit maximal flow's backlog + if (q->qs[x].qlen > 5) goto drop; sch->stats.bytes += skb->len; sch->stats.packets++; return 1; } - +drop: sfq_drop(sch); return 0; } @@ -300,6 +305,7 @@ __skb_queue_head(&q->qs[x], skb); sfq_inc(q, x); if (q->qs[x].qlen == 1) { /* The flow is new */ + if (++q->flows > q->max_flows) q->max_flows = q->flows; if (q->tail == SFQ_DEPTH) { /* It is the first flow */ q->tail = x; q->next[x] = x; @@ -341,6 +347,7 @@ /* Is the slot empty? */ if (q->qs[a].qlen == 0) { + q->flows--; a = q->next[a]; if (a == old_a) { q->tail = SFQ_DEPTH; @@ -417,6 +424,8 @@ q->dep[i+SFQ_DEPTH].prev = i+SFQ_DEPTH; } q->max_depth = 0; + q->max_flows = 0; + q->flows = 0; q->tail = SFQ_DEPTH; if (opt == NULL) { q->quantum = psched_mtu(sch->dev); @@ -450,8 +459,8 @@ opt.perturb_period = q->perturb_period/HZ; opt.limit = SFQ_DEPTH; - opt.divisor = SFQ_HASH_DIVISOR; - opt.flows = SFQ_DEPTH; + opt.divisor = q->max_flows; + opt.flows = q->flows; RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);