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>
This commit is contained in:
committed by
David S. Miller
parent
71bcb09a57
commit
c1b56878fb
@@ -45,5 +45,6 @@ extern void gen_kill_estimator(struct gnet_stats_basic *bstats,
|
|||||||
extern int gen_replace_estimator(struct gnet_stats_basic *bstats,
|
extern int gen_replace_estimator(struct gnet_stats_basic *bstats,
|
||||||
struct gnet_stats_rate_est *rate_est,
|
struct gnet_stats_rate_est *rate_est,
|
||||||
spinlock_t *stats_lock, struct nlattr *opt);
|
spinlock_t *stats_lock, struct nlattr *opt);
|
||||||
|
extern int gen_estimator_active(const struct gnet_stats_rate_est *rate_est);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -242,6 +242,7 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(gen_new_estimator);
|
||||||
|
|
||||||
static void __gen_kill_estimator(struct rcu_head *head)
|
static void __gen_kill_estimator(struct rcu_head *head)
|
||||||
{
|
{
|
||||||
@@ -275,6 +276,7 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats,
|
|||||||
call_rcu(&e->e_rcu, __gen_kill_estimator);
|
call_rcu(&e->e_rcu, __gen_kill_estimator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(gen_kill_estimator);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gen_replace_estimator - replace rate estimator configuration
|
* gen_replace_estimator - replace rate estimator configuration
|
||||||
@@ -295,8 +297,30 @@ int gen_replace_estimator(struct gnet_stats_basic *bstats,
|
|||||||
gen_kill_estimator(bstats, rate_est);
|
gen_kill_estimator(bstats, rate_est);
|
||||||
return gen_new_estimator(bstats, rate_est, stats_lock, opt);
|
return gen_new_estimator(bstats, rate_est, stats_lock, opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(gen_kill_estimator);
|
|
||||||
EXPORT_SYMBOL(gen_new_estimator);
|
|
||||||
EXPORT_SYMBOL(gen_replace_estimator);
|
EXPORT_SYMBOL(gen_replace_estimator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gen_estimator_active - test if estimator is currently in use
|
||||||
|
* @rate_est: rate estimator statistics
|
||||||
|
*
|
||||||
|
* Returns 1 if estimator is active, and 0 if not.
|
||||||
|
*/
|
||||||
|
int gen_estimator_active(const struct gnet_stats_rate_est *rate_est)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
struct gen_estimator *e;
|
||||||
|
|
||||||
|
ASSERT_RTNL();
|
||||||
|
|
||||||
|
for (idx=0; idx <= EST_MAX_INTERVAL; idx++) {
|
||||||
|
if (!elist[idx].timer.function)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list_for_each_entry(e, &elist[idx].list, list) {
|
||||||
|
if (e->rate_est == rate_est)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(gen_estimator_active);
|
||||||
|
@@ -182,6 +182,12 @@ override:
|
|||||||
R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]);
|
R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]);
|
||||||
if (R_tab == NULL)
|
if (R_tab == NULL)
|
||||||
goto failure;
|
goto failure;
|
||||||
|
|
||||||
|
if (!est && !gen_estimator_active(&police->tcf_rate_est)) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
if (parm->peakrate.rate) {
|
if (parm->peakrate.rate) {
|
||||||
P_tab = qdisc_get_rtab(&parm->peakrate,
|
P_tab = qdisc_get_rtab(&parm->peakrate,
|
||||||
tb[TCA_POLICE_PEAKRATE]);
|
tb[TCA_POLICE_PEAKRATE]);
|
||||||
|
Reference in New Issue
Block a user