net: sched: cls_u32: Undo tcf_bind_filter if u32_replace_hw_knode
When u32_replace_hw_knode fails, we need to undo the tcf_bind_filter
operation done at u32_set_parms.
Fixes: d34e3e1813
("net: cls_u32: Add support for skip-sw flag to tc u32 classifier.")
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Pedro Tammela <pctammela@mojatatu.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b3d0e04894
commit
9cb36faede
|
@ -712,8 +712,23 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
|
||||||
[TCA_U32_FLAGS] = { .type = NLA_U32 },
|
[TCA_U32_FLAGS] = { .type = NLA_U32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void u32_unbind_filter(struct tcf_proto *tp, struct tc_u_knode *n,
|
||||||
|
struct nlattr **tb)
|
||||||
|
{
|
||||||
|
if (tb[TCA_U32_CLASSID])
|
||||||
|
tcf_unbind_filter(tp, &n->res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void u32_bind_filter(struct tcf_proto *tp, struct tc_u_knode *n,
|
||||||
|
unsigned long base, struct nlattr **tb)
|
||||||
|
{
|
||||||
|
if (tb[TCA_U32_CLASSID]) {
|
||||||
|
n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
|
||||||
|
tcf_bind_filter(tp, &n->res, base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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_knode *n, struct nlattr **tb,
|
struct tc_u_knode *n, struct nlattr **tb,
|
||||||
struct nlattr *est, u32 flags, u32 fl_flags,
|
struct nlattr *est, u32 flags, u32 fl_flags,
|
||||||
struct netlink_ext_ack *extack)
|
struct netlink_ext_ack *extack)
|
||||||
|
@ -760,10 +775,6 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
|
||||||
if (ht_old)
|
if (ht_old)
|
||||||
ht_old->refcnt--;
|
ht_old->refcnt--;
|
||||||
}
|
}
|
||||||
if (tb[TCA_U32_CLASSID]) {
|
|
||||||
n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
|
|
||||||
tcf_bind_filter(tp, &n->res, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ifindex >= 0)
|
if (ifindex >= 0)
|
||||||
n->ifindex = ifindex;
|
n->ifindex = ifindex;
|
||||||
|
@ -903,17 +914,20 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
|
||||||
if (!new)
|
if (!new)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
err = u32_set_parms(net, tp, base, new, tb,
|
err = u32_set_parms(net, tp, new, tb, tca[TCA_RATE],
|
||||||
tca[TCA_RATE], flags, new->flags,
|
flags, new->flags, extack);
|
||||||
extack);
|
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
__u32_destroy_key(new);
|
__u32_destroy_key(new);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32_bind_filter(tp, new, base, tb);
|
||||||
|
|
||||||
err = u32_replace_hw_knode(tp, new, flags, extack);
|
err = u32_replace_hw_knode(tp, new, flags, extack);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
u32_unbind_filter(tp, new, tb);
|
||||||
|
|
||||||
__u32_destroy_key(new);
|
__u32_destroy_key(new);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1074,15 +1088,18 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
err = u32_set_parms(net, tp, base, n, tb, tca[TCA_RATE],
|
err = u32_set_parms(net, tp, n, tb, tca[TCA_RATE],
|
||||||
flags, n->flags, extack);
|
flags, n->flags, extack);
|
||||||
|
|
||||||
|
u32_bind_filter(tp, n, base, tb);
|
||||||
|
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
struct tc_u_knode __rcu **ins;
|
struct tc_u_knode __rcu **ins;
|
||||||
struct tc_u_knode *pins;
|
struct tc_u_knode *pins;
|
||||||
|
|
||||||
err = u32_replace_hw_knode(tp, n, flags, extack);
|
err = u32_replace_hw_knode(tp, n, flags, extack);
|
||||||
if (err)
|
if (err)
|
||||||
goto errhw;
|
goto errunbind;
|
||||||
|
|
||||||
if (!tc_in_hw(n->flags))
|
if (!tc_in_hw(n->flags))
|
||||||
n->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
|
n->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
|
||||||
|
@ -1100,7 +1117,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
errhw:
|
errunbind:
|
||||||
|
u32_unbind_filter(tp, n, tb);
|
||||||
|
|
||||||
#ifdef CONFIG_CLS_U32_MARK
|
#ifdef CONFIG_CLS_U32_MARK
|
||||||
free_percpu(n->pcpu_success);
|
free_percpu(n->pcpu_success);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue