Support source address based searching. Mobile IPv6 will use it. Based on MIPL2 kernel patch. --- include/linux/xfrm.h | 1 + include/net/xfrm.h | 32 ++++++++++++++++++++++++++++++++ net/ipv4/xfrm4_state.c | 5 +++++ net/ipv6/xfrm6_state.c | 5 +++++ net/xfrm/xfrm_state.c | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 0 deletions(-)
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 7dff1c8..55d1ce4 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -263,6 +263,7 @@ struct xfrm_usersa_id { __u32 spi; __u16 family; __u8 proto; + xfrm_address_t saddr; }; struct xfrm_aevent_id { diff --git a/include/net/xfrm.h b/include/net/xfrm.h index ca537b5..75649da 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -94,6 +94,9 @@ struct xfrm_state { /* Note: bydst is re-used during gc */ struct list_head bydst; +#ifdef CONFIG_XFRM_ADVANCED + struct list_head bysrc; +#endif struct list_head byspi; atomic_t refcnt; @@ -235,6 +238,9 @@ struct xfrm_state_afinfo { unsigned short family; rwlock_t lock; struct list_head *state_bydst; +#ifdef CONFIG_XFRM_ADVANCED + struct list_head *state_bysrc; +#endif struct list_head *state_byspi; int (*init_flags)(struct xfrm_state *x); void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, @@ -411,6 +417,32 @@ unsigned xfrm_dst_hash(xfrm_address_t *a return 0; } +#ifdef CONFIG_XFRM_ADVANCED +static __inline__ +unsigned __xfrm4_src_hash(xfrm_address_t *addr) +{ + return __xfrm4_dst_hash(addr); +} + +static __inline__ +unsigned __xfrm6_src_hash(xfrm_address_t *addr) +{ + return __xfrm6_dst_hash(addr); +} + +static __inline__ +unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family) +{ + switch (family) { + case AF_INET: + return __xfrm4_src_hash(addr); + case AF_INET6: + return __xfrm6_src_hash(addr); + } + return 0; +} +#endif + static __inline__ unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) { diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 171cdc5..6de2ce0 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -122,6 +122,11 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 add_timer(&x0->timer); xfrm_state_hold(x0); list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h); +#ifdef CONFIG_XFRM_ADVANCED + h = __xfrm4_src_hash(saddr); + xfrm_state_hold(x0); + list_add_tail(&x0->bysrc, xfrm4_state_afinfo.state_bysrc+h); +#endif wake_up(&km_waitq); } if (x0) diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index 71c40bb..00b6c17 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c @@ -126,6 +126,11 @@ __xfrm6_find_acq(u8 mode, u32 reqid, u8 add_timer(&x0->timer); xfrm_state_hold(x0); list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h); +#ifdef CONFIG_XFRM_ADVANCED + h = __xfrm6_src_hash(saddr); + xfrm_state_hold(x0); + list_add_tail(&x0->bysrc, xfrm6_state_afinfo.state_bysrc+h); +#endif wake_up(&km_waitq); } if (x0) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 6cf080f..1942bb1 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -45,6 +45,9 @@ static DEFINE_SPINLOCK(xfrm_state_lock); * Also, it can be used by ah/esp icmp error handler to find offending SA. */ static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE]; +#ifdef CONFIG_XFRM_ADVANCED +static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE]; +#endif static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; DECLARE_WAIT_QUEUE_HEAD(km_waitq); @@ -199,6 +202,9 @@ struct xfrm_state *xfrm_state_alloc(void atomic_set(&x->refcnt, 1); atomic_set(&x->tunnel_users, 0); INIT_LIST_HEAD(&x->bydst); +#ifdef CONFIG_XFRM_ADVANCED + INIT_LIST_HEAD(&x->bysrc); +#endif INIT_LIST_HEAD(&x->byspi); init_timer(&x->timer); x->timer.function = xfrm_timer_handler; @@ -239,6 +245,10 @@ int __xfrm_state_delete(struct xfrm_stat spin_lock(&xfrm_state_lock); list_del(&x->bydst); __xfrm_state_put(x); +#ifdef CONFIG_XFRM_ADVANCED + list_del(&x->bysrc); + __xfrm_state_put(x); +#endif if (x->id.spi) { list_del(&x->byspi); __xfrm_state_put(x); @@ -406,6 +416,10 @@ xfrm_state_find(xfrm_address_t *daddr, x x->km.state = XFRM_STATE_ACQ; list_add_tail(&x->bydst, xfrm_state_bydst+h); xfrm_state_hold(x); +#ifdef CONFIG_XFRM_ADVANCED + list_add_tail(&x->bysrc, xfrm_state_bysrc+h); + xfrm_state_hold(x); +#endif if (x->id.spi) { h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); list_add(&x->byspi, xfrm_state_byspi+h); @@ -439,10 +453,25 @@ static void __xfrm_state_insert(struct x list_add(&x->bydst, xfrm_state_bydst+h); xfrm_state_hold(x); +#ifdef CONFIG_XFRM_ADVANCED + h = xfrm_src_hash(&x->props.saddr, x->props.family); + + list_add(&x->bysrc, xfrm_state_bysrc+h); + xfrm_state_hold(x); + + if (xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY)) { + h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, + x->props.family); + + list_add(&x->byspi, xfrm_state_byspi+h); + xfrm_state_hold(x); + } +#else h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); list_add(&x->byspi, xfrm_state_byspi+h); xfrm_state_hold(x); +#endif if (!mod_timer(&x->timer, jiffies + HZ)) xfrm_state_hold(x); @@ -1066,6 +1095,9 @@ int xfrm_state_register_afinfo(struct xf err = -ENOBUFS; else { afinfo->state_bydst = xfrm_state_bydst; +#ifdef CONFIG_XFRM_ADVANCED + afinfo->state_bysrc = xfrm_state_bysrc; +#endif afinfo->state_byspi = xfrm_state_byspi; xfrm_state_afinfo[afinfo->family] = afinfo; } @@ -1088,6 +1120,9 @@ int xfrm_state_unregister_afinfo(struct else { xfrm_state_afinfo[afinfo->family] = NULL; afinfo->state_byspi = NULL; +#ifdef CONFIG_XFRM_ADVANCED + afinfo->state_bysrc = NULL; +#endif afinfo->state_bydst = NULL; } } @@ -1210,6 +1245,9 @@ void __init xfrm_state_init(void) for (i=0; i<XFRM_DST_HSIZE; i++) { INIT_LIST_HEAD(&xfrm_state_bydst[i]); +#ifdef CONFIG_XFRM_ADVANCED + INIT_LIST_HEAD(&xfrm_state_bysrc[i]); +#endif INIT_LIST_HEAD(&xfrm_state_byspi[i]); } INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL); -- 1.4.1 - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html