aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasahide NAKAMURA <nakam@linux-ipv6.org>2006-10-03 18:56:09 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-10-04 03:31:02 -0400
commit667bbcb6c099d1b74f95c6963ddf37a32e7afc29 (patch)
treea4deb7718b21098bb9fbdeacfd55b78a1eb32bb4
parentc5e29460f5f9eb189cab5d9fdaa137e64f7734b6 (diff)
[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: Masahide NAKAMURA <nakam@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/xfrm/xfrm_hash.h7
-rw-r--r--net/xfrm/xfrm_state.c16
2 files changed, 13 insertions, 10 deletions
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h
index 6ac4e4f033ac..d401dc8f05ed 100644
--- a/net/xfrm/xfrm_hash.h
+++ b/net/xfrm/xfrm_hash.h
@@ -41,17 +41,18 @@ static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t
41 return (h ^ (h >> 16)) & hmask; 41 return (h ^ (h >> 16)) & hmask;
42} 42}
43 43
44static inline unsigned __xfrm_src_hash(xfrm_address_t *saddr, 44static inline unsigned __xfrm_src_hash(xfrm_address_t *daddr,
45 xfrm_address_t *saddr,
45 unsigned short family, 46 unsigned short family,
46 unsigned int hmask) 47 unsigned int hmask)
47{ 48{
48 unsigned int h = family; 49 unsigned int h = family;
49 switch (family) { 50 switch (family) {
50 case AF_INET: 51 case AF_INET:
51 h ^= __xfrm4_addr_hash(saddr); 52 h ^= __xfrm4_daddr_saddr_hash(daddr, saddr);
52 break; 53 break;
53 case AF_INET6: 54 case AF_INET6:
54 h ^= __xfrm6_addr_hash(saddr); 55 h ^= __xfrm6_daddr_saddr_hash(daddr, saddr);
55 break; 56 break;
56 }; 57 };
57 return (h ^ (h >> 16)) & hmask; 58 return (h ^ (h >> 16)) & hmask;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index f927b7330f02..39b8bf3a9ded 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -63,10 +63,11 @@ static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
63 return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); 63 return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask);
64} 64}
65 65
66static inline unsigned int xfrm_src_hash(xfrm_address_t *addr, 66static inline unsigned int xfrm_src_hash(xfrm_address_t *daddr,
67 xfrm_address_t *saddr,
67 unsigned short family) 68 unsigned short family)
68{ 69{
69 return __xfrm_src_hash(addr, family, xfrm_state_hmask); 70 return __xfrm_src_hash(daddr, saddr, family, xfrm_state_hmask);
70} 71}
71 72
72static inline unsigned int 73static inline unsigned int
@@ -92,7 +93,8 @@ static void xfrm_hash_transfer(struct hlist_head *list,
92 nhashmask); 93 nhashmask);
93 hlist_add_head(&x->bydst, ndsttable+h); 94 hlist_add_head(&x->bydst, ndsttable+h);
94 95
95 h = __xfrm_src_hash(&x->props.saddr, x->props.family, 96 h = __xfrm_src_hash(&x->id.daddr, &x->props.saddr,
97 x->props.family,
96 nhashmask); 98 nhashmask);
97 hlist_add_head(&x->bysrc, nsrctable+h); 99 hlist_add_head(&x->bysrc, nsrctable+h);
98 100
@@ -458,7 +460,7 @@ static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi,
458 460
459static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) 461static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
460{ 462{
461 unsigned int h = xfrm_src_hash(saddr, family); 463 unsigned int h = xfrm_src_hash(daddr, saddr, family);
462 struct xfrm_state *x; 464 struct xfrm_state *x;
463 struct hlist_node *entry; 465 struct hlist_node *entry;
464 466
@@ -587,7 +589,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
587 if (km_query(x, tmpl, pol) == 0) { 589 if (km_query(x, tmpl, pol) == 0) {
588 x->km.state = XFRM_STATE_ACQ; 590 x->km.state = XFRM_STATE_ACQ;
589 hlist_add_head(&x->bydst, xfrm_state_bydst+h); 591 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
590 h = xfrm_src_hash(saddr, family); 592 h = xfrm_src_hash(daddr, saddr, family);
591 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); 593 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
592 if (x->id.spi) { 594 if (x->id.spi) {
593 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); 595 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 x->props.reqid, x->props.family); 624 x->props.reqid, x->props.family);
623 hlist_add_head(&x->bydst, xfrm_state_bydst+h); 625 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
624 626
625 h = xfrm_src_hash(&x->props.saddr, x->props.family); 627 h = xfrm_src_hash(&x->id.daddr, &x->props.saddr, x->props.family);
626 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); 628 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
627 629
628 if (x->id.spi) { 630 if (x->id.spi) {
@@ -748,7 +750,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
748 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; 750 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
749 add_timer(&x->timer); 751 add_timer(&x->timer);
750 hlist_add_head(&x->bydst, xfrm_state_bydst+h); 752 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
751 h = xfrm_src_hash(saddr, family); 753 h = xfrm_src_hash(daddr, saddr, family);
752 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); 754 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
753 wake_up(&km_waitq); 755 wake_up(&km_waitq);
754 } 756 }