Blame view
net/sched/act_police.c
9.63 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 |
/* * net/sched/police.c Input police filter. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> * J Hadi Salim (action changes) */ |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 |
#include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <linux/string.h> |
1da177e4c Linux-2.6.12-rc2 |
16 |
#include <linux/errno.h> |
1da177e4c Linux-2.6.12-rc2 |
17 |
#include <linux/skbuff.h> |
1da177e4c Linux-2.6.12-rc2 |
18 19 |
#include <linux/rtnetlink.h> #include <linux/init.h> |
5a0e3ad6a include cleanup: ... |
20 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
21 |
#include <net/act_api.h> |
dc5fc579b [NETLINK]: Use nl... |
22 |
#include <net/netlink.h> |
1da177e4c Linux-2.6.12-rc2 |
23 |
|
cc7ec456f net_sched: cleanups |
24 25 |
#define L2T(p, L) qdisc_l2t((p)->tcfp_R_tab, L) #define L2T_P(p, L) qdisc_l2t((p)->tcfp_P_tab, L) |
1da177e4c Linux-2.6.12-rc2 |
26 |
|
e9ce1cd3c [PKT_SCHED]: Kill... |
27 28 29 30 |
#define POL_TAB_MASK 15 static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1]; static u32 police_idx_gen; static DEFINE_RWLOCK(police_lock); |
1da177e4c Linux-2.6.12-rc2 |
31 |
|
e9ce1cd3c [PKT_SCHED]: Kill... |
32 33 34 35 36 |
static struct tcf_hashinfo police_hash_info = { .htab = tcf_police_ht, .hmask = POL_TAB_MASK, .lock = &police_lock, }; |
1da177e4c Linux-2.6.12-rc2 |
37 |
|
1e9b3d533 [NET_SCHED]: poli... |
38 |
/* old policer structure from before tc actions */ |
cc7ec456f net_sched: cleanups |
39 |
struct tc_police_compat { |
1e9b3d533 [NET_SCHED]: poli... |
40 41 42 43 44 45 46 47 |
u32 index; int action; u32 limit; u32 burst; u32 mtu; struct tc_ratespec rate; struct tc_ratespec peakrate; }; |
e9ce1cd3c [PKT_SCHED]: Kill... |
48 |
/* Each policer is serialized by its individual spinlock */ |
1da177e4c Linux-2.6.12-rc2 |
49 |
|
83b950c89 [PKT_SCHED] act_p... |
50 |
static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, |
10297b993 [NET] SCHED: Fix ... |
51 |
int type, struct tc_action *a) |
1da177e4c Linux-2.6.12-rc2 |
52 |
{ |
e9ce1cd3c [PKT_SCHED]: Kill... |
53 |
struct tcf_common *p; |
1da177e4c Linux-2.6.12-rc2 |
54 |
int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; |
4b3550ef5 [NET_SCHED]: Use ... |
55 |
struct nlattr *nest; |
1da177e4c Linux-2.6.12-rc2 |
56 |
|
e1e992e52 [NET_SCHED] prote... |
57 |
read_lock_bh(&police_lock); |
1da177e4c Linux-2.6.12-rc2 |
58 59 |
s_i = cb->args[0]; |
e9ce1cd3c [PKT_SCHED]: Kill... |
60 61 |
for (i = 0; i < (POL_TAB_MASK + 1); i++) { p = tcf_police_ht[tcf_hash(i, POL_TAB_MASK)]; |
1da177e4c Linux-2.6.12-rc2 |
62 |
|
e9ce1cd3c [PKT_SCHED]: Kill... |
63 |
for (; p; p = p->tcfc_next) { |
1da177e4c Linux-2.6.12-rc2 |
64 65 66 67 68 |
index++; if (index < s_i) continue; a->priv = p; a->order = index; |
4b3550ef5 [NET_SCHED]: Use ... |
69 70 71 |
nest = nla_nest_start(skb, a->order); if (nest == NULL) goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
72 73 74 75 76 77 |
if (type == RTM_DELACTION) err = tcf_action_dump_1(skb, a, 0, 1); else err = tcf_action_dump_1(skb, a, 0, 0); if (err < 0) { index--; |
4b3550ef5 [NET_SCHED]: Use ... |
78 |
nla_nest_cancel(skb, nest); |
1da177e4c Linux-2.6.12-rc2 |
79 80 |
goto done; } |
4b3550ef5 [NET_SCHED]: Use ... |
81 |
nla_nest_end(skb, nest); |
1da177e4c Linux-2.6.12-rc2 |
82 83 84 85 |
n_i++; } } done: |
e1e992e52 [NET_SCHED] prote... |
86 |
read_unlock_bh(&police_lock); |
1da177e4c Linux-2.6.12-rc2 |
87 88 89 |
if (n_i) cb->args[0] += n_i; return n_i; |
7ba699c60 [NET_SCHED]: Conv... |
90 |
nla_put_failure: |
4b3550ef5 [NET_SCHED]: Use ... |
91 |
nla_nest_cancel(skb, nest); |
1da177e4c Linux-2.6.12-rc2 |
92 93 |
goto done; } |
1da177e4c Linux-2.6.12-rc2 |
94 |
|
c3bc7cff8 [NET_SCHED]: Kill... |
95 |
static void tcf_police_destroy(struct tcf_police *p) |
1da177e4c Linux-2.6.12-rc2 |
96 |
{ |
e9ce1cd3c [PKT_SCHED]: Kill... |
97 98 |
unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK); struct tcf_common **p1p; |
10297b993 [NET] SCHED: Fix ... |
99 |
|
e9ce1cd3c [PKT_SCHED]: Kill... |
100 101 |
for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->tcfc_next) { if (*p1p == &p->common) { |
1da177e4c Linux-2.6.12-rc2 |
102 |
write_lock_bh(&police_lock); |
e9ce1cd3c [PKT_SCHED]: Kill... |
103 |
*p1p = p->tcf_next; |
1da177e4c Linux-2.6.12-rc2 |
104 |
write_unlock_bh(&police_lock); |
e9ce1cd3c [PKT_SCHED]: Kill... |
105 106 |
gen_kill_estimator(&p->tcf_bstats, &p->tcf_rate_est); |
e9ce1cd3c [PKT_SCHED]: Kill... |
107 108 109 110 |
if (p->tcfp_R_tab) qdisc_put_rtab(p->tcfp_R_tab); if (p->tcfp_P_tab) qdisc_put_rtab(p->tcfp_P_tab); |
c7de2cf05 pkt_sched: gen_ki... |
111 112 113 114 |
/* * gen_estimator est_timer() might access p->tcf_lock * or bstats, wait a RCU grace period before freeing p */ |
5957b1ac5 net,rcu: convert ... |
115 |
kfree_rcu(p, tcf_rcu); |
1da177e4c Linux-2.6.12-rc2 |
116 117 118 |
return; } } |
547b792ca net: convert BUG_... |
119 |
WARN_ON(1); |
1da177e4c Linux-2.6.12-rc2 |
120 |
} |
53b2bf3f8 [NET_SCHED]: Use ... |
121 122 123 124 125 126 |
static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = { [TCA_POLICE_RATE] = { .len = TC_RTAB_SIZE }, [TCA_POLICE_PEAKRATE] = { .len = TC_RTAB_SIZE }, [TCA_POLICE_AVRATE] = { .type = NLA_U32 }, [TCA_POLICE_RESULT] = { .type = NLA_U32 }, }; |
7ba699c60 [NET_SCHED]: Conv... |
127 |
static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est, |
10297b993 [NET] SCHED: Fix ... |
128 |
struct tc_action *a, int ovr, int bind) |
1da177e4c Linux-2.6.12-rc2 |
129 |
{ |
cc7ec456f net_sched: cleanups |
130 |
unsigned int h; |
1da177e4c Linux-2.6.12-rc2 |
131 |
int ret = 0, err; |
7ba699c60 [NET_SCHED]: Conv... |
132 |
struct nlattr *tb[TCA_POLICE_MAX + 1]; |
1da177e4c Linux-2.6.12-rc2 |
133 |
struct tc_police *parm; |
e9ce1cd3c [PKT_SCHED]: Kill... |
134 |
struct tcf_police *police; |
1da177e4c Linux-2.6.12-rc2 |
135 |
struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; |
1e9b3d533 [NET_SCHED]: poli... |
136 |
int size; |
1da177e4c Linux-2.6.12-rc2 |
137 |
|
cee63723b [NET_SCHED]: Prop... |
138 |
if (nla == NULL) |
1da177e4c Linux-2.6.12-rc2 |
139 |
return -EINVAL; |
53b2bf3f8 [NET_SCHED]: Use ... |
140 |
err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy); |
cee63723b [NET_SCHED]: Prop... |
141 142 |
if (err < 0) return err; |
7ba699c60 [NET_SCHED]: Conv... |
143 |
if (tb[TCA_POLICE_TBF] == NULL) |
1e9b3d533 [NET_SCHED]: poli... |
144 |
return -EINVAL; |
7ba699c60 [NET_SCHED]: Conv... |
145 |
size = nla_len(tb[TCA_POLICE_TBF]); |
1e9b3d533 [NET_SCHED]: poli... |
146 |
if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat)) |
1da177e4c Linux-2.6.12-rc2 |
147 |
return -EINVAL; |
7ba699c60 [NET_SCHED]: Conv... |
148 |
parm = nla_data(tb[TCA_POLICE_TBF]); |
1da177e4c Linux-2.6.12-rc2 |
149 |
|
e9ce1cd3c [PKT_SCHED]: Kill... |
150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
if (parm->index) { struct tcf_common *pc; pc = tcf_hash_lookup(parm->index, &police_hash_info); if (pc != NULL) { a->priv = pc; police = to_police(pc); if (bind) { police->tcf_bindcnt += 1; police->tcf_refcnt += 1; } if (ovr) goto override; return ret; |
1da177e4c Linux-2.6.12-rc2 |
164 |
} |
1da177e4c Linux-2.6.12-rc2 |
165 |
} |
e9ce1cd3c [PKT_SCHED]: Kill... |
166 167 |
police = kzalloc(sizeof(*police), GFP_KERNEL); if (police == NULL) |
1da177e4c Linux-2.6.12-rc2 |
168 |
return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
169 |
ret = ACT_P_CREATED; |
e9ce1cd3c [PKT_SCHED]: Kill... |
170 171 |
police->tcf_refcnt = 1; spin_lock_init(&police->tcf_lock); |
1da177e4c Linux-2.6.12-rc2 |
172 |
if (bind) |
e9ce1cd3c [PKT_SCHED]: Kill... |
173 |
police->tcf_bindcnt = 1; |
1da177e4c Linux-2.6.12-rc2 |
174 175 176 |
override: if (parm->rate.rate) { err = -ENOMEM; |
7ba699c60 [NET_SCHED]: Conv... |
177 |
R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); |
1da177e4c Linux-2.6.12-rc2 |
178 179 |
if (R_tab == NULL) goto failure; |
c1b56878f tc: policing requ... |
180 |
|
1da177e4c Linux-2.6.12-rc2 |
181 182 |
if (parm->peakrate.rate) { P_tab = qdisc_get_rtab(&parm->peakrate, |
7ba699c60 [NET_SCHED]: Conv... |
183 |
tb[TCA_POLICE_PEAKRATE]); |
71bcb09a5 tc: check for err... |
184 |
if (P_tab == NULL) |
1da177e4c Linux-2.6.12-rc2 |
185 |
goto failure; |
1da177e4c Linux-2.6.12-rc2 |
186 187 |
} } |
71bcb09a5 tc: check for err... |
188 |
|
e9ce1cd3c [PKT_SCHED]: Kill... |
189 |
spin_lock_bh(&police->tcf_lock); |
71bcb09a5 tc: check for err... |
190 191 192 193 194 195 |
if (est) { err = gen_replace_estimator(&police->tcf_bstats, &police->tcf_rate_est, &police->tcf_lock, est); if (err) goto failure_unlock; |
a883bf564 pkt_sched: act_po... |
196 197 198 199 200 201 |
} else if (tb[TCA_POLICE_AVRATE] && (ret == ACT_P_CREATED || !gen_estimator_active(&police->tcf_bstats, &police->tcf_rate_est))) { err = -EINVAL; goto failure_unlock; |
71bcb09a5 tc: check for err... |
202 203 204 |
} /* No failure allowed after this point */ |
1da177e4c Linux-2.6.12-rc2 |
205 |
if (R_tab != NULL) { |
e9ce1cd3c [PKT_SCHED]: Kill... |
206 207 |
qdisc_put_rtab(police->tcfp_R_tab); police->tcfp_R_tab = R_tab; |
1da177e4c Linux-2.6.12-rc2 |
208 209 |
} if (P_tab != NULL) { |
e9ce1cd3c [PKT_SCHED]: Kill... |
210 211 |
qdisc_put_rtab(police->tcfp_P_tab); police->tcfp_P_tab = P_tab; |
1da177e4c Linux-2.6.12-rc2 |
212 |
} |
7ba699c60 [NET_SCHED]: Conv... |
213 |
if (tb[TCA_POLICE_RESULT]) |
1587bac49 [NET_SCHED]: Use ... |
214 |
police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]); |
e9ce1cd3c [PKT_SCHED]: Kill... |
215 216 217 218 219 220 |
police->tcfp_toks = police->tcfp_burst = parm->burst; police->tcfp_mtu = parm->mtu; if (police->tcfp_mtu == 0) { police->tcfp_mtu = ~0; if (police->tcfp_R_tab) police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log; |
1da177e4c Linux-2.6.12-rc2 |
221 |
} |
e9ce1cd3c [PKT_SCHED]: Kill... |
222 223 224 |
if (police->tcfp_P_tab) police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); police->tcf_action = parm->action; |
1da177e4c Linux-2.6.12-rc2 |
225 |
|
7ba699c60 [NET_SCHED]: Conv... |
226 |
if (tb[TCA_POLICE_AVRATE]) |
1587bac49 [NET_SCHED]: Use ... |
227 |
police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]); |
1da177e4c Linux-2.6.12-rc2 |
228 |
|
e9ce1cd3c [PKT_SCHED]: Kill... |
229 |
spin_unlock_bh(&police->tcf_lock); |
1da177e4c Linux-2.6.12-rc2 |
230 231 |
if (ret != ACT_P_CREATED) return ret; |
3bebcda28 [NET_SCHED]: turn... |
232 |
police->tcfp_t_c = psched_get_time(); |
e9ce1cd3c [PKT_SCHED]: Kill... |
233 234 235 |
police->tcf_index = parm->index ? parm->index : tcf_hash_new_index(&police_idx_gen, &police_hash_info); h = tcf_hash(police->tcf_index, POL_TAB_MASK); |
1da177e4c Linux-2.6.12-rc2 |
236 |
write_lock_bh(&police_lock); |
e9ce1cd3c [PKT_SCHED]: Kill... |
237 238 |
police->tcf_next = tcf_police_ht[h]; tcf_police_ht[h] = &police->common; |
1da177e4c Linux-2.6.12-rc2 |
239 |
write_unlock_bh(&police_lock); |
e9ce1cd3c [PKT_SCHED]: Kill... |
240 |
a->priv = police; |
1da177e4c Linux-2.6.12-rc2 |
241 |
return ret; |
71bcb09a5 tc: check for err... |
242 243 |
failure_unlock: spin_unlock_bh(&police->tcf_lock); |
1da177e4c Linux-2.6.12-rc2 |
244 |
failure: |
71bcb09a5 tc: check for err... |
245 246 247 248 |
if (P_tab) qdisc_put_rtab(P_tab); if (R_tab) qdisc_put_rtab(R_tab); |
1da177e4c Linux-2.6.12-rc2 |
249 |
if (ret == ACT_P_CREATED) |
e9ce1cd3c [PKT_SCHED]: Kill... |
250 |
kfree(police); |
1da177e4c Linux-2.6.12-rc2 |
251 252 253 254 255 |
return err; } static int tcf_act_police_cleanup(struct tc_action *a, int bind) { |
e9ce1cd3c [PKT_SCHED]: Kill... |
256 |
struct tcf_police *p = a->priv; |
c3bc7cff8 [NET_SCHED]: Kill... |
257 |
int ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
258 |
|
c3bc7cff8 [NET_SCHED]: Kill... |
259 260 261 262 263 264 265 266 267 268 269 |
if (p != NULL) { if (bind) p->tcf_bindcnt--; p->tcf_refcnt--; if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) { tcf_police_destroy(p); ret = 1; } } return ret; |
1da177e4c Linux-2.6.12-rc2 |
270 |
} |
dc7f9f6e8 net: sched: const... |
271 |
static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, |
10297b993 [NET] SCHED: Fix ... |
272 |
struct tcf_result *res) |
1da177e4c Linux-2.6.12-rc2 |
273 |
{ |
e9ce1cd3c [PKT_SCHED]: Kill... |
274 |
struct tcf_police *police = a->priv; |
1da177e4c Linux-2.6.12-rc2 |
275 |
psched_time_t now; |
1da177e4c Linux-2.6.12-rc2 |
276 277 |
long toks; long ptoks = 0; |
e9ce1cd3c [PKT_SCHED]: Kill... |
278 |
spin_lock(&police->tcf_lock); |
1da177e4c Linux-2.6.12-rc2 |
279 |
|
bfe0d0298 net_sched: factor... |
280 |
bstats_update(&police->tcf_bstats, skb); |
1da177e4c Linux-2.6.12-rc2 |
281 |
|
e9ce1cd3c [PKT_SCHED]: Kill... |
282 283 284 |
if (police->tcfp_ewma_rate && police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { police->tcf_qstats.overlimits++; |
b96475805 pkt_sched: Update... |
285 286 |
if (police->tcf_action == TC_ACT_SHOT) police->tcf_qstats.drops++; |
e9ce1cd3c [PKT_SCHED]: Kill... |
287 288 |
spin_unlock(&police->tcf_lock); return police->tcf_action; |
1da177e4c Linux-2.6.12-rc2 |
289 |
} |
1da177e4c Linux-2.6.12-rc2 |
290 |
|
0abf77e55 net_sched: Add ac... |
291 |
if (qdisc_pkt_len(skb) <= police->tcfp_mtu) { |
e9ce1cd3c [PKT_SCHED]: Kill... |
292 293 294 |
if (police->tcfp_R_tab == NULL) { spin_unlock(&police->tcf_lock); return police->tcfp_result; |
1da177e4c Linux-2.6.12-rc2 |
295 |
} |
3bebcda28 [NET_SCHED]: turn... |
296 |
now = psched_get_time(); |
03cc45c0a [NET_SCHED]: turn... |
297 298 |
toks = psched_tdiff_bounded(now, police->tcfp_t_c, police->tcfp_burst); |
e9ce1cd3c [PKT_SCHED]: Kill... |
299 300 301 302 |
if (police->tcfp_P_tab) { ptoks = toks + police->tcfp_ptoks; if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) ptoks = (long)L2T_P(police, police->tcfp_mtu); |
0abf77e55 net_sched: Add ac... |
303 |
ptoks -= L2T_P(police, qdisc_pkt_len(skb)); |
1da177e4c Linux-2.6.12-rc2 |
304 |
} |
e9ce1cd3c [PKT_SCHED]: Kill... |
305 306 307 |
toks += police->tcfp_toks; if (toks > (long)police->tcfp_burst) toks = police->tcfp_burst; |
0abf77e55 net_sched: Add ac... |
308 |
toks -= L2T(police, qdisc_pkt_len(skb)); |
1da177e4c Linux-2.6.12-rc2 |
309 |
if ((toks|ptoks) >= 0) { |
e9ce1cd3c [PKT_SCHED]: Kill... |
310 311 312 313 314 |
police->tcfp_t_c = now; police->tcfp_toks = toks; police->tcfp_ptoks = ptoks; spin_unlock(&police->tcf_lock); return police->tcfp_result; |
1da177e4c Linux-2.6.12-rc2 |
315 316 |
} } |
e9ce1cd3c [PKT_SCHED]: Kill... |
317 |
police->tcf_qstats.overlimits++; |
b96475805 pkt_sched: Update... |
318 319 |
if (police->tcf_action == TC_ACT_SHOT) police->tcf_qstats.drops++; |
e9ce1cd3c [PKT_SCHED]: Kill... |
320 321 |
spin_unlock(&police->tcf_lock); return police->tcf_action; |
1da177e4c Linux-2.6.12-rc2 |
322 323 324 325 326 |
} static int tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) { |
27a884dc3 [SK_BUFF]: Conver... |
327 |
unsigned char *b = skb_tail_pointer(skb); |
e9ce1cd3c [PKT_SCHED]: Kill... |
328 |
struct tcf_police *police = a->priv; |
0f04cfd09 net sched: fix ke... |
329 330 331 332 333 334 335 336 |
struct tc_police opt = { .index = police->tcf_index, .action = police->tcf_action, .mtu = police->tcfp_mtu, .burst = police->tcfp_burst, .refcnt = police->tcf_refcnt - ref, .bindcnt = police->tcf_bindcnt - bind, }; |
e9ce1cd3c [PKT_SCHED]: Kill... |
337 338 |
if (police->tcfp_R_tab) opt.rate = police->tcfp_R_tab->rate; |
e9ce1cd3c [PKT_SCHED]: Kill... |
339 340 |
if (police->tcfp_P_tab) opt.peakrate = police->tcfp_P_tab->rate; |
7ba699c60 [NET_SCHED]: Conv... |
341 |
NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); |
e9ce1cd3c [PKT_SCHED]: Kill... |
342 |
if (police->tcfp_result) |
24beeab53 [NET_SCHED]: Use ... |
343 |
NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result); |
e9ce1cd3c [PKT_SCHED]: Kill... |
344 |
if (police->tcfp_ewma_rate) |
24beeab53 [NET_SCHED]: Use ... |
345 |
NLA_PUT_U32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate); |
1da177e4c Linux-2.6.12-rc2 |
346 |
return skb->len; |
7ba699c60 [NET_SCHED]: Conv... |
347 |
nla_put_failure: |
dc5fc579b [NETLINK]: Use nl... |
348 |
nlmsg_trim(skb, b); |
1da177e4c Linux-2.6.12-rc2 |
349 350 351 352 353 354 355 356 357 |
return -1; } MODULE_AUTHOR("Alexey Kuznetsov"); MODULE_DESCRIPTION("Policing actions"); MODULE_LICENSE("GPL"); static struct tc_action_ops act_police_ops = { .kind = "police", |
e9ce1cd3c [PKT_SCHED]: Kill... |
358 |
.hinfo = &police_hash_info, |
1da177e4c Linux-2.6.12-rc2 |
359 360 361 362 363 364 |
.type = TCA_ID_POLICE, .capab = TCA_CAP_NONE, .owner = THIS_MODULE, .act = tcf_act_police, .dump = tcf_act_police_dump, .cleanup = tcf_act_police_cleanup, |
e9ce1cd3c [PKT_SCHED]: Kill... |
365 |
.lookup = tcf_hash_search, |
1da177e4c Linux-2.6.12-rc2 |
366 |
.init = tcf_act_police_locate, |
83b950c89 [PKT_SCHED] act_p... |
367 |
.walk = tcf_act_police_walker |
1da177e4c Linux-2.6.12-rc2 |
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
}; static int __init police_init_module(void) { return tcf_register_action(&act_police_ops); } static void __exit police_cleanup_module(void) { tcf_unregister_action(&act_police_ops); } module_init(police_init_module); module_exit(police_cleanup_module); |