Commit 667bbcb6 authored by Masahide NAKAMURA's avatar Masahide NAKAMURA Committed by David S. Miller

[XFRM] STATE: Use destination address for src hash.

Src hash is introduced for Mobile IPv6 route optimization usage.
On current kenrel code it is calculated with source address only.
It results we uses the same hash value for outbound state (when
the node has only one address for Mobile IPv6).
This patch use also destination address as peer information for
src hash to be dispersed.
Signed-off-by: default avatarMasahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c5e29460
...@@ -41,17 +41,18 @@ static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t ...@@ -41,17 +41,18 @@ static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t
return (h ^ (h >> 16)) & hmask; return (h ^ (h >> 16)) & hmask;
} }
static inline unsigned __xfrm_src_hash(xfrm_address_t *saddr, static inline unsigned __xfrm_src_hash(xfrm_address_t *daddr,
xfrm_address_t *saddr,
unsigned short family, unsigned short family,
unsigned int hmask) unsigned int hmask)
{ {
unsigned int h = family; unsigned int h = family;
switch (family) { switch (family) {
case AF_INET: case AF_INET:
h ^= __xfrm4_addr_hash(saddr); h ^= __xfrm4_daddr_saddr_hash(daddr, saddr);
break; break;
case AF_INET6: case AF_INET6:
h ^= __xfrm6_addr_hash(saddr); h ^= __xfrm6_daddr_saddr_hash(daddr, saddr);
break; break;
}; };
return (h ^ (h >> 16)) & hmask; return (h ^ (h >> 16)) & hmask;
......
...@@ -63,10 +63,11 @@ static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, ...@@ -63,10 +63,11 @@ static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask);
} }
static inline unsigned int xfrm_src_hash(xfrm_address_t *addr, static inline unsigned int xfrm_src_hash(xfrm_address_t *daddr,
xfrm_address_t *saddr,
unsigned short family) unsigned short family)
{ {
return __xfrm_src_hash(addr, family, xfrm_state_hmask); return __xfrm_src_hash(daddr, saddr, family, xfrm_state_hmask);
} }
static inline unsigned int static inline unsigned int
...@@ -92,7 +93,8 @@ static void xfrm_hash_transfer(struct hlist_head *list, ...@@ -92,7 +93,8 @@ static void xfrm_hash_transfer(struct hlist_head *list,
nhashmask); nhashmask);
hlist_add_head(&x->bydst, ndsttable+h); hlist_add_head(&x->bydst, ndsttable+h);
h = __xfrm_src_hash(&x->props.saddr, x->props.family, h = __xfrm_src_hash(&x->id.daddr, &x->props.saddr,
x->props.family,
nhashmask); nhashmask);
hlist_add_head(&x->bysrc, nsrctable+h); hlist_add_head(&x->bysrc, nsrctable+h);
...@@ -458,7 +460,7 @@ static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, ...@@ -458,7 +460,7 @@ static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi,
static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
{ {
unsigned int h = xfrm_src_hash(saddr, family); unsigned int h = xfrm_src_hash(daddr, saddr, family);
struct xfrm_state *x; struct xfrm_state *x;
struct hlist_node *entry; struct hlist_node *entry;
...@@ -587,7 +589,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, ...@@ -587,7 +589,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
if (km_query(x, tmpl, pol) == 0) { if (km_query(x, tmpl, pol) == 0) {
x->km.state = XFRM_STATE_ACQ; x->km.state = XFRM_STATE_ACQ;
hlist_add_head(&x->bydst, xfrm_state_bydst+h); hlist_add_head(&x->bydst, xfrm_state_bydst+h);
h = xfrm_src_hash(saddr, family); h = xfrm_src_hash(daddr, saddr, family);
hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
if (x->id.spi) { if (x->id.spi) {
h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
...@@ -622,7 +624,7 @@ static void __xfrm_state_insert(struct xfrm_state *x) ...@@ -622,7 +624,7 @@ static void __xfrm_state_insert(struct xfrm_state *x)
x->props.reqid, x->props.family); x->props.reqid, x->props.family);
hlist_add_head(&x->bydst, xfrm_state_bydst+h); hlist_add_head(&x->bydst, xfrm_state_bydst+h);
h = xfrm_src_hash(&x->props.saddr, x->props.family); h = xfrm_src_hash(&x->id.daddr, &x->props.saddr, x->props.family);
hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
if (x->id.spi) { if (x->id.spi) {
...@@ -748,7 +750,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re ...@@ -748,7 +750,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
add_timer(&x->timer); add_timer(&x->timer);
hlist_add_head(&x->bydst, xfrm_state_bydst+h); hlist_add_head(&x->bydst, xfrm_state_bydst+h);
h = xfrm_src_hash(saddr, family); h = xfrm_src_hash(daddr, saddr, family);
hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
wake_up(&km_waitq); wake_up(&km_waitq);
} }
......
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