From 367a8ce896f14018cc2c6cf2681aa440fff274f4 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Tue, 23 May 2017 09:42:37 -0700 Subject: [PATCH] net_sched: only create filter chains for new filters/actions tcf_chain_get() always creates a new filter chain if not found in existing ones. This is totally unnecessary when we get or delete filters, new chain should be only created for new filters (or new actions). Fixes: 5bc1701881e3 ("net: sched: introduce multichain support for filters") Cc: Jamal Hadi Salim Cc: Jiri Pirko Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/net/pkt_cls.h | 3 ++- net/sched/act_api.c | 2 +- net/sched/cls_api.c | 13 +++++++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 2c213a69c196..f7762295b7b8 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -18,7 +18,8 @@ int register_tcf_proto_ops(struct tcf_proto_ops *ops); int unregister_tcf_proto_ops(struct tcf_proto_ops *ops); #ifdef CONFIG_NET_CLS -struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index); +struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index, + bool create); void tcf_chain_put(struct tcf_chain *chain); int tcf_block_get(struct tcf_block **p_block, struct tcf_proto __rcu **p_filter_chain); diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 0ecf2a858767..aed6cf2e9fd8 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -34,7 +34,7 @@ static int tcf_action_goto_chain_init(struct tc_action *a, struct tcf_proto *tp) if (!tp) return -EINVAL; - a->goto_chain = tcf_chain_get(tp->chain->block, chain_index); + a->goto_chain = tcf_chain_get(tp->chain->block, chain_index, true); if (!a->goto_chain) return -ENOMEM; return 0; diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 89fbb35bc666..39da0c5801c9 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -220,7 +220,8 @@ static void tcf_chain_destroy(struct tcf_chain *chain) kfree(chain); } -struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index) +struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index, + bool create) { struct tcf_chain *chain; @@ -230,7 +231,10 @@ struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index) return chain; } } - return tcf_chain_create(block, chain_index); + if (create) + return tcf_chain_create(block, chain_index); + else + return NULL; } EXPORT_SYMBOL(tcf_chain_get); @@ -511,9 +515,10 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, err = -EINVAL; goto errout; } - chain = tcf_chain_get(block, chain_index); + chain = tcf_chain_get(block, chain_index, + n->nlmsg_type == RTM_NEWTFILTER); if (!chain) { - err = -ENOMEM; + err = n->nlmsg_type == RTM_NEWTFILTER ? -ENOMEM : -EINVAL; goto errout; } -- GitLab