aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/xfrm/xfrm_state.c75
1 files changed, 35 insertions, 40 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 535d43c14720..7e5daafc1863 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -35,7 +35,7 @@ EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);
35/* Each xfrm_state may be linked to two tables: 35/* Each xfrm_state may be linked to two tables:
36 36
37 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) 37 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
38 2. Hash table by daddr to find what SAs exist for given 38 2. Hash table by (daddr,family,reqid) to find what SAs exist for given
39 destination/tunnel endpoint. (output) 39 destination/tunnel endpoint. (output)
40 */ 40 */
41 41
@@ -55,62 +55,56 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
55static unsigned int xfrm_state_num; 55static unsigned int xfrm_state_num;
56static unsigned int xfrm_state_genid; 56static unsigned int xfrm_state_genid;
57 57
58static inline unsigned int __xfrm4_dst_hash(xfrm_address_t *addr, unsigned int hmask) 58static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr)
59{ 59{
60 unsigned int h; 60 return ntohl(addr->a4);
61 h = ntohl(addr->a4);
62 h = (h ^ (h>>16)) & hmask;
63 return h;
64}
65
66static inline unsigned int __xfrm6_dst_hash(xfrm_address_t *addr, unsigned int hmask)
67{
68 unsigned int h;
69 h = ntohl(addr->a6[2]^addr->a6[3]);
70 h = (h ^ (h>>16)) & hmask;
71 return h;
72} 61}
73 62
74static inline unsigned int __xfrm4_src_hash(xfrm_address_t *addr, unsigned int hmask) 63static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr)
75{ 64{
76 return __xfrm4_dst_hash(addr, hmask); 65 return ntohl(addr->a6[2]^addr->a6[3]);
77} 66}
78 67
79static inline unsigned int __xfrm6_src_hash(xfrm_address_t *addr, unsigned int hmask) 68static inline unsigned int __xfrm_dst_hash(xfrm_address_t *addr,
80{ 69 u32 reqid, unsigned short family,
81 return __xfrm6_dst_hash(addr, hmask); 70 unsigned int hmask)
82}
83
84static inline unsigned __xfrm_src_hash(xfrm_address_t *addr, unsigned short family, unsigned int hmask)
85{ 71{
72 unsigned int h = family ^ reqid;
86 switch (family) { 73 switch (family) {
87 case AF_INET: 74 case AF_INET:
88 return __xfrm4_src_hash(addr, hmask); 75 h ^= __xfrm4_addr_hash(addr);
76 break;
89 case AF_INET6: 77 case AF_INET6:
90 return __xfrm6_src_hash(addr, hmask); 78 h ^= __xfrm6_addr_hash(addr);
91 } 79 break;
92 return 0; 80 };
81 return (h ^ (h >> 16)) & hmask;
93} 82}
94 83
95static inline unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family) 84static inline unsigned int xfrm_dst_hash(xfrm_address_t *addr, u32 reqid,
85 unsigned short family)
96{ 86{
97 return __xfrm_src_hash(addr, family, xfrm_state_hmask); 87 return __xfrm_dst_hash(addr, reqid, family, xfrm_state_hmask);
98} 88}
99 89
100static inline unsigned int __xfrm_dst_hash(xfrm_address_t *addr, unsigned short family, unsigned int hmask) 90static inline unsigned __xfrm_src_hash(xfrm_address_t *addr, unsigned short family,
91 unsigned int hmask)
101{ 92{
93 unsigned int h = family;
102 switch (family) { 94 switch (family) {
103 case AF_INET: 95 case AF_INET:
104 return __xfrm4_dst_hash(addr, hmask); 96 h ^= __xfrm4_addr_hash(addr);
97 break;
105 case AF_INET6: 98 case AF_INET6:
106 return __xfrm6_dst_hash(addr, hmask); 99 h ^= __xfrm6_addr_hash(addr);
107 } 100 break;
108 return 0; 101 };
102 return (h ^ (h >> 16)) & hmask;
109} 103}
110 104
111static inline unsigned int xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) 105static inline unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family)
112{ 106{
113 return __xfrm_dst_hash(addr, family, xfrm_state_hmask); 107 return __xfrm_src_hash(addr, family, xfrm_state_hmask);
114} 108}
115 109
116static inline unsigned int __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, 110static inline unsigned int __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto,
@@ -190,7 +184,8 @@ static void xfrm_hash_transfer(struct hlist_head *list,
190 hlist_for_each_entry_safe(x, entry, tmp, list, bydst) { 184 hlist_for_each_entry_safe(x, entry, tmp, list, bydst) {
191 unsigned int h; 185 unsigned int h;
192 186
193 h = __xfrm_dst_hash(&x->id.daddr, x->props.family, nhashmask); 187 h = __xfrm_dst_hash(&x->id.daddr, x->props.reqid,
188 x->props.family, nhashmask);
194 hlist_add_head(&x->bydst, ndsttable+h); 189 hlist_add_head(&x->bydst, ndsttable+h);
195 190
196 h = __xfrm_src_hash(&x->props.saddr, x->props.family, 191 h = __xfrm_src_hash(&x->props.saddr, x->props.family,
@@ -635,7 +630,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
635 struct xfrm_policy *pol, int *err, 630 struct xfrm_policy *pol, int *err,
636 unsigned short family) 631 unsigned short family)
637{ 632{
638 unsigned int h = xfrm_dst_hash(daddr, family); 633 unsigned int h = xfrm_dst_hash(daddr, tmpl->reqid, family);
639 struct hlist_node *entry; 634 struct hlist_node *entry;
640 struct xfrm_state *x, *x0; 635 struct xfrm_state *x, *x0;
641 int acquire_in_progress = 0; 636 int acquire_in_progress = 0;
@@ -744,15 +739,15 @@ out:
744 739
745static void __xfrm_state_insert(struct xfrm_state *x) 740static void __xfrm_state_insert(struct xfrm_state *x)
746{ 741{
747 unsigned int h = xfrm_dst_hash(&x->id.daddr, x->props.family); 742 unsigned int h;
748 743
749 x->genid = ++xfrm_state_genid; 744 x->genid = ++xfrm_state_genid;
750 745
746 h = xfrm_dst_hash(&x->id.daddr, x->props.reqid, x->props.family);
751 hlist_add_head(&x->bydst, xfrm_state_bydst+h); 747 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
752 xfrm_state_hold(x); 748 xfrm_state_hold(x);
753 749
754 h = xfrm_src_hash(&x->props.saddr, x->props.family); 750 h = xfrm_src_hash(&x->props.saddr, x->props.family);
755
756 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); 751 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
757 xfrm_state_hold(x); 752 xfrm_state_hold(x);
758 753
@@ -794,7 +789,7 @@ EXPORT_SYMBOL(xfrm_state_insert);
794/* xfrm_state_lock is held */ 789/* xfrm_state_lock is held */
795static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) 790static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create)
796{ 791{
797 unsigned int h = xfrm_dst_hash(daddr, family); 792 unsigned int h = xfrm_dst_hash(daddr, reqid, family);
798 struct hlist_node *entry; 793 struct hlist_node *entry;
799 struct xfrm_state *x; 794 struct xfrm_state *x;
800 795