diff options
Diffstat (limited to 'net/sched/act_police.c')
-rw-r--r-- | net/sched/act_police.c | 105 |
1 files changed, 64 insertions, 41 deletions
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index a9de23297d47..823463adbd21 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -22,8 +22,23 @@ | |||
22 | #include <net/act_api.h> | 22 | #include <net/act_api.h> |
23 | #include <net/netlink.h> | 23 | #include <net/netlink.h> |
24 | 24 | ||
25 | #define L2T(p, L) qdisc_l2t((p)->tcfp_R_tab, L) | 25 | struct tcf_police { |
26 | #define L2T_P(p, L) qdisc_l2t((p)->tcfp_P_tab, L) | 26 | struct tcf_common common; |
27 | int tcfp_result; | ||
28 | u32 tcfp_ewma_rate; | ||
29 | s64 tcfp_burst; | ||
30 | u32 tcfp_mtu; | ||
31 | s64 tcfp_toks; | ||
32 | s64 tcfp_ptoks; | ||
33 | s64 tcfp_mtu_ptoks; | ||
34 | s64 tcfp_t_c; | ||
35 | struct psched_ratecfg rate; | ||
36 | bool rate_present; | ||
37 | struct psched_ratecfg peak; | ||
38 | bool peak_present; | ||
39 | }; | ||
40 | #define to_police(pc) \ | ||
41 | container_of(pc, struct tcf_police, common) | ||
27 | 42 | ||
28 | #define POL_TAB_MASK 15 | 43 | #define POL_TAB_MASK 15 |
29 | static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1]; | 44 | static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1]; |
@@ -108,10 +123,6 @@ static void tcf_police_destroy(struct tcf_police *p) | |||
108 | write_unlock_bh(&police_lock); | 123 | write_unlock_bh(&police_lock); |
109 | gen_kill_estimator(&p->tcf_bstats, | 124 | gen_kill_estimator(&p->tcf_bstats, |
110 | &p->tcf_rate_est); | 125 | &p->tcf_rate_est); |
111 | if (p->tcfp_R_tab) | ||
112 | qdisc_put_rtab(p->tcfp_R_tab); | ||
113 | if (p->tcfp_P_tab) | ||
114 | qdisc_put_rtab(p->tcfp_P_tab); | ||
115 | /* | 126 | /* |
116 | * gen_estimator est_timer() might access p->tcf_lock | 127 | * gen_estimator est_timer() might access p->tcf_lock |
117 | * or bstats, wait a RCU grace period before freeing p | 128 | * or bstats, wait a RCU grace period before freeing p |
@@ -130,8 +141,9 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { | |||
130 | [TCA_POLICE_RESULT] = { .type = NLA_U32 }, | 141 | [TCA_POLICE_RESULT] = { .type = NLA_U32 }, |
131 | }; | 142 | }; |
132 | 143 | ||
133 | static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est, | 144 | static int tcf_act_police_locate(struct net *net, struct nlattr *nla, |
134 | struct tc_action *a, int ovr, int bind) | 145 | struct nlattr *est, struct tc_action *a, |
146 | int ovr, int bind) | ||
135 | { | 147 | { |
136 | unsigned int h; | 148 | unsigned int h; |
137 | int ret = 0, err; | 149 | int ret = 0, err; |
@@ -211,26 +223,36 @@ override: | |||
211 | } | 223 | } |
212 | 224 | ||
213 | /* No failure allowed after this point */ | 225 | /* No failure allowed after this point */ |
214 | if (R_tab != NULL) { | 226 | police->tcfp_mtu = parm->mtu; |
215 | qdisc_put_rtab(police->tcfp_R_tab); | 227 | if (police->tcfp_mtu == 0) { |
216 | 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; | ||
217 | } | 238 | } |
218 | if (P_tab != NULL) { | 239 | if (P_tab) { |
219 | qdisc_put_rtab(police->tcfp_P_tab); | 240 | police->peak_present = true; |
220 | 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; | ||
221 | } | 245 | } |
222 | 246 | ||
223 | if (tb[TCA_POLICE_RESULT]) | 247 | if (tb[TCA_POLICE_RESULT]) |
224 | police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]); | 248 | police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]); |
225 | police->tcfp_toks = police->tcfp_burst = parm->burst; | 249 | police->tcfp_burst = PSCHED_TICKS2NS(parm->burst); |
226 | police->tcfp_mtu = parm->mtu; | 250 | police->tcfp_toks = police->tcfp_burst; |
227 | if (police->tcfp_mtu == 0) { | 251 | if (police->peak_present) { |
228 | police->tcfp_mtu = ~0; | 252 | police->tcfp_mtu_ptoks = (s64) psched_l2t_ns(&police->peak, |
229 | if (police->tcfp_R_tab) | 253 | police->tcfp_mtu); |
230 | police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log; | 254 | police->tcfp_ptoks = police->tcfp_mtu_ptoks; |
231 | } | 255 | } |
232 | if (police->tcfp_P_tab) | ||
233 | police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); | ||
234 | police->tcf_action = parm->action; | 256 | police->tcf_action = parm->action; |
235 | 257 | ||
236 | if (tb[TCA_POLICE_AVRATE]) | 258 | if (tb[TCA_POLICE_AVRATE]) |
@@ -240,7 +262,7 @@ override: | |||
240 | if (ret != ACT_P_CREATED) | 262 | if (ret != ACT_P_CREATED) |
241 | return ret; | 263 | return ret; |
242 | 264 | ||
243 | police->tcfp_t_c = psched_get_time(); | 265 | police->tcfp_t_c = ktime_to_ns(ktime_get()); |
244 | police->tcf_index = parm->index ? parm->index : | 266 | police->tcf_index = parm->index ? parm->index : |
245 | tcf_hash_new_index(&police_idx_gen, &police_hash_info); | 267 | tcf_hash_new_index(&police_idx_gen, &police_hash_info); |
246 | h = tcf_hash(police->tcf_index, POL_TAB_MASK); | 268 | h = tcf_hash(police->tcf_index, POL_TAB_MASK); |
@@ -286,9 +308,9 @@ static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, | |||
286 | struct tcf_result *res) | 308 | struct tcf_result *res) |
287 | { | 309 | { |
288 | struct tcf_police *police = a->priv; | 310 | struct tcf_police *police = a->priv; |
289 | psched_time_t now; | 311 | s64 now; |
290 | long toks; | 312 | s64 toks; |
291 | long ptoks = 0; | 313 | s64 ptoks = 0; |
292 | 314 | ||
293 | spin_lock(&police->tcf_lock); | 315 | spin_lock(&police->tcf_lock); |
294 | 316 | ||
@@ -304,24 +326,25 @@ static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, | |||
304 | } | 326 | } |
305 | 327 | ||
306 | if (qdisc_pkt_len(skb) <= police->tcfp_mtu) { | 328 | if (qdisc_pkt_len(skb) <= police->tcfp_mtu) { |
307 | if (police->tcfp_R_tab == NULL) { | 329 | if (!police->rate_present) { |
308 | spin_unlock(&police->tcf_lock); | 330 | spin_unlock(&police->tcf_lock); |
309 | return police->tcfp_result; | 331 | return police->tcfp_result; |
310 | } | 332 | } |
311 | 333 | ||
312 | now = psched_get_time(); | 334 | now = ktime_to_ns(ktime_get()); |
313 | toks = psched_tdiff_bounded(now, police->tcfp_t_c, | 335 | toks = min_t(s64, now - police->tcfp_t_c, |
314 | police->tcfp_burst); | 336 | police->tcfp_burst); |
315 | if (police->tcfp_P_tab) { | 337 | if (police->peak_present) { |
316 | ptoks = toks + police->tcfp_ptoks; | 338 | ptoks = toks + police->tcfp_ptoks; |
317 | if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) | 339 | if (ptoks > police->tcfp_mtu_ptoks) |
318 | ptoks = (long)L2T_P(police, police->tcfp_mtu); | 340 | ptoks = police->tcfp_mtu_ptoks; |
319 | ptoks -= L2T_P(police, qdisc_pkt_len(skb)); | 341 | ptoks -= (s64) psched_l2t_ns(&police->peak, |
342 | qdisc_pkt_len(skb)); | ||
320 | } | 343 | } |
321 | toks += police->tcfp_toks; | 344 | toks += police->tcfp_toks; |
322 | if (toks > (long)police->tcfp_burst) | 345 | if (toks > police->tcfp_burst) |
323 | toks = police->tcfp_burst; | 346 | toks = police->tcfp_burst; |
324 | toks -= L2T(police, qdisc_pkt_len(skb)); | 347 | toks -= (s64) psched_l2t_ns(&police->rate, qdisc_pkt_len(skb)); |
325 | if ((toks|ptoks) >= 0) { | 348 | if ((toks|ptoks) >= 0) { |
326 | police->tcfp_t_c = now; | 349 | police->tcfp_t_c = now; |
327 | police->tcfp_toks = toks; | 350 | police->tcfp_toks = toks; |
@@ -347,15 +370,15 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | |||
347 | .index = police->tcf_index, | 370 | .index = police->tcf_index, |
348 | .action = police->tcf_action, | 371 | .action = police->tcf_action, |
349 | .mtu = police->tcfp_mtu, | 372 | .mtu = police->tcfp_mtu, |
350 | .burst = police->tcfp_burst, | 373 | .burst = PSCHED_NS2TICKS(police->tcfp_burst), |
351 | .refcnt = police->tcf_refcnt - ref, | 374 | .refcnt = police->tcf_refcnt - ref, |
352 | .bindcnt = police->tcf_bindcnt - bind, | 375 | .bindcnt = police->tcf_bindcnt - bind, |
353 | }; | 376 | }; |
354 | 377 | ||
355 | if (police->tcfp_R_tab) | 378 | if (police->rate_present) |
356 | opt.rate = police->tcfp_R_tab->rate; | 379 | opt.rate.rate = psched_ratecfg_getrate(&police->rate); |
357 | if (police->tcfp_P_tab) | 380 | if (police->peak_present) |
358 | opt.peakrate = police->tcfp_P_tab->rate; | 381 | opt.peakrate.rate = psched_ratecfg_getrate(&police->peak); |
359 | if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt)) | 382 | if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt)) |
360 | goto nla_put_failure; | 383 | goto nla_put_failure; |
361 | if (police->tcfp_result && | 384 | if (police->tcfp_result && |