diff options
author | Stephen Hemminger <shemminger@vyatta.com> | 2008-11-26 00:14:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-26 00:14:06 -0500 |
commit | c1b56878fb68e9c14070939ea4537ad4db79ffae (patch) | |
tree | 589f890f81e075380493905509244a0970d942f8 | |
parent | 71bcb09a57894fa35591ce93dd972065eeecb63a (diff) |
tc: policing requires a rate estimator
Found that while trying average rate policing, it was possible to
request average rate policing without a rate estimator. This results
in no policing which is harmless but incorrect.
Since policing could be setup in two steps, need to check
in the kernel.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/gen_stats.h | 1 | ||||
-rw-r--r-- | net/core/gen_estimator.c | 30 | ||||
-rw-r--r-- | net/sched/act_police.c | 6 |
3 files changed, 34 insertions, 3 deletions
diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h index 8cd8185fa2ed..dcf5bfa7d4f1 100644 --- a/include/net/gen_stats.h +++ b/include/net/gen_stats.h | |||
@@ -45,5 +45,6 @@ extern void gen_kill_estimator(struct gnet_stats_basic *bstats, | |||
45 | extern int gen_replace_estimator(struct gnet_stats_basic *bstats, | 45 | extern int gen_replace_estimator(struct gnet_stats_basic *bstats, |
46 | struct gnet_stats_rate_est *rate_est, | 46 | struct gnet_stats_rate_est *rate_est, |
47 | spinlock_t *stats_lock, struct nlattr *opt); | 47 | spinlock_t *stats_lock, struct nlattr *opt); |
48 | extern int gen_estimator_active(const struct gnet_stats_rate_est *rate_est); | ||
48 | 49 | ||
49 | #endif | 50 | #endif |
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 80aa160877e9..3885550f0187 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
@@ -242,6 +242,7 @@ int gen_new_estimator(struct gnet_stats_basic *bstats, | |||
242 | 242 | ||
243 | return 0; | 243 | return 0; |
244 | } | 244 | } |
245 | EXPORT_SYMBOL(gen_new_estimator); | ||
245 | 246 | ||
246 | static void __gen_kill_estimator(struct rcu_head *head) | 247 | static void __gen_kill_estimator(struct rcu_head *head) |
247 | { | 248 | { |
@@ -275,6 +276,7 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats, | |||
275 | call_rcu(&e->e_rcu, __gen_kill_estimator); | 276 | call_rcu(&e->e_rcu, __gen_kill_estimator); |
276 | } | 277 | } |
277 | } | 278 | } |
279 | EXPORT_SYMBOL(gen_kill_estimator); | ||
278 | 280 | ||
279 | /** | 281 | /** |
280 | * gen_replace_estimator - replace rate estimator configuration | 282 | * gen_replace_estimator - replace rate estimator configuration |
@@ -295,8 +297,30 @@ int gen_replace_estimator(struct gnet_stats_basic *bstats, | |||
295 | gen_kill_estimator(bstats, rate_est); | 297 | gen_kill_estimator(bstats, rate_est); |
296 | return gen_new_estimator(bstats, rate_est, stats_lock, opt); | 298 | return gen_new_estimator(bstats, rate_est, stats_lock, opt); |
297 | } | 299 | } |
300 | EXPORT_SYMBOL(gen_replace_estimator); | ||
301 | |||
302 | /** | ||
303 | * gen_estimator_active - test if estimator is currently in use | ||
304 | * @rate_est: rate estimator statistics | ||
305 | * | ||
306 | * Returns 1 if estimator is active, and 0 if not. | ||
307 | */ | ||
308 | int gen_estimator_active(const struct gnet_stats_rate_est *rate_est) | ||
309 | { | ||
310 | int idx; | ||
311 | struct gen_estimator *e; | ||
298 | 312 | ||
313 | ASSERT_RTNL(); | ||
299 | 314 | ||
300 | EXPORT_SYMBOL(gen_kill_estimator); | 315 | for (idx=0; idx <= EST_MAX_INTERVAL; idx++) { |
301 | EXPORT_SYMBOL(gen_new_estimator); | 316 | if (!elist[idx].timer.function) |
302 | EXPORT_SYMBOL(gen_replace_estimator); | 317 | continue; |
318 | |||
319 | list_for_each_entry(e, &elist[idx].list, list) { | ||
320 | if (e->rate_est == rate_est) | ||
321 | return 1; | ||
322 | } | ||
323 | } | ||
324 | return 0; | ||
325 | } | ||
326 | EXPORT_SYMBOL(gen_estimator_active); | ||
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index e19a0261144a..c39f60cea6ee 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -182,6 +182,12 @@ override: | |||
182 | R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); | 182 | R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); |
183 | if (R_tab == NULL) | 183 | if (R_tab == NULL) |
184 | goto failure; | 184 | goto failure; |
185 | |||
186 | if (!est && !gen_estimator_active(&police->tcf_rate_est)) { | ||
187 | err = -EINVAL; | ||
188 | goto failure; | ||
189 | } | ||
190 | |||
185 | if (parm->peakrate.rate) { | 191 | if (parm->peakrate.rate) { |
186 | P_tab = qdisc_get_rtab(&parm->peakrate, | 192 | P_tab = qdisc_get_rtab(&parm->peakrate, |
187 | tb[TCA_POLICE_PEAKRATE]); | 193 | tb[TCA_POLICE_PEAKRATE]); |