Skip to content

Commit 65a206c

Browse files
mishuang2017davem330
authored andcommitted
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 <[email protected]> Signed-off-by: Jiri Pirko <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c15ab23 commit 65a206c

18 files changed

+278
-344
lines changed

include/net/act_api.h

Lines changed: 24 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,9 @@
1010
#include <net/net_namespace.h>
1111
#include <net/netns/generic.h>
1212

13-
14-
struct tcf_hashinfo {
15-
struct hlist_head *htab;
16-
unsigned int hmask;
17-
spinlock_t lock;
18-
u32 index;
13+
struct tcf_idrinfo {
14+
spinlock_t lock;
15+
struct idr action_idr;
1916
};
2017

2118
struct tc_action_ops;
@@ -25,9 +22,8 @@ struct tc_action {
2522
__u32 type; /* for backward compat(TCA_OLD_COMPAT) */
2623
__u32 order;
2724
struct list_head list;
28-
struct tcf_hashinfo *hinfo;
25+
struct tcf_idrinfo *idrinfo;
2926

30-
struct hlist_node tcfa_head;
3127
u32 tcfa_index;
3228
int tcfa_refcnt;
3329
int tcfa_bindcnt;
@@ -44,7 +40,6 @@ struct tc_action {
4440
struct tc_cookie *act_cookie;
4541
struct tcf_chain *goto_chain;
4642
};
47-
#define tcf_head common.tcfa_head
4843
#define tcf_index common.tcfa_index
4944
#define tcf_refcnt common.tcfa_refcnt
5045
#define tcf_bindcnt common.tcfa_bindcnt
@@ -57,27 +52,6 @@ struct tc_action {
5752
#define tcf_lock common.tcfa_lock
5853
#define tcf_rcu common.tcfa_rcu
5954

60-
static inline unsigned int tcf_hash(u32 index, unsigned int hmask)
61-
{
62-
return index & hmask;
63-
}
64-
65-
static inline int tcf_hashinfo_init(struct tcf_hashinfo *hf, unsigned int mask)
66-
{
67-
int i;
68-
69-
spin_lock_init(&hf->lock);
70-
hf->index = 0;
71-
hf->hmask = mask;
72-
hf->htab = kzalloc((mask + 1) * sizeof(struct hlist_head),
73-
GFP_KERNEL);
74-
if (!hf->htab)
75-
return -ENOMEM;
76-
for (i = 0; i < mask + 1; i++)
77-
INIT_HLIST_HEAD(&hf->htab[i]);
78-
return 0;
79-
}
80-
8155
/* Update lastuse only if needed, to avoid dirtying a cache line.
8256
* We use a temp variable to avoid fetching jiffies twice.
8357
*/
@@ -126,53 +100,51 @@ struct tc_action_ops {
126100
};
127101

128102
struct tc_action_net {
129-
struct tcf_hashinfo *hinfo;
103+
struct tcf_idrinfo *idrinfo;
130104
const struct tc_action_ops *ops;
131105
};
132106

133107
static inline
134108
int tc_action_net_init(struct tc_action_net *tn,
135-
const struct tc_action_ops *ops, unsigned int mask)
109+
const struct tc_action_ops *ops)
136110
{
137111
int err = 0;
138112

139-
tn->hinfo = kmalloc(sizeof(*tn->hinfo), GFP_KERNEL);
140-
if (!tn->hinfo)
113+
tn->idrinfo = kmalloc(sizeof(*tn->idrinfo), GFP_KERNEL);
114+
if (!tn->idrinfo)
141115
return -ENOMEM;
142116
tn->ops = ops;
143-
err = tcf_hashinfo_init(tn->hinfo, mask);
144-
if (err)
145-
kfree(tn->hinfo);
117+
spin_lock_init(&tn->idrinfo->lock);
118+
idr_init(&tn->idrinfo->action_idr);
146119
return err;
147120
}
148121

149-
void tcf_hashinfo_destroy(const struct tc_action_ops *ops,
150-
struct tcf_hashinfo *hinfo);
122+
void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
123+
struct tcf_idrinfo *idrinfo);
151124

152125
static inline void tc_action_net_exit(struct tc_action_net *tn)
153126
{
154-
tcf_hashinfo_destroy(tn->ops, tn->hinfo);
155-
kfree(tn->hinfo);
127+
tcf_idrinfo_destroy(tn->ops, tn->idrinfo);
128+
kfree(tn->idrinfo);
156129
}
157130

158131
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
159132
struct netlink_callback *cb, int type,
160133
const struct tc_action_ops *ops);
161-
int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
162-
u32 tcf_hash_new_index(struct tc_action_net *tn);
163-
bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
134+
int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
135+
bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
164136
int bind);
165-
int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
166-
struct tc_action **a, const struct tc_action_ops *ops, int bind,
167-
bool cpustats);
168-
void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
169-
void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a);
137+
int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
138+
struct tc_action **a, const struct tc_action_ops *ops,
139+
int bind, bool cpustats);
140+
void tcf_idr_cleanup(struct tc_action *a, struct nlattr *est);
141+
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a);
170142

171-
int __tcf_hash_release(struct tc_action *a, bool bind, bool strict);
143+
int __tcf_idr_release(struct tc_action *a, bool bind, bool strict);
172144

173-
static inline int tcf_hash_release(struct tc_action *a, bool bind)
145+
static inline int tcf_idr_release(struct tc_action *a, bool bind)
174146
{
175-
return __tcf_hash_release(a, bind, false);
147+
return __tcf_idr_release(a, bind, false);
176148
}
177149

178150
int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops);

0 commit comments

Comments
 (0)