Commit 2f7ef2f8 authored by Cong Wang's avatar Cong Wang Committed by David S. Miller

sched, cls: check if we could overwrite actions when changing a filter

When actions are attached to a filter, they are a part of the filter
itself, so when changing a filter we should allow to overwrite the actions
inside as well.

In my specific case, when I tried to _append_ a new action to an existing
filter which already has an action, I got EEXIST since kernel refused
to overwrite the existing one in kernel.

This patch checks if we are changing the filter checking NLM_F_CREATE flag
(Sigh, filters don't use NLM_F_REPLACE...) and then passes the boolean down
to actions. This fixes the problem above.

Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: default avatarCong Wang <cwang@twopensource.com>
Signed-off-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4940b8cd
...@@ -136,7 +136,7 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts, ...@@ -136,7 +136,7 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
int tcf_exts_validate(struct net *net, struct tcf_proto *tp, int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
struct nlattr **tb, struct nlattr *rate_tlv, struct nlattr **tb, struct nlattr *rate_tlv,
struct tcf_exts *exts); struct tcf_exts *exts, bool ovr);
void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts); void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts);
void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
struct tcf_exts *src); struct tcf_exts *src);
......
...@@ -199,7 +199,7 @@ struct tcf_proto_ops { ...@@ -199,7 +199,7 @@ struct tcf_proto_ops {
int (*change)(struct net *net, struct sk_buff *, int (*change)(struct net *net, struct sk_buff *,
struct tcf_proto*, unsigned long, struct tcf_proto*, unsigned long,
u32 handle, struct nlattr **, u32 handle, struct nlattr **,
unsigned long *); unsigned long *, bool);
int (*delete)(struct tcf_proto*, unsigned long); int (*delete)(struct tcf_proto*, unsigned long);
void (*walk)(struct tcf_proto*, struct tcf_walker *arg); void (*walk)(struct tcf_proto*, struct tcf_walker *arg);
......
...@@ -317,7 +317,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -317,7 +317,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
} }
} }
err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh); err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE);
if (err == 0) { if (err == 0) {
if (tp_created) { if (tp_created) {
spin_lock_bh(root_lock); spin_lock_bh(root_lock);
...@@ -504,7 +505,7 @@ void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts) ...@@ -504,7 +505,7 @@ void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
EXPORT_SYMBOL(tcf_exts_destroy); EXPORT_SYMBOL(tcf_exts_destroy);
int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
struct nlattr *rate_tlv, struct tcf_exts *exts) struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr)
{ {
#ifdef CONFIG_NET_CLS_ACT #ifdef CONFIG_NET_CLS_ACT
{ {
...@@ -513,7 +514,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, ...@@ -513,7 +514,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
INIT_LIST_HEAD(&exts->actions); INIT_LIST_HEAD(&exts->actions);
if (exts->police && tb[exts->police]) { if (exts->police && tb[exts->police]) {
act = tcf_action_init_1(net, tb[exts->police], rate_tlv, act = tcf_action_init_1(net, tb[exts->police], rate_tlv,
"police", TCA_ACT_NOREPLACE, "police", ovr,
TCA_ACT_BIND); TCA_ACT_BIND);
if (IS_ERR(act)) if (IS_ERR(act))
return PTR_ERR(act); return PTR_ERR(act);
...@@ -523,7 +524,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, ...@@ -523,7 +524,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
} else if (exts->action && tb[exts->action]) { } else if (exts->action && tb[exts->action]) {
int err; int err;
err = tcf_action_init(net, tb[exts->action], rate_tlv, err = tcf_action_init(net, tb[exts->action], rate_tlv,
NULL, TCA_ACT_NOREPLACE, NULL, ovr,
TCA_ACT_BIND, &exts->actions); TCA_ACT_BIND, &exts->actions);
if (err) if (err)
return err; return err;
......
...@@ -130,14 +130,14 @@ static const struct nla_policy basic_policy[TCA_BASIC_MAX + 1] = { ...@@ -130,14 +130,14 @@ static const struct nla_policy basic_policy[TCA_BASIC_MAX + 1] = {
static int basic_set_parms(struct net *net, struct tcf_proto *tp, static int basic_set_parms(struct net *net, struct tcf_proto *tp,
struct basic_filter *f, unsigned long base, struct basic_filter *f, unsigned long base,
struct nlattr **tb, struct nlattr **tb,
struct nlattr *est) struct nlattr *est, bool ovr)
{ {
int err; int err;
struct tcf_exts e; struct tcf_exts e;
struct tcf_ematch_tree t; struct tcf_ematch_tree t;
tcf_exts_init(&e, TCA_BASIC_ACT, TCA_BASIC_POLICE); tcf_exts_init(&e, TCA_BASIC_ACT, TCA_BASIC_POLICE);
err = tcf_exts_validate(net, tp, tb, est, &e); err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
if (err < 0) if (err < 0)
return err; return err;
...@@ -161,7 +161,7 @@ static int basic_set_parms(struct net *net, struct tcf_proto *tp, ...@@ -161,7 +161,7 @@ static int basic_set_parms(struct net *net, struct tcf_proto *tp,
static int basic_change(struct net *net, struct sk_buff *in_skb, static int basic_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, unsigned long *arg) struct nlattr **tca, unsigned long *arg, bool ovr)
{ {
int err; int err;
struct basic_head *head = tp->root; struct basic_head *head = tp->root;
...@@ -179,7 +179,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, ...@@ -179,7 +179,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
if (f != NULL) { if (f != NULL) {
if (handle && f->handle != handle) if (handle && f->handle != handle)
return -EINVAL; return -EINVAL;
return basic_set_parms(net, tp, f, base, tb, tca[TCA_RATE]); return basic_set_parms(net, tp, f, base, tb, tca[TCA_RATE], ovr);
} }
err = -ENOBUFS; err = -ENOBUFS;
...@@ -206,7 +206,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, ...@@ -206,7 +206,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
f->handle = head->hgenerator; f->handle = head->hgenerator;
} }
err = basic_set_parms(net, tp, f, base, tb, tca[TCA_RATE]); err = basic_set_parms(net, tp, f, base, tb, tca[TCA_RATE], ovr);
if (err < 0) if (err < 0)
goto errout; goto errout;
......
...@@ -156,7 +156,7 @@ static void cls_bpf_put(struct tcf_proto *tp, unsigned long f) ...@@ -156,7 +156,7 @@ static void cls_bpf_put(struct tcf_proto *tp, unsigned long f)
static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
struct cls_bpf_prog *prog, struct cls_bpf_prog *prog,
unsigned long base, struct nlattr **tb, unsigned long base, struct nlattr **tb,
struct nlattr *est) struct nlattr *est, bool ovr)
{ {
struct sock_filter *bpf_ops, *bpf_old; struct sock_filter *bpf_ops, *bpf_old;
struct tcf_exts exts; struct tcf_exts exts;
...@@ -170,7 +170,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, ...@@ -170,7 +170,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp,
return -EINVAL; return -EINVAL;
tcf_exts_init(&exts, TCA_BPF_ACT, TCA_BPF_POLICE); tcf_exts_init(&exts, TCA_BPF_ACT, TCA_BPF_POLICE);
ret = tcf_exts_validate(net, tp, tb, est, &exts); ret = tcf_exts_validate(net, tp, tb, est, &exts, ovr);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -242,7 +242,7 @@ static u32 cls_bpf_grab_new_handle(struct tcf_proto *tp, ...@@ -242,7 +242,7 @@ static u32 cls_bpf_grab_new_handle(struct tcf_proto *tp,
static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
unsigned long *arg) unsigned long *arg, bool ovr)
{ {
struct cls_bpf_head *head = tp->root; struct cls_bpf_head *head = tp->root;
struct cls_bpf_prog *prog = (struct cls_bpf_prog *) *arg; struct cls_bpf_prog *prog = (struct cls_bpf_prog *) *arg;
...@@ -260,7 +260,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, ...@@ -260,7 +260,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
if (handle && prog->handle != handle) if (handle && prog->handle != handle)
return -EINVAL; return -EINVAL;
return cls_bpf_modify_existing(net, tp, prog, base, tb, return cls_bpf_modify_existing(net, tp, prog, base, tb,
tca[TCA_RATE]); tca[TCA_RATE], ovr);
} }
prog = kzalloc(sizeof(*prog), GFP_KERNEL); prog = kzalloc(sizeof(*prog), GFP_KERNEL);
...@@ -277,7 +277,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, ...@@ -277,7 +277,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
goto errout; goto errout;
} }
ret = cls_bpf_modify_existing(net, tp, prog, base, tb, tca[TCA_RATE]); ret = cls_bpf_modify_existing(net, tp, prog, base, tb, tca[TCA_RATE], ovr);
if (ret < 0) if (ret < 0)
goto errout; goto errout;
......
...@@ -83,7 +83,7 @@ static const struct nla_policy cgroup_policy[TCA_CGROUP_MAX + 1] = { ...@@ -83,7 +83,7 @@ static const struct nla_policy cgroup_policy[TCA_CGROUP_MAX + 1] = {
static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb, static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
unsigned long *arg) unsigned long *arg, bool ovr)
{ {
struct nlattr *tb[TCA_CGROUP_MAX + 1]; struct nlattr *tb[TCA_CGROUP_MAX + 1];
struct cls_cgroup_head *head = tp->root; struct cls_cgroup_head *head = tp->root;
...@@ -119,7 +119,7 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb, ...@@ -119,7 +119,7 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
tcf_exts_init(&e, TCA_CGROUP_ACT, TCA_CGROUP_POLICE); tcf_exts_init(&e, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e); err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -349,7 +349,7 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = { ...@@ -349,7 +349,7 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = {
static int flow_change(struct net *net, struct sk_buff *in_skb, static int flow_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
unsigned long *arg) unsigned long *arg, bool ovr)
{ {
struct flow_head *head = tp->root; struct flow_head *head = tp->root;
struct flow_filter *f; struct flow_filter *f;
...@@ -393,7 +393,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb, ...@@ -393,7 +393,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
} }
tcf_exts_init(&e, TCA_FLOW_ACT, TCA_FLOW_POLICE); tcf_exts_init(&e, TCA_FLOW_ACT, TCA_FLOW_POLICE);
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e); err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -169,7 +169,7 @@ static const struct nla_policy fw_policy[TCA_FW_MAX + 1] = { ...@@ -169,7 +169,7 @@ static const struct nla_policy fw_policy[TCA_FW_MAX + 1] = {
static int static int
fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f, fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
struct nlattr **tb, struct nlattr **tca, unsigned long base) struct nlattr **tb, struct nlattr **tca, unsigned long base, bool ovr)
{ {
struct fw_head *head = tp->root; struct fw_head *head = tp->root;
struct tcf_exts e; struct tcf_exts e;
...@@ -177,7 +177,7 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f, ...@@ -177,7 +177,7 @@ fw_change_attrs(struct net *net, struct tcf_proto *tp, struct fw_filter *f,
int err; int err;
tcf_exts_init(&e, TCA_FW_ACT, TCA_FW_POLICE); tcf_exts_init(&e, TCA_FW_ACT, TCA_FW_POLICE);
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e); err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
if (err < 0) if (err < 0)
return err; return err;
...@@ -218,7 +218,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, ...@@ -218,7 +218,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, u32 handle,
struct nlattr **tca, struct nlattr **tca,
unsigned long *arg) unsigned long *arg, bool ovr)
{ {
struct fw_head *head = tp->root; struct fw_head *head = tp->root;
struct fw_filter *f = (struct fw_filter *) *arg; struct fw_filter *f = (struct fw_filter *) *arg;
...@@ -236,7 +236,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, ...@@ -236,7 +236,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
if (f != NULL) { if (f != NULL) {
if (f->id != handle && handle) if (f->id != handle && handle)
return -EINVAL; return -EINVAL;
return fw_change_attrs(net, tp, f, tb, tca, base); return fw_change_attrs(net, tp, f, tb, tca, base, ovr);
} }
if (!handle) if (!handle)
...@@ -264,7 +264,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, ...@@ -264,7 +264,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
tcf_exts_init(&f->exts, TCA_FW_ACT, TCA_FW_POLICE); tcf_exts_init(&f->exts, TCA_FW_ACT, TCA_FW_POLICE);
f->id = handle; f->id = handle;
err = fw_change_attrs(net, tp, f, tb, tca, base); err = fw_change_attrs(net, tp, f, tb, tca, base, ovr);
if (err < 0) if (err < 0)
goto errout; goto errout;
......
...@@ -333,7 +333,8 @@ static const struct nla_policy route4_policy[TCA_ROUTE4_MAX + 1] = { ...@@ -333,7 +333,8 @@ static const struct nla_policy route4_policy[TCA_ROUTE4_MAX + 1] = {
static int route4_set_parms(struct net *net, struct tcf_proto *tp, static int route4_set_parms(struct net *net, struct tcf_proto *tp,
unsigned long base, struct route4_filter *f, unsigned long base, struct route4_filter *f,
u32 handle, struct route4_head *head, u32 handle, struct route4_head *head,
struct nlattr **tb, struct nlattr *est, int new) struct nlattr **tb, struct nlattr *est, int new,
bool ovr)
{ {
int err; int err;
u32 id = 0, to = 0, nhandle = 0x8000; u32 id = 0, to = 0, nhandle = 0x8000;
...@@ -343,7 +344,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp, ...@@ -343,7 +344,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
struct tcf_exts e; struct tcf_exts e;
tcf_exts_init(&e, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE); tcf_exts_init(&e, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
err = tcf_exts_validate(net, tp, tb, est, &e); err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
if (err < 0) if (err < 0)
return err; return err;
...@@ -428,7 +429,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, ...@@ -428,7 +429,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, u32 handle,
struct nlattr **tca, struct nlattr **tca,
unsigned long *arg) unsigned long *arg, bool ovr)
{ {
struct route4_head *head = tp->root; struct route4_head *head = tp->root;
struct route4_filter *f, *f1, **fp; struct route4_filter *f, *f1, **fp;
...@@ -455,7 +456,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, ...@@ -455,7 +456,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
old_handle = f->handle; old_handle = f->handle;
err = route4_set_parms(net, tp, base, f, handle, head, tb, err = route4_set_parms(net, tp, base, f, handle, head, tb,
tca[TCA_RATE], 0); tca[TCA_RATE], 0, ovr);
if (err < 0) if (err < 0)
return err; return err;
...@@ -479,7 +480,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, ...@@ -479,7 +480,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
tcf_exts_init(&f->exts, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE); tcf_exts_init(&f->exts, TCA_ROUTE4_ACT, TCA_ROUTE4_POLICE);
err = route4_set_parms(net, tp, base, f, handle, head, tb, err = route4_set_parms(net, tp, base, f, handle, head, tb,
tca[TCA_RATE], 1); tca[TCA_RATE], 1, ovr);
if (err < 0) if (err < 0)
goto errout; goto errout;
......
...@@ -415,7 +415,7 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb, ...@@ -415,7 +415,7 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, u32 handle,
struct nlattr **tca, struct nlattr **tca,
unsigned long *arg) unsigned long *arg, bool ovr)
{ {
struct rsvp_head *data = tp->root; struct rsvp_head *data = tp->root;
struct rsvp_filter *f, **fp; struct rsvp_filter *f, **fp;
...@@ -436,7 +436,7 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb, ...@@ -436,7 +436,7 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
tcf_exts_init(&e, TCA_RSVP_ACT, TCA_RSVP_POLICE); tcf_exts_init(&e, TCA_RSVP_ACT, TCA_RSVP_POLICE);
err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e); err = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &e, ovr);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -192,7 +192,7 @@ static int ...@@ -192,7 +192,7 @@ 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,
struct tcindex_filter_result *r, struct nlattr **tb, struct tcindex_filter_result *r, struct nlattr **tb,
struct nlattr *est) struct nlattr *est, bool ovr)
{ {
int err, balloc = 0; int err, balloc = 0;
struct tcindex_filter_result new_filter_result, *old_r = r; struct tcindex_filter_result new_filter_result, *old_r = r;
...@@ -202,7 +202,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -202,7 +202,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
struct tcf_exts e; struct tcf_exts e;
tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); tcf_exts_init(&e, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
err = tcf_exts_validate(net, tp, tb, est, &e); err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
if (err < 0) if (err < 0)
return err; return err;
...@@ -331,7 +331,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ...@@ -331,7 +331,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
static int static int
tcindex_change(struct net *net, struct sk_buff *in_skb, tcindex_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, unsigned long *arg) struct nlattr **tca, unsigned long *arg, bool ovr)
{ {
struct nlattr *opt = tca[TCA_OPTIONS]; struct nlattr *opt = tca[TCA_OPTIONS];
struct nlattr *tb[TCA_TCINDEX_MAX + 1]; struct nlattr *tb[TCA_TCINDEX_MAX + 1];
...@@ -351,7 +351,7 @@ tcindex_change(struct net *net, struct sk_buff *in_skb, ...@@ -351,7 +351,7 @@ tcindex_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
return tcindex_set_parms(net, tp, base, handle, p, r, tb, return tcindex_set_parms(net, tp, base, handle, p, r, tb,
tca[TCA_RATE]); tca[TCA_RATE], ovr);
} }
......
...@@ -486,13 +486,13 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = { ...@@ -486,13 +486,13 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
static int u32_set_parms(struct net *net, struct tcf_proto *tp, static int u32_set_parms(struct net *net, struct tcf_proto *tp,
unsigned long base, struct tc_u_hnode *ht, unsigned long base, struct tc_u_hnode *ht,
struct tc_u_knode *n, struct nlattr **tb, struct tc_u_knode *n, struct nlattr **tb,
struct nlattr *est) struct nlattr *est, bool ovr)
{ {
int err; int err;
struct tcf_exts e; struct tcf_exts e;
tcf_exts_init(&e, TCA_U32_ACT, TCA_U32_POLICE); tcf_exts_init(&e, TCA_U32_ACT, TCA_U32_POLICE);
err = tcf_exts_validate(net, tp, tb, est, &e); err = tcf_exts_validate(net, tp, tb, est, &e, ovr);
if (err < 0) if (err < 0)
return err; return err;
...@@ -545,7 +545,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp, ...@@ -545,7 +545,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
static int u32_change(struct net *net, struct sk_buff *in_skb, static int u32_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, struct nlattr **tca,
unsigned long *arg) unsigned long *arg, bool ovr)
{ {
struct tc_u_common *tp_c = tp->data; struct tc_u_common *tp_c = tp->data;
struct tc_u_hnode *ht; struct tc_u_hnode *ht;
...@@ -569,7 +569,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, ...@@ -569,7 +569,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
return -EINVAL; return -EINVAL;
return u32_set_parms(net, tp, base, n->ht_up, n, tb, return u32_set_parms(net, tp, base, n->ht_up, n, tb,
tca[TCA_RATE]); tca[TCA_RATE], ovr);
} }
if (tb[TCA_U32_DIVISOR]) { if (tb[TCA_U32_DIVISOR]) {
...@@ -656,7 +656,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, ...@@ -656,7 +656,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
} }
#endif #endif
err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE]); err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE], ovr);
if (err == 0) { if (err == 0) {
struct tc_u_knode **ins; struct tc_u_knode **ins;
for (ins = &ht->ht[TC_U32_HASH(handle)]; *ins; ins = &(*ins)->next) for (ins = &ht->ht[TC_U32_HASH(handle)]; *ins; ins = &(*ins)->next)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment