From a73ed26bbae7327370c5bd298f07de78df9e3466 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 9 Dec 2011 02:46:45 +0000 Subject: sch_red: generalize accurate MAX_P support to RED/GRED/CHOKE Now RED uses a Q0.32 number to store max_p (max probability), allow RED/GRED/CHOKE to use/report full resolution at config/dump time. Old tc binaries are non aware of new attributes, and still set/get Plog. New tc binary set/get both Plog and max_p for backward compatibility, they display "probability value" if they get max_p from new kernels. # tc -d qdisc show dev ... ... qdisc red 10: parent 1:1 limit 360Kb min 30Kb max 90Kb ecn ewma 5 probability 0.09 Scell_log 15 Make sure we avoid potential divides by 0 in reciprocal_value(), if (max_th - min_th) is big. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/pkt_sched.h | 2 ++ include/net/red.h | 16 +++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index e41e0d4de24b..8786ea741f52 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -216,6 +216,7 @@ enum { TCA_GRED_PARMS, TCA_GRED_STAB, TCA_GRED_DPS, + TCA_GRED_MAX_P, __TCA_GRED_MAX, }; @@ -255,6 +256,7 @@ enum { TCA_CHOKE_UNSPEC, TCA_CHOKE_PARMS, TCA_CHOKE_STAB, + TCA_CHOKE_MAX_P, __TCA_CHOKE_MAX, }; diff --git a/include/net/red.h b/include/net/red.h index 24606b22d01e..ef715a16cce4 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -155,9 +155,10 @@ static inline u32 red_maxp(u8 Plog) static inline void red_set_parms(struct red_parms *p, u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog, - u8 Scell_log, u8 *stab) + u8 Scell_log, u8 *stab, u32 max_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 @@ -173,10 +174,14 @@ static inline void red_set_parms(struct red_parms *p, if (delta < 0) delta = 1; p->qth_delta = delta; - p->max_P = red_maxp(Plog); - p->max_P *= delta; /* max_P = (qth_max-qth_min)/2^Plog */ - - p->max_P_reciprocal = reciprocal_value(p->max_P / delta); + if (!max_P) { + max_P = red_maxp(Plog); + max_P *= delta; /* max_P = (qth_max - qth_min)/2^Plog */ + } + p->max_P = max_P; + max_p_delta = max_P / delta; + max_p_delta = max(max_p_delta, 1U); + p->max_P_reciprocal = reciprocal_value(max_p_delta); /* RED Adaptative target : * [min_th + 0.4*(min_th - max_th), @@ -380,6 +385,7 @@ static inline void red_adaptative_algo(struct red_parms *p) p->max_P = (p->max_P/10)*9; /* maxp = maxp * Beta */ max_p_delta = DIV_ROUND_CLOSEST(p->max_P, p->qth_delta); + max_p_delta = max(max_p_delta, 1U); p->max_P_reciprocal = reciprocal_value(max_p_delta); } #endif -- cgit v1.2.3