aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-08-24 03:13:10 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:08:38 -0400
commit2770834c9f44afd1bfa13914c7285470775af657 (patch)
tree40191fdc632e572bc7878f57dc8fb385109a3aa8 /net/xfrm/xfrm_state.c
parent64d9fdda8e1bdf416b2d9203c3ad9c249ea301be (diff)
[XFRM]: Pull xfrm_state_bydst hash table knowledge out of afinfo.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c110
1 files changed, 100 insertions, 10 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 622e92a08d0b..80f5f9dc2b9e 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -48,6 +48,18 @@ static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE];
48static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE]; 48static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE];
49static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; 49static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE];
50 50
51static __inline__
52unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family)
53{
54 switch (family) {
55 case AF_INET:
56 return __xfrm4_dst_hash(addr);
57 case AF_INET6:
58 return __xfrm6_dst_hash(addr);
59 }
60 return 0;
61}
62
51DECLARE_WAIT_QUEUE_HEAD(km_waitq); 63DECLARE_WAIT_QUEUE_HEAD(km_waitq);
52EXPORT_SYMBOL(km_waitq); 64EXPORT_SYMBOL(km_waitq);
53 65
@@ -489,6 +501,89 @@ void xfrm_state_insert(struct xfrm_state *x)
489} 501}
490EXPORT_SYMBOL(xfrm_state_insert); 502EXPORT_SYMBOL(xfrm_state_insert);
491 503
504/* xfrm_state_lock is held */
505static 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)
506{
507 unsigned int h = xfrm_dst_hash(daddr, family);
508 struct xfrm_state *x;
509
510 list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
511 if (x->props.reqid != reqid ||
512 x->props.mode != mode ||
513 x->props.family != family ||
514 x->km.state != XFRM_STATE_ACQ ||
515 x->id.spi != 0)
516 continue;
517
518 switch (family) {
519 case AF_INET:
520 if (x->id.daddr.a4 != daddr->a4 ||
521 x->props.saddr.a4 != saddr->a4)
522 continue;
523 break;
524 case AF_INET6:
525 if (!ipv6_addr_equal((struct in6_addr *)x->id.daddr.a6,
526 (struct in6_addr *)daddr) ||
527 !ipv6_addr_equal((struct in6_addr *)
528 x->props.saddr.a6,
529 (struct in6_addr *)saddr))
530 continue;
531 break;
532 };
533
534 xfrm_state_hold(x);
535 return x;
536 }
537
538 if (!create)
539 return NULL;
540
541 x = xfrm_state_alloc();
542 if (likely(x)) {
543 switch (family) {
544 case AF_INET:
545 x->sel.daddr.a4 = daddr->a4;
546 x->sel.saddr.a4 = saddr->a4;
547 x->sel.prefixlen_d = 32;
548 x->sel.prefixlen_s = 32;
549 x->props.saddr.a4 = saddr->a4;
550 x->id.daddr.a4 = daddr->a4;
551 break;
552
553 case AF_INET6:
554 ipv6_addr_copy((struct in6_addr *)x->sel.daddr.a6,
555 (struct in6_addr *)daddr);
556 ipv6_addr_copy((struct in6_addr *)x->sel.saddr.a6,
557 (struct in6_addr *)saddr);
558 x->sel.prefixlen_d = 128;
559 x->sel.prefixlen_s = 128;
560 ipv6_addr_copy((struct in6_addr *)x->props.saddr.a6,
561 (struct in6_addr *)saddr);
562 ipv6_addr_copy((struct in6_addr *)x->id.daddr.a6,
563 (struct in6_addr *)daddr);
564 break;
565 };
566
567 x->km.state = XFRM_STATE_ACQ;
568 x->id.proto = proto;
569 x->props.family = family;
570 x->props.mode = mode;
571 x->props.reqid = reqid;
572 x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
573 xfrm_state_hold(x);
574 x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
575 add_timer(&x->timer);
576 xfrm_state_hold(x);
577 list_add_tail(&x->bydst, xfrm_state_bydst+h);
578 h = xfrm_src_hash(saddr, family);
579 xfrm_state_hold(x);
580 list_add_tail(&x->bysrc, xfrm_state_bysrc+h);
581 wake_up(&km_waitq);
582 }
583
584 return x;
585}
586
492static inline struct xfrm_state * 587static inline struct xfrm_state *
493__xfrm_state_locate(struct xfrm_state_afinfo *afinfo, struct xfrm_state *x, 588__xfrm_state_locate(struct xfrm_state_afinfo *afinfo, struct xfrm_state *x,
494 int use_spi) 589 int use_spi)
@@ -533,9 +628,9 @@ int xfrm_state_add(struct xfrm_state *x)
533 } 628 }
534 629
535 if (use_spi && !x1) 630 if (use_spi && !x1)
536 x1 = afinfo->find_acq( 631 x1 = __find_acq_core(family, x->props.mode, x->props.reqid,
537 x->props.mode, x->props.reqid, x->id.proto, 632 x->id.proto,
538 &x->id.daddr, &x->props.saddr, 0); 633 &x->id.daddr, &x->props.saddr, 0);
539 634
540 __xfrm_state_insert(x); 635 __xfrm_state_insert(x);
541 err = 0; 636 err = 0;
@@ -716,14 +811,11 @@ xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
716 int create, unsigned short family) 811 int create, unsigned short family)
717{ 812{
718 struct xfrm_state *x; 813 struct xfrm_state *x;
719 struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
720 if (!afinfo)
721 return NULL;
722 814
723 spin_lock_bh(&xfrm_state_lock); 815 spin_lock_bh(&xfrm_state_lock);
724 x = afinfo->find_acq(mode, reqid, proto, daddr, saddr, create); 816 x = __find_acq_core(family, mode, reqid, proto, daddr, saddr, create);
725 spin_unlock_bh(&xfrm_state_lock); 817 spin_unlock_bh(&xfrm_state_lock);
726 xfrm_state_put_afinfo(afinfo); 818
727 return x; 819 return x;
728} 820}
729EXPORT_SYMBOL(xfrm_find_acq); 821EXPORT_SYMBOL(xfrm_find_acq);
@@ -1181,7 +1273,6 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
1181 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) 1273 if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
1182 err = -ENOBUFS; 1274 err = -ENOBUFS;
1183 else { 1275 else {
1184 afinfo->state_bydst = xfrm_state_bydst;
1185 afinfo->state_bysrc = xfrm_state_bysrc; 1276 afinfo->state_bysrc = xfrm_state_bysrc;
1186 afinfo->state_byspi = xfrm_state_byspi; 1277 afinfo->state_byspi = xfrm_state_byspi;
1187 xfrm_state_afinfo[afinfo->family] = afinfo; 1278 xfrm_state_afinfo[afinfo->family] = afinfo;
@@ -1206,7 +1297,6 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
1206 xfrm_state_afinfo[afinfo->family] = NULL; 1297 xfrm_state_afinfo[afinfo->family] = NULL;
1207 afinfo->state_byspi = NULL; 1298 afinfo->state_byspi = NULL;
1208 afinfo->state_bysrc = NULL; 1299 afinfo->state_bysrc = NULL;
1209 afinfo->state_bydst = NULL;
1210 } 1300 }
1211 } 1301 }
1212 write_unlock_bh(&xfrm_state_afinfo_lock); 1302 write_unlock_bh(&xfrm_state_afinfo_lock);