diff options
-rw-r--r-- | net/xfrm/xfrm_state.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 0bc6a4b1ceae..37213f9f6a02 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -65,26 +65,40 @@ static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) | |||
65 | return ntohl(addr->a6[2]^addr->a6[3]); | 65 | return ntohl(addr->a6[2]^addr->a6[3]); |
66 | } | 66 | } |
67 | 67 | ||
68 | static inline unsigned int __xfrm_dst_hash(xfrm_address_t *addr, | 68 | static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) |
69 | { | ||
70 | return ntohl(daddr->a4 ^ saddr->a4); | ||
71 | } | ||
72 | |||
73 | static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | ||
74 | { | ||
75 | return ntohl(daddr->a6[2] ^ daddr->a6[3] ^ | ||
76 | saddr->a6[2] ^ saddr->a6[3]); | ||
77 | } | ||
78 | |||
79 | static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, | ||
80 | xfrm_address_t *saddr, | ||
69 | u32 reqid, unsigned short family, | 81 | u32 reqid, unsigned short family, |
70 | unsigned int hmask) | 82 | unsigned int hmask) |
71 | { | 83 | { |
72 | unsigned int h = family ^ reqid; | 84 | unsigned int h = family ^ reqid; |
73 | switch (family) { | 85 | switch (family) { |
74 | case AF_INET: | 86 | case AF_INET: |
75 | h ^= __xfrm4_addr_hash(addr); | 87 | h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); |
76 | break; | 88 | break; |
77 | case AF_INET6: | 89 | case AF_INET6: |
78 | h ^= __xfrm6_addr_hash(addr); | 90 | h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); |
79 | break; | 91 | break; |
80 | }; | 92 | }; |
81 | return (h ^ (h >> 16)) & hmask; | 93 | return (h ^ (h >> 16)) & hmask; |
82 | } | 94 | } |
83 | 95 | ||
84 | static inline unsigned int xfrm_dst_hash(xfrm_address_t *addr, u32 reqid, | 96 | static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, |
97 | xfrm_address_t *saddr, | ||
98 | u32 reqid, | ||
85 | unsigned short family) | 99 | unsigned short family) |
86 | { | 100 | { |
87 | return __xfrm_dst_hash(addr, reqid, family, xfrm_state_hmask); | 101 | return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); |
88 | } | 102 | } |
89 | 103 | ||
90 | static inline unsigned __xfrm_src_hash(xfrm_address_t *addr, unsigned short family, | 104 | static inline unsigned __xfrm_src_hash(xfrm_address_t *addr, unsigned short family, |
@@ -108,25 +122,25 @@ static inline unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family | |||
108 | } | 122 | } |
109 | 123 | ||
110 | static inline unsigned int | 124 | static inline unsigned int |
111 | __xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family, | 125 | __xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, |
112 | unsigned int hmask) | 126 | unsigned short family, unsigned int hmask) |
113 | { | 127 | { |
114 | unsigned int h = spi ^ proto; | 128 | unsigned int h = spi ^ proto; |
115 | switch (family) { | 129 | switch (family) { |
116 | case AF_INET: | 130 | case AF_INET: |
117 | h ^= __xfrm4_addr_hash(addr); | 131 | h ^= __xfrm4_addr_hash(daddr); |
118 | break; | 132 | break; |
119 | case AF_INET6: | 133 | case AF_INET6: |
120 | h ^= __xfrm6_addr_hash(addr); | 134 | h ^= __xfrm6_addr_hash(daddr); |
121 | break; | 135 | break; |
122 | } | 136 | } |
123 | return (h ^ (h >> 10) ^ (h >> 20)) & hmask; | 137 | return (h ^ (h >> 10) ^ (h >> 20)) & hmask; |
124 | } | 138 | } |
125 | 139 | ||
126 | static inline unsigned int | 140 | static inline unsigned int |
127 | xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family) | 141 | xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) |
128 | { | 142 | { |
129 | return __xfrm_spi_hash(addr, spi, proto, family, xfrm_state_hmask); | 143 | return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask); |
130 | } | 144 | } |
131 | 145 | ||
132 | static struct hlist_head *xfrm_state_hash_alloc(unsigned int sz) | 146 | static struct hlist_head *xfrm_state_hash_alloc(unsigned int sz) |
@@ -169,8 +183,9 @@ static void xfrm_hash_transfer(struct hlist_head *list, | |||
169 | hlist_for_each_entry_safe(x, entry, tmp, list, bydst) { | 183 | hlist_for_each_entry_safe(x, entry, tmp, list, bydst) { |
170 | unsigned int h; | 184 | unsigned int h; |
171 | 185 | ||
172 | h = __xfrm_dst_hash(&x->id.daddr, x->props.reqid, | 186 | h = __xfrm_dst_hash(&x->id.daddr, &x->props.saddr, |
173 | x->props.family, nhashmask); | 187 | x->props.reqid, x->props.family, |
188 | nhashmask); | ||
174 | hlist_add_head(&x->bydst, ndsttable+h); | 189 | hlist_add_head(&x->bydst, ndsttable+h); |
175 | 190 | ||
176 | h = __xfrm_src_hash(&x->props.saddr, x->props.family, | 191 | h = __xfrm_src_hash(&x->props.saddr, x->props.family, |
@@ -587,7 +602,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
587 | struct xfrm_policy *pol, int *err, | 602 | struct xfrm_policy *pol, int *err, |
588 | unsigned short family) | 603 | unsigned short family) |
589 | { | 604 | { |
590 | unsigned int h = xfrm_dst_hash(daddr, tmpl->reqid, family); | 605 | unsigned int h = xfrm_dst_hash(daddr, saddr, tmpl->reqid, family); |
591 | struct hlist_node *entry; | 606 | struct hlist_node *entry; |
592 | struct xfrm_state *x, *x0; | 607 | struct xfrm_state *x, *x0; |
593 | int acquire_in_progress = 0; | 608 | int acquire_in_progress = 0; |
@@ -696,7 +711,8 @@ static void __xfrm_state_insert(struct xfrm_state *x) | |||
696 | 711 | ||
697 | x->genid = ++xfrm_state_genid; | 712 | x->genid = ++xfrm_state_genid; |
698 | 713 | ||
699 | h = xfrm_dst_hash(&x->id.daddr, x->props.reqid, x->props.family); | 714 | h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr, |
715 | x->props.reqid, x->props.family); | ||
700 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 716 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
701 | 717 | ||
702 | h = xfrm_src_hash(&x->props.saddr, x->props.family); | 718 | h = xfrm_src_hash(&x->props.saddr, x->props.family); |
@@ -732,11 +748,12 @@ static void __xfrm_state_bump_genids(struct xfrm_state *xnew) | |||
732 | struct hlist_node *entry; | 748 | struct hlist_node *entry; |
733 | unsigned int h; | 749 | unsigned int h; |
734 | 750 | ||
735 | h = xfrm_dst_hash(&xnew->id.daddr, reqid, family); | 751 | h = xfrm_dst_hash(&xnew->id.daddr, &xnew->props.saddr, reqid, family); |
736 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 752 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { |
737 | if (x->props.family == family && | 753 | if (x->props.family == family && |
738 | x->props.reqid == reqid && | 754 | x->props.reqid == reqid && |
739 | !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family)) | 755 | !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && |
756 | !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family)) | ||
740 | x->genid = xfrm_state_genid; | 757 | x->genid = xfrm_state_genid; |
741 | } | 758 | } |
742 | } | 759 | } |
@@ -753,7 +770,7 @@ EXPORT_SYMBOL(xfrm_state_insert); | |||
753 | /* xfrm_state_lock is held */ | 770 | /* xfrm_state_lock is held */ |
754 | static 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) | 771 | static 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) |
755 | { | 772 | { |
756 | unsigned int h = xfrm_dst_hash(daddr, reqid, family); | 773 | unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family); |
757 | struct hlist_node *entry; | 774 | struct hlist_node *entry; |
758 | struct xfrm_state *x; | 775 | struct xfrm_state *x; |
759 | 776 | ||