diff options
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r-- | net/xfrm/xfrm_state.c | 92 |
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 | */ |
49 | static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE]; | 49 | static struct hlist_head xfrm_state_bydst[XFRM_DST_HSIZE]; |
50 | static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE]; | 50 | static struct hlist_head xfrm_state_bysrc[XFRM_DST_HSIZE]; |
51 | static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; | 51 | static struct hlist_head xfrm_state_byspi[XFRM_DST_HSIZE]; |
52 | 52 | ||
53 | static __inline__ | 53 | static __inline__ |
54 | unsigned __xfrm4_dst_hash(xfrm_address_t *addr) | 54 | unsigned __xfrm4_dst_hash(xfrm_address_t *addr) |
@@ -141,7 +141,7 @@ static DEFINE_RWLOCK(xfrm_state_afinfo_lock); | |||
141 | static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; | 141 | static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; |
142 | 142 | ||
143 | static struct work_struct xfrm_state_gc_work; | 143 | static struct work_struct xfrm_state_gc_work; |
144 | static struct list_head xfrm_state_gc_list = LIST_HEAD_INIT(xfrm_state_gc_list); | 144 | static HLIST_HEAD(xfrm_state_gc_list); |
145 | static DEFINE_SPINLOCK(xfrm_state_gc_lock); | 145 | static DEFINE_SPINLOCK(xfrm_state_gc_lock); |
146 | 146 | ||
147 | static int xfrm_state_gc_flush_bundles; | 147 | static int xfrm_state_gc_flush_bundles; |
@@ -178,8 +178,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
178 | static void xfrm_state_gc_task(void *data) | 178 | static 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); | |||
378 | void xfrm_state_flush(u8 proto) | 378 | void 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; | ||
385 | restart: | 386 | restart: |
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); | |||
648 | 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) | 653 | 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) |
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); | |||
977 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) | 983 | static 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 | } |