|
@@ -188,6 +188,12 @@ static const struct nla_policy tcindex_policy[TCA_TCINDEX_MAX + 1] = {
|
|
[TCA_TCINDEX_CLASSID] = { .type = NLA_U32 },
|
|
[TCA_TCINDEX_CLASSID] = { .type = NLA_U32 },
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static void tcindex_filter_result_init(struct tcindex_filter_result *r)
|
|
|
|
+{
|
|
|
|
+ memset(r, 0, sizeof(*r));
|
|
|
|
+ tcf_exts_init(&r->exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
|
|
|
|
+}
|
|
|
|
+
|
|
static int
|
|
static int
|
|
tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|
tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|
u32 handle, struct tcindex_data *p,
|
|
u32 handle, struct tcindex_data *p,
|
|
@@ -207,15 +213,11 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|
return err;
|
|
return err;
|
|
|
|
|
|
memcpy(&cp, p, sizeof(cp));
|
|
memcpy(&cp, p, sizeof(cp));
|
|
- memset(&new_filter_result, 0, sizeof(new_filter_result));
|
|
|
|
- tcf_exts_init(&new_filter_result.exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
|
|
|
|
|
|
+ tcindex_filter_result_init(&new_filter_result);
|
|
|
|
|
|
|
|
+ tcindex_filter_result_init(&cr);
|
|
if (old_r)
|
|
if (old_r)
|
|
- memcpy(&cr, r, sizeof(cr));
|
|
|
|
- else {
|
|
|
|
- memset(&cr, 0, sizeof(cr));
|
|
|
|
- tcf_exts_init(&cr.exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
|
|
|
|
- }
|
|
|
|
|
|
+ cr.res = r->res;
|
|
|
|
|
|
if (tb[TCA_TCINDEX_HASH])
|
|
if (tb[TCA_TCINDEX_HASH])
|
|
cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
|
|
cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
|
|
@@ -267,9 +269,14 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|
err = -ENOMEM;
|
|
err = -ENOMEM;
|
|
if (!cp.perfect && !cp.h) {
|
|
if (!cp.perfect && !cp.h) {
|
|
if (valid_perfect_hash(&cp)) {
|
|
if (valid_perfect_hash(&cp)) {
|
|
|
|
+ int i;
|
|
|
|
+
|
|
cp.perfect = kcalloc(cp.hash, sizeof(*r), GFP_KERNEL);
|
|
cp.perfect = kcalloc(cp.hash, sizeof(*r), GFP_KERNEL);
|
|
if (!cp.perfect)
|
|
if (!cp.perfect)
|
|
goto errout;
|
|
goto errout;
|
|
|
|
+ for (i = 0; i < cp.hash; i++)
|
|
|
|
+ tcf_exts_init(&cp.perfect[i].exts, TCA_TCINDEX_ACT,
|
|
|
|
+ TCA_TCINDEX_POLICE);
|
|
balloc = 1;
|
|
balloc = 1;
|
|
} else {
|
|
} else {
|
|
cp.h = kcalloc(cp.hash, sizeof(f), GFP_KERNEL);
|
|
cp.h = kcalloc(cp.hash, sizeof(f), GFP_KERNEL);
|
|
@@ -295,14 +302,17 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|
tcf_bind_filter(tp, &cr.res, base);
|
|
tcf_bind_filter(tp, &cr.res, base);
|
|
}
|
|
}
|
|
|
|
|
|
- tcf_exts_change(tp, &cr.exts, &e);
|
|
|
|
|
|
+ if (old_r)
|
|
|
|
+ tcf_exts_change(tp, &r->exts, &e);
|
|
|
|
+ else
|
|
|
|
+ tcf_exts_change(tp, &cr.exts, &e);
|
|
|
|
|
|
tcf_tree_lock(tp);
|
|
tcf_tree_lock(tp);
|
|
if (old_r && old_r != r)
|
|
if (old_r && old_r != r)
|
|
- memset(old_r, 0, sizeof(*old_r));
|
|
|
|
|
|
+ tcindex_filter_result_init(old_r);
|
|
|
|
|
|
memcpy(p, &cp, sizeof(cp));
|
|
memcpy(p, &cp, sizeof(cp));
|
|
- memcpy(r, &cr, sizeof(cr));
|
|
|
|
|
|
+ r->res = cr.res;
|
|
|
|
|
|
if (r == &new_filter_result) {
|
|
if (r == &new_filter_result) {
|
|
struct tcindex_filter **fp;
|
|
struct tcindex_filter **fp;
|