forked from luck/tmp_suning_uos_patched
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
6db70e3e1d
|
@ -50,8 +50,8 @@ struct netns_xfrm {
|
|||
struct list_head policy_all;
|
||||
struct hlist_head *policy_byidx;
|
||||
unsigned int policy_idx_hmask;
|
||||
struct hlist_head policy_inexact[XFRM_POLICY_MAX * 2];
|
||||
struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2];
|
||||
struct hlist_head policy_inexact[XFRM_POLICY_MAX];
|
||||
struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX];
|
||||
unsigned int policy_count[XFRM_POLICY_MAX * 2];
|
||||
struct work_struct policy_hash_work;
|
||||
struct xfrm_policy_hthresh policy_hthresh;
|
||||
|
|
|
@ -95,6 +95,7 @@ vti6_tnl_lookup(struct net *net, const struct in6_addr *remote,
|
|||
unsigned int hash = HASH(remote, local);
|
||||
struct ip6_tnl *t;
|
||||
struct vti6_net *ip6n = net_generic(net, vti6_net_id);
|
||||
struct in6_addr any;
|
||||
|
||||
for_each_vti6_tunnel_rcu(ip6n->tnls_r_l[hash]) {
|
||||
if (ipv6_addr_equal(local, &t->parms.laddr) &&
|
||||
|
@ -102,6 +103,22 @@ vti6_tnl_lookup(struct net *net, const struct in6_addr *remote,
|
|||
(t->dev->flags & IFF_UP))
|
||||
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]);
|
||||
if (t && (t->dev->flags & IFF_UP))
|
||||
return t;
|
||||
|
|
|
@ -55,6 +55,7 @@ static int stale_bundle(struct dst_entry *dst);
|
|||
static int xfrm_bundle_ok(struct xfrm_dst *xdst);
|
||||
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,
|
||||
int dir);
|
||||
|
||||
|
@ -561,7 +562,7 @@ static void xfrm_hash_resize(struct work_struct *work)
|
|||
mutex_lock(&hash_resize_mutex);
|
||||
|
||||
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))
|
||||
xfrm_bydst_resize(net, dir);
|
||||
}
|
||||
|
@ -601,7 +602,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
|
|||
write_lock_bh(&net->xfrm.xfrm_policy_lock);
|
||||
|
||||
/* 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]);
|
||||
hmask = net->xfrm.policy_bydst[dir].hmask;
|
||||
odst = net->xfrm.policy_bydst[dir].table;
|
||||
|
@ -779,8 +780,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
|
|||
hlist_add_behind(&policy->bydst, newpos);
|
||||
else
|
||||
hlist_add_head(&policy->bydst, chain);
|
||||
xfrm_pol_hold(policy);
|
||||
net->xfrm.policy_count[dir]++;
|
||||
__xfrm_policy_link(policy, dir);
|
||||
atomic_inc(&net->xfrm.flow_cache_genid);
|
||||
|
||||
/* 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)
|
|||
policy->curlft.use_time = 0;
|
||||
if (!mod_timer(&policy->timer, jiffies + HZ))
|
||||
xfrm_pol_hold(policy);
|
||||
list_add(&policy->walk.all, &net->xfrm.policy_all);
|
||||
write_unlock_bh(&net->xfrm.xfrm_policy_lock);
|
||||
|
||||
if (delpol)
|
||||
|
@ -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)
|
||||
{
|
||||
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);
|
||||
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]++;
|
||||
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,
|
||||
|
@ -1265,17 +1257,31 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
|
|||
{
|
||||
struct net *net = xp_net(pol);
|
||||
|
||||
if (hlist_unhashed(&pol->bydst))
|
||||
if (list_empty(&pol->walk.all))
|
||||
return NULL;
|
||||
|
||||
hlist_del_init(&pol->bydst);
|
||||
hlist_del(&pol->byidx);
|
||||
list_del(&pol->walk.all);
|
||||
/* Socket policies are not hashed. */
|
||||
if (!hlist_unhashed(&pol->bydst)) {
|
||||
hlist_del(&pol->bydst);
|
||||
hlist_del(&pol->byidx);
|
||||
}
|
||||
|
||||
list_del_init(&pol->walk.all);
|
||||
net->xfrm.policy_count[dir]--;
|
||||
|
||||
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)
|
||||
{
|
||||
struct net *net = xp_net(pol);
|
||||
|
@ -1307,7 +1313,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
|
|||
if (pol) {
|
||||
pol->curlft.add_time = get_seconds();
|
||||
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 (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
|
||||
* 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);
|
||||
|
||||
|
@ -1349,7 +1355,7 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir)
|
|||
memcpy(newp->xfrm_vec, old->xfrm_vec,
|
||||
newp->xfrm_nr*sizeof(struct xfrm_tmpl));
|
||||
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);
|
||||
xfrm_pol_put(newp);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
int err = 0;
|
||||
struct sk_buff *skb;
|
||||
struct sock *sk;
|
||||
struct dst_entry *dst;
|
||||
|
@ -1941,7 +1946,7 @@ static void xfrm_policy_queue_process(unsigned long arg)
|
|||
skb_dst_drop(skb);
|
||||
skb_dst_set(skb, dst);
|
||||
|
||||
err = dst_output(skb);
|
||||
dst_output(skb);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -2966,10 +2971,11 @@ static int __net_init xfrm_policy_init(struct net *net)
|
|||
goto out_byidx;
|
||||
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;
|
||||
|
||||
net->xfrm.policy_count[dir] = 0;
|
||||
net->xfrm.policy_count[XFRM_POLICY_MAX + dir] = 0;
|
||||
INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
|
||||
|
||||
htab = &net->xfrm.policy_bydst[dir];
|
||||
|
@ -3021,7 +3027,7 @@ static void xfrm_policy_fini(struct net *net)
|
|||
|
||||
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;
|
||||
|
||||
WARN_ON(!hlist_empty(&net->xfrm.policy_inexact[dir]));
|
||||
|
|
|
@ -824,13 +824,15 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
|
|||
ret = xfrm_mark_put(skb, &x->mark);
|
||||
if (ret)
|
||||
goto out;
|
||||
if (x->replay_esn) {
|
||||
if (x->replay_esn)
|
||||
ret = nla_put(skb, XFRMA_REPLAY_ESN_VAL,
|
||||
xfrm_replay_state_esn_len(x->replay_esn),
|
||||
x->replay_esn);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
ret = nla_put(skb, XFRMA_REPLAY_VAL, sizeof(x->replay),
|
||||
&x->replay);
|
||||
if (ret)
|
||||
goto out;
|
||||
if (x->security)
|
||||
ret = copy_sec_ctx(x->security, skb);
|
||||
out:
|
||||
|
@ -2569,6 +2571,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
|
|||
l += nla_total_size(sizeof(x->tfcpad));
|
||||
if (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)
|
||||
l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) +
|
||||
x->security->ctx_len);
|
||||
|
|
Loading…
Reference in New Issue
Block a user