Commit a74eab63 authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next

Steffen Klassert says:

====================
pull request (net-next): ipsec-next 2015-05-28

1) Remove xfrm_queue_purge as this is the same as skb_queue_purge.

2) Optimize policy and state walk.

3) Use a sane return code if afinfo registration fails.

4) Only check fori a acquire state if the state is not valid.

5) Remove a unnecessary NULL check before xfrm_pol_hold
   as it checks the input for NULL.

6) Return directly if the xfrm hold queue is empty, avoid
   to take a lock as it is nothing to do in this case.

7) Optimize the inexact policy search and allow for matching
   of policies with priority ~0U.

All from Li RongQing.

Please pull or let me know if there are problems.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d7a32b6e 8faf491e
...@@ -29,7 +29,7 @@ int xfrm_input_register_afinfo(struct xfrm_input_afinfo *afinfo) ...@@ -29,7 +29,7 @@ int xfrm_input_register_afinfo(struct xfrm_input_afinfo *afinfo)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
spin_lock_bh(&xfrm_input_afinfo_lock); spin_lock_bh(&xfrm_input_afinfo_lock);
if (unlikely(xfrm_input_afinfo[afinfo->family] != NULL)) if (unlikely(xfrm_input_afinfo[afinfo->family] != NULL))
err = -ENOBUFS; err = -EEXIST;
else else
rcu_assign_pointer(xfrm_input_afinfo[afinfo->family], afinfo); rcu_assign_pointer(xfrm_input_afinfo[afinfo->family], afinfo);
spin_unlock_bh(&xfrm_input_afinfo_lock); spin_unlock_bh(&xfrm_input_afinfo_lock);
...@@ -239,13 +239,13 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) ...@@ -239,13 +239,13 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
skb->sp->xvec[skb->sp->len++] = x; skb->sp->xvec[skb->sp->len++] = x;
spin_lock(&x->lock); spin_lock(&x->lock);
if (unlikely(x->km.state == XFRM_STATE_ACQ)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR);
goto drop_unlock;
}
if (unlikely(x->km.state != XFRM_STATE_VALID)) { if (unlikely(x->km.state != XFRM_STATE_VALID)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEINVALID); if (x->km.state == XFRM_STATE_ACQ)
XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR);
else
XFRM_INC_STATS(net,
LINUX_MIB_XFRMINSTATEINVALID);
goto drop_unlock; goto drop_unlock;
} }
......
...@@ -315,14 +315,6 @@ void xfrm_policy_destroy(struct xfrm_policy *policy) ...@@ -315,14 +315,6 @@ void xfrm_policy_destroy(struct xfrm_policy *policy)
} }
EXPORT_SYMBOL(xfrm_policy_destroy); EXPORT_SYMBOL(xfrm_policy_destroy);
static void xfrm_queue_purge(struct sk_buff_head *list)
{
struct sk_buff *skb;
while ((skb = skb_dequeue(list)) != NULL)
kfree_skb(skb);
}
/* Rule must be locked. Release descentant resources, announce /* Rule must be locked. Release descentant resources, announce
* entry dead. The rule must be unlinked from lists to the moment. * entry dead. The rule must be unlinked from lists to the moment.
*/ */
...@@ -335,7 +327,7 @@ static void xfrm_policy_kill(struct xfrm_policy *policy) ...@@ -335,7 +327,7 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
if (del_timer(&policy->polq.hold_timer)) if (del_timer(&policy->polq.hold_timer))
xfrm_pol_put(policy); xfrm_pol_put(policy);
xfrm_queue_purge(&policy->polq.hold_queue); skb_queue_purge(&policy->polq.hold_queue);
if (del_timer(&policy->timer)) if (del_timer(&policy->timer))
xfrm_pol_put(policy); xfrm_pol_put(policy);
...@@ -708,6 +700,9 @@ static void xfrm_policy_requeue(struct xfrm_policy *old, ...@@ -708,6 +700,9 @@ static void xfrm_policy_requeue(struct xfrm_policy *old,
struct xfrm_policy_queue *pq = &old->polq; struct xfrm_policy_queue *pq = &old->polq;
struct sk_buff_head list; struct sk_buff_head list;
if (skb_queue_empty(&pq->hold_queue))
return;
__skb_queue_head_init(&list); __skb_queue_head_init(&list);
spin_lock_bh(&pq->hold_queue.lock); spin_lock_bh(&pq->hold_queue.lock);
...@@ -716,9 +711,6 @@ static void xfrm_policy_requeue(struct xfrm_policy *old, ...@@ -716,9 +711,6 @@ static void xfrm_policy_requeue(struct xfrm_policy *old,
xfrm_pol_put(old); xfrm_pol_put(old);
spin_unlock_bh(&pq->hold_queue.lock); spin_unlock_bh(&pq->hold_queue.lock);
if (skb_queue_empty(&list))
return;
pq = &new->polq; pq = &new->polq;
spin_lock_bh(&pq->hold_queue.lock); spin_lock_bh(&pq->hold_queue.lock);
...@@ -1012,7 +1004,9 @@ int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, ...@@ -1012,7 +1004,9 @@ int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
if (list_empty(&walk->walk.all)) if (list_empty(&walk->walk.all))
x = list_first_entry(&net->xfrm.policy_all, struct xfrm_policy_walk_entry, all); x = list_first_entry(&net->xfrm.policy_all, struct xfrm_policy_walk_entry, all);
else else
x = list_entry(&walk->walk.all, struct xfrm_policy_walk_entry, all); x = list_first_entry(&walk->walk.all,
struct xfrm_policy_walk_entry, all);
list_for_each_entry_from(x, &net->xfrm.policy_all, all) { list_for_each_entry_from(x, &net->xfrm.policy_all, all) {
if (x->dead) if (x->dead)
continue; continue;
...@@ -1120,6 +1114,9 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type, ...@@ -1120,6 +1114,9 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type,
} }
chain = &net->xfrm.policy_inexact[dir]; chain = &net->xfrm.policy_inexact[dir];
hlist_for_each_entry(pol, chain, bydst) { hlist_for_each_entry(pol, chain, bydst) {
if ((pol->priority >= priority) && ret)
break;
err = xfrm_policy_match(pol, fl, type, family, dir); err = xfrm_policy_match(pol, fl, type, family, dir);
if (err) { if (err) {
if (err == -ESRCH) if (err == -ESRCH)
...@@ -1128,12 +1125,12 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type, ...@@ -1128,12 +1125,12 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type,
ret = ERR_PTR(err); ret = ERR_PTR(err);
goto fail; goto fail;
} }
} else if (pol->priority < priority) { } else {
ret = pol; ret = pol;
break; break;
} }
} }
if (ret)
xfrm_pol_hold(ret); xfrm_pol_hold(ret);
fail: fail:
read_unlock_bh(&net->xfrm.xfrm_policy_lock); read_unlock_bh(&net->xfrm.xfrm_policy_lock);
...@@ -1955,7 +1952,7 @@ static void xfrm_policy_queue_process(unsigned long arg) ...@@ -1955,7 +1952,7 @@ static void xfrm_policy_queue_process(unsigned long arg)
purge_queue: purge_queue:
pq->timeout = 0; pq->timeout = 0;
xfrm_queue_purge(&pq->hold_queue); skb_queue_purge(&pq->hold_queue);
xfrm_pol_put(pol); xfrm_pol_put(pol);
} }
...@@ -2814,7 +2811,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) ...@@ -2814,7 +2811,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
spin_lock(&xfrm_policy_afinfo_lock); spin_lock(&xfrm_policy_afinfo_lock);
if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL)) if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL))
err = -ENOBUFS; err = -EEXIST;
else { else {
struct dst_ops *dst_ops = afinfo->dst_ops; struct dst_ops *dst_ops = afinfo->dst_ops;
if (likely(dst_ops->kmem_cachep == NULL)) if (likely(dst_ops->kmem_cachep == NULL))
...@@ -3209,15 +3206,16 @@ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector * ...@@ -3209,15 +3206,16 @@ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *
} }
chain = &net->xfrm.policy_inexact[dir]; chain = &net->xfrm.policy_inexact[dir];
hlist_for_each_entry(pol, chain, bydst) { hlist_for_each_entry(pol, chain, bydst) {
if ((pol->priority >= priority) && ret)
break;
if (xfrm_migrate_selector_match(sel, &pol->selector) && if (xfrm_migrate_selector_match(sel, &pol->selector) &&
pol->type == type && pol->type == type) {
pol->priority < priority) {
ret = pol; ret = pol;
break; break;
} }
} }
if (ret)
xfrm_pol_hold(ret); xfrm_pol_hold(ret);
read_unlock_bh(&net->xfrm.xfrm_policy_lock); read_unlock_bh(&net->xfrm.xfrm_policy_lock);
......
...@@ -1626,7 +1626,7 @@ int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, ...@@ -1626,7 +1626,7 @@ int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
if (list_empty(&walk->all)) if (list_empty(&walk->all))
x = list_first_entry(&net->xfrm.state_all, struct xfrm_state_walk, all); x = list_first_entry(&net->xfrm.state_all, struct xfrm_state_walk, all);
else else
x = list_entry(&walk->all, struct xfrm_state_walk, all); x = list_first_entry(&walk->all, struct xfrm_state_walk, all);
list_for_each_entry_from(x, &net->xfrm.state_all, all) { list_for_each_entry_from(x, &net->xfrm.state_all, all) {
if (x->state == XFRM_STATE_DEAD) if (x->state == XFRM_STATE_DEAD)
continue; continue;
...@@ -1908,7 +1908,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) ...@@ -1908,7 +1908,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
spin_lock_bh(&xfrm_state_afinfo_lock); spin_lock_bh(&xfrm_state_afinfo_lock);
if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
err = -ENOBUFS; err = -EEXIST;
else else
rcu_assign_pointer(xfrm_state_afinfo[afinfo->family], afinfo); rcu_assign_pointer(xfrm_state_afinfo[afinfo->family], afinfo);
spin_unlock_bh(&xfrm_state_afinfo_lock); spin_unlock_bh(&xfrm_state_afinfo_lock);
......
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