]> Pileus Git - ~andy/linux/blobdiff - drivers/net/vxlan.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[~andy/linux] / drivers / net / vxlan.c
index 474a99ed0222d7470139b0d1434de2e77f0e1d06..481f85d604a4881d25cb0125a284b34820f2a076 100644 (file)
@@ -1381,20 +1381,6 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
        return false;
 }
 
-static void vxlan_sock_put(struct sk_buff *skb)
-{
-       sock_put(skb->sk);
-}
-
-/* On transmit, associate with the tunnel socket */
-static void vxlan_set_owner(struct sock *sk, struct sk_buff *skb)
-{
-       skb_orphan(skb);
-       sock_hold(sk);
-       skb->sk = sk;
-       skb->destructor = vxlan_sock_put;
-}
-
 /* Compute source port for outgoing packet
  *   first choice to use L4 flow hash since it will spread
  *     better and maybe available from hardware
@@ -1514,8 +1500,6 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs,
        ip6h->daddr       = *daddr;
        ip6h->saddr       = *saddr;
 
-       vxlan_set_owner(vs->sock->sk, skb);
-
        err = handle_offloads(skb);
        if (err)
                return err;
@@ -1572,8 +1556,6 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
        uh->len = htons(skb->len);
        uh->check = 0;
 
-       vxlan_set_owner(vs->sock->sk, skb);
-
        err = handle_offloads(skb);
        if (err)
                return err;
@@ -1786,7 +1768,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct ethhdr *eth;
        bool did_rsc = false;
-       struct vxlan_rdst *rdst;
+       struct vxlan_rdst *rdst, *fdst = NULL;
        struct vxlan_fdb *f;
 
        skb_reset_mac_header(skb);
@@ -1828,7 +1810,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
                                vxlan_fdb_miss(vxlan, eth->h_dest);
 
                        dev->stats.tx_dropped++;
-                       dev_kfree_skb(skb);
+                       kfree_skb(skb);
                        return NETDEV_TX_OK;
                }
        }
@@ -1836,12 +1818,19 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        list_for_each_entry_rcu(rdst, &f->remotes, list) {
                struct sk_buff *skb1;
 
+               if (!fdst) {
+                       fdst = rdst;
+                       continue;
+               }
                skb1 = skb_clone(skb, GFP_ATOMIC);
                if (skb1)
                        vxlan_xmit_one(skb1, dev, rdst, did_rsc);
        }
 
-       dev_kfree_skb(skb);
+       if (fdst)
+               vxlan_xmit_one(skb, dev, fdst, did_rsc);
+       else
+               kfree_skb(skb);
        return NETDEV_TX_OK;
 }
 
@@ -2477,7 +2466,8 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
                /* update header length based on lower device */
                dev->hard_header_len = lowerdev->hard_header_len +
                                       (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
-       }
+       } else if (use_ipv6)
+               vxlan->flags |= VXLAN_F_IPV6;
 
        if (data[IFLA_VXLAN_TOS])
                vxlan->tos  = nla_get_u8(data[IFLA_VXLAN_TOS]);