Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec...
authorDavid S. Miller <davem@davemloft.net>
Tue, 9 Dec 2014 02:30:21 +0000 (21:30 -0500)
committerDavid S. Miller <davem@davemloft.net>
Tue, 9 Dec 2014 02:30:21 +0000 (21:30 -0500)
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>
1  2 
net/ipv6/ip6_vti.c
net/xfrm/xfrm_policy.c

diff --combined net/ipv6/ip6_vti.c
@@@ -95,6 -95,7 +95,7 @@@ vti6_tnl_lookup(struct net *net, const 
        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) &&
                    (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;
@@@ -172,6 -189,10 +189,6 @@@ static int vti6_tnl_create2(struct net_
        struct vti6_net *ip6n = net_generic(net, vti6_net_id);
        int err;
  
 -      err = vti6_dev_init(dev);
 -      if (err < 0)
 -              goto out;
 -
        err = register_netdevice(dev);
        if (err < 0)
                goto out;
@@@ -287,8 -308,8 +304,8 @@@ static int vti6_rcv(struct sk_buff *skb
        const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
  
        rcu_read_lock();
 -      if ((t = vti6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr,
 -                               &ipv6h->daddr)) != NULL) {
 +      t = vti6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr, &ipv6h->daddr);
 +      if (t != NULL) {
                if (t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) {
                        rcu_read_unlock();
                        goto discard;
@@@ -412,7 -433,6 +429,7 @@@ vti6_xmit(struct sk_buff *skb, struct n
        struct net_device_stats *stats = &t->dev->stats;
        struct dst_entry *dst = skb_dst(skb);
        struct net_device *tdev;
 +      struct xfrm_state *x;
        int err = -1;
  
        if (!dst)
                goto tx_err_link_failure;
        }
  
 -      if (!vti6_state_check(dst->xfrm, &t->parms.raddr, &t->parms.laddr))
 +      x = dst->xfrm;
 +      if (!vti6_state_check(x, &t->parms.raddr, &t->parms.laddr))
 +              goto tx_err_link_failure;
 +
 +      if (!ip6_tnl_xmit_ctl(t, (const struct in6_addr *)&x->props.saddr,
 +                            (const struct in6_addr *)&x->id.daddr))
                goto tx_err_link_failure;
  
        tdev = dst->dev;
@@@ -486,7 -501,7 +503,7 @@@ vti6_tnl_xmit(struct sk_buff *skb, stru
                ipv6h = ipv6_hdr(skb);
  
                if ((t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) ||
 -                  !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h))
 +                  vti6_addr_conflict(t, ipv6h))
                        goto tx_err;
  
                xfrm_decode_session(skb, &fl, AF_INET6);
@@@ -785,7 -800,6 +802,7 @@@ static int vti6_change_mtu(struct net_d
  }
  
  static const struct net_device_ops vti6_netdev_ops = {
 +      .ndo_init       = vti6_dev_init,
        .ndo_uninit     = vti6_dev_uninit,
        .ndo_start_xmit = vti6_tnl_xmit,
        .ndo_do_ioctl   = vti6_ioctl,
@@@ -855,10 -869,16 +872,10 @@@ static int __net_init vti6_fb_tnl_dev_i
        struct ip6_tnl *t = netdev_priv(dev);
        struct net *net = dev_net(dev);
        struct vti6_net *ip6n = net_generic(net, vti6_net_id);
 -      int err = vti6_dev_init_gen(dev);
 -
 -      if (err)
 -              return err;
  
        t->parms.proto = IPPROTO_IPV6;
        dev_hold(dev);
  
 -      vti6_link_config(t);
 -
        rcu_assign_pointer(ip6n->tnls_wc[0], t);
        return 0;
  }
@@@ -911,15 -931,6 +928,15 @@@ static int vti6_newlink(struct net *src
        return vti6_tnl_create2(dev);
  }
  
 +static void vti6_dellink(struct net_device *dev, struct list_head *head)
 +{
 +      struct net *net = dev_net(dev);
 +      struct vti6_net *ip6n = net_generic(net, vti6_net_id);
 +
 +      if (dev != ip6n->fb_tnl_dev)
 +              unregister_netdevice_queue(dev, head);
 +}
 +
  static int vti6_changelink(struct net_device *dev, struct nlattr *tb[],
                           struct nlattr *data[])
  {
@@@ -995,7 -1006,6 +1012,7 @@@ static struct rtnl_link_ops vti6_link_o
        .setup          = vti6_dev_setup,
        .validate       = vti6_validate,
        .newlink        = vti6_newlink,
 +      .dellink        = vti6_dellink,
        .changelink     = vti6_changelink,
        .get_size       = vti6_get_size,
        .fill_info      = vti6_fill_info,
@@@ -1036,7 -1046,6 +1053,7 @@@ static int __net_init vti6_init_net(str
        if (!ip6n->fb_tnl_dev)
                goto err_alloc_dev;
        dev_net_set(ip6n->fb_tnl_dev, net);
 +      ip6n->fb_tnl_dev->rtnl_link_ops = &vti6_link_ops;
  
        err = vti6_fb_tnl_dev_init(ip6n->fb_tnl_dev);
        if (err < 0)
diff --combined net/xfrm/xfrm_policy.c
@@@ -55,6 -55,7 +55,7 @@@ static int stale_bundle(struct dst_entr
  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 +562,7 @@@ static void xfrm_hash_resize(struct wor
        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 +602,7 @@@ static void xfrm_hash_rebuild(struct wo
        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 +780,7 @@@ int xfrm_policy_insert(int dir, struct 
                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 */
        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)
  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,
  {
        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 +1313,7 @@@ int xfrm_sk_policy_insert(struct sock *
        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)
                /* 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 +1355,7 @@@ static struct xfrm_policy *clone_policy
                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 +1884,6 @@@ xfrm_resolve_and_create_bundle(struct x
  
  static void xfrm_policy_queue_process(unsigned long arg)
  {
-       int err = 0;
        struct sk_buff *skb;
        struct sock *sk;
        struct dst_entry *dst;
                skb_dst_drop(skb);
                skb_dst_set(skb, dst);
  
-               err = dst_output(skb);
+               dst_output(skb);
        }
  
  out:
@@@ -1962,7 -1967,7 +1967,7 @@@ static int xdst_queue_output(struct soc
        struct xfrm_policy *pol = xdst->pols[0];
        struct xfrm_policy_queue *pq = &pol->polq;
  
 -      if (unlikely(skb_fclone_busy(skb))) {
 +      if (unlikely(skb_fclone_busy(sk, skb))) {
                kfree_skb(skb);
                return 0;
        }
@@@ -2966,10 -2971,11 +2971,11 @@@ static int __net_init xfrm_policy_init(
                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 +3027,7 @@@ static void xfrm_policy_fini(struct ne
  
        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]));