|
@@ -137,7 +137,9 @@ struct red_parms {
|
|
|
u8 Wlog; /* log(W) */
|
|
|
u8 Plog; /* random number bits */
|
|
|
u8 Stab[RED_STAB_SIZE];
|
|
|
+};
|
|
|
|
|
|
+struct red_vars {
|
|
|
/* Variables */
|
|
|
int qcount; /* Number of packets since last random
|
|
|
number generation */
|
|
@@ -152,6 +154,16 @@ static inline u32 red_maxp(u8 Plog)
|
|
|
return Plog < 32 ? (~0U >> Plog) : ~0U;
|
|
|
}
|
|
|
|
|
|
+static inline void red_set_vars(struct red_vars *v)
|
|
|
+{
|
|
|
+ /* Reset average queue length, the value is strictly bound
|
|
|
+ * to the parameters below, reseting hurts a bit but leaving
|
|
|
+ * it might result in an unreasonable qavg for a while. --TGR
|
|
|
+ */
|
|
|
+ v->qavg = 0;
|
|
|
+
|
|
|
+ v->qcount = -1;
|
|
|
+}
|
|
|
|
|
|
static inline void red_set_parms(struct red_parms *p,
|
|
|
u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog,
|
|
@@ -160,13 +172,6 @@ static inline void red_set_parms(struct red_parms *p,
|
|
|
int delta = qth_max - qth_min;
|
|
|
u32 max_p_delta;
|
|
|
|
|
|
- /* Reset average queue length, the value is strictly bound
|
|
|
- * to the parameters below, reseting hurts a bit but leaving
|
|
|
- * it might result in an unreasonable qavg for a while. --TGR
|
|
|
- */
|
|
|
- p->qavg = 0;
|
|
|
-
|
|
|
- p->qcount = -1;
|
|
|
p->qth_min = qth_min << Wlog;
|
|
|
p->qth_max = qth_max << Wlog;
|
|
|
p->Wlog = Wlog;
|
|
@@ -197,31 +202,32 @@ static inline void red_set_parms(struct red_parms *p,
|
|
|
memcpy(p->Stab, stab, sizeof(p->Stab));
|
|
|
}
|
|
|
|
|
|
-static inline int red_is_idling(const struct red_parms *p)
|
|
|
+static inline int red_is_idling(const struct red_vars *v)
|
|
|
{
|
|
|
- return p->qidlestart.tv64 != 0;
|
|
|
+ return v->qidlestart.tv64 != 0;
|
|
|
}
|
|
|
|
|
|
-static inline void red_start_of_idle_period(struct red_parms *p)
|
|
|
+static inline void red_start_of_idle_period(struct red_vars *v)
|
|
|
{
|
|
|
- p->qidlestart = ktime_get();
|
|
|
+ v->qidlestart = ktime_get();
|
|
|
}
|
|
|
|
|
|
-static inline void red_end_of_idle_period(struct red_parms *p)
|
|
|
+static inline void red_end_of_idle_period(struct red_vars *v)
|
|
|
{
|
|
|
- p->qidlestart.tv64 = 0;
|
|
|
+ v->qidlestart.tv64 = 0;
|
|
|
}
|
|
|
|
|
|
-static inline void red_restart(struct red_parms *p)
|
|
|
+static inline void red_restart(struct red_vars *v)
|
|
|
{
|
|
|
- red_end_of_idle_period(p);
|
|
|
- p->qavg = 0;
|
|
|
- p->qcount = -1;
|
|
|
+ red_end_of_idle_period(v);
|
|
|
+ v->qavg = 0;
|
|
|
+ v->qcount = -1;
|
|
|
}
|
|
|
|
|
|
-static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms *p)
|
|
|
+static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms *p,
|
|
|
+ const struct red_vars *v)
|
|
|
{
|
|
|
- s64 delta = ktime_us_delta(ktime_get(), p->qidlestart);
|
|
|
+ s64 delta = ktime_us_delta(ktime_get(), v->qidlestart);
|
|
|
long us_idle = min_t(s64, delta, p->Scell_max);
|
|
|
int shift;
|
|
|
|
|
@@ -248,7 +254,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms
|
|
|
shift = p->Stab[(us_idle >> p->Scell_log) & RED_STAB_MASK];
|
|
|
|
|
|
if (shift)
|
|
|
- return p->qavg >> shift;
|
|
|
+ return v->qavg >> shift;
|
|
|
else {
|
|
|
/* Approximate initial part of exponent with linear function:
|
|
|
*
|
|
@@ -257,16 +263,17 @@ static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms
|
|
|
* Seems, it is the best solution to
|
|
|
* problem of too coarse exponent tabulation.
|
|
|
*/
|
|
|
- us_idle = (p->qavg * (u64)us_idle) >> p->Scell_log;
|
|
|
+ us_idle = (v->qavg * (u64)us_idle) >> p->Scell_log;
|
|
|
|
|
|
- if (us_idle < (p->qavg >> 1))
|
|
|
- return p->qavg - us_idle;
|
|
|
+ if (us_idle < (v->qavg >> 1))
|
|
|
+ return v->qavg - us_idle;
|
|
|
else
|
|
|
- return p->qavg >> 1;
|
|
|
+ return v->qavg >> 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p,
|
|
|
+ const struct red_vars *v,
|
|
|
unsigned int backlog)
|
|
|
{
|
|
|
/*
|
|
@@ -278,16 +285,17 @@ static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p
|
|
|
*
|
|
|
* --ANK (980924)
|
|
|
*/
|
|
|
- return p->qavg + (backlog - (p->qavg >> p->Wlog));
|
|
|
+ return v->qavg + (backlog - (v->qavg >> p->Wlog));
|
|
|
}
|
|
|
|
|
|
static inline unsigned long red_calc_qavg(const struct red_parms *p,
|
|
|
+ const struct red_vars *v,
|
|
|
unsigned int backlog)
|
|
|
{
|
|
|
- if (!red_is_idling(p))
|
|
|
- return red_calc_qavg_no_idle_time(p, backlog);
|
|
|
+ if (!red_is_idling(v))
|
|
|
+ return red_calc_qavg_no_idle_time(p, v, backlog);
|
|
|
else
|
|
|
- return red_calc_qavg_from_idle_time(p);
|
|
|
+ return red_calc_qavg_from_idle_time(p, v);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -296,7 +304,9 @@ static inline u32 red_random(const struct red_parms *p)
|
|
|
return reciprocal_divide(net_random(), p->max_P_reciprocal);
|
|
|
}
|
|
|
|
|
|
-static inline int red_mark_probability(const struct red_parms *p, unsigned long qavg)
|
|
|
+static inline int red_mark_probability(const struct red_parms *p,
|
|
|
+ const struct red_vars *v,
|
|
|
+ unsigned long qavg)
|
|
|
{
|
|
|
/* The formula used below causes questions.
|
|
|
|
|
@@ -314,7 +324,7 @@ static inline int red_mark_probability(const struct red_parms *p, unsigned long
|
|
|
|
|
|
Any questions? --ANK (980924)
|
|
|
*/
|
|
|
- return !(((qavg - p->qth_min) >> p->Wlog) * p->qcount < p->qR);
|
|
|
+ return !(((qavg - p->qth_min) >> p->Wlog) * v->qcount < v->qR);
|
|
|
}
|
|
|
|
|
|
enum {
|
|
@@ -323,7 +333,7 @@ enum {
|
|
|
RED_ABOVE_MAX_TRESH,
|
|
|
};
|
|
|
|
|
|
-static inline int red_cmp_thresh(struct red_parms *p, unsigned long qavg)
|
|
|
+static inline int red_cmp_thresh(const struct red_parms *p, unsigned long qavg)
|
|
|
{
|
|
|
if (qavg < p->qth_min)
|
|
|
return RED_BELOW_MIN_THRESH;
|
|
@@ -339,27 +349,29 @@ enum {
|
|
|
RED_HARD_MARK,
|
|
|
};
|
|
|
|
|
|
-static inline int red_action(struct red_parms *p, unsigned long qavg)
|
|
|
+static inline int red_action(const struct red_parms *p,
|
|
|
+ struct red_vars *v,
|
|
|
+ unsigned long qavg)
|
|
|
{
|
|
|
switch (red_cmp_thresh(p, qavg)) {
|
|
|
case RED_BELOW_MIN_THRESH:
|
|
|
- p->qcount = -1;
|
|
|
+ v->qcount = -1;
|
|
|
return RED_DONT_MARK;
|
|
|
|
|
|
case RED_BETWEEN_TRESH:
|
|
|
- if (++p->qcount) {
|
|
|
- if (red_mark_probability(p, qavg)) {
|
|
|
- p->qcount = 0;
|
|
|
- p->qR = red_random(p);
|
|
|
+ if (++v->qcount) {
|
|
|
+ if (red_mark_probability(p, v, qavg)) {
|
|
|
+ v->qcount = 0;
|
|
|
+ v->qR = red_random(p);
|
|
|
return RED_PROB_MARK;
|
|
|
}
|
|
|
} else
|
|
|
- p->qR = red_random(p);
|
|
|
+ v->qR = red_random(p);
|
|
|
|
|
|
return RED_DONT_MARK;
|
|
|
|
|
|
case RED_ABOVE_MAX_TRESH:
|
|
|
- p->qcount = -1;
|
|
|
+ v->qcount = -1;
|
|
|
return RED_HARD_MARK;
|
|
|
}
|
|
|
|
|
@@ -367,14 +379,14 @@ static inline int red_action(struct red_parms *p, unsigned long qavg)
|
|
|
return RED_DONT_MARK;
|
|
|
}
|
|
|
|
|
|
-static inline void red_adaptative_algo(struct red_parms *p)
|
|
|
+static inline void red_adaptative_algo(struct red_parms *p, struct red_vars *v)
|
|
|
{
|
|
|
unsigned long qavg;
|
|
|
u32 max_p_delta;
|
|
|
|
|
|
- qavg = p->qavg;
|
|
|
- if (red_is_idling(p))
|
|
|
- qavg = red_calc_qavg_from_idle_time(p);
|
|
|
+ qavg = v->qavg;
|
|
|
+ if (red_is_idling(v))
|
|
|
+ qavg = red_calc_qavg_from_idle_time(p, v);
|
|
|
|
|
|
/* p->qavg is fixed point number with point at Wlog */
|
|
|
qavg >>= p->Wlog;
|