7 #include <linux/module.h>
8 #include <linux/types.h>
9 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/slab.h>
23 #define PERFECT_HASH_THRESHOLD 64
24 #define DEFAULT_HASH_SIZE 64
27 #define PRIV(tp) ((struct tcindex_data *) (tp)->root)
61 return tcf_exts_is_predicative(&r->
exts) || r->
res.classid;
70 return tcindex_filter_is_set(p->
perfect + key) ?
73 for (f = p->
h[key % p->
hash]; f; f = f->
next)
87 int key = (skb->tc_index & p->
mask) >> p->
shift;
89 pr_debug(
"tcindex_classify(skb %p,tp %p,res %p),p %p\n",
92 f = tcindex_lookup(p, key);
104 return tcf_exts_exec(skb, &f->
exts, res);
113 pr_debug(
"tcindex_get(tp %p,handle 0x%08x)\n", tp, handle);
116 r = tcindex_lookup(p, handle);
117 return r && tcindex_filter_is_set(r) ? (
unsigned long) r : 0
UL;
121 static void tcindex_put(
struct tcf_proto *tp,
unsigned long f)
123 pr_debug(
"tcindex_put(tp %p,f 0x%lx)\n", tp, f);
127 static int tcindex_init(
struct tcf_proto *tp)
131 pr_debug(
"tcindex_init(tp %p)\n", tp);
146 __tcindex_delete(
struct tcf_proto *tp,
unsigned long arg,
int lock)
152 pr_debug(
"tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n", tp, arg, p, f);
160 for (i = 0; i < p->
hash; i++)
161 for (walk = p->
h+i; *walk; walk = &(*walk)->
next)
162 if (&(*walk)->result == r)
174 tcf_unbind_filter(tp, &r->
res);
180 static int tcindex_delete(
struct tcf_proto *tp,
unsigned long arg)
182 return __tcindex_delete(tp, arg, 1);
200 tcindex_set_parms(
struct tcf_proto *tp,
unsigned long base,
u32 handle,
216 memset(&new_filter_result, 0,
sizeof(new_filter_result));
224 cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
227 cp.mask = nla_get_u16(tb[TCA_TCINDEX_MASK]);
230 cp.shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]);
237 if (!valid_perfect_hash(&
cp) ||
238 cp.hash >
cp.alloc_hash)
240 }
else if (
cp.h &&
cp.hash !=
cp.alloc_hash)
245 cp.fall_through = nla_get_u32(tb[TCA_TCINDEX_FALL_THROUGH]);
252 cp.hash = (
cp.mask >>
cp.shift) + 1;
257 if (!
cp.perfect && !
cp.h)
258 cp.alloc_hash =
cp.hash;
265 if (
cp.perfect || valid_perfect_hash(&
cp))
266 if (handle >=
cp.alloc_hash)
271 if (!
cp.perfect && !
cp.h) {
272 if (valid_perfect_hash(&
cp)) {
288 r = tcindex_lookup(&
cp, handle) ? : &new_filter_result;
290 if (r == &new_filter_result) {
297 cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
298 tcf_bind_filter(tp, &
cr.res, base);
304 if (old_r && old_r != r)
305 memset(old_r, 0,
sizeof(*old_r));
310 if (r == &new_filter_result) {
314 f->
result = new_filter_result;
316 for (fp = p->
h+(handle % p->
hash); *fp; fp = &(*fp)->
next)
327 else if (balloc == 2)
335 tcindex_change(
struct sk_buff *in_skb,
345 pr_debug(
"tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
346 "p %p,r %p,*arg 0x%lx\n",
347 tp, handle, tca, arg, opt, p, r, arg ? *arg : 0L);
356 return tcindex_set_parms(tp, base, handle, p, r, tb, tca[
TCA_RATE]);
366 pr_debug(
"tcindex_walk(tp %p,walker %p),p %p\n", tp, walker, p);
368 for (i = 0; i < p->
hash; i++) {
373 (
unsigned long) (p->
perfect+i), walker)
384 for (i = 0; i < p->
hash; i++) {
385 for (f = p->
h[i]; f; f = next) {
388 if (walker->
fn(tp, (
unsigned long) &f->
result,
400 static int tcindex_destroy_element(
struct tcf_proto *tp,
403 return __tcindex_delete(tp, arg, 0);
407 static void tcindex_destroy(
struct tcf_proto *tp)
412 pr_debug(
"tcindex_destroy(tp %p),p %p\n", tp, p);
415 walker.
fn = &tcindex_destroy_element;
416 tcindex_walk(tp, &walker);
424 static int tcindex_dump(
struct tcf_proto *tp,
unsigned long fh,
429 unsigned char *
b = skb_tail_pointer(skb);
432 pr_debug(
"tcindex_dump(tp %p,fh 0x%lx,skb %p,t %p),p %p,r %p,b %p\n",
433 tp, fh, skb, t, p, r, b);
438 goto nla_put_failure;
442 if (nla_put_u32(skb, TCA_TCINDEX_HASH, p->
hash) ||
443 nla_put_u16(skb, TCA_TCINDEX_MASK, p->
mask) ||
444 nla_put_u32(skb, TCA_TCINDEX_SHIFT, p->
shift) ||
445 nla_put_u32(skb, TCA_TCINDEX_FALL_THROUGH, p->
fall_through))
446 goto nla_put_failure;
447 nla_nest_end(skb, nest);
466 nla_put_u32(skb, TCA_TCINDEX_CLASSID, r->
res.classid))
467 goto nla_put_failure;
470 goto nla_put_failure;
471 nla_nest_end(skb, nest);
474 goto nla_put_failure;
486 .classify = tcindex_classify,
487 .init = tcindex_init,
488 .destroy = tcindex_destroy,
491 .change = tcindex_change,
492 .delete = tcindex_delete,
493 .walk = tcindex_walk,
494 .dump = tcindex_dump,
498 static int __init init_tcindex(
void)
503 static void __exit exit_tcindex(
void)