aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2008-02-29 00:31:08 -0500
committerDavid S. Miller <davem@davemloft.net>2008-02-29 00:31:08 -0500
commit4c563f7669c10a12354b72b518c2287ffc6ebfb3 (patch)
tree056ec93f192f31640f32983c9e11bc7ce1c0692f /include
parent1e04d530705280770e003ac8db516722cca54758 (diff)
[XFRM]: Speed up xfrm_policy and xfrm_state walking
Change xfrm_policy and xfrm_state walking algorithm from O(n^2) to O(n). This is achieved adding the entries to one more list which is used solely for walking the entries. This also fixes some races where the dump can have duplicate or missing entries when the SPD/SADB is modified during an ongoing dump. Dumping SADB with 20000 entries using "time ip xfrm state" the sys time dropped from 1.012s to 0.080s. Signed-off-by: Timo Teras <timo.teras@iki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/linux/xfrm.h3
-rw-r--r--include/net/xfrm.h52
2 files changed, 52 insertions, 3 deletions
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index e31b8c84f2c9..0c82c80b277f 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -113,7 +113,8 @@ enum
113{ 113{
114 XFRM_POLICY_TYPE_MAIN = 0, 114 XFRM_POLICY_TYPE_MAIN = 0,
115 XFRM_POLICY_TYPE_SUB = 1, 115 XFRM_POLICY_TYPE_SUB = 1,
116 XFRM_POLICY_TYPE_MAX = 2 116 XFRM_POLICY_TYPE_MAX = 2,
117 XFRM_POLICY_TYPE_ANY = 255
117}; 118};
118 119
119enum 120enum
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index eea7785cc757..9b6205665190 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -121,6 +121,7 @@ extern struct mutex xfrm_cfg_mutex;
121struct xfrm_state 121struct xfrm_state
122{ 122{
123 /* Note: bydst is re-used during gc */ 123 /* Note: bydst is re-used during gc */
124 struct list_head all;
124 struct hlist_node bydst; 125 struct hlist_node bydst;
125 struct hlist_node bysrc; 126 struct hlist_node bysrc;
126 struct hlist_node byspi; 127 struct hlist_node byspi;
@@ -424,6 +425,7 @@ struct xfrm_tmpl
424struct xfrm_policy 425struct xfrm_policy
425{ 426{
426 struct xfrm_policy *next; 427 struct xfrm_policy *next;
428 struct list_head bytype;
427 struct hlist_node bydst; 429 struct hlist_node bydst;
428 struct hlist_node byidx; 430 struct hlist_node byidx;
429 431
@@ -1160,6 +1162,18 @@ struct xfrm6_tunnel {
1160 int priority; 1162 int priority;
1161}; 1163};
1162 1164
1165struct xfrm_state_walk {
1166 struct xfrm_state *state;
1167 int count;
1168 u8 proto;
1169};
1170
1171struct xfrm_policy_walk {
1172 struct xfrm_policy *policy;
1173 int count;
1174 u8 type, cur_type;
1175};
1176
1163extern void xfrm_init(void); 1177extern void xfrm_init(void);
1164extern void xfrm4_init(void); 1178extern void xfrm4_init(void);
1165extern void xfrm_state_init(void); 1179extern void xfrm_state_init(void);
@@ -1184,7 +1198,23 @@ static inline void xfrm6_fini(void)
1184extern int xfrm_proc_init(void); 1198extern int xfrm_proc_init(void);
1185#endif 1199#endif
1186 1200
1187extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *); 1201static inline void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto)
1202{
1203 walk->proto = proto;
1204 walk->state = NULL;
1205 walk->count = 0;
1206}
1207
1208static inline void xfrm_state_walk_done(struct xfrm_state_walk *walk)
1209{
1210 if (walk->state != NULL) {
1211 xfrm_state_put(walk->state);
1212 walk->state = NULL;
1213 }
1214}
1215
1216extern int xfrm_state_walk(struct xfrm_state_walk *walk,
1217 int (*func)(struct xfrm_state *, int, void*), void *);
1188extern struct xfrm_state *xfrm_state_alloc(void); 1218extern struct xfrm_state *xfrm_state_alloc(void);
1189extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 1219extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
1190 struct flowi *fl, struct xfrm_tmpl *tmpl, 1220 struct flowi *fl, struct xfrm_tmpl *tmpl,
@@ -1306,7 +1336,25 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
1306#endif 1336#endif
1307 1337
1308struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp); 1338struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp);
1309extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), void *); 1339
1340static inline void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type)
1341{
1342 walk->cur_type = XFRM_POLICY_TYPE_MAIN;
1343 walk->type = type;
1344 walk->policy = NULL;
1345 walk->count = 0;
1346}
1347
1348static inline void xfrm_policy_walk_done(struct xfrm_policy_walk *walk)
1349{
1350 if (walk->policy != NULL) {
1351 xfrm_pol_put(walk->policy);
1352 walk->policy = NULL;
1353 }
1354}
1355
1356extern int xfrm_policy_walk(struct xfrm_policy_walk *walk,
1357 int (*func)(struct xfrm_policy *, int, int, void*), void *);
1310int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); 1358int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
1311struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, 1359struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
1312 struct xfrm_selector *sel, 1360 struct xfrm_selector *sel,