|
@@ -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;
|
|
|
}
|
|
|
|