Commit 2518c7c2 authored by David S. Miller's avatar David S. Miller

[XFRM]: Hash policies when non-prefixed.

This idea is from Alexey Kuznetsov.

It is common for policies to be non-prefixed.  And for
that case we can optimize lookups, insert, etc. quite
a bit.

For each direction, we have a dynamically sized policy
hash table for non-prefixed policies.  We also have a
hash table on policy->index.

For prefixed policies, we have a list per-direction which
we will consult on lookups when a non-prefix hashtable
lookup fails.

This still isn't as efficient as I would like it.  There
are four immediate problems:

1) Lots of excessive refcounting, which can be fixed just
   like xfrm_state was
2) We do 2 hash probes on insert, one to look for dups and
   one to allocate a unique policy->index.  Althought I wonder
   how much this matters since xfrm_state inserts do up to
   3 hash probes and that seems to perform fine.
3) xfrm_policy_insert() is very complex because of the priority
   ordering and entry replacement logic.
4) Lots of counter bumping, in addition to policy refcounts,
   in the form of xfrm_policy_count[].  This is merely used
   to let code path(s) know that some IPSEC rules exist.  So
   this count is indexed per-direction, maybe that is overkill.
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c1969f29
...@@ -331,7 +331,8 @@ struct xfrm_tmpl ...@@ -331,7 +331,8 @@ struct xfrm_tmpl
struct xfrm_policy struct xfrm_policy
{ {
struct xfrm_policy *next; struct xfrm_policy *next;
struct list_head list; struct hlist_node bydst;
struct hlist_node byidx;
/* This lock only affects elements except for entry. */ /* This lock only affects elements except for entry. */
rwlock_t lock; rwlock_t lock;
...@@ -385,21 +386,7 @@ struct xfrm_mgr ...@@ -385,21 +386,7 @@ struct xfrm_mgr
extern int xfrm_register_km(struct xfrm_mgr *km); extern int xfrm_register_km(struct xfrm_mgr *km);
extern int xfrm_unregister_km(struct xfrm_mgr *km); extern int xfrm_unregister_km(struct xfrm_mgr *km);
extern unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];
extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
#ifdef CONFIG_XFRM_SUB_POLICY
extern struct xfrm_policy *xfrm_policy_list_sub[XFRM_POLICY_MAX*2];
static inline int xfrm_policy_lists_empty(int dir)
{
return (!xfrm_policy_list[dir] && !xfrm_policy_list_sub[dir]);
}
#else
static inline int xfrm_policy_lists_empty(int dir)
{
return (!xfrm_policy_list[dir]);
}
#endif
static inline void xfrm_pol_hold(struct xfrm_policy *policy) static inline void xfrm_pol_hold(struct xfrm_policy *policy)
{ {
...@@ -678,7 +665,7 @@ static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *sk ...@@ -678,7 +665,7 @@ static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *sk
if (sk && sk->sk_policy[XFRM_POLICY_IN]) if (sk && sk->sk_policy[XFRM_POLICY_IN])
return __xfrm_policy_check(sk, dir, skb, family); return __xfrm_policy_check(sk, dir, skb, family);
return (xfrm_policy_lists_empty(dir) && !skb->sp) || return (!xfrm_policy_count[dir] && !skb->sp) ||
(skb->dst->flags & DST_NOPOLICY) || (skb->dst->flags & DST_NOPOLICY) ||
__xfrm_policy_check(sk, dir, skb, family); __xfrm_policy_check(sk, dir, skb, family);
} }
...@@ -698,7 +685,7 @@ extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family); ...@@ -698,7 +685,7 @@ extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family) static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
{ {
return xfrm_policy_lists_empty(XFRM_POLICY_OUT) || return !xfrm_policy_count[XFRM_POLICY_OUT] ||
(skb->dst->flags & DST_NOXFRM) || (skb->dst->flags & DST_NOXFRM) ||
__xfrm_route_forward(skb, family); __xfrm_route_forward(skb, family);
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment