aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c92
1 files changed, 51 insertions, 41 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 4a3832f81c37..fe3c8c38d5e1 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -46,9 +46,9 @@ static DEFINE_SPINLOCK(xfrm_state_lock);
46 * Main use is finding SA after policy selected tunnel or transport mode. 46 * Main use is finding SA after policy selected tunnel or transport mode.
47 * Also, it can be used by ah/esp icmp error handler to find offending SA. 47 * Also, it can be used by ah/esp icmp error handler to find offending SA.
48 */ 48 */
49static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE]; 49static struct hlist_head xfrm_state_bydst[XFRM_DST_HSIZE];
50static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE]; 50static struct hlist_head xfrm_state_bysrc[XFRM_DST_HSIZE];
51static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; 51static struct hlist_head xfrm_state_byspi[XFRM_DST_HSIZE];
52 52
53static __inline__ 53static __inline__
54unsigned __xfrm4_dst_hash(xfrm_address_t *addr) 54unsigned __xfrm4_dst_hash(xfrm_address_t *addr)
@@ -141,7 +141,7 @@ static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
141static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; 141static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
142 142
143static struct work_struct xfrm_state_gc_work; 143static struct work_struct xfrm_state_gc_work;
144static struct list_head xfrm_state_gc_list = LIST_HEAD_INIT(xfrm_state_gc_list); 144static HLIST_HEAD(xfrm_state_gc_list);
145static DEFINE_SPINLOCK(xfrm_state_gc_lock); 145static DEFINE_SPINLOCK(xfrm_state_gc_lock);
146 146
147static int xfrm_state_gc_flush_bundles; 147static int xfrm_state_gc_flush_bundles;
@@ -178,8 +178,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
178static void xfrm_state_gc_task(void *data) 178static void xfrm_state_gc_task(void *data)
179{ 179{
180 struct xfrm_state *x; 180 struct xfrm_state *x;
181 struct list_head *entry, *tmp; 181 struct hlist_node *entry, *tmp;
182 struct list_head gc_list = LIST_HEAD_INIT(gc_list); 182 struct hlist_head gc_list;
183 183
184 if (xfrm_state_gc_flush_bundles) { 184 if (xfrm_state_gc_flush_bundles) {
185 xfrm_state_gc_flush_bundles = 0; 185 xfrm_state_gc_flush_bundles = 0;
@@ -187,13 +187,13 @@ static void xfrm_state_gc_task(void *data)
187 } 187 }
188 188
189 spin_lock_bh(&xfrm_state_gc_lock); 189 spin_lock_bh(&xfrm_state_gc_lock);
190 list_splice_init(&xfrm_state_gc_list, &gc_list); 190 gc_list.first = xfrm_state_gc_list.first;
191 INIT_HLIST_HEAD(&xfrm_state_gc_list);
191 spin_unlock_bh(&xfrm_state_gc_lock); 192 spin_unlock_bh(&xfrm_state_gc_lock);
192 193
193 list_for_each_safe(entry, tmp, &gc_list) { 194 hlist_for_each_entry_safe(x, entry, tmp, &gc_list, bydst)
194 x = list_entry(entry, struct xfrm_state, bydst);
195 xfrm_state_gc_destroy(x); 195 xfrm_state_gc_destroy(x);
196 } 196
197 wake_up(&km_waitq); 197 wake_up(&km_waitq);
198} 198}
199 199
@@ -287,9 +287,9 @@ struct xfrm_state *xfrm_state_alloc(void)
287 if (x) { 287 if (x) {
288 atomic_set(&x->refcnt, 1); 288 atomic_set(&x->refcnt, 1);
289 atomic_set(&x->tunnel_users, 0); 289 atomic_set(&x->tunnel_users, 0);
290 INIT_LIST_HEAD(&x->bydst); 290 INIT_HLIST_NODE(&x->bydst);
291 INIT_LIST_HEAD(&x->bysrc); 291 INIT_HLIST_NODE(&x->bysrc);
292 INIT_LIST_HEAD(&x->byspi); 292 INIT_HLIST_NODE(&x->byspi);
293 init_timer(&x->timer); 293 init_timer(&x->timer);
294 x->timer.function = xfrm_timer_handler; 294 x->timer.function = xfrm_timer_handler;
295 x->timer.data = (unsigned long)x; 295 x->timer.data = (unsigned long)x;
@@ -314,7 +314,7 @@ void __xfrm_state_destroy(struct xfrm_state *x)
314 BUG_TRAP(x->km.state == XFRM_STATE_DEAD); 314 BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
315 315
316 spin_lock_bh(&xfrm_state_gc_lock); 316 spin_lock_bh(&xfrm_state_gc_lock);
317 list_add(&x->bydst, &xfrm_state_gc_list); 317 hlist_add_head(&x->bydst, &xfrm_state_gc_list);
318 spin_unlock_bh(&xfrm_state_gc_lock); 318 spin_unlock_bh(&xfrm_state_gc_lock);
319 schedule_work(&xfrm_state_gc_work); 319 schedule_work(&xfrm_state_gc_work);
320} 320}
@@ -327,12 +327,12 @@ int __xfrm_state_delete(struct xfrm_state *x)
327 if (x->km.state != XFRM_STATE_DEAD) { 327 if (x->km.state != XFRM_STATE_DEAD) {
328 x->km.state = XFRM_STATE_DEAD; 328 x->km.state = XFRM_STATE_DEAD;
329 spin_lock(&xfrm_state_lock); 329 spin_lock(&xfrm_state_lock);
330 list_del(&x->bydst); 330 hlist_del(&x->bydst);
331 __xfrm_state_put(x); 331 __xfrm_state_put(x);
332 list_del(&x->bysrc); 332 hlist_del(&x->bysrc);
333 __xfrm_state_put(x); 333 __xfrm_state_put(x);
334 if (x->id.spi) { 334 if (x->id.spi) {
335 list_del(&x->byspi); 335 hlist_del(&x->byspi);
336 __xfrm_state_put(x); 336 __xfrm_state_put(x);
337 } 337 }
338 spin_unlock(&xfrm_state_lock); 338 spin_unlock(&xfrm_state_lock);
@@ -378,12 +378,13 @@ EXPORT_SYMBOL(xfrm_state_delete);
378void xfrm_state_flush(u8 proto) 378void xfrm_state_flush(u8 proto)
379{ 379{
380 int i; 380 int i;
381 struct xfrm_state *x;
382 381
383 spin_lock_bh(&xfrm_state_lock); 382 spin_lock_bh(&xfrm_state_lock);
384 for (i = 0; i < XFRM_DST_HSIZE; i++) { 383 for (i = 0; i < XFRM_DST_HSIZE; i++) {
384 struct hlist_node *entry;
385 struct xfrm_state *x;
385restart: 386restart:
386 list_for_each_entry(x, xfrm_state_bydst+i, bydst) { 387 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
387 if (!xfrm_state_kern(x) && 388 if (!xfrm_state_kern(x) &&
388 xfrm_id_proto_match(x->id.proto, proto)) { 389 xfrm_id_proto_match(x->id.proto, proto)) {
389 xfrm_state_hold(x); 390 xfrm_state_hold(x);
@@ -420,8 +421,9 @@ static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8
420{ 421{
421 unsigned int h = xfrm_spi_hash(daddr, spi, proto, family); 422 unsigned int h = xfrm_spi_hash(daddr, spi, proto, family);
422 struct xfrm_state *x; 423 struct xfrm_state *x;
424 struct hlist_node *entry;
423 425
424 list_for_each_entry(x, xfrm_state_byspi+h, byspi) { 426 hlist_for_each_entry(x, entry, xfrm_state_byspi+h, byspi) {
425 if (x->props.family != family || 427 if (x->props.family != family ||
426 x->id.spi != spi || 428 x->id.spi != spi ||
427 x->id.proto != proto) 429 x->id.proto != proto)
@@ -451,8 +453,9 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm
451{ 453{
452 unsigned int h = xfrm_src_hash(saddr, family); 454 unsigned int h = xfrm_src_hash(saddr, family);
453 struct xfrm_state *x; 455 struct xfrm_state *x;
456 struct hlist_node *entry;
454 457
455 list_for_each_entry(x, xfrm_state_bysrc+h, bysrc) { 458 hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) {
456 if (x->props.family != family || 459 if (x->props.family != family ||
457 x->id.proto != proto) 460 x->id.proto != proto)
458 continue; 461 continue;
@@ -499,14 +502,15 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
499 struct xfrm_policy *pol, int *err, 502 struct xfrm_policy *pol, int *err,
500 unsigned short family) 503 unsigned short family)
501{ 504{
502 unsigned h = xfrm_dst_hash(daddr, family); 505 unsigned int h = xfrm_dst_hash(daddr, family);
506 struct hlist_node *entry;
503 struct xfrm_state *x, *x0; 507 struct xfrm_state *x, *x0;
504 int acquire_in_progress = 0; 508 int acquire_in_progress = 0;
505 int error = 0; 509 int error = 0;
506 struct xfrm_state *best = NULL; 510 struct xfrm_state *best = NULL;
507 511
508 spin_lock_bh(&xfrm_state_lock); 512 spin_lock_bh(&xfrm_state_lock);
509 list_for_each_entry(x, xfrm_state_bydst+h, bydst) { 513 hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
510 if (x->props.family == family && 514 if (x->props.family == family &&
511 x->props.reqid == tmpl->reqid && 515 x->props.reqid == tmpl->reqid &&
512 !(x->props.flags & XFRM_STATE_WILDRECV) && 516 !(x->props.flags & XFRM_STATE_WILDRECV) &&
@@ -575,13 +579,14 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
575 579
576 if (km_query(x, tmpl, pol) == 0) { 580 if (km_query(x, tmpl, pol) == 0) {
577 x->km.state = XFRM_STATE_ACQ; 581 x->km.state = XFRM_STATE_ACQ;
578 list_add_tail(&x->bydst, xfrm_state_bydst+h); 582 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
579 xfrm_state_hold(x); 583 xfrm_state_hold(x);
580 list_add_tail(&x->bysrc, xfrm_state_bysrc+h); 584 h = xfrm_src_hash(saddr, family);
585 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
581 xfrm_state_hold(x); 586 xfrm_state_hold(x);
582 if (x->id.spi) { 587 if (x->id.spi) {
583 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); 588 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
584 list_add(&x->byspi, xfrm_state_byspi+h); 589 hlist_add_head(&x->byspi, xfrm_state_byspi+h);
585 xfrm_state_hold(x); 590 xfrm_state_hold(x);
586 } 591 }
587 x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; 592 x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
@@ -608,19 +613,19 @@ static void __xfrm_state_insert(struct xfrm_state *x)
608{ 613{
609 unsigned h = xfrm_dst_hash(&x->id.daddr, x->props.family); 614 unsigned h = xfrm_dst_hash(&x->id.daddr, x->props.family);
610 615
611 list_add(&x->bydst, xfrm_state_bydst+h); 616 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
612 xfrm_state_hold(x); 617 xfrm_state_hold(x);
613 618
614 h = xfrm_src_hash(&x->props.saddr, x->props.family); 619 h = xfrm_src_hash(&x->props.saddr, x->props.family);
615 620
616 list_add(&x->bysrc, xfrm_state_bysrc+h); 621 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
617 xfrm_state_hold(x); 622 xfrm_state_hold(x);
618 623
619 if (xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY)) { 624 if (xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY)) {
620 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, 625 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto,
621 x->props.family); 626 x->props.family);
622 627
623 list_add(&x->byspi, xfrm_state_byspi+h); 628 hlist_add_head(&x->byspi, xfrm_state_byspi+h);
624 xfrm_state_hold(x); 629 xfrm_state_hold(x);
625 } 630 }
626 631
@@ -648,9 +653,10 @@ EXPORT_SYMBOL(xfrm_state_insert);
648static 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) 653static 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)
649{ 654{
650 unsigned int h = xfrm_dst_hash(daddr, family); 655 unsigned int h = xfrm_dst_hash(daddr, family);
656 struct hlist_node *entry;
651 struct xfrm_state *x; 657 struct xfrm_state *x;
652 658
653 list_for_each_entry(x, xfrm_state_bydst+h, bydst) { 659 hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
654 if (x->props.reqid != reqid || 660 if (x->props.reqid != reqid ||
655 x->props.mode != mode || 661 x->props.mode != mode ||
656 x->props.family != family || 662 x->props.family != family ||
@@ -717,10 +723,10 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
717 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; 723 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
718 add_timer(&x->timer); 724 add_timer(&x->timer);
719 xfrm_state_hold(x); 725 xfrm_state_hold(x);
720 list_add_tail(&x->bydst, xfrm_state_bydst+h); 726 hlist_add_head(&x->bydst, xfrm_state_bydst+h);
721 h = xfrm_src_hash(saddr, family); 727 h = xfrm_src_hash(saddr, family);
722 xfrm_state_hold(x); 728 xfrm_state_hold(x);
723 list_add_tail(&x->bysrc, xfrm_state_bysrc+h); 729 hlist_add_head(&x->bysrc, xfrm_state_bysrc+h);
724 wake_up(&km_waitq); 730 wake_up(&km_waitq);
725 } 731 }
726 732
@@ -977,11 +983,14 @@ EXPORT_SYMBOL(xfrm_state_sort);
977static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) 983static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq)
978{ 984{
979 int i; 985 int i;
980 struct xfrm_state *x;
981 986
982 for (i = 0; i < XFRM_DST_HSIZE; i++) { 987 for (i = 0; i < XFRM_DST_HSIZE; i++) {
983 list_for_each_entry(x, xfrm_state_bydst+i, bydst) { 988 struct hlist_node *entry;
984 if (x->km.seq == seq && x->km.state == XFRM_STATE_ACQ) { 989 struct xfrm_state *x;
990
991 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
992 if (x->km.seq == seq &&
993 x->km.state == XFRM_STATE_ACQ) {
985 xfrm_state_hold(x); 994 xfrm_state_hold(x);
986 return x; 995 return x;
987 } 996 }
@@ -1047,7 +1056,7 @@ xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
1047 if (x->id.spi) { 1056 if (x->id.spi) {
1048 spin_lock_bh(&xfrm_state_lock); 1057 spin_lock_bh(&xfrm_state_lock);
1049 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); 1058 h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family);
1050 list_add(&x->byspi, xfrm_state_byspi+h); 1059 hlist_add_head(&x->byspi, xfrm_state_byspi+h);
1051 xfrm_state_hold(x); 1060 xfrm_state_hold(x);
1052 spin_unlock_bh(&xfrm_state_lock); 1061 spin_unlock_bh(&xfrm_state_lock);
1053 wake_up(&km_waitq); 1062 wake_up(&km_waitq);
@@ -1060,12 +1069,13 @@ int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
1060{ 1069{
1061 int i; 1070 int i;
1062 struct xfrm_state *x; 1071 struct xfrm_state *x;
1072 struct hlist_node *entry;
1063 int count = 0; 1073 int count = 0;
1064 int err = 0; 1074 int err = 0;
1065 1075
1066 spin_lock_bh(&xfrm_state_lock); 1076 spin_lock_bh(&xfrm_state_lock);
1067 for (i = 0; i < XFRM_DST_HSIZE; i++) { 1077 for (i = 0; i < XFRM_DST_HSIZE; i++) {
1068 list_for_each_entry(x, xfrm_state_bydst+i, bydst) { 1078 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
1069 if (xfrm_id_proto_match(x->id.proto, proto)) 1079 if (xfrm_id_proto_match(x->id.proto, proto))
1070 count++; 1080 count++;
1071 } 1081 }
@@ -1076,7 +1086,7 @@ int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
1076 } 1086 }
1077 1087
1078 for (i = 0; i < XFRM_DST_HSIZE; i++) { 1088 for (i = 0; i < XFRM_DST_HSIZE; i++) {
1079 list_for_each_entry(x, xfrm_state_bydst+i, bydst) { 1089 hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
1080 if (!xfrm_id_proto_match(x->id.proto, proto)) 1090 if (!xfrm_id_proto_match(x->id.proto, proto))
1081 continue; 1091 continue;
1082 err = func(x, --count, data); 1092 err = func(x, --count, data);
@@ -1524,9 +1534,9 @@ void __init xfrm_state_init(void)
1524 int i; 1534 int i;
1525 1535
1526 for (i=0; i<XFRM_DST_HSIZE; i++) { 1536 for (i=0; i<XFRM_DST_HSIZE; i++) {
1527 INIT_LIST_HEAD(&xfrm_state_bydst[i]); 1537 INIT_HLIST_HEAD(&xfrm_state_bydst[i]);
1528 INIT_LIST_HEAD(&xfrm_state_bysrc[i]); 1538 INIT_HLIST_HEAD(&xfrm_state_bysrc[i]);
1529 INIT_LIST_HEAD(&xfrm_state_byspi[i]); 1539 INIT_HLIST_HEAD(&xfrm_state_byspi[i]);
1530 } 1540 }
1531 INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL); 1541 INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);
1532} 1542}