.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * 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 | 4 | * |
---|
9 | 5 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
---|
10 | 6 | * J Hadi Salim (action changes) |
---|
.. | .. |
---|
21 | 17 | #include <linux/slab.h> |
---|
22 | 18 | #include <net/act_api.h> |
---|
23 | 19 | #include <net/netlink.h> |
---|
24 | | - |
---|
25 | | -struct tcf_police { |
---|
26 | | - struct tc_action 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 | | - |
---|
41 | | -#define to_police(pc) ((struct tcf_police *)pc) |
---|
42 | | - |
---|
43 | | -/* old policer structure from before tc actions */ |
---|
44 | | -struct tc_police_compat { |
---|
45 | | - u32 index; |
---|
46 | | - int action; |
---|
47 | | - u32 limit; |
---|
48 | | - u32 burst; |
---|
49 | | - u32 mtu; |
---|
50 | | - struct tc_ratespec rate; |
---|
51 | | - struct tc_ratespec peakrate; |
---|
52 | | -}; |
---|
| 20 | +#include <net/pkt_cls.h> |
---|
| 21 | +#include <net/tc_act/tc_police.h> |
---|
53 | 22 | |
---|
54 | 23 | /* Each policer is serialized by its individual spinlock */ |
---|
55 | 24 | |
---|
.. | .. |
---|
71 | 40 | [TCA_POLICE_PEAKRATE] = { .len = TC_RTAB_SIZE }, |
---|
72 | 41 | [TCA_POLICE_AVRATE] = { .type = NLA_U32 }, |
---|
73 | 42 | [TCA_POLICE_RESULT] = { .type = NLA_U32 }, |
---|
| 43 | + [TCA_POLICE_RATE64] = { .type = NLA_U64 }, |
---|
| 44 | + [TCA_POLICE_PEAKRATE64] = { .type = NLA_U64 }, |
---|
74 | 45 | }; |
---|
75 | 46 | |
---|
76 | 47 | static int tcf_police_init(struct net *net, struct nlattr *nla, |
---|
77 | 48 | struct nlattr *est, struct tc_action **a, |
---|
78 | 49 | int ovr, int bind, bool rtnl_held, |
---|
| 50 | + struct tcf_proto *tp, u32 flags, |
---|
79 | 51 | struct netlink_ext_ack *extack) |
---|
80 | 52 | { |
---|
81 | | - int ret = 0, err; |
---|
| 53 | + int ret = 0, tcfp_result = TC_ACT_OK, err, size; |
---|
82 | 54 | struct nlattr *tb[TCA_POLICE_MAX + 1]; |
---|
| 55 | + struct tcf_chain *goto_ch = NULL; |
---|
83 | 56 | struct tc_police *parm; |
---|
84 | 57 | struct tcf_police *police; |
---|
85 | 58 | struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; |
---|
86 | 59 | struct tc_action_net *tn = net_generic(net, police_net_id); |
---|
| 60 | + struct tcf_police_params *new; |
---|
87 | 61 | bool exists = false; |
---|
88 | 62 | u32 index; |
---|
89 | | - int size; |
---|
| 63 | + u64 rate64, prate64; |
---|
90 | 64 | |
---|
91 | 65 | if (nla == NULL) |
---|
92 | 66 | return -EINVAL; |
---|
93 | 67 | |
---|
94 | | - err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy, NULL); |
---|
| 68 | + err = nla_parse_nested_deprecated(tb, TCA_POLICE_MAX, nla, |
---|
| 69 | + police_policy, NULL); |
---|
95 | 70 | if (err < 0) |
---|
96 | 71 | return err; |
---|
97 | 72 | |
---|
.. | .. |
---|
112 | 87 | |
---|
113 | 88 | if (!exists) { |
---|
114 | 89 | ret = tcf_idr_create(tn, index, NULL, a, |
---|
115 | | - &act_police_ops, bind, false); |
---|
| 90 | + &act_police_ops, bind, true, flags); |
---|
116 | 91 | if (ret) { |
---|
117 | 92 | tcf_idr_cleanup(tn, index); |
---|
118 | 93 | return ret; |
---|
119 | 94 | } |
---|
120 | 95 | ret = ACT_P_CREATED; |
---|
| 96 | + spin_lock_init(&(to_police(*a)->tcfp_lock)); |
---|
121 | 97 | } else if (!ovr) { |
---|
122 | 98 | tcf_idr_release(*a, bind); |
---|
123 | 99 | return -EEXIST; |
---|
124 | 100 | } |
---|
| 101 | + err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); |
---|
| 102 | + if (err < 0) |
---|
| 103 | + goto release_idr; |
---|
125 | 104 | |
---|
126 | 105 | police = to_police(*a); |
---|
127 | 106 | if (parm->rate.rate) { |
---|
.. | .. |
---|
139 | 118 | } |
---|
140 | 119 | |
---|
141 | 120 | if (est) { |
---|
142 | | - err = gen_replace_estimator(&police->tcf_bstats, NULL, |
---|
| 121 | + err = gen_replace_estimator(&police->tcf_bstats, |
---|
| 122 | + police->common.cpu_bstats, |
---|
143 | 123 | &police->tcf_rate_est, |
---|
144 | 124 | &police->tcf_lock, |
---|
145 | 125 | NULL, est); |
---|
.. | .. |
---|
152 | 132 | goto failure; |
---|
153 | 133 | } |
---|
154 | 134 | |
---|
155 | | - spin_lock_bh(&police->tcf_lock); |
---|
| 135 | + if (tb[TCA_POLICE_RESULT]) { |
---|
| 136 | + tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]); |
---|
| 137 | + if (TC_ACT_EXT_CMP(tcfp_result, TC_ACT_GOTO_CHAIN)) { |
---|
| 138 | + NL_SET_ERR_MSG(extack, |
---|
| 139 | + "goto chain not allowed on fallback"); |
---|
| 140 | + err = -EINVAL; |
---|
| 141 | + goto failure; |
---|
| 142 | + } |
---|
| 143 | + } |
---|
| 144 | + |
---|
| 145 | + new = kzalloc(sizeof(*new), GFP_KERNEL); |
---|
| 146 | + if (unlikely(!new)) { |
---|
| 147 | + err = -ENOMEM; |
---|
| 148 | + goto failure; |
---|
| 149 | + } |
---|
| 150 | + |
---|
156 | 151 | /* No failure allowed after this point */ |
---|
157 | | - police->tcfp_mtu = parm->mtu; |
---|
158 | | - if (police->tcfp_mtu == 0) { |
---|
159 | | - police->tcfp_mtu = ~0; |
---|
| 152 | + new->tcfp_result = tcfp_result; |
---|
| 153 | + new->tcfp_mtu = parm->mtu; |
---|
| 154 | + if (!new->tcfp_mtu) { |
---|
| 155 | + new->tcfp_mtu = ~0; |
---|
160 | 156 | if (R_tab) |
---|
161 | | - police->tcfp_mtu = 255 << R_tab->rate.cell_log; |
---|
| 157 | + new->tcfp_mtu = 255 << R_tab->rate.cell_log; |
---|
162 | 158 | } |
---|
163 | 159 | if (R_tab) { |
---|
164 | | - police->rate_present = true; |
---|
165 | | - psched_ratecfg_precompute(&police->rate, &R_tab->rate, 0); |
---|
| 160 | + new->rate_present = true; |
---|
| 161 | + rate64 = tb[TCA_POLICE_RATE64] ? |
---|
| 162 | + nla_get_u64(tb[TCA_POLICE_RATE64]) : 0; |
---|
| 163 | + psched_ratecfg_precompute(&new->rate, &R_tab->rate, rate64); |
---|
166 | 164 | qdisc_put_rtab(R_tab); |
---|
167 | 165 | } else { |
---|
168 | | - police->rate_present = false; |
---|
| 166 | + new->rate_present = false; |
---|
169 | 167 | } |
---|
170 | 168 | if (P_tab) { |
---|
171 | | - police->peak_present = true; |
---|
172 | | - psched_ratecfg_precompute(&police->peak, &P_tab->rate, 0); |
---|
| 169 | + new->peak_present = true; |
---|
| 170 | + prate64 = tb[TCA_POLICE_PEAKRATE64] ? |
---|
| 171 | + nla_get_u64(tb[TCA_POLICE_PEAKRATE64]) : 0; |
---|
| 172 | + psched_ratecfg_precompute(&new->peak, &P_tab->rate, prate64); |
---|
173 | 173 | qdisc_put_rtab(P_tab); |
---|
174 | 174 | } else { |
---|
175 | | - police->peak_present = false; |
---|
| 175 | + new->peak_present = false; |
---|
176 | 176 | } |
---|
177 | 177 | |
---|
178 | | - if (tb[TCA_POLICE_RESULT]) |
---|
179 | | - police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]); |
---|
180 | | - police->tcfp_burst = PSCHED_TICKS2NS(parm->burst); |
---|
181 | | - police->tcfp_toks = police->tcfp_burst; |
---|
182 | | - if (police->peak_present) { |
---|
183 | | - police->tcfp_mtu_ptoks = (s64) psched_l2t_ns(&police->peak, |
---|
184 | | - police->tcfp_mtu); |
---|
185 | | - police->tcfp_ptoks = police->tcfp_mtu_ptoks; |
---|
186 | | - } |
---|
187 | | - police->tcf_action = parm->action; |
---|
| 178 | + new->tcfp_burst = PSCHED_TICKS2NS(parm->burst); |
---|
| 179 | + if (new->peak_present) |
---|
| 180 | + new->tcfp_mtu_ptoks = (s64)psched_l2t_ns(&new->peak, |
---|
| 181 | + new->tcfp_mtu); |
---|
188 | 182 | |
---|
189 | 183 | if (tb[TCA_POLICE_AVRATE]) |
---|
190 | | - police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]); |
---|
| 184 | + new->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]); |
---|
191 | 185 | |
---|
192 | | - spin_unlock_bh(&police->tcf_lock); |
---|
193 | | - if (ret != ACT_P_CREATED) |
---|
194 | | - return ret; |
---|
195 | | - |
---|
| 186 | + spin_lock_bh(&police->tcf_lock); |
---|
| 187 | + spin_lock_bh(&police->tcfp_lock); |
---|
196 | 188 | police->tcfp_t_c = ktime_get_ns(); |
---|
197 | | - tcf_idr_insert(tn, *a); |
---|
| 189 | + police->tcfp_toks = new->tcfp_burst; |
---|
| 190 | + if (new->peak_present) |
---|
| 191 | + police->tcfp_ptoks = new->tcfp_mtu_ptoks; |
---|
| 192 | + spin_unlock_bh(&police->tcfp_lock); |
---|
| 193 | + goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
---|
| 194 | + new = rcu_replace_pointer(police->params, |
---|
| 195 | + new, |
---|
| 196 | + lockdep_is_held(&police->tcf_lock)); |
---|
| 197 | + spin_unlock_bh(&police->tcf_lock); |
---|
| 198 | + |
---|
| 199 | + if (goto_ch) |
---|
| 200 | + tcf_chain_put_by_act(goto_ch); |
---|
| 201 | + if (new) |
---|
| 202 | + kfree_rcu(new, rcu); |
---|
198 | 203 | |
---|
199 | 204 | return ret; |
---|
200 | 205 | |
---|
201 | 206 | failure: |
---|
202 | 207 | qdisc_put_rtab(P_tab); |
---|
203 | 208 | qdisc_put_rtab(R_tab); |
---|
| 209 | + if (goto_ch) |
---|
| 210 | + tcf_chain_put_by_act(goto_ch); |
---|
| 211 | +release_idr: |
---|
204 | 212 | tcf_idr_release(*a, bind); |
---|
205 | 213 | return err; |
---|
| 214 | +} |
---|
| 215 | + |
---|
| 216 | +static bool tcf_police_mtu_check(struct sk_buff *skb, u32 limit) |
---|
| 217 | +{ |
---|
| 218 | + u32 len; |
---|
| 219 | + |
---|
| 220 | + if (skb_is_gso(skb)) |
---|
| 221 | + return skb_gso_validate_mac_len(skb, limit); |
---|
| 222 | + |
---|
| 223 | + len = qdisc_pkt_len(skb); |
---|
| 224 | + if (skb_at_tc_ingress(skb)) |
---|
| 225 | + len += skb->mac_len; |
---|
| 226 | + |
---|
| 227 | + return len <= limit; |
---|
206 | 228 | } |
---|
207 | 229 | |
---|
208 | 230 | static int tcf_police_act(struct sk_buff *skb, const struct tc_action *a, |
---|
209 | 231 | struct tcf_result *res) |
---|
210 | 232 | { |
---|
211 | 233 | struct tcf_police *police = to_police(a); |
---|
212 | | - s64 now; |
---|
213 | | - s64 toks; |
---|
214 | | - s64 ptoks = 0; |
---|
| 234 | + struct tcf_police_params *p; |
---|
| 235 | + s64 now, toks, ptoks = 0; |
---|
| 236 | + int ret; |
---|
215 | 237 | |
---|
216 | | - spin_lock(&police->tcf_lock); |
---|
217 | | - |
---|
218 | | - bstats_update(&police->tcf_bstats, skb); |
---|
219 | 238 | tcf_lastuse_update(&police->tcf_tm); |
---|
| 239 | + bstats_cpu_update(this_cpu_ptr(police->common.cpu_bstats), skb); |
---|
220 | 240 | |
---|
221 | | - if (police->tcfp_ewma_rate) { |
---|
| 241 | + ret = READ_ONCE(police->tcf_action); |
---|
| 242 | + p = rcu_dereference_bh(police->params); |
---|
| 243 | + |
---|
| 244 | + if (p->tcfp_ewma_rate) { |
---|
222 | 245 | struct gnet_stats_rate_est64 sample; |
---|
223 | 246 | |
---|
224 | 247 | if (!gen_estimator_read(&police->tcf_rate_est, &sample) || |
---|
225 | | - sample.bps >= police->tcfp_ewma_rate) { |
---|
226 | | - police->tcf_qstats.overlimits++; |
---|
227 | | - if (police->tcf_action == TC_ACT_SHOT) |
---|
228 | | - police->tcf_qstats.drops++; |
---|
229 | | - spin_unlock(&police->tcf_lock); |
---|
230 | | - return police->tcf_action; |
---|
231 | | - } |
---|
| 248 | + sample.bps >= p->tcfp_ewma_rate) |
---|
| 249 | + goto inc_overlimits; |
---|
232 | 250 | } |
---|
233 | 251 | |
---|
234 | | - if (qdisc_pkt_len(skb) <= police->tcfp_mtu) { |
---|
235 | | - if (!police->rate_present) { |
---|
236 | | - spin_unlock(&police->tcf_lock); |
---|
237 | | - return police->tcfp_result; |
---|
| 252 | + if (tcf_police_mtu_check(skb, p->tcfp_mtu)) { |
---|
| 253 | + if (!p->rate_present) { |
---|
| 254 | + ret = p->tcfp_result; |
---|
| 255 | + goto end; |
---|
238 | 256 | } |
---|
239 | 257 | |
---|
240 | 258 | now = ktime_get_ns(); |
---|
241 | | - toks = min_t(s64, now - police->tcfp_t_c, |
---|
242 | | - police->tcfp_burst); |
---|
243 | | - if (police->peak_present) { |
---|
| 259 | + spin_lock_bh(&police->tcfp_lock); |
---|
| 260 | + toks = min_t(s64, now - police->tcfp_t_c, p->tcfp_burst); |
---|
| 261 | + if (p->peak_present) { |
---|
244 | 262 | ptoks = toks + police->tcfp_ptoks; |
---|
245 | | - if (ptoks > police->tcfp_mtu_ptoks) |
---|
246 | | - ptoks = police->tcfp_mtu_ptoks; |
---|
247 | | - ptoks -= (s64) psched_l2t_ns(&police->peak, |
---|
248 | | - qdisc_pkt_len(skb)); |
---|
| 263 | + if (ptoks > p->tcfp_mtu_ptoks) |
---|
| 264 | + ptoks = p->tcfp_mtu_ptoks; |
---|
| 265 | + ptoks -= (s64)psched_l2t_ns(&p->peak, |
---|
| 266 | + qdisc_pkt_len(skb)); |
---|
249 | 267 | } |
---|
250 | 268 | toks += police->tcfp_toks; |
---|
251 | | - if (toks > police->tcfp_burst) |
---|
252 | | - toks = police->tcfp_burst; |
---|
253 | | - toks -= (s64) psched_l2t_ns(&police->rate, qdisc_pkt_len(skb)); |
---|
| 269 | + if (toks > p->tcfp_burst) |
---|
| 270 | + toks = p->tcfp_burst; |
---|
| 271 | + toks -= (s64)psched_l2t_ns(&p->rate, qdisc_pkt_len(skb)); |
---|
254 | 272 | if ((toks|ptoks) >= 0) { |
---|
255 | 273 | police->tcfp_t_c = now; |
---|
256 | 274 | police->tcfp_toks = toks; |
---|
257 | 275 | police->tcfp_ptoks = ptoks; |
---|
258 | | - if (police->tcfp_result == TC_ACT_SHOT) |
---|
259 | | - police->tcf_qstats.drops++; |
---|
260 | | - spin_unlock(&police->tcf_lock); |
---|
261 | | - return police->tcfp_result; |
---|
| 276 | + spin_unlock_bh(&police->tcfp_lock); |
---|
| 277 | + ret = p->tcfp_result; |
---|
| 278 | + goto inc_drops; |
---|
262 | 279 | } |
---|
| 280 | + spin_unlock_bh(&police->tcfp_lock); |
---|
263 | 281 | } |
---|
264 | 282 | |
---|
265 | | - police->tcf_qstats.overlimits++; |
---|
266 | | - if (police->tcf_action == TC_ACT_SHOT) |
---|
267 | | - police->tcf_qstats.drops++; |
---|
268 | | - spin_unlock(&police->tcf_lock); |
---|
269 | | - return police->tcf_action; |
---|
| 283 | +inc_overlimits: |
---|
| 284 | + qstats_overlimit_inc(this_cpu_ptr(police->common.cpu_qstats)); |
---|
| 285 | +inc_drops: |
---|
| 286 | + if (ret == TC_ACT_SHOT) |
---|
| 287 | + qstats_drop_inc(this_cpu_ptr(police->common.cpu_qstats)); |
---|
| 288 | +end: |
---|
| 289 | + return ret; |
---|
| 290 | +} |
---|
| 291 | + |
---|
| 292 | +static void tcf_police_cleanup(struct tc_action *a) |
---|
| 293 | +{ |
---|
| 294 | + struct tcf_police *police = to_police(a); |
---|
| 295 | + struct tcf_police_params *p; |
---|
| 296 | + |
---|
| 297 | + p = rcu_dereference_protected(police->params, 1); |
---|
| 298 | + if (p) |
---|
| 299 | + kfree_rcu(p, rcu); |
---|
| 300 | +} |
---|
| 301 | + |
---|
| 302 | +static void tcf_police_stats_update(struct tc_action *a, |
---|
| 303 | + u64 bytes, u64 packets, u64 drops, |
---|
| 304 | + u64 lastuse, bool hw) |
---|
| 305 | +{ |
---|
| 306 | + struct tcf_police *police = to_police(a); |
---|
| 307 | + struct tcf_t *tm = &police->tcf_tm; |
---|
| 308 | + |
---|
| 309 | + tcf_action_update_stats(a, bytes, packets, drops, hw); |
---|
| 310 | + tm->lastuse = max_t(u64, tm->lastuse, lastuse); |
---|
270 | 311 | } |
---|
271 | 312 | |
---|
272 | 313 | static int tcf_police_dump(struct sk_buff *skb, struct tc_action *a, |
---|
.. | .. |
---|
274 | 315 | { |
---|
275 | 316 | unsigned char *b = skb_tail_pointer(skb); |
---|
276 | 317 | struct tcf_police *police = to_police(a); |
---|
| 318 | + struct tcf_police_params *p; |
---|
277 | 319 | struct tc_police opt = { |
---|
278 | 320 | .index = police->tcf_index, |
---|
279 | 321 | .refcnt = refcount_read(&police->tcf_refcnt) - ref, |
---|
.. | .. |
---|
283 | 325 | |
---|
284 | 326 | spin_lock_bh(&police->tcf_lock); |
---|
285 | 327 | opt.action = police->tcf_action; |
---|
286 | | - opt.mtu = police->tcfp_mtu; |
---|
287 | | - opt.burst = PSCHED_NS2TICKS(police->tcfp_burst); |
---|
288 | | - if (police->rate_present) |
---|
289 | | - psched_ratecfg_getrate(&opt.rate, &police->rate); |
---|
290 | | - if (police->peak_present) |
---|
291 | | - psched_ratecfg_getrate(&opt.peakrate, &police->peak); |
---|
| 328 | + p = rcu_dereference_protected(police->params, |
---|
| 329 | + lockdep_is_held(&police->tcf_lock)); |
---|
| 330 | + opt.mtu = p->tcfp_mtu; |
---|
| 331 | + opt.burst = PSCHED_NS2TICKS(p->tcfp_burst); |
---|
| 332 | + if (p->rate_present) { |
---|
| 333 | + psched_ratecfg_getrate(&opt.rate, &p->rate); |
---|
| 334 | + if ((police->params->rate.rate_bytes_ps >= (1ULL << 32)) && |
---|
| 335 | + nla_put_u64_64bit(skb, TCA_POLICE_RATE64, |
---|
| 336 | + police->params->rate.rate_bytes_ps, |
---|
| 337 | + TCA_POLICE_PAD)) |
---|
| 338 | + goto nla_put_failure; |
---|
| 339 | + } |
---|
| 340 | + if (p->peak_present) { |
---|
| 341 | + psched_ratecfg_getrate(&opt.peakrate, &p->peak); |
---|
| 342 | + if ((police->params->peak.rate_bytes_ps >= (1ULL << 32)) && |
---|
| 343 | + nla_put_u64_64bit(skb, TCA_POLICE_PEAKRATE64, |
---|
| 344 | + police->params->peak.rate_bytes_ps, |
---|
| 345 | + TCA_POLICE_PAD)) |
---|
| 346 | + goto nla_put_failure; |
---|
| 347 | + } |
---|
292 | 348 | if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt)) |
---|
293 | 349 | goto nla_put_failure; |
---|
294 | | - if (police->tcfp_result && |
---|
295 | | - nla_put_u32(skb, TCA_POLICE_RESULT, police->tcfp_result)) |
---|
| 350 | + if (p->tcfp_result && |
---|
| 351 | + nla_put_u32(skb, TCA_POLICE_RESULT, p->tcfp_result)) |
---|
296 | 352 | goto nla_put_failure; |
---|
297 | | - if (police->tcfp_ewma_rate && |
---|
298 | | - nla_put_u32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate)) |
---|
| 353 | + if (p->tcfp_ewma_rate && |
---|
| 354 | + nla_put_u32(skb, TCA_POLICE_AVRATE, p->tcfp_ewma_rate)) |
---|
299 | 355 | goto nla_put_failure; |
---|
300 | 356 | |
---|
301 | | - t.install = jiffies_to_clock_t(jiffies - police->tcf_tm.install); |
---|
302 | | - t.lastuse = jiffies_to_clock_t(jiffies - police->tcf_tm.lastuse); |
---|
303 | | - t.firstuse = jiffies_to_clock_t(jiffies - police->tcf_tm.firstuse); |
---|
304 | | - t.expires = jiffies_to_clock_t(police->tcf_tm.expires); |
---|
| 357 | + tcf_tm_dump(&t, &police->tcf_tm); |
---|
305 | 358 | if (nla_put_64bit(skb, TCA_POLICE_TM, sizeof(t), &t, TCA_POLICE_PAD)) |
---|
306 | 359 | goto nla_put_failure; |
---|
307 | 360 | spin_unlock_bh(&police->tcf_lock); |
---|
.. | .. |
---|
314 | 367 | return -1; |
---|
315 | 368 | } |
---|
316 | 369 | |
---|
317 | | -static int tcf_police_search(struct net *net, struct tc_action **a, u32 index, |
---|
318 | | - struct netlink_ext_ack *extack) |
---|
| 370 | +static int tcf_police_search(struct net *net, struct tc_action **a, u32 index) |
---|
319 | 371 | { |
---|
320 | 372 | struct tc_action_net *tn = net_generic(net, police_net_id); |
---|
321 | 373 | |
---|
.. | .. |
---|
328 | 380 | |
---|
329 | 381 | static struct tc_action_ops act_police_ops = { |
---|
330 | 382 | .kind = "police", |
---|
331 | | - .type = TCA_ID_POLICE, |
---|
| 383 | + .id = TCA_ID_POLICE, |
---|
332 | 384 | .owner = THIS_MODULE, |
---|
| 385 | + .stats_update = tcf_police_stats_update, |
---|
333 | 386 | .act = tcf_police_act, |
---|
334 | 387 | .dump = tcf_police_dump, |
---|
335 | 388 | .init = tcf_police_init, |
---|
336 | 389 | .walk = tcf_police_walker, |
---|
337 | 390 | .lookup = tcf_police_search, |
---|
| 391 | + .cleanup = tcf_police_cleanup, |
---|
338 | 392 | .size = sizeof(struct tcf_police), |
---|
339 | 393 | }; |
---|
340 | 394 | |
---|