summaryrefslogtreecommitdiff
path: root/drivers/net/tap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/tap.c')
-rw-r--r--drivers/net/tap.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index fae115915c8e..5d2d34d24ce8 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -1074,10 +1074,21 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
skb_reset_mac_header(skb);
skb->protocol = eth_hdr(skb)->h_proto;
+ rcu_read_lock();
+ tap = rcu_dereference(q->tap);
+ if (!tap) {
+ kfree_skb(skb);
+ rcu_read_unlock();
+ return 0;
+ }
+ skb->dev = tap->dev;
+
if (vnet_hdr_len) {
err = tun_vnet_hdr_to_skb(q->flags, skb, gso);
- if (err)
+ if (err) {
+ rcu_read_unlock();
goto err_kfree;
+ }
}
/* Move network header to the right position for VLAN tagged packets */
@@ -1085,15 +1096,8 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
skb_set_network_header(skb, depth);
- rcu_read_lock();
- tap = rcu_dereference(q->tap);
- if (tap) {
- skb->dev = tap->dev;
- skb_probe_transport_header(skb);
- dev_queue_xmit(skb);
- } else {
- kfree_skb(skb);
- }
+ skb_probe_transport_header(skb);
+ dev_queue_xmit(skb);
rcu_read_unlock();
return 0;