]> err.no Git - linux-2.6/commitdiff
[PKT_SCHED]: (G)RED: Introduce hard dropping
authorThomas Graf <tgraf@suug.ch>
Sat, 5 Nov 2005 20:14:28 +0000 (21:14 +0100)
committerThomas Graf <tgr@axs.localdomain>
Sat, 5 Nov 2005 21:02:29 +0000 (22:02 +0100)
Introduces a new flag TC_RED_HARDDROP which specifies that if ECN
marking is enabled packets should still be dropped once the
average queue length exceeds the maximum threshold.

This _may_ help to avoid global synchronisation during small
bursts of peers advertising but not caring about ECN. Use this
option very carefully, it does more harm than good if
(qth_max - qth_min) does not cover at least two average burst
cycles.

The difference to the current behaviour, in which we'd run into
the hard queue limit, is that due to the low pass filter of RED
short bursts are less likely to cause a global synchronisation.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
include/linux/pkt_sched.h
net/sched/sch_gred.c
net/sched/sch_red.c

index 0ebe320223e2b9a974c5d98311e19502f6d4d687..e87b233615b349a4d982174779eaceaa7c1f127f 100644 (file)
@@ -93,6 +93,7 @@ struct tc_fifo_qopt
 /* PRIO section */
 
 #define TCQ_PRIO_BANDS 16
+#define TCQ_MIN_PRIO_BANDS 2
 
 struct tc_prio_qopt
 {
@@ -169,6 +170,7 @@ struct tc_red_qopt
        unsigned char   Scell_log;      /* cell size for idle damping */
        unsigned char   flags;
 #define TC_RED_ECN     1
+#define TC_RED_HARDDROP        2
 };
 
 struct tc_red_xstats
index 079b0a4ea1c2dbc0a3dac2b866f2aab7b8194138..29a2dd9f30296f613123118976c963f557e899d6 100644 (file)
@@ -146,6 +146,11 @@ static inline int gred_use_ecn(struct gred_sched *t)
        return t->red_flags & TC_RED_ECN;
 }
 
+static inline int gred_use_harddrop(struct gred_sched *t)
+{
+       return t->red_flags & TC_RED_HARDDROP;
+}
+
 static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 {
        struct gred_sched_data *q=NULL;
@@ -214,7 +219,8 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 
                case RED_HARD_MARK:
                        sch->qstats.overlimits++;
-                       if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) {
+                       if (gred_use_harddrop(t) || !gred_use_ecn(t) ||
+                           !INET_ECN_set_ce(skb)) {
                                q->stats.forced_drop++;
                                goto congestion_drop;
                        }
index 0d89dee751a945bd33c9b3a3f2aee28eb111bfa7..dccfa44c2d71d3be7d7d766987a7b1d0bdc9977d 100644 (file)
@@ -51,6 +51,11 @@ static inline int red_use_ecn(struct red_sched_data *q)
        return q->flags & TC_RED_ECN;
 }
 
+static inline int red_use_harddrop(struct red_sched_data *q)
+{
+       return q->flags & TC_RED_HARDDROP;
+}
+
 static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 {
        struct red_sched_data *q = qdisc_priv(sch);
@@ -76,7 +81,8 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 
                case RED_HARD_MARK:
                        sch->qstats.overlimits++;
-                       if (!red_use_ecn(q) || !INET_ECN_set_ce(skb)) {
+                       if (red_use_harddrop(q) || !red_use_ecn(q) ||
+                           !INET_ECN_set_ce(skb)) {
                                q->stats.forced_drop++;
                                goto congestion_drop;
                        }