virtio-net: restore VIRTIO_HDR_F_DATA_VALID on receiving
authorJason Wang <jasowang@redhat.com>
Fri, 20 Jan 2017 06:32:42 +0000 (14:32 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 4 Feb 2017 08:47:09 +0000 (09:47 +0100)
[ Upstream commit 6391a4481ba0796805d6581e42f9f0418c099e34 ]

Commit 501db511397f ("virtio: don't set VIRTIO_NET_HDR_F_DATA_VALID on
xmit") in fact disables VIRTIO_HDR_F_DATA_VALID on receiving path too,
fixing this by adding a hint (has_data_valid) and set it only on the
receiving path.

Cc: Rolf Neugebauer <rolf.neugebauer@docker.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Acked-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/macvtap.c
drivers/net/tun.c
drivers/net/virtio_net.c
include/linux/virtio_net.h
net/packet/af_packet.c

index 7869b06..6f38daf 100644 (file)
@@ -827,7 +827,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
                        return -EINVAL;
 
                ret = virtio_net_hdr_from_skb(skb, &vnet_hdr,
-                                             macvtap_is_little_endian(q));
+                                             macvtap_is_little_endian(q), true);
                if (ret)
                        BUG();
 
index db6acec..18402d7 100644 (file)
@@ -1374,7 +1374,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                        return -EINVAL;
 
                ret = virtio_net_hdr_from_skb(skb, &gso,
-                                             tun_is_little_endian(tun));
+                                             tun_is_little_endian(tun), true);
                if (ret) {
                        struct skb_shared_info *sinfo = skb_shinfo(skb);
                        pr_err("unexpected GSO type: "
index cbf1c61..51fc0c3 100644 (file)
@@ -840,7 +840,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
                hdr = skb_vnet_hdr(skb);
 
        if (virtio_net_hdr_from_skb(skb, &hdr->hdr,
-                                   virtio_is_little_endian(vi->vdev)))
+                                   virtio_is_little_endian(vi->vdev), false))
                BUG();
 
        if (vi->mergeable_rx_bufs)
index 40914bb..f211c34 100644 (file)
@@ -56,7 +56,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
 
 static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
                                          struct virtio_net_hdr *hdr,
-                                         bool little_endian)
+                                         bool little_endian,
+                                         bool has_data_valid)
 {
        memset(hdr, 0, sizeof(*hdr));
 
@@ -91,6 +92,9 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
                                skb_checksum_start_offset(skb));
                hdr->csum_offset = __cpu_to_virtio16(little_endian,
                                skb->csum_offset);
+       } else if (has_data_valid &&
+                  skb->ip_summed == CHECKSUM_UNNECESSARY) {
+               hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
        } /* else everything is zero */
 
        return 0;
index dd23323..94e4a59 100644 (file)
@@ -1972,7 +1972,7 @@ static int __packet_rcv_vnet(const struct sk_buff *skb,
 {
        *vnet_hdr = (const struct virtio_net_hdr) { 0 };
 
-       if (virtio_net_hdr_from_skb(skb, vnet_hdr, vio_le()))
+       if (virtio_net_hdr_from_skb(skb, vnet_hdr, vio_le(), true))
                BUG();
 
        return 0;