Commit 6c44e6b7 authored by Masahide NAKAMURA's avatar Masahide NAKAMURA Committed by David S. Miller

[XFRM] STATE: Add source address list.

Support source address based searching.
Mobile IPv6 will use it.
Based on MIPL2 kernel patch.
Signed-off-by: default avatarMasahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 622dc828
...@@ -95,6 +95,7 @@ struct xfrm_state ...@@ -95,6 +95,7 @@ struct xfrm_state
{ {
/* Note: bydst is re-used during gc */ /* Note: bydst is re-used during gc */
struct list_head bydst; struct list_head bydst;
struct list_head bysrc;
struct list_head byspi; struct list_head byspi;
atomic_t refcnt; atomic_t refcnt;
...@@ -236,6 +237,7 @@ extern int __xfrm_state_delete(struct xfrm_state *x); ...@@ -236,6 +237,7 @@ extern int __xfrm_state_delete(struct xfrm_state *x);
struct xfrm_state_afinfo { struct xfrm_state_afinfo {
unsigned short family; unsigned short family;
struct list_head *state_bydst; struct list_head *state_bydst;
struct list_head *state_bysrc;
struct list_head *state_byspi; struct list_head *state_byspi;
int (*init_flags)(struct xfrm_state *x); int (*init_flags)(struct xfrm_state *x);
void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
...@@ -420,6 +422,30 @@ unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) ...@@ -420,6 +422,30 @@ unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family)
return 0; return 0;
} }
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;
}
static __inline__ static __inline__
unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto)
{ {
......
...@@ -122,6 +122,9 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto, ...@@ -122,6 +122,9 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto,
add_timer(&x0->timer); add_timer(&x0->timer);
xfrm_state_hold(x0); xfrm_state_hold(x0);
list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h); list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h);
h = __xfrm4_src_hash(saddr);
xfrm_state_hold(x0);
list_add_tail(&x0->bysrc, xfrm4_state_afinfo.state_bysrc+h);
wake_up(&km_waitq); wake_up(&km_waitq);
} }
if (x0) if (x0)
......
...@@ -126,6 +126,9 @@ __xfrm6_find_acq(u8 mode, u32 reqid, u8 proto, ...@@ -126,6 +126,9 @@ __xfrm6_find_acq(u8 mode, u32 reqid, u8 proto,
add_timer(&x0->timer); add_timer(&x0->timer);
xfrm_state_hold(x0); xfrm_state_hold(x0);
list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h); list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h);
h = __xfrm6_src_hash(saddr);
xfrm_state_hold(x0);
list_add_tail(&x0->bysrc, xfrm6_state_afinfo.state_bysrc+h);
wake_up(&km_waitq); wake_up(&km_waitq);
} }
if (x0) if (x0)
......
...@@ -45,6 +45,7 @@ static DEFINE_SPINLOCK(xfrm_state_lock); ...@@ -45,6 +45,7 @@ static DEFINE_SPINLOCK(xfrm_state_lock);
* Also, it can be used by ah/esp icmp error handler to find offending SA. * 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]; static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE];
static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE];
static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE];
DECLARE_WAIT_QUEUE_HEAD(km_waitq); DECLARE_WAIT_QUEUE_HEAD(km_waitq);
...@@ -200,6 +201,7 @@ struct xfrm_state *xfrm_state_alloc(void) ...@@ -200,6 +201,7 @@ struct xfrm_state *xfrm_state_alloc(void)
atomic_set(&x->refcnt, 1); atomic_set(&x->refcnt, 1);
atomic_set(&x->tunnel_users, 0); atomic_set(&x->tunnel_users, 0);
INIT_LIST_HEAD(&x->bydst); INIT_LIST_HEAD(&x->bydst);
INIT_LIST_HEAD(&x->bysrc);
INIT_LIST_HEAD(&x->byspi); INIT_LIST_HEAD(&x->byspi);
init_timer(&x->timer); init_timer(&x->timer);
x->timer.function = xfrm_timer_handler; x->timer.function = xfrm_timer_handler;
...@@ -240,6 +242,8 @@ int __xfrm_state_delete(struct xfrm_state *x) ...@@ -240,6 +242,8 @@ int __xfrm_state_delete(struct xfrm_state *x)
spin_lock(&xfrm_state_lock); spin_lock(&xfrm_state_lock);
list_del(&x->bydst); list_del(&x->bydst);
__xfrm_state_put(x); __xfrm_state_put(x);
list_del(&x->bysrc);
__xfrm_state_put(x);
if (x->id.spi) { if (x->id.spi) {
list_del(&x->byspi); list_del(&x->byspi);
__xfrm_state_put(x); __xfrm_state_put(x);
...@@ -415,6 +419,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, ...@@ -415,6 +419,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
x->km.state = XFRM_STATE_ACQ; x->km.state = XFRM_STATE_ACQ;
list_add_tail(&x->bydst, xfrm_state_bydst+h); list_add_tail(&x->bydst, xfrm_state_bydst+h);
xfrm_state_hold(x); xfrm_state_hold(x);
list_add_tail(&x->bysrc, xfrm_state_bysrc+h);
xfrm_state_hold(x);
if (x->id.spi) { if (x->id.spi) {
h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
list_add(&x->byspi, xfrm_state_byspi+h); list_add(&x->byspi, xfrm_state_byspi+h);
...@@ -448,11 +454,19 @@ static void __xfrm_state_insert(struct xfrm_state *x) ...@@ -448,11 +454,19 @@ static void __xfrm_state_insert(struct xfrm_state *x)
list_add(&x->bydst, xfrm_state_bydst+h); list_add(&x->bydst, xfrm_state_bydst+h);
xfrm_state_hold(x); xfrm_state_hold(x);
h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); h = xfrm_src_hash(&x->props.saddr, x->props.family);
list_add(&x->byspi, xfrm_state_byspi+h); list_add(&x->bysrc, xfrm_state_bysrc+h);
xfrm_state_hold(x); 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);
}
if (!mod_timer(&x->timer, jiffies + HZ)) if (!mod_timer(&x->timer, jiffies + HZ))
xfrm_state_hold(x); xfrm_state_hold(x);
...@@ -1075,6 +1089,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) ...@@ -1075,6 +1089,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
err = -ENOBUFS; err = -ENOBUFS;
else { else {
afinfo->state_bydst = xfrm_state_bydst; afinfo->state_bydst = xfrm_state_bydst;
afinfo->state_bysrc = xfrm_state_bysrc;
afinfo->state_byspi = xfrm_state_byspi; afinfo->state_byspi = xfrm_state_byspi;
xfrm_state_afinfo[afinfo->family] = afinfo; xfrm_state_afinfo[afinfo->family] = afinfo;
} }
...@@ -1097,6 +1112,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) ...@@ -1097,6 +1112,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
else { else {
xfrm_state_afinfo[afinfo->family] = NULL; xfrm_state_afinfo[afinfo->family] = NULL;
afinfo->state_byspi = NULL; afinfo->state_byspi = NULL;
afinfo->state_bysrc = NULL;
afinfo->state_bydst = NULL; afinfo->state_bydst = NULL;
} }
} }
...@@ -1218,6 +1234,7 @@ void __init xfrm_state_init(void) ...@@ -1218,6 +1234,7 @@ void __init xfrm_state_init(void)
for (i=0; i<XFRM_DST_HSIZE; i++) { for (i=0; i<XFRM_DST_HSIZE; i++) {
INIT_LIST_HEAD(&xfrm_state_bydst[i]); INIT_LIST_HEAD(&xfrm_state_bydst[i]);
INIT_LIST_HEAD(&xfrm_state_bysrc[i]);
INIT_LIST_HEAD(&xfrm_state_byspi[i]); INIT_LIST_HEAD(&xfrm_state_byspi[i]);
} }
INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL); INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment