@@ -713,6 +713,7 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
};
#define U32_SET_FLAGS_BOUND 0x1
+#define U32_SET_FLAGS_DECR_HTDOWN 0x2
static int u32_set_parms(struct net *net, struct tcf_proto *tp,
unsigned long base,
@@ -759,8 +760,10 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
ht_old = rtnl_dereference(n->ht_down);
rcu_assign_pointer(n->ht_down, ht_down);
- if (ht_old)
+ if (ht_old) {
+ *set_flags |= U32_SET_FLAGS_DECR_HTDOWN;
ht_old->refcnt--;
+ }
}
if (tb[TCA_U32_CLASSID]) {
n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
@@ -921,6 +924,13 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
if (set_flags & U32_SET_FLAGS_BOUND)
tcf_unbind_filter(tp, &new->res);
+ if (set_flags & U32_SET_FLAGS_DECR_HTDOWN) {
+ struct tc_u_hnode *ht_old;
+
+ ht_old = rtnl_dereference(n->ht_down);
+ if (ht_old)
+ ht_old->refcnt++;
+ }
__u32_destroy_key(new);
return err;
}