net/sched: Change act_api and act_xxx modules to use IDR

Typically, each TC filter has its own action. All the actions of the
same type are saved in its hash table. But the hash buckets are too
small that it degrades to a list. And the performance is greatly
affected. For example, it takes about 0m11.914s to insert 64K rules.
If we convert the hash table to IDR, it only takes about 0m1.500s.
The improvement is huge.

But please note that the test result is based on previous patch that
cls_flower uses IDR.

Signed-off-by: Chris Mi <chrism@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Chris Mi
2017-08-30 02:31:59 -04:00
committed by David S. Miller
parent c15ab236d6
commit 65a206c01e
18 changed files with 275 additions and 341 deletions

View File

@@ -25,7 +25,6 @@
#include <linux/if_arp.h>
#define SAMPLE_TAB_MASK 7
static unsigned int sample_net_id;
static struct tc_action_ops act_sample_ops;
@@ -59,18 +58,18 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_SAMPLE_PARMS]);
exists = tcf_hash_check(tn, parm->index, a, bind);
exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
if (!exists) {
ret = tcf_hash_create(tn, parm->index, est, a,
&act_sample_ops, bind, false);
ret = tcf_idr_create(tn, parm->index, est, a,
&act_sample_ops, bind, false);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
tcf_hash_release(*a, bind);
tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -82,7 +81,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
psample_group = psample_group_get(net, s->psample_group_num);
if (!psample_group) {
if (ret == ACT_P_CREATED)
tcf_hash_release(*a, bind);
tcf_idr_release(*a, bind);
return -ENOMEM;
}
RCU_INIT_POINTER(s->psample_group, psample_group);
@@ -93,7 +92,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
}
if (ret == ACT_P_CREATED)
tcf_hash_insert(tn, *a);
tcf_idr_insert(tn, *a);
return ret;
}
@@ -221,7 +220,7 @@ static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, sample_net_id);
return tcf_hash_search(tn, a, index);
return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_sample_ops = {
@@ -241,7 +240,7 @@ static __net_init int sample_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, sample_net_id);
return tc_action_net_init(tn, &act_sample_ops, SAMPLE_TAB_MASK);
return tc_action_net_init(tn, &act_sample_ops);
}
static void __net_exit sample_exit_net(struct net *net)