diff options
author | Vlad Buslov <vladbu@mellanox.com> | 2019-02-11 10:55:44 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-02-12 13:41:33 -0500 |
commit | 7d5509fa0d3ddfe252b4418513e493ac98de3317 (patch) | |
tree | d20be370f7b681c84946808aa29e4a4456594227 | |
parent | ec6743a10996d38e0438e5f45f2347ff2f42df0a (diff) | |
download | linux-7d5509fa0d3ddfe252b4418513e493ac98de3317.tar.bz2 |
net: sched: extend proto ops with 'put' callback
Add optional tp->ops->put() API to be implemented for filter reference
counting. This new function is called by cls API to release filter
reference for filters returned by tp->ops->change() or tp->ops->get()
functions. Implement tfilter_put() helper to call tp->ops->put() only for
classifiers that implement it.
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/sch_generic.h | 1 | ||||
-rw-r--r-- | net/sched/cls_api.c | 12 |
2 files changed, 12 insertions, 1 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index e8cf36ed3e87..410dda80ca62 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -277,6 +277,7 @@ struct tcf_proto_ops { struct netlink_ext_ack *extack); void* (*get)(struct tcf_proto*, u32 handle); + void (*put)(struct tcf_proto *tp, void *f); int (*change)(struct net *net, struct sk_buff *, struct tcf_proto*, unsigned long, u32 handle, struct nlattr **, diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index a3e715d34efb..8fe38aa180cf 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -1870,6 +1870,12 @@ static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb, q, parent, NULL, event, false); } +static void tfilter_put(struct tcf_proto *tp, void *fh) +{ + if (tp->ops->put && fh) + tp->ops->put(tp, fh); +} + static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, struct netlink_ext_ack *extack) { @@ -2012,6 +2018,7 @@ replay: goto errout; } } else if (n->nlmsg_flags & NLM_F_EXCL) { + tfilter_put(tp, fh); NL_SET_ERR_MSG(extack, "Filter already exists"); err = -EEXIST; goto errout; @@ -2026,9 +2033,11 @@ replay: 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, extack); - if (err == 0) + if (err == 0) { tfilter_notify(net, skb, n, tp, block, q, parent, fh, RTM_NEWTFILTER, false); + tfilter_put(tp, fh); + } errout: if (err && tp_created) @@ -2259,6 +2268,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n, NL_SET_ERR_MSG(extack, "Failed to send filter notify message"); } + tfilter_put(tp, fh); errout: if (chain) { if (tp && !IS_ERR(tp)) |