act_police.c (93be42f9173bbc133bd72915b658394308437d00) | act_police.c (2d550dbad83c88fc7cb594a1803e77457fe625f9) |
---|---|
1/* 2 * net/sched/act_police.c Input police filter 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * --- 8 unchanged lines hidden (view full) --- 17#include <linux/errno.h> 18#include <linux/skbuff.h> 19#include <linux/rtnetlink.h> 20#include <linux/init.h> 21#include <linux/slab.h> 22#include <net/act_api.h> 23#include <net/netlink.h> 24 | 1/* 2 * net/sched/act_police.c Input police filter 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * --- 8 unchanged lines hidden (view full) --- 17#include <linux/errno.h> 18#include <linux/skbuff.h> 19#include <linux/rtnetlink.h> 20#include <linux/init.h> 21#include <linux/slab.h> 22#include <net/act_api.h> 23#include <net/netlink.h> 24 |
25struct tcf_police { 26 struct tc_action common; | 25struct tcf_police_params { |
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; | 26 int tcfp_result; 27 u32 tcfp_ewma_rate; 28 s64 tcfp_burst; 29 u32 tcfp_mtu; 30 s64 tcfp_toks; 31 s64 tcfp_ptoks; 32 s64 tcfp_mtu_ptoks; 33 s64 tcfp_t_c; 34 struct psched_ratecfg rate; 35 bool rate_present; 36 struct psched_ratecfg peak; 37 bool peak_present; |
38 struct rcu_head rcu; |
|
39}; 40 | 39}; 40 |
41struct tcf_police { 42 struct tc_action common; 43 struct tcf_police_params __rcu *params; 44}; 45 |
|
41#define to_police(pc) ((struct tcf_police *)pc) 42 43/* old policer structure from before tc actions */ 44struct tc_police_compat { 45 u32 index; 46 int action; 47 u32 limit; 48 u32 burst; --- 30 unchanged lines hidden (view full) --- 79 struct netlink_ext_ack *extack) 80{ 81 int ret = 0, err; 82 struct nlattr *tb[TCA_POLICE_MAX + 1]; 83 struct tc_police *parm; 84 struct tcf_police *police; 85 struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; 86 struct tc_action_net *tn = net_generic(net, police_net_id); | 46#define to_police(pc) ((struct tcf_police *)pc) 47 48/* old policer structure from before tc actions */ 49struct tc_police_compat { 50 u32 index; 51 int action; 52 u32 limit; 53 u32 burst; --- 30 unchanged lines hidden (view full) --- 84 struct netlink_ext_ack *extack) 85{ 86 int ret = 0, err; 87 struct nlattr *tb[TCA_POLICE_MAX + 1]; 88 struct tc_police *parm; 89 struct tcf_police *police; 90 struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; 91 struct tc_action_net *tn = net_generic(net, police_net_id); |
92 struct tcf_police_params *new; |
|
87 bool exists = false; 88 int size; 89 90 if (nla == NULL) 91 return -EINVAL; 92 93 err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy, NULL); 94 if (err < 0) --- 51 unchanged lines hidden (view full) --- 146 goto failure; 147 } else if (tb[TCA_POLICE_AVRATE] && 148 (ret == ACT_P_CREATED || 149 !gen_estimator_active(&police->tcf_rate_est))) { 150 err = -EINVAL; 151 goto failure; 152 } 153 | 93 bool exists = false; 94 int size; 95 96 if (nla == NULL) 97 return -EINVAL; 98 99 err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy, NULL); 100 if (err < 0) --- 51 unchanged lines hidden (view full) --- 152 goto failure; 153 } else if (tb[TCA_POLICE_AVRATE] && 154 (ret == ACT_P_CREATED || 155 !gen_estimator_active(&police->tcf_rate_est))) { 156 err = -EINVAL; 157 goto failure; 158 } 159 |
154 spin_lock_bh(&police->tcf_lock); | 160 new = kzalloc(sizeof(*new), GFP_KERNEL); 161 if (unlikely(!new)) { 162 err = -ENOMEM; 163 goto failure; 164 } 165 |
155 /* No failure allowed after this point */ | 166 /* No failure allowed after this point */ |
156 police->tcfp_mtu = parm->mtu; 157 if (police->tcfp_mtu == 0) { 158 police->tcfp_mtu = ~0; | 167 new->tcfp_mtu = parm->mtu; 168 if (!new->tcfp_mtu) { 169 new->tcfp_mtu = ~0; |
159 if (R_tab) | 170 if (R_tab) |
160 police->tcfp_mtu = 255 << R_tab->rate.cell_log; | 171 new->tcfp_mtu = 255 << R_tab->rate.cell_log; |
161 } 162 if (R_tab) { | 172 } 173 if (R_tab) { |
163 police->rate_present = true; 164 psched_ratecfg_precompute(&police->rate, &R_tab->rate, 0); | 174 new->rate_present = true; 175 psched_ratecfg_precompute(&new->rate, &R_tab->rate, 0); |
165 qdisc_put_rtab(R_tab); 166 } else { | 176 qdisc_put_rtab(R_tab); 177 } else { |
167 police->rate_present = false; | 178 new->rate_present = false; |
168 } 169 if (P_tab) { | 179 } 180 if (P_tab) { |
170 police->peak_present = true; 171 psched_ratecfg_precompute(&police->peak, &P_tab->rate, 0); | 181 new->peak_present = true; 182 psched_ratecfg_precompute(&new->peak, &P_tab->rate, 0); |
172 qdisc_put_rtab(P_tab); 173 } else { | 183 qdisc_put_rtab(P_tab); 184 } else { |
174 police->peak_present = false; | 185 new->peak_present = false; |
175 } 176 177 if (tb[TCA_POLICE_RESULT]) | 186 } 187 188 if (tb[TCA_POLICE_RESULT]) |
178 police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]); 179 police->tcfp_burst = PSCHED_TICKS2NS(parm->burst); 180 police->tcfp_toks = police->tcfp_burst; 181 if (police->peak_present) { 182 police->tcfp_mtu_ptoks = (s64) psched_l2t_ns(&police->peak, 183 police->tcfp_mtu); 184 police->tcfp_ptoks = police->tcfp_mtu_ptoks; | 189 new->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]); 190 new->tcfp_burst = PSCHED_TICKS2NS(parm->burst); 191 new->tcfp_toks = new->tcfp_burst; 192 if (new->peak_present) { 193 new->tcfp_mtu_ptoks = (s64)psched_l2t_ns(&new->peak, 194 new->tcfp_mtu); 195 new->tcfp_ptoks = new->tcfp_mtu_ptoks; |
185 } | 196 } |
186 police->tcf_action = parm->action; | |
187 188 if (tb[TCA_POLICE_AVRATE]) | 197 198 if (tb[TCA_POLICE_AVRATE]) |
189 police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]); | 199 new->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]); |
190 | 200 |
201 spin_lock_bh(&police->tcf_lock); 202 new->tcfp_t_c = ktime_get_ns(); 203 police->tcf_action = parm->action; 204 rcu_swap_protected(police->params, 205 new, 206 lockdep_is_held(&police->tcf_lock)); |
|
191 spin_unlock_bh(&police->tcf_lock); | 207 spin_unlock_bh(&police->tcf_lock); |
192 if (ret != ACT_P_CREATED) 193 return ret; | |
194 | 208 |
195 police->tcfp_t_c = ktime_get_ns(); 196 tcf_idr_insert(tn, *a); | 209 if (new) 210 kfree_rcu(new, rcu); |
197 | 211 |
212 if (ret == ACT_P_CREATED) 213 tcf_idr_insert(tn, *a); |
|
198 return ret; 199 200failure: 201 qdisc_put_rtab(P_tab); 202 qdisc_put_rtab(R_tab); 203 tcf_idr_release(*a, bind); 204 return err; 205} 206 207static int tcf_police_act(struct sk_buff *skb, const struct tc_action *a, 208 struct tcf_result *res) 209{ 210 struct tcf_police *police = to_police(a); | 214 return ret; 215 216failure: 217 qdisc_put_rtab(P_tab); 218 qdisc_put_rtab(R_tab); 219 tcf_idr_release(*a, bind); 220 return err; 221} 222 223static int tcf_police_act(struct sk_buff *skb, const struct tc_action *a, 224 struct tcf_result *res) 225{ 226 struct tcf_police *police = to_police(a); |
227 struct tcf_police_params *p; |
|
211 s64 now, toks, ptoks = 0; 212 int ret; 213 214 tcf_lastuse_update(&police->tcf_tm); 215 bstats_cpu_update(this_cpu_ptr(police->common.cpu_bstats), skb); 216 | 228 s64 now, toks, ptoks = 0; 229 int ret; 230 231 tcf_lastuse_update(&police->tcf_tm); 232 bstats_cpu_update(this_cpu_ptr(police->common.cpu_bstats), skb); 233 |
217 spin_lock(&police->tcf_lock); 218 if (police->tcfp_ewma_rate) { | 234 ret = READ_ONCE(police->tcf_action); 235 p = rcu_dereference_bh(police->params); 236 237 if (p->tcfp_ewma_rate) { |
219 struct gnet_stats_rate_est64 sample; 220 221 if (!gen_estimator_read(&police->tcf_rate_est, &sample) || | 238 struct gnet_stats_rate_est64 sample; 239 240 if (!gen_estimator_read(&police->tcf_rate_est, &sample) || |
222 sample.bps >= police->tcfp_ewma_rate) { 223 ret = police->tcf_action; | 241 sample.bps >= p->tcfp_ewma_rate) |
224 goto inc_overlimits; | 242 goto inc_overlimits; |
225 } | |
226 } 227 | 243 } 244 |
228 if (qdisc_pkt_len(skb) <= police->tcfp_mtu) { 229 if (!police->rate_present) { 230 ret = police->tcfp_result; 231 goto unlock; | 245 if (qdisc_pkt_len(skb) <= p->tcfp_mtu) { 246 if (!p->rate_present) { 247 ret = p->tcfp_result; 248 goto end; |
232 } 233 234 now = ktime_get_ns(); | 249 } 250 251 now = ktime_get_ns(); |
235 toks = min_t(s64, now - police->tcfp_t_c, 236 police->tcfp_burst); 237 if (police->peak_present) { 238 ptoks = toks + police->tcfp_ptoks; 239 if (ptoks > police->tcfp_mtu_ptoks) 240 ptoks = police->tcfp_mtu_ptoks; 241 ptoks -= (s64) psched_l2t_ns(&police->peak, 242 qdisc_pkt_len(skb)); | 252 toks = min_t(s64, now - p->tcfp_t_c, p->tcfp_burst); 253 if (p->peak_present) { 254 ptoks = toks + p->tcfp_ptoks; 255 if (ptoks > p->tcfp_mtu_ptoks) 256 ptoks = p->tcfp_mtu_ptoks; 257 ptoks -= (s64)psched_l2t_ns(&p->peak, 258 qdisc_pkt_len(skb)); |
243 } | 259 } |
244 toks += police->tcfp_toks; 245 if (toks > police->tcfp_burst) 246 toks = police->tcfp_burst; 247 toks -= (s64) psched_l2t_ns(&police->rate, qdisc_pkt_len(skb)); | 260 toks += p->tcfp_toks; 261 if (toks > p->tcfp_burst) 262 toks = p->tcfp_burst; 263 toks -= (s64)psched_l2t_ns(&p->rate, qdisc_pkt_len(skb)); |
248 if ((toks|ptoks) >= 0) { | 264 if ((toks|ptoks) >= 0) { |
249 police->tcfp_t_c = now; 250 police->tcfp_toks = toks; 251 police->tcfp_ptoks = ptoks; 252 ret = police->tcfp_result; | 265 p->tcfp_t_c = now; 266 p->tcfp_toks = toks; 267 p->tcfp_ptoks = ptoks; 268 ret = p->tcfp_result; |
253 goto inc_drops; 254 } 255 } | 269 goto inc_drops; 270 } 271 } |
256 ret = police->tcf_action; | |
257 258inc_overlimits: 259 qstats_overlimit_inc(this_cpu_ptr(police->common.cpu_qstats)); 260inc_drops: 261 if (ret == TC_ACT_SHOT) 262 qstats_drop_inc(this_cpu_ptr(police->common.cpu_qstats)); | 272 273inc_overlimits: 274 qstats_overlimit_inc(this_cpu_ptr(police->common.cpu_qstats)); 275inc_drops: 276 if (ret == TC_ACT_SHOT) 277 qstats_drop_inc(this_cpu_ptr(police->common.cpu_qstats)); |
263unlock: 264 spin_unlock(&police->tcf_lock); | 278end: |
265 return ret; 266} 267 | 279 return ret; 280} 281 |
282static void tcf_police_cleanup(struct tc_action *a) 283{ 284 struct tcf_police *police = to_police(a); 285 struct tcf_police_params *p; 286 287 p = rcu_dereference_protected(police->params, 1); 288 if (p) 289 kfree_rcu(p, rcu); 290} 291 |
|
268static int tcf_police_dump(struct sk_buff *skb, struct tc_action *a, 269 int bind, int ref) 270{ 271 unsigned char *b = skb_tail_pointer(skb); 272 struct tcf_police *police = to_police(a); | 292static int tcf_police_dump(struct sk_buff *skb, struct tc_action *a, 293 int bind, int ref) 294{ 295 unsigned char *b = skb_tail_pointer(skb); 296 struct tcf_police *police = to_police(a); |
297 struct tcf_police_params *p; |
|
273 struct tc_police opt = { 274 .index = police->tcf_index, 275 .refcnt = refcount_read(&police->tcf_refcnt) - ref, 276 .bindcnt = atomic_read(&police->tcf_bindcnt) - bind, 277 }; 278 struct tcf_t t; 279 280 spin_lock_bh(&police->tcf_lock); 281 opt.action = police->tcf_action; | 298 struct tc_police opt = { 299 .index = police->tcf_index, 300 .refcnt = refcount_read(&police->tcf_refcnt) - ref, 301 .bindcnt = atomic_read(&police->tcf_bindcnt) - bind, 302 }; 303 struct tcf_t t; 304 305 spin_lock_bh(&police->tcf_lock); 306 opt.action = police->tcf_action; |
282 opt.mtu = police->tcfp_mtu; 283 opt.burst = PSCHED_NS2TICKS(police->tcfp_burst); 284 if (police->rate_present) 285 psched_ratecfg_getrate(&opt.rate, &police->rate); 286 if (police->peak_present) 287 psched_ratecfg_getrate(&opt.peakrate, &police->peak); | 307 p = rcu_dereference_protected(police->params, 308 lockdep_is_held(&police->tcf_lock)); 309 opt.mtu = p->tcfp_mtu; 310 opt.burst = PSCHED_NS2TICKS(p->tcfp_burst); 311 if (p->rate_present) 312 psched_ratecfg_getrate(&opt.rate, &p->rate); 313 if (p->peak_present) 314 psched_ratecfg_getrate(&opt.peakrate, &p->peak); |
288 if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt)) 289 goto nla_put_failure; | 315 if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt)) 316 goto nla_put_failure; |
290 if (police->tcfp_result && 291 nla_put_u32(skb, TCA_POLICE_RESULT, police->tcfp_result)) | 317 if (p->tcfp_result && 318 nla_put_u32(skb, TCA_POLICE_RESULT, p->tcfp_result)) |
292 goto nla_put_failure; | 319 goto nla_put_failure; |
293 if (police->tcfp_ewma_rate && 294 nla_put_u32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate)) | 320 if (p->tcfp_ewma_rate && 321 nla_put_u32(skb, TCA_POLICE_AVRATE, p->tcfp_ewma_rate)) |
295 goto nla_put_failure; 296 297 t.install = jiffies_to_clock_t(jiffies - police->tcf_tm.install); 298 t.lastuse = jiffies_to_clock_t(jiffies - police->tcf_tm.lastuse); 299 t.firstuse = jiffies_to_clock_t(jiffies - police->tcf_tm.firstuse); 300 t.expires = jiffies_to_clock_t(police->tcf_tm.expires); 301 if (nla_put_64bit(skb, TCA_POLICE_TM, sizeof(t), &t, TCA_POLICE_PAD)) 302 goto nla_put_failure; --- 22 unchanged lines hidden (view full) --- 325 .kind = "police", 326 .type = TCA_ID_POLICE, 327 .owner = THIS_MODULE, 328 .act = tcf_police_act, 329 .dump = tcf_police_dump, 330 .init = tcf_police_init, 331 .walk = tcf_police_walker, 332 .lookup = tcf_police_search, | 322 goto nla_put_failure; 323 324 t.install = jiffies_to_clock_t(jiffies - police->tcf_tm.install); 325 t.lastuse = jiffies_to_clock_t(jiffies - police->tcf_tm.lastuse); 326 t.firstuse = jiffies_to_clock_t(jiffies - police->tcf_tm.firstuse); 327 t.expires = jiffies_to_clock_t(police->tcf_tm.expires); 328 if (nla_put_64bit(skb, TCA_POLICE_TM, sizeof(t), &t, TCA_POLICE_PAD)) 329 goto nla_put_failure; --- 22 unchanged lines hidden (view full) --- 352 .kind = "police", 353 .type = TCA_ID_POLICE, 354 .owner = THIS_MODULE, 355 .act = tcf_police_act, 356 .dump = tcf_police_dump, 357 .init = tcf_police_init, 358 .walk = tcf_police_walker, 359 .lookup = tcf_police_search, |
360 .cleanup = tcf_police_cleanup, |
|
333 .size = sizeof(struct tcf_police), 334}; 335 336static __net_init int police_init_net(struct net *net) 337{ 338 struct tc_action_net *tn = net_generic(net, police_net_id); 339 340 return tc_action_net_init(tn, &act_police_ops); --- 26 unchanged lines hidden --- | 361 .size = sizeof(struct tcf_police), 362}; 363 364static __net_init int police_init_net(struct net *net) 365{ 366 struct tc_action_net *tn = net_generic(net, police_net_id); 367 368 return tc_action_net_init(tn, &act_police_ops); --- 26 unchanged lines hidden --- |