--- a/include/net/xfrm.h 2005/04/28 14:05:00 1.1 +++ b/include/net/xfrm.h 2005/04/28 14:05:48 @@ -302,6 +302,7 @@ struct dst_entry *bundles; __u16 family; __u8 action; + __u8 dir; __u8 flags; __u8 dead; __u8 xfrm_nr; --- a/net/xfrm/xfrm_user.c 2005/04/28 13:59:27 1.1 +++ b/net/xfrm/xfrm_user.c 2005/04/28 14:01:58 @@ -653,6 +653,7 @@ memcpy(&xp->selector, &p->sel, sizeof(xp->selector)); memcpy(&xp->lft, &p->lft, sizeof(xp->lft)); xp->action = p->action; + xp->dir = p->dir; xp->flags = p->flags; xp->family = p->sel.family; /* XXX xp->share = p->share; */ --- a/net/xfrm/xfrm_policy.c 2005/04/27 11:32:13 1.1 +++ b/net/xfrm/xfrm_policy.c 2005/04/28 14:02:18 @@ -163,7 +163,7 @@ if (xp->dead) goto out; - dir = xp->index & 7; + dir = xp->dir; if (xp->lft.hard_add_expires_seconds) { long tmo = xp->lft.hard_add_expires_seconds + @@ -345,7 +345,10 @@ write_lock_bh(&xfrm_policy_lock); for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) { - if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0) { + if (!delpol && + ((!excl && policy->index && + (policy->index == pol->index)) || + (memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0))) { if (excl) { write_unlock_bh(&xfrm_policy_lock); return -EEXIST; @@ -370,7 +373,9 @@ policy->next = *p; *p = policy; atomic_inc(&flow_cache_genid); - policy->index = delpol ? delpol->index : xfrm_gen_index(dir); + if (!policy->index) + policy->index = delpol ? delpol->index : xfrm_gen_index(dir); + policy->curlft.add_time = (unsigned long)xtime.tv_sec; policy->curlft.use_time = 0; if (!mod_timer(&policy->timer, jiffies + HZ)) @@ -413,7 +418,7 @@ struct xfrm_policy *pol, **p; write_lock_bh(&xfrm_policy_lock); - for (p = &xfrm_policy_list[id & 7]; (pol=*p)!=NULL; p = &pol->next) { + for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { if (pol->index == id) { xfrm_pol_hold(pol); if (delete)