Commit 6db70e3e 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 2014-12-03

1) Fix a set but not used warning. From Fabian Frederick.

2) Currently we make sequence number values available to userspace
   only if we use ESN. Make the sequence number values also available
   for non ESN states. From Zhi Ding.

3) Remove socket policy hashing. We don't need it because socket
   policies are always looked up via a linked list. From Herbert Xu.

4) After removing socket policy hashing, we can use __xfrm_policy_link
   in xfrm_policy_insert. From Herbert Xu.

5) Add a lookup method for vti6 tunnels with wildcard endpoints.
   I forgot this when I initially implemented vti6.

Please pull or let me know if there are problems.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f5f04bcf fbe68ee8
...@@ -50,8 +50,8 @@ struct netns_xfrm { ...@@ -50,8 +50,8 @@ struct netns_xfrm {
struct list_head policy_all; struct list_head policy_all;
struct hlist_head *policy_byidx; struct hlist_head *policy_byidx;
unsigned int policy_idx_hmask; unsigned int policy_idx_hmask;
struct hlist_head policy_inexact[XFRM_POLICY_MAX * 2]; struct hlist_head policy_inexact[XFRM_POLICY_MAX];
struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2]; struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX];
unsigned int policy_count[XFRM_POLICY_MAX * 2]; unsigned int policy_count[XFRM_POLICY_MAX * 2];
struct work_struct policy_hash_work; struct work_struct policy_hash_work;
struct xfrm_policy_hthresh policy_hthresh; struct xfrm_policy_hthresh policy_hthresh;
......
...@@ -95,6 +95,7 @@ vti6_tnl_lookup(struct net *net, const struct in6_addr *remote, ...@@ -95,6 +95,7 @@ vti6_tnl_lookup(struct net *net, const struct in6_addr *remote,
unsigned int hash = HASH(remote, local); unsigned int hash = HASH(remote, local);
struct ip6_tnl *t; struct ip6_tnl *t;
struct vti6_net *ip6n = net_generic(net, vti6_net_id); struct vti6_net *ip6n = net_generic(net, vti6_net_id);
struct in6_addr any;
for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) { for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
if (ipv6_addr_equal(local, &t->parms.laddr) && if (ipv6_addr_equal(local, &t->parms.laddr) &&
...@@ -102,6 +103,22 @@ vti6_tnl_lookup(struct net *net, const struct in6_addr *remote, ...@@ -102,6 +103,22 @@ vti6_tnl_lookup(struct net *net, const struct in6_addr *remote,
(t->dev->flags & IFF_UP)) (t->dev->flags & IFF_UP))
return t; return t;
} }
memset(&any, 0, sizeof(any));
hash = HASH(&any, local);
for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
if (ipv6_addr_equal(local, &t->parms.laddr) &&
(t->dev->flags & IFF_UP))
return t;
}
hash = HASH(remote, &any);
for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
if (ipv6_addr_equal(remote, &t->parms.raddr) &&
(t->dev->flags & IFF_UP))
return t;
}
t = rcu_dereference(ip6n->tnls_wc[0]); t = rcu_dereference(ip6n->tnls_wc[0]);
if (t && (t->dev->flags & IFF_UP)) if (t && (t->dev->flags & IFF_UP))
return t; return t;
......
...@@ -55,6 +55,7 @@ static int stale_bundle(struct dst_entry *dst); ...@@ -55,6 +55,7 @@ static int stale_bundle(struct dst_entry *dst);
static int xfrm_bundle_ok(struct xfrm_dst *xdst); static int xfrm_bundle_ok(struct xfrm_dst *xdst);
static void xfrm_policy_queue_process(unsigned long arg); static void xfrm_policy_queue_process(unsigned long arg);
static void __xfrm_policy_link(struct xfrm_policy *pol, int dir);
static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
int dir); int dir);
...@@ -561,7 +562,7 @@ static void xfrm_hash_resize(struct work_struct *work) ...@@ -561,7 +562,7 @@ static void xfrm_hash_resize(struct work_struct *work)
mutex_lock(&hash_resize_mutex); mutex_lock(&hash_resize_mutex);
total = 0; total = 0;
for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
if (xfrm_bydst_should_resize(net, dir, &total)) if (xfrm_bydst_should_resize(net, dir, &total))
xfrm_bydst_resize(net, dir); xfrm_bydst_resize(net, dir);
} }
...@@ -601,7 +602,7 @@ static void xfrm_hash_rebuild(struct work_struct *work) ...@@ -601,7 +602,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
write_lock_bh(&net->xfrm.xfrm_policy_lock); write_lock_bh(&net->xfrm.xfrm_policy_lock);
/* reset the bydst and inexact table in all directions */ /* reset the bydst and inexact table in all directions */
for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]); INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
hmask = net->xfrm.policy_bydst[dir].hmask; hmask = net->xfrm.policy_bydst[dir].hmask;
odst = net->xfrm.policy_bydst[dir].table; odst = net->xfrm.policy_bydst[dir].table;
...@@ -779,8 +780,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) ...@@ -779,8 +780,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
hlist_add_behind(&policy->bydst, newpos); hlist_add_behind(&policy->bydst, newpos);
else else
hlist_add_head(&policy->bydst, chain); hlist_add_head(&policy->bydst, chain);
xfrm_pol_hold(policy); __xfrm_policy_link(policy, dir);
net->xfrm.policy_count[dir]++;
atomic_inc(&net->xfrm.flow_cache_genid); atomic_inc(&net->xfrm.flow_cache_genid);
/* After previous checking, family can either be AF_INET or AF_INET6 */ /* After previous checking, family can either be AF_INET or AF_INET6 */
...@@ -799,7 +799,6 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) ...@@ -799,7 +799,6 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
policy->curlft.use_time = 0; policy->curlft.use_time = 0;
if (!mod_timer(&policy->timer, jiffies + HZ)) if (!mod_timer(&policy->timer, jiffies + HZ))
xfrm_pol_hold(policy); xfrm_pol_hold(policy);
list_add(&policy->walk.all, &net->xfrm.policy_all);
write_unlock_bh(&net->xfrm.xfrm_policy_lock); write_unlock_bh(&net->xfrm.xfrm_policy_lock);
if (delpol) if (delpol)
...@@ -1247,17 +1246,10 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, ...@@ -1247,17 +1246,10 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir,
static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
{ {
struct net *net = xp_net(pol); struct net *net = xp_net(pol);
struct hlist_head *chain = policy_hash_bysel(net, &pol->selector,
pol->family, dir);
list_add(&pol->walk.all, &net->xfrm.policy_all); list_add(&pol->walk.all, &net->xfrm.policy_all);
hlist_add_head(&pol->bydst, chain);
hlist_add_head(&pol->byidx, net->xfrm.policy_byidx+idx_hash(net, pol->index));
net->xfrm.policy_count[dir]++; net->xfrm.policy_count[dir]++;
xfrm_pol_hold(pol); xfrm_pol_hold(pol);
if (xfrm_bydst_should_resize(net, dir, NULL))
schedule_work(&net->xfrm.policy_hash_work);
} }
static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
...@@ -1265,17 +1257,31 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, ...@@ -1265,17 +1257,31 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
{ {
struct net *net = xp_net(pol); struct net *net = xp_net(pol);
if (hlist_unhashed(&pol->bydst)) if (list_empty(&pol->walk.all))
return NULL; return NULL;
hlist_del_init(&pol->bydst); /* Socket policies are not hashed. */
hlist_del(&pol->byidx); if (!hlist_unhashed(&pol->bydst)) {
list_del(&pol->walk.all); hlist_del(&pol->bydst);
hlist_del(&pol->byidx);
}
list_del_init(&pol->walk.all);
net->xfrm.policy_count[dir]--; net->xfrm.policy_count[dir]--;
return pol; return pol;
} }
static void xfrm_sk_policy_link(struct xfrm_policy *pol, int dir)
{
__xfrm_policy_link(pol, XFRM_POLICY_MAX + dir);
}
static void xfrm_sk_policy_unlink(struct xfrm_policy *pol, int dir)
{
__xfrm_policy_unlink(pol, XFRM_POLICY_MAX + dir);
}
int xfrm_policy_delete(struct xfrm_policy *pol, int dir) int xfrm_policy_delete(struct xfrm_policy *pol, int dir)
{ {
struct net *net = xp_net(pol); struct net *net = xp_net(pol);
...@@ -1307,7 +1313,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) ...@@ -1307,7 +1313,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
if (pol) { if (pol) {
pol->curlft.add_time = get_seconds(); pol->curlft.add_time = get_seconds();
pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir, 0); pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir, 0);
__xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); xfrm_sk_policy_link(pol, dir);
} }
if (old_pol) { if (old_pol) {
if (pol) if (pol)
...@@ -1316,7 +1322,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) ...@@ -1316,7 +1322,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
/* Unlinking succeeds always. This is the only function /* Unlinking succeeds always. This is the only function
* allowed to delete or replace socket policy. * allowed to delete or replace socket policy.
*/ */
__xfrm_policy_unlink(old_pol, XFRM_POLICY_MAX+dir); xfrm_sk_policy_unlink(old_pol, dir);
} }
write_unlock_bh(&net->xfrm.xfrm_policy_lock); write_unlock_bh(&net->xfrm.xfrm_policy_lock);
...@@ -1349,7 +1355,7 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir) ...@@ -1349,7 +1355,7 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir)
memcpy(newp->xfrm_vec, old->xfrm_vec, memcpy(newp->xfrm_vec, old->xfrm_vec,
newp->xfrm_nr*sizeof(struct xfrm_tmpl)); newp->xfrm_nr*sizeof(struct xfrm_tmpl));
write_lock_bh(&net->xfrm.xfrm_policy_lock); write_lock_bh(&net->xfrm.xfrm_policy_lock);
__xfrm_policy_link(newp, XFRM_POLICY_MAX+dir); xfrm_sk_policy_link(newp, dir);
write_unlock_bh(&net->xfrm.xfrm_policy_lock); write_unlock_bh(&net->xfrm.xfrm_policy_lock);
xfrm_pol_put(newp); xfrm_pol_put(newp);
} }
...@@ -1878,7 +1884,6 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols, ...@@ -1878,7 +1884,6 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
static void xfrm_policy_queue_process(unsigned long arg) static void xfrm_policy_queue_process(unsigned long arg)
{ {
int err = 0;
struct sk_buff *skb; struct sk_buff *skb;
struct sock *sk; struct sock *sk;
struct dst_entry *dst; struct dst_entry *dst;
...@@ -1941,7 +1946,7 @@ static void xfrm_policy_queue_process(unsigned long arg) ...@@ -1941,7 +1946,7 @@ static void xfrm_policy_queue_process(unsigned long arg)
skb_dst_drop(skb); skb_dst_drop(skb);
skb_dst_set(skb, dst); skb_dst_set(skb, dst);
err = dst_output(skb); dst_output(skb);
} }
out: out:
...@@ -2966,10 +2971,11 @@ static int __net_init xfrm_policy_init(struct net *net) ...@@ -2966,10 +2971,11 @@ static int __net_init xfrm_policy_init(struct net *net)
goto out_byidx; goto out_byidx;
net->xfrm.policy_idx_hmask = hmask; net->xfrm.policy_idx_hmask = hmask;
for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
struct xfrm_policy_hash *htab; struct xfrm_policy_hash *htab;
net->xfrm.policy_count[dir] = 0; net->xfrm.policy_count[dir] = 0;
net->xfrm.policy_count[XFRM_POLICY_MAX + dir] = 0;
INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]); INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
htab = &net->xfrm.policy_bydst[dir]; htab = &net->xfrm.policy_bydst[dir];
...@@ -3021,7 +3027,7 @@ static void xfrm_policy_fini(struct net *net) ...@@ -3021,7 +3027,7 @@ static void xfrm_policy_fini(struct net *net)
WARN_ON(!list_empty(&net->xfrm.policy_all)); WARN_ON(!list_empty(&net->xfrm.policy_all));
for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
struct xfrm_policy_hash *htab; struct xfrm_policy_hash *htab;
WARN_ON(!hlist_empty(&net->xfrm.policy_inexact[dir])); WARN_ON(!hlist_empty(&net->xfrm.policy_inexact[dir]));
......
...@@ -824,13 +824,15 @@ static int copy_to_user_state_extra(struct xfrm_state *x, ...@@ -824,13 +824,15 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
ret = xfrm_mark_put(skb, &x->mark); ret = xfrm_mark_put(skb, &x->mark);
if (ret) if (ret)
goto out; goto out;
if (x->replay_esn) { if (x->replay_esn)
ret = nla_put(skb, XFRMA_REPLAY_ESN_VAL, ret = nla_put(skb, XFRMA_REPLAY_ESN_VAL,
xfrm_replay_state_esn_len(x->replay_esn), xfrm_replay_state_esn_len(x->replay_esn),
x->replay_esn); x->replay_esn);
if (ret) else
goto out; ret = nla_put(skb, XFRMA_REPLAY_VAL, sizeof(x->replay),
} &x->replay);
if (ret)
goto out;
if (x->security) if (x->security)
ret = copy_sec_ctx(x->security, skb); ret = copy_sec_ctx(x->security, skb);
out: out:
...@@ -2569,6 +2571,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x) ...@@ -2569,6 +2571,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
l += nla_total_size(sizeof(x->tfcpad)); l += nla_total_size(sizeof(x->tfcpad));
if (x->replay_esn) if (x->replay_esn)
l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn)); l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn));
else
l += nla_total_size(sizeof(struct xfrm_replay_state));
if (x->security) if (x->security)
l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) + l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) +
x->security->ctx_len); x->security->ctx_len);
......
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