Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

virtio-net: restore VIRTIO_HDR_F_DATA_VALID on receiving

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>

authored by

Jason Wang and committed by
David S. Miller
6391a448 69fed99b

+10 -6
+1 -1
drivers/net/macvtap.c
··· 825 825 return -EINVAL; 826 826 827 827 if (virtio_net_hdr_from_skb(skb, &vnet_hdr, 828 - macvtap_is_little_endian(q))) 828 + macvtap_is_little_endian(q), true)) 829 829 BUG(); 830 830 831 831 if (copy_to_iter(&vnet_hdr, sizeof(vnet_hdr), iter) !=
+1 -1
drivers/net/tun.c
··· 1360 1360 return -EINVAL; 1361 1361 1362 1362 if (virtio_net_hdr_from_skb(skb, &gso, 1363 - tun_is_little_endian(tun))) { 1363 + tun_is_little_endian(tun), true)) { 1364 1364 struct skb_shared_info *sinfo = skb_shinfo(skb); 1365 1365 pr_err("unexpected GSO type: " 1366 1366 "0x%x, gso_size %d, hdr_len %d\n",
+1 -1
drivers/net/virtio_net.c
··· 1104 1104 hdr = skb_vnet_hdr(skb); 1105 1105 1106 1106 if (virtio_net_hdr_from_skb(skb, &hdr->hdr, 1107 - virtio_is_little_endian(vi->vdev))) 1107 + virtio_is_little_endian(vi->vdev), false)) 1108 1108 BUG(); 1109 1109 1110 1110 if (vi->mergeable_rx_bufs)
+5 -1
include/linux/virtio_net.h
··· 56 56 57 57 static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, 58 58 struct virtio_net_hdr *hdr, 59 - bool little_endian) 59 + bool little_endian, 60 + bool has_data_valid) 60 61 { 61 62 memset(hdr, 0, sizeof(*hdr)); /* no info leak */ 62 63 ··· 92 91 skb_checksum_start_offset(skb)); 93 92 hdr->csum_offset = __cpu_to_virtio16(little_endian, 94 93 skb->csum_offset); 94 + } else if (has_data_valid && 95 + skb->ip_summed == CHECKSUM_UNNECESSARY) { 96 + hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; 95 97 } /* else everything is zero */ 96 98 97 99 return 0;
+2 -2
net/packet/af_packet.c
··· 1976 1976 return -EINVAL; 1977 1977 *len -= sizeof(vnet_hdr); 1978 1978 1979 - if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le())) 1979 + if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true)) 1980 1980 return -EINVAL; 1981 1981 1982 1982 return memcpy_to_msg(msg, (void *)&vnet_hdr, sizeof(vnet_hdr)); ··· 2237 2237 if (po->has_vnet_hdr) { 2238 2238 if (virtio_net_hdr_from_skb(skb, h.raw + macoff - 2239 2239 sizeof(struct virtio_net_hdr), 2240 - vio_le())) { 2240 + vio_le(), true)) { 2241 2241 spin_lock(&sk->sk_receive_queue.lock); 2242 2242 goto drop_n_account; 2243 2243 }