diff options
| author | David S. Miller <davem@sunset.davemloft.net> | 2006-08-24 03:42:45 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:08:39 -0400 |
| commit | edcd582152090bfb0ccb4ad444c151798a73eda8 (patch) | |
| tree | 9d6051e71c5c22c50315d6b2c740170002469288 | |
| parent | 2770834c9f44afd1bfa13914c7285470775af657 (diff) | |
[XFRM]: Pull xfrm_state_by{spi,src} hash table knowledge out of afinfo.
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/net/xfrm.h | 78 | ||||
| -rw-r--r-- | net/ipv4/xfrm4_state.c | 28 | ||||
| -rw-r--r-- | net/ipv6/xfrm6_state.c | 40 | ||||
| -rw-r--r-- | net/xfrm/xfrm_state.c | 210 |
4 files changed, 159 insertions, 197 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index cc83443f301e..dd3b84b9c04e 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
| @@ -243,14 +243,10 @@ extern int __xfrm_state_delete(struct xfrm_state *x); | |||
| 243 | 243 | ||
| 244 | struct xfrm_state_afinfo { | 244 | struct xfrm_state_afinfo { |
| 245 | unsigned short family; | 245 | unsigned short family; |
| 246 | struct list_head *state_bysrc; | ||
| 247 | struct list_head *state_byspi; | ||
| 248 | int (*init_flags)(struct xfrm_state *x); | 246 | int (*init_flags)(struct xfrm_state *x); |
| 249 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, | 247 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, |
| 250 | struct xfrm_tmpl *tmpl, | 248 | struct xfrm_tmpl *tmpl, |
| 251 | xfrm_address_t *daddr, xfrm_address_t *saddr); | 249 | xfrm_address_t *daddr, xfrm_address_t *saddr); |
| 252 | struct xfrm_state *(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto); | ||
| 253 | struct xfrm_state *(*state_lookup_byaddr)(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto); | ||
| 254 | int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); | 250 | int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); |
| 255 | int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); | 251 | int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); |
| 256 | }; | 252 | }; |
| @@ -431,80 +427,6 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) | |||
| 431 | } | 427 | } |
| 432 | #endif | 428 | #endif |
| 433 | 429 | ||
| 434 | #define XFRM_DST_HSIZE 1024 | ||
| 435 | |||
| 436 | static __inline__ | ||
| 437 | unsigned __xfrm4_dst_hash(xfrm_address_t *addr) | ||
| 438 | { | ||
| 439 | unsigned h; | ||
| 440 | h = ntohl(addr->a4); | ||
| 441 | h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | ||
| 442 | return h; | ||
| 443 | } | ||
| 444 | |||
| 445 | static __inline__ | ||
| 446 | unsigned __xfrm6_dst_hash(xfrm_address_t *addr) | ||
| 447 | { | ||
| 448 | unsigned h; | ||
| 449 | h = ntohl(addr->a6[2]^addr->a6[3]); | ||
| 450 | h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | ||
| 451 | return h; | ||
| 452 | } | ||
| 453 | |||
| 454 | static __inline__ | ||
| 455 | unsigned __xfrm4_src_hash(xfrm_address_t *addr) | ||
| 456 | { | ||
| 457 | return __xfrm4_dst_hash(addr); | ||
| 458 | } | ||
| 459 | |||
| 460 | static __inline__ | ||
| 461 | unsigned __xfrm6_src_hash(xfrm_address_t *addr) | ||
| 462 | { | ||
| 463 | return __xfrm6_dst_hash(addr); | ||
| 464 | } | ||
| 465 | |||
| 466 | static __inline__ | ||
| 467 | unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family) | ||
| 468 | { | ||
| 469 | switch (family) { | ||
| 470 | case AF_INET: | ||
| 471 | return __xfrm4_src_hash(addr); | ||
| 472 | case AF_INET6: | ||
| 473 | return __xfrm6_src_hash(addr); | ||
| 474 | } | ||
| 475 | return 0; | ||
| 476 | } | ||
| 477 | |||
| 478 | static __inline__ | ||
| 479 | unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | ||
| 480 | { | ||
| 481 | unsigned h; | ||
| 482 | h = ntohl(addr->a4^spi^proto); | ||
| 483 | h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | ||
| 484 | return h; | ||
| 485 | } | ||
| 486 | |||
| 487 | static __inline__ | ||
| 488 | unsigned __xfrm6_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | ||
| 489 | { | ||
| 490 | unsigned h; | ||
| 491 | h = ntohl(addr->a6[2]^addr->a6[3]^spi^proto); | ||
| 492 | h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | ||
| 493 | return h; | ||
| 494 | } | ||
| 495 | |||
| 496 | static __inline__ | ||
| 497 | unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family) | ||
| 498 | { | ||
| 499 | switch (family) { | ||
| 500 | case AF_INET: | ||
| 501 | return __xfrm4_spi_hash(addr, spi, proto); | ||
| 502 | case AF_INET6: | ||
| 503 | return __xfrm6_spi_hash(addr, spi, proto); | ||
| 504 | } | ||
| 505 | return 0; /*XXX*/ | ||
| 506 | } | ||
| 507 | |||
| 508 | extern void __xfrm_state_destroy(struct xfrm_state *); | 430 | extern void __xfrm_state_destroy(struct xfrm_state *); |
| 509 | 431 | ||
| 510 | static inline void __xfrm_state_put(struct xfrm_state *x) | 432 | static inline void __xfrm_state_put(struct xfrm_state *x) |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 9dc1afc17b6d..6a2a4ab42772 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
| @@ -62,38 +62,10 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
| 62 | x->props.family = AF_INET; | 62 | x->props.family = AF_INET; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | static struct xfrm_state * | ||
| 66 | __xfrm4_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto) | ||
| 67 | { | ||
| 68 | unsigned h = __xfrm4_spi_hash(daddr, spi, proto); | ||
| 69 | struct xfrm_state *x; | ||
| 70 | |||
| 71 | list_for_each_entry(x, xfrm4_state_afinfo.state_byspi+h, byspi) { | ||
| 72 | if (x->props.family == AF_INET && | ||
| 73 | spi == x->id.spi && | ||
| 74 | daddr->a4 == x->id.daddr.a4 && | ||
| 75 | proto == x->id.proto) { | ||
| 76 | xfrm_state_hold(x); | ||
| 77 | return x; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | return NULL; | ||
| 81 | } | ||
| 82 | |||
| 83 | /* placeholder until ipv4's code is written */ | ||
| 84 | static struct xfrm_state * | ||
| 85 | __xfrm4_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
| 86 | u8 proto) | ||
| 87 | { | ||
| 88 | return NULL; | ||
| 89 | } | ||
| 90 | |||
| 91 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { | 65 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { |
| 92 | .family = AF_INET, | 66 | .family = AF_INET, |
| 93 | .init_flags = xfrm4_init_flags, | 67 | .init_flags = xfrm4_init_flags, |
| 94 | .init_tempsel = __xfrm4_init_tempsel, | 68 | .init_tempsel = __xfrm4_init_tempsel, |
| 95 | .state_lookup = __xfrm4_state_lookup, | ||
| 96 | .state_lookup_byaddr = __xfrm4_state_lookup_byaddr, | ||
| 97 | }; | 69 | }; |
| 98 | 70 | ||
| 99 | void __init xfrm4_state_init(void) | 71 | void __init xfrm4_state_init(void) |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index 40fcaab7e028..d88cd92c864e 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
| @@ -63,44 +63,6 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
| 63 | x->props.family = AF_INET6; | 63 | x->props.family = AF_INET6; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | static struct xfrm_state * | ||
| 67 | __xfrm6_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
| 68 | u8 proto) | ||
| 69 | { | ||
| 70 | struct xfrm_state *x = NULL; | ||
| 71 | unsigned h; | ||
| 72 | |||
| 73 | h = __xfrm6_src_hash(saddr); | ||
| 74 | list_for_each_entry(x, xfrm6_state_afinfo.state_bysrc+h, bysrc) { | ||
| 75 | if (x->props.family == AF_INET6 && | ||
| 76 | ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) && | ||
| 77 | ipv6_addr_equal((struct in6_addr *)saddr, (struct in6_addr *)x->props.saddr.a6) && | ||
| 78 | proto == x->id.proto) { | ||
| 79 | xfrm_state_hold(x); | ||
| 80 | return x; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | return NULL; | ||
| 84 | } | ||
| 85 | |||
| 86 | static struct xfrm_state * | ||
| 87 | __xfrm6_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto) | ||
| 88 | { | ||
| 89 | unsigned h = __xfrm6_spi_hash(daddr, spi, proto); | ||
| 90 | struct xfrm_state *x; | ||
| 91 | |||
| 92 | list_for_each_entry(x, xfrm6_state_afinfo.state_byspi+h, byspi) { | ||
| 93 | if (x->props.family == AF_INET6 && | ||
| 94 | spi == x->id.spi && | ||
| 95 | ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) && | ||
| 96 | proto == x->id.proto) { | ||
| 97 | xfrm_state_hold(x); | ||
| 98 | return x; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | return NULL; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int | 66 | static int |
| 105 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) | 67 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) |
| 106 | { | 68 | { |
| @@ -223,8 +185,6 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) | |||
| 223 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { | 185 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { |
| 224 | .family = AF_INET6, | 186 | .family = AF_INET6, |
| 225 | .init_tempsel = __xfrm6_init_tempsel, | 187 | .init_tempsel = __xfrm6_init_tempsel, |
| 226 | .state_lookup = __xfrm6_state_lookup, | ||
| 227 | .state_lookup_byaddr = __xfrm6_state_lookup_byaddr, | ||
| 228 | .tmpl_sort = __xfrm6_tmpl_sort, | 188 | .tmpl_sort = __xfrm6_tmpl_sort, |
| 229 | .state_sort = __xfrm6_state_sort, | 189 | .state_sort = __xfrm6_state_sort, |
| 230 | }; | 190 | }; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 80f5f9dc2b9e..4a3832f81c37 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -38,6 +38,8 @@ EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth); | |||
| 38 | 38 | ||
| 39 | static DEFINE_SPINLOCK(xfrm_state_lock); | 39 | static DEFINE_SPINLOCK(xfrm_state_lock); |
| 40 | 40 | ||
| 41 | #define XFRM_DST_HSIZE 1024 | ||
| 42 | |||
| 41 | /* Hash table to find appropriate SA towards given target (endpoint | 43 | /* Hash table to find appropriate SA towards given target (endpoint |
| 42 | * of tunnel or destination of transport mode) allowed by selector. | 44 | * of tunnel or destination of transport mode) allowed by selector. |
| 43 | * | 45 | * |
| @@ -49,6 +51,48 @@ static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE]; | |||
| 49 | static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; | 51 | static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; |
| 50 | 52 | ||
| 51 | static __inline__ | 53 | static __inline__ |
| 54 | unsigned __xfrm4_dst_hash(xfrm_address_t *addr) | ||
| 55 | { | ||
| 56 | unsigned h; | ||
| 57 | h = ntohl(addr->a4); | ||
| 58 | h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | ||
| 59 | return h; | ||
| 60 | } | ||
| 61 | |||
| 62 | static __inline__ | ||
| 63 | unsigned __xfrm6_dst_hash(xfrm_address_t *addr) | ||
| 64 | { | ||
| 65 | unsigned h; | ||
| 66 | h = ntohl(addr->a6[2]^addr->a6[3]); | ||
| 67 | h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | ||
| 68 | return h; | ||
| 69 | } | ||
| 70 | |||
| 71 | static __inline__ | ||
| 72 | unsigned __xfrm4_src_hash(xfrm_address_t *addr) | ||
| 73 | { | ||
| 74 | return __xfrm4_dst_hash(addr); | ||
| 75 | } | ||
| 76 | |||
| 77 | static __inline__ | ||
| 78 | unsigned __xfrm6_src_hash(xfrm_address_t *addr) | ||
| 79 | { | ||
| 80 | return __xfrm6_dst_hash(addr); | ||
| 81 | } | ||
| 82 | |||
| 83 | static __inline__ | ||
| 84 | unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family) | ||
| 85 | { | ||
| 86 | switch (family) { | ||
| 87 | case AF_INET: | ||
| 88 | return __xfrm4_src_hash(addr); | ||
| 89 | case AF_INET6: | ||
| 90 | return __xfrm6_src_hash(addr); | ||
| 91 | } | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | static __inline__ | ||
| 52 | unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) | 96 | unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) |
| 53 | { | 97 | { |
| 54 | switch (family) { | 98 | switch (family) { |
| @@ -60,6 +104,36 @@ unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) | |||
| 60 | return 0; | 104 | return 0; |
| 61 | } | 105 | } |
| 62 | 106 | ||
| 107 | static __inline__ | ||
| 108 | unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | ||
| 109 | { | ||
| 110 | unsigned h; | ||
| 111 | h = ntohl(addr->a4^spi^proto); | ||
| 112 | h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | ||
| 113 | return h; | ||
| 114 | } | ||
| 115 | |||
| 116 | static __inline__ | ||
| 117 | unsigned __xfrm6_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | ||
| 118 | { | ||
| 119 | unsigned h; | ||
| 120 | h = ntohl(addr->a6[2]^addr->a6[3]^spi^proto); | ||
| 121 | h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | ||
| 122 | return h; | ||
| 123 | } | ||
| 124 | |||
| 125 | static __inline__ | ||
| 126 | unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family) | ||
| 127 | { | ||
| 128 | switch (family) { | ||
| 129 | case AF_INET: | ||
| 130 | return __xfrm4_spi_hash(addr, spi, proto); | ||
| 131 | case AF_INET6: | ||
| 132 | return __xfrm6_spi_hash(addr, spi, proto); | ||
| 133 | } | ||
| 134 | return 0; /*XXX*/ | ||
| 135 | } | ||
| 136 | |||
| 63 | DECLARE_WAIT_QUEUE_HEAD(km_waitq); | 137 | DECLARE_WAIT_QUEUE_HEAD(km_waitq); |
| 64 | EXPORT_SYMBOL(km_waitq); | 138 | EXPORT_SYMBOL(km_waitq); |
| 65 | 139 | ||
| @@ -342,6 +416,83 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
| 342 | return 0; | 416 | return 0; |
| 343 | } | 417 | } |
| 344 | 418 | ||
| 419 | static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) | ||
| 420 | { | ||
| 421 | unsigned int h = xfrm_spi_hash(daddr, spi, proto, family); | ||
| 422 | struct xfrm_state *x; | ||
| 423 | |||
| 424 | list_for_each_entry(x, xfrm_state_byspi+h, byspi) { | ||
| 425 | if (x->props.family != family || | ||
| 426 | x->id.spi != spi || | ||
| 427 | x->id.proto != proto) | ||
| 428 | continue; | ||
| 429 | |||
| 430 | switch (family) { | ||
| 431 | case AF_INET: | ||
| 432 | if (x->id.daddr.a4 != daddr->a4) | ||
| 433 | continue; | ||
| 434 | break; | ||
| 435 | case AF_INET6: | ||
| 436 | if (!ipv6_addr_equal((struct in6_addr *)daddr, | ||
| 437 | (struct in6_addr *) | ||
| 438 | x->id.daddr.a6)) | ||
| 439 | continue; | ||
| 440 | break; | ||
| 441 | }; | ||
| 442 | |||
| 443 | xfrm_state_hold(x); | ||
| 444 | return x; | ||
| 445 | } | ||
| 446 | |||
| 447 | return NULL; | ||
| 448 | } | ||
| 449 | |||
| 450 | static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) | ||
| 451 | { | ||
| 452 | unsigned int h = xfrm_src_hash(saddr, family); | ||
| 453 | struct xfrm_state *x; | ||
| 454 | |||
| 455 | list_for_each_entry(x, xfrm_state_bysrc+h, bysrc) { | ||
| 456 | if (x->props.family != family || | ||
| 457 | x->id.proto != proto) | ||
| 458 | continue; | ||
| 459 | |||
| 460 | switch (family) { | ||
| 461 | case AF_INET: | ||
| 462 | if (x->id.daddr.a4 != daddr->a4 || | ||
| 463 | x->props.saddr.a4 != saddr->a4) | ||
| 464 | continue; | ||
| 465 | break; | ||
| 466 | case AF_INET6: | ||
| 467 | if (!ipv6_addr_equal((struct in6_addr *)daddr, | ||
| 468 | (struct in6_addr *) | ||
| 469 | x->id.daddr.a6) || | ||
| 470 | !ipv6_addr_equal((struct in6_addr *)saddr, | ||
| 471 | (struct in6_addr *) | ||
| 472 | x->props.saddr.a6)) | ||
| 473 | continue; | ||
| 474 | break; | ||
| 475 | }; | ||
| 476 | |||
| 477 | xfrm_state_hold(x); | ||
| 478 | return x; | ||
| 479 | } | ||
| 480 | |||
| 481 | return NULL; | ||
| 482 | } | ||
| 483 | |||
| 484 | static inline struct xfrm_state * | ||
| 485 | __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) | ||
| 486 | { | ||
| 487 | if (use_spi) | ||
| 488 | return __xfrm_state_lookup(&x->id.daddr, x->id.spi, | ||
| 489 | x->id.proto, family); | ||
| 490 | else | ||
| 491 | return __xfrm_state_lookup_byaddr(&x->id.daddr, | ||
| 492 | &x->props.saddr, | ||
| 493 | x->id.proto, family); | ||
| 494 | } | ||
| 495 | |||
| 345 | struct xfrm_state * | 496 | struct xfrm_state * |
| 346 | xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | 497 | xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, |
| 347 | struct flowi *fl, struct xfrm_tmpl *tmpl, | 498 | struct flowi *fl, struct xfrm_tmpl *tmpl, |
| @@ -353,14 +504,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 353 | int acquire_in_progress = 0; | 504 | int acquire_in_progress = 0; |
| 354 | int error = 0; | 505 | int error = 0; |
| 355 | struct xfrm_state *best = NULL; | 506 | struct xfrm_state *best = NULL; |
| 356 | struct xfrm_state_afinfo *afinfo; | ||
| 357 | 507 | ||
| 358 | afinfo = xfrm_state_get_afinfo(family); | ||
| 359 | if (afinfo == NULL) { | ||
| 360 | *err = -EAFNOSUPPORT; | ||
| 361 | return NULL; | ||
| 362 | } | ||
| 363 | |||
| 364 | spin_lock_bh(&xfrm_state_lock); | 508 | spin_lock_bh(&xfrm_state_lock); |
| 365 | list_for_each_entry(x, xfrm_state_bydst+h, bydst) { | 509 | list_for_each_entry(x, xfrm_state_bydst+h, bydst) { |
| 366 | if (x->props.family == family && | 510 | if (x->props.family == family && |
| @@ -406,8 +550,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 406 | x = best; | 550 | x = best; |
| 407 | if (!x && !error && !acquire_in_progress) { | 551 | if (!x && !error && !acquire_in_progress) { |
| 408 | if (tmpl->id.spi && | 552 | if (tmpl->id.spi && |
| 409 | (x0 = afinfo->state_lookup(daddr, tmpl->id.spi, | 553 | (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi, |
| 410 | tmpl->id.proto)) != NULL) { | 554 | tmpl->id.proto, family)) != NULL) { |
| 411 | xfrm_state_put(x0); | 555 | xfrm_state_put(x0); |
| 412 | error = -EEXIST; | 556 | error = -EEXIST; |
| 413 | goto out; | 557 | goto out; |
| @@ -457,7 +601,6 @@ out: | |||
| 457 | else | 601 | else |
| 458 | *err = acquire_in_progress ? -EAGAIN : error; | 602 | *err = acquire_in_progress ? -EAGAIN : error; |
| 459 | spin_unlock_bh(&xfrm_state_lock); | 603 | spin_unlock_bh(&xfrm_state_lock); |
| 460 | xfrm_state_put_afinfo(afinfo); | ||
| 461 | return x; | 604 | return x; |
| 462 | } | 605 | } |
| 463 | 606 | ||
| @@ -584,34 +727,20 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
| 584 | return x; | 727 | return x; |
| 585 | } | 728 | } |
| 586 | 729 | ||
| 587 | static inline struct xfrm_state * | ||
| 588 | __xfrm_state_locate(struct xfrm_state_afinfo *afinfo, struct xfrm_state *x, | ||
| 589 | int use_spi) | ||
| 590 | { | ||
| 591 | if (use_spi) | ||
| 592 | return afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto); | ||
| 593 | else | ||
| 594 | return afinfo->state_lookup_byaddr(&x->id.daddr, &x->props.saddr, x->id.proto); | ||
| 595 | } | ||
| 596 | |||
| 597 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); | 730 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); |
| 598 | 731 | ||
| 599 | int xfrm_state_add(struct xfrm_state *x) | 732 | int xfrm_state_add(struct xfrm_state *x) |
| 600 | { | 733 | { |
| 601 | struct xfrm_state_afinfo *afinfo; | ||
| 602 | struct xfrm_state *x1; | 734 | struct xfrm_state *x1; |
| 603 | int family; | 735 | int family; |
| 604 | int err; | 736 | int err; |
| 605 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); | 737 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); |
| 606 | 738 | ||
| 607 | family = x->props.family; | 739 | family = x->props.family; |
| 608 | afinfo = xfrm_state_get_afinfo(family); | ||
| 609 | if (unlikely(afinfo == NULL)) | ||
| 610 | return -EAFNOSUPPORT; | ||
| 611 | 740 | ||
| 612 | spin_lock_bh(&xfrm_state_lock); | 741 | spin_lock_bh(&xfrm_state_lock); |
| 613 | 742 | ||
| 614 | x1 = __xfrm_state_locate(afinfo, x, use_spi); | 743 | x1 = __xfrm_state_locate(x, use_spi, family); |
| 615 | if (x1) { | 744 | if (x1) { |
| 616 | xfrm_state_put(x1); | 745 | xfrm_state_put(x1); |
| 617 | x1 = NULL; | 746 | x1 = NULL; |
| @@ -637,7 +766,6 @@ int xfrm_state_add(struct xfrm_state *x) | |||
| 637 | 766 | ||
| 638 | out: | 767 | out: |
| 639 | spin_unlock_bh(&xfrm_state_lock); | 768 | spin_unlock_bh(&xfrm_state_lock); |
| 640 | xfrm_state_put_afinfo(afinfo); | ||
| 641 | 769 | ||
| 642 | if (!err) | 770 | if (!err) |
| 643 | xfrm_flush_all_bundles(); | 771 | xfrm_flush_all_bundles(); |
| @@ -653,17 +781,12 @@ EXPORT_SYMBOL(xfrm_state_add); | |||
| 653 | 781 | ||
| 654 | int xfrm_state_update(struct xfrm_state *x) | 782 | int xfrm_state_update(struct xfrm_state *x) |
| 655 | { | 783 | { |
| 656 | struct xfrm_state_afinfo *afinfo; | ||
| 657 | struct xfrm_state *x1; | 784 | struct xfrm_state *x1; |
| 658 | int err; | 785 | int err; |
| 659 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); | 786 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); |
| 660 | 787 | ||
| 661 | afinfo = xfrm_state_get_afinfo(x->props.family); | ||
| 662 | if (unlikely(afinfo == NULL)) | ||
| 663 | return -EAFNOSUPPORT; | ||
| 664 | |||
| 665 | spin_lock_bh(&xfrm_state_lock); | 788 | spin_lock_bh(&xfrm_state_lock); |
| 666 | x1 = __xfrm_state_locate(afinfo, x, use_spi); | 789 | x1 = __xfrm_state_locate(x, use_spi, x->props.family); |
| 667 | 790 | ||
| 668 | err = -ESRCH; | 791 | err = -ESRCH; |
| 669 | if (!x1) | 792 | if (!x1) |
| @@ -683,7 +806,6 @@ int xfrm_state_update(struct xfrm_state *x) | |||
| 683 | 806 | ||
| 684 | out: | 807 | out: |
| 685 | spin_unlock_bh(&xfrm_state_lock); | 808 | spin_unlock_bh(&xfrm_state_lock); |
| 686 | xfrm_state_put_afinfo(afinfo); | ||
| 687 | 809 | ||
| 688 | if (err) | 810 | if (err) |
| 689 | return err; | 811 | return err; |
| @@ -776,14 +898,10 @@ xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, | |||
| 776 | unsigned short family) | 898 | unsigned short family) |
| 777 | { | 899 | { |
| 778 | struct xfrm_state *x; | 900 | struct xfrm_state *x; |
| 779 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | ||
| 780 | if (!afinfo) | ||
| 781 | return NULL; | ||
| 782 | 901 | ||
| 783 | spin_lock_bh(&xfrm_state_lock); | 902 | spin_lock_bh(&xfrm_state_lock); |
| 784 | x = afinfo->state_lookup(daddr, spi, proto); | 903 | x = __xfrm_state_lookup(daddr, spi, proto, family); |
| 785 | spin_unlock_bh(&xfrm_state_lock); | 904 | spin_unlock_bh(&xfrm_state_lock); |
| 786 | xfrm_state_put_afinfo(afinfo); | ||
| 787 | return x; | 905 | return x; |
| 788 | } | 906 | } |
| 789 | EXPORT_SYMBOL(xfrm_state_lookup); | 907 | EXPORT_SYMBOL(xfrm_state_lookup); |
| @@ -793,14 +911,10 @@ xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 793 | u8 proto, unsigned short family) | 911 | u8 proto, unsigned short family) |
| 794 | { | 912 | { |
| 795 | struct xfrm_state *x; | 913 | struct xfrm_state *x; |
| 796 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | ||
| 797 | if (!afinfo) | ||
| 798 | return NULL; | ||
| 799 | 914 | ||
| 800 | spin_lock_bh(&xfrm_state_lock); | 915 | spin_lock_bh(&xfrm_state_lock); |
| 801 | x = afinfo->state_lookup_byaddr(daddr, saddr, proto); | 916 | x = __xfrm_state_lookup_byaddr(daddr, saddr, proto, family); |
| 802 | spin_unlock_bh(&xfrm_state_lock); | 917 | spin_unlock_bh(&xfrm_state_lock); |
| 803 | xfrm_state_put_afinfo(afinfo); | ||
| 804 | return x; | 918 | return x; |
| 805 | } | 919 | } |
| 806 | EXPORT_SYMBOL(xfrm_state_lookup_byaddr); | 920 | EXPORT_SYMBOL(xfrm_state_lookup_byaddr); |
| @@ -1272,11 +1386,8 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) | |||
| 1272 | write_lock_bh(&xfrm_state_afinfo_lock); | 1386 | write_lock_bh(&xfrm_state_afinfo_lock); |
| 1273 | if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) | 1387 | if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) |
| 1274 | err = -ENOBUFS; | 1388 | err = -ENOBUFS; |
| 1275 | else { | 1389 | else |
| 1276 | afinfo->state_bysrc = xfrm_state_bysrc; | ||
| 1277 | afinfo->state_byspi = xfrm_state_byspi; | ||
| 1278 | xfrm_state_afinfo[afinfo->family] = afinfo; | 1390 | xfrm_state_afinfo[afinfo->family] = afinfo; |
| 1279 | } | ||
| 1280 | write_unlock_bh(&xfrm_state_afinfo_lock); | 1391 | write_unlock_bh(&xfrm_state_afinfo_lock); |
| 1281 | return err; | 1392 | return err; |
| 1282 | } | 1393 | } |
| @@ -1293,11 +1404,8 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) | |||
| 1293 | if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { | 1404 | if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { |
| 1294 | if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) | 1405 | if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) |
| 1295 | err = -EINVAL; | 1406 | err = -EINVAL; |
| 1296 | else { | 1407 | else |
| 1297 | xfrm_state_afinfo[afinfo->family] = NULL; | 1408 | xfrm_state_afinfo[afinfo->family] = NULL; |
| 1298 | afinfo->state_byspi = NULL; | ||
| 1299 | afinfo->state_bysrc = NULL; | ||
| 1300 | } | ||
| 1301 | } | 1409 | } |
| 1302 | write_unlock_bh(&xfrm_state_afinfo_lock); | 1410 | write_unlock_bh(&xfrm_state_afinfo_lock); |
| 1303 | return err; | 1411 | return err; |
