aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sched/act_police.c99
1 files changed, 53 insertions, 46 deletions
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 378a6494ba5a..823463adbd21 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -26,20 +26,20 @@ struct tcf_police {
26 struct tcf_common common; 26 struct tcf_common common;
27 int tcfp_result; 27 int tcfp_result;
28 u32 tcfp_ewma_rate; 28 u32 tcfp_ewma_rate;
29 u32 tcfp_burst; 29 s64 tcfp_burst;
30 u32 tcfp_mtu; 30 u32 tcfp_mtu;
31 u32 tcfp_toks; 31 s64 tcfp_toks;
32 u32 tcfp_ptoks; 32 s64 tcfp_ptoks;
33 psched_time_t tcfp_t_c; 33 s64 tcfp_mtu_ptoks;
34 struct qdisc_rate_table *tcfp_R_tab; 34 s64 tcfp_t_c;
35 struct qdisc_rate_table *tcfp_P_tab; 35 struct psched_ratecfg rate;
36 bool rate_present;
37 struct psched_ratecfg peak;
38 bool peak_present;
36}; 39};
37#define to_police(pc) \ 40#define to_police(pc) \
38 container_of(pc, struct tcf_police, common) 41 container_of(pc, struct tcf_police, common)
39 42
40#define L2T(p, L) qdisc_l2t((p)->tcfp_R_tab, L)
41#define L2T_P(p, L) qdisc_l2t((p)->tcfp_P_tab, L)
42
43#define POL_TAB_MASK 15 43#define POL_TAB_MASK 15
44static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1]; 44static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1];
45static u32 police_idx_gen; 45static u32 police_idx_gen;
@@ -123,10 +123,6 @@ static void tcf_police_destroy(struct tcf_police *p)
123 write_unlock_bh(&police_lock); 123 write_unlock_bh(&police_lock);
124 gen_kill_estimator(&p->tcf_bstats, 124 gen_kill_estimator(&p->tcf_bstats,
125 &p->tcf_rate_est); 125 &p->tcf_rate_est);
126 if (p->tcfp_R_tab)
127 qdisc_put_rtab(p->tcfp_R_tab);
128 if (p->tcfp_P_tab)
129 qdisc_put_rtab(p->tcfp_P_tab);
130 /* 126 /*
131 * gen_estimator est_timer() might access p->tcf_lock 127 * gen_estimator est_timer() might access p->tcf_lock
132 * or bstats, wait a RCU grace period before freeing p 128 * or bstats, wait a RCU grace period before freeing p
@@ -227,26 +223,36 @@ override:
227 } 223 }
228 224
229 /* No failure allowed after this point */ 225 /* No failure allowed after this point */
230 if (R_tab != NULL) { 226 police->tcfp_mtu = parm->mtu;
231 qdisc_put_rtab(police->tcfp_R_tab); 227 if (police->tcfp_mtu == 0) {
232 police->tcfp_R_tab = R_tab; 228 police->tcfp_mtu = ~0;
229 if (R_tab)
230 police->tcfp_mtu = 255 << R_tab->rate.cell_log;
231 }
232 if (R_tab) {
233 police->rate_present = true;
234 psched_ratecfg_precompute(&police->rate, R_tab->rate.rate);
235 qdisc_put_rtab(R_tab);
236 } else {
237 police->rate_present = false;
233 } 238 }
234 if (P_tab != NULL) { 239 if (P_tab) {
235 qdisc_put_rtab(police->tcfp_P_tab); 240 police->peak_present = true;
236 police->tcfp_P_tab = P_tab; 241 psched_ratecfg_precompute(&police->peak, P_tab->rate.rate);
242 qdisc_put_rtab(P_tab);
243 } else {
244 police->peak_present = false;
237 } 245 }
238 246
239 if (tb[TCA_POLICE_RESULT]) 247 if (tb[TCA_POLICE_RESULT])
240 police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]); 248 police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
241 police->tcfp_toks = police->tcfp_burst = parm->burst; 249 police->tcfp_burst = PSCHED_TICKS2NS(parm->burst);
242 police->tcfp_mtu = parm->mtu; 250 police->tcfp_toks = police->tcfp_burst;
243 if (police->tcfp_mtu == 0) { 251 if (police->peak_present) {
244 police->tcfp_mtu = ~0; 252 police->tcfp_mtu_ptoks = (s64) psched_l2t_ns(&police->peak,
245 if (police->tcfp_R_tab) 253 police->tcfp_mtu);
246 police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log; 254 police->tcfp_ptoks = police->tcfp_mtu_ptoks;
247 } 255 }
248 if (police->tcfp_P_tab)
249 police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
250 police->tcf_action = parm->action; 256 police->tcf_action = parm->action;
251 257
252 if (tb[TCA_POLICE_AVRATE]) 258 if (tb[TCA_POLICE_AVRATE])
@@ -256,7 +262,7 @@ override:
256 if (ret != ACT_P_CREATED) 262 if (ret != ACT_P_CREATED)
257 return ret; 263 return ret;
258 264
259 police->tcfp_t_c = psched_get_time(); 265 police->tcfp_t_c = ktime_to_ns(ktime_get());
260 police->tcf_index = parm->index ? parm->index : 266 police->tcf_index = parm->index ? parm->index :
261 tcf_hash_new_index(&police_idx_gen, &police_hash_info); 267 tcf_hash_new_index(&police_idx_gen, &police_hash_info);
262 h = tcf_hash(police->tcf_index, POL_TAB_MASK); 268 h = tcf_hash(police->tcf_index, POL_TAB_MASK);
@@ -302,9 +308,9 @@ static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
302 struct tcf_result *res) 308 struct tcf_result *res)
303{ 309{
304 struct tcf_police *police = a->priv; 310 struct tcf_police *police = a->priv;
305 psched_time_t now; 311 s64 now;
306 long toks; 312 s64 toks;
307 long ptoks = 0; 313 s64 ptoks = 0;
308 314
309 spin_lock(&police->tcf_lock); 315 spin_lock(&police->tcf_lock);
310 316
@@ -320,24 +326,25 @@ static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
320 } 326 }
321 327
322 if (qdisc_pkt_len(skb) <= police->tcfp_mtu) { 328 if (qdisc_pkt_len(skb) <= police->tcfp_mtu) {
323 if (police->tcfp_R_tab == NULL) { 329 if (!police->rate_present) {
324 spin_unlock(&police->tcf_lock); 330 spin_unlock(&police->tcf_lock);
325 return police->tcfp_result; 331 return police->tcfp_result;
326 } 332 }
327 333
328 now = psched_get_time(); 334 now = ktime_to_ns(ktime_get());
329 toks = psched_tdiff_bounded(now, police->tcfp_t_c, 335 toks = min_t(s64, now - police->tcfp_t_c,
330 police->tcfp_burst); 336 police->tcfp_burst);
331 if (police->tcfp_P_tab) { 337 if (police->peak_present) {
332 ptoks = toks + police->tcfp_ptoks; 338 ptoks = toks + police->tcfp_ptoks;
333 if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) 339 if (ptoks > police->tcfp_mtu_ptoks)
334 ptoks = (long)L2T_P(police, police->tcfp_mtu); 340 ptoks = police->tcfp_mtu_ptoks;
335 ptoks -= L2T_P(police, qdisc_pkt_len(skb)); 341 ptoks -= (s64) psched_l2t_ns(&police->peak,
342 qdisc_pkt_len(skb));
336 } 343 }
337 toks += police->tcfp_toks; 344 toks += police->tcfp_toks;
338 if (toks > (long)police->tcfp_burst) 345 if (toks > police->tcfp_burst)
339 toks = police->tcfp_burst; 346 toks = police->tcfp_burst;
340 toks -= L2T(police, qdisc_pkt_len(skb)); 347 toks -= (s64) psched_l2t_ns(&police->rate, qdisc_pkt_len(skb));
341 if ((toks|ptoks) >= 0) { 348 if ((toks|ptoks) >= 0) {
342 police->tcfp_t_c = now; 349 police->tcfp_t_c = now;
343 police->tcfp_toks = toks; 350 police->tcfp_toks = toks;
@@ -363,15 +370,15 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
363 .index = police->tcf_index, 370 .index = police->tcf_index,
364 .action = police->tcf_action, 371 .action = police->tcf_action,
365 .mtu = police->tcfp_mtu, 372 .mtu = police->tcfp_mtu,
366 .burst = police->tcfp_burst, 373 .burst = PSCHED_NS2TICKS(police->tcfp_burst),
367 .refcnt = police->tcf_refcnt - ref, 374 .refcnt = police->tcf_refcnt - ref,
368 .bindcnt = police->tcf_bindcnt - bind, 375 .bindcnt = police->tcf_bindcnt - bind,
369 }; 376 };
370 377
371 if (police->tcfp_R_tab) 378 if (police->rate_present)
372 opt.rate = police->tcfp_R_tab->rate; 379 opt.rate.rate = psched_ratecfg_getrate(&police->rate);
373 if (police->tcfp_P_tab) 380 if (police->peak_present)
374 opt.peakrate = police->tcfp_P_tab->rate; 381 opt.peakrate.rate = psched_ratecfg_getrate(&police->peak);
375 if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt)) 382 if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt))
376 goto nla_put_failure; 383 goto nla_put_failure;
377 if (police->tcfp_result && 384 if (police->tcfp_result &&