Skip to content

Commit 9cb36fa

Browse files
vbnogueiradavem330
authored andcommitted
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: d34e3e1 ("net: cls_u32: Add support for skip-sw flag to tc u32 classifier.") Signed-off-by: Victor Nogueira <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Reviewed-by: Pedro Tammela <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b3d0e04 commit 9cb36fa

File tree

1 file changed

+30
-11
lines changed

1 file changed

+30
-11
lines changed

net/sched/cls_u32.c

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -712,8 +712,23 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
712712
[TCA_U32_FLAGS] = { .type = NLA_U32 },
713713
};
714714

715+
static void u32_unbind_filter(struct tcf_proto *tp, struct tc_u_knode *n,
716+
struct nlattr **tb)
717+
{
718+
if (tb[TCA_U32_CLASSID])
719+
tcf_unbind_filter(tp, &n->res);
720+
}
721+
722+
static void u32_bind_filter(struct tcf_proto *tp, struct tc_u_knode *n,
723+
unsigned long base, struct nlattr **tb)
724+
{
725+
if (tb[TCA_U32_CLASSID]) {
726+
n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
727+
tcf_bind_filter(tp, &n->res, base);
728+
}
729+
}
730+
715731
static int u32_set_parms(struct net *net, struct tcf_proto *tp,
716-
unsigned long base,
717732
struct tc_u_knode *n, struct nlattr **tb,
718733
struct nlattr *est, u32 flags, u32 fl_flags,
719734
struct netlink_ext_ack *extack)
@@ -760,10 +775,6 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
760775
if (ht_old)
761776
ht_old->refcnt--;
762777
}
763-
if (tb[TCA_U32_CLASSID]) {
764-
n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
765-
tcf_bind_filter(tp, &n->res, base);
766-
}
767778

768779
if (ifindex >= 0)
769780
n->ifindex = ifindex;
@@ -903,17 +914,20 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
903914
if (!new)
904915
return -ENOMEM;
905916

906-
err = u32_set_parms(net, tp, base, new, tb,
907-
tca[TCA_RATE], flags, new->flags,
908-
extack);
917+
err = u32_set_parms(net, tp, new, tb, tca[TCA_RATE],
918+
flags, new->flags, extack);
909919

910920
if (err) {
911921
__u32_destroy_key(new);
912922
return err;
913923
}
914924

925+
u32_bind_filter(tp, new, base, tb);
926+
915927
err = u32_replace_hw_knode(tp, new, flags, extack);
916928
if (err) {
929+
u32_unbind_filter(tp, new, tb);
930+
917931
__u32_destroy_key(new);
918932
return err;
919933
}
@@ -1074,15 +1088,18 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
10741088
}
10751089
#endif
10761090

1077-
err = u32_set_parms(net, tp, base, n, tb, tca[TCA_RATE],
1091+
err = u32_set_parms(net, tp, n, tb, tca[TCA_RATE],
10781092
flags, n->flags, extack);
1093+
1094+
u32_bind_filter(tp, n, base, tb);
1095+
10791096
if (err == 0) {
10801097
struct tc_u_knode __rcu **ins;
10811098
struct tc_u_knode *pins;
10821099

10831100
err = u32_replace_hw_knode(tp, n, flags, extack);
10841101
if (err)
1085-
goto errhw;
1102+
goto errunbind;
10861103

10871104
if (!tc_in_hw(n->flags))
10881105
n->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
@@ -1100,7 +1117,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
11001117
return 0;
11011118
}
11021119

1103-
errhw:
1120+
errunbind:
1121+
u32_unbind_filter(tp, n, tb);
1122+
11041123
#ifdef CONFIG_CLS_U32_MARK
11051124
free_percpu(n->pcpu_success);
11061125
#endif

0 commit comments

Comments
 (0)