net_sched: only create filter chains for new filters/actions
authorWANG Cong <xiyou.wangcong@gmail.com>
Tue, 23 May 2017 16:42:37 +0000 (09:42 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 25 May 2017 16:15:05 +0000 (12:15 -0400)
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 <jhs@mojatatu.com>
Cc: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/pkt_cls.h
net/sched/act_api.c
net/sched/cls_api.c

index 2c213a69c196827cc3ab9f9521f6c09bdf0bad3e..f7762295b7b8d407e41a14d02be032c28adb1f0a 100644 (file)
@@ -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);
index 0ecf2a858767a768f00ce08f30fb57f0a6dc50c2..aed6cf2e9fd87792e5124838466a98045fd60ce4 100644 (file)
@@ -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;
index 89fbb35bc666c251ba9fde582763c886921912c4..39da0c5801c908e28c4e258319adefde836c6b0c 100644 (file)
@@ -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 @@ replay:
                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;
        }