Skip to content

Commit 16be004

Browse files
committed
Merge branch 'virtio_net-csum-xdp-fixes'
Heng Qi says: ==================== virtio_net: fixes for checksum offloading and XDP handling This series of patches aim to address two specific issues identified in the virtio_net driver related to checksum offloading and XDP processing of fully checksummed packets. The first patch corrects the handling of checksum offloading in the driver. The second patch addresses an issue where the XDP program had no trouble with fully checksummed packets. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 7be4cb7 + 703eec1 commit 16be004

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

drivers/net/virtio_net.c

+29-3
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,10 @@ static struct sk_buff *receive_small_xdp(struct net_device *dev,
13601360
if (unlikely(hdr->hdr.gso_type))
13611361
goto err_xdp;
13621362

1363+
/* Partially checksummed packets must be dropped. */
1364+
if (unlikely(hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM))
1365+
goto err_xdp;
1366+
13631367
buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) +
13641368
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
13651369

@@ -1677,6 +1681,10 @@ static void *mergeable_xdp_get_buf(struct virtnet_info *vi,
16771681
if (unlikely(hdr->hdr.gso_type))
16781682
return NULL;
16791683

1684+
/* Partially checksummed packets must be dropped. */
1685+
if (unlikely(hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM))
1686+
return NULL;
1687+
16801688
/* Now XDP core assumes frag size is PAGE_SIZE, but buffers
16811689
* with headroom may add hole in truesize, which
16821690
* make their length exceed PAGE_SIZE. So we disabled the
@@ -1943,6 +1951,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
19431951
struct net_device *dev = vi->dev;
19441952
struct sk_buff *skb;
19451953
struct virtio_net_common_hdr *hdr;
1954+
u8 flags;
19461955

19471956
if (unlikely(len < vi->hdr_len + ETH_HLEN)) {
19481957
pr_debug("%s: short packet %i\n", dev->name, len);
@@ -1951,6 +1960,15 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
19511960
return;
19521961
}
19531962

1963+
/* 1. Save the flags early, as the XDP program might overwrite them.
1964+
* These flags ensure packets marked as VIRTIO_NET_HDR_F_DATA_VALID
1965+
* stay valid after XDP processing.
1966+
* 2. XDP doesn't work with partially checksummed packets (refer to
1967+
* virtnet_xdp_set()), so packets marked as
1968+
* VIRTIO_NET_HDR_F_NEEDS_CSUM get dropped during XDP processing.
1969+
*/
1970+
flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags;
1971+
19541972
if (vi->mergeable_rx_bufs)
19551973
skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit,
19561974
stats);
@@ -1966,7 +1984,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
19661984
if (dev->features & NETIF_F_RXHASH && vi->has_rss_hash_report)
19671985
virtio_skb_set_hash(&hdr->hash_v1_hdr, skb);
19681986

1969-
if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID)
1987+
if (flags & VIRTIO_NET_HDR_F_DATA_VALID)
19701988
skb->ip_summed = CHECKSUM_UNNECESSARY;
19711989

19721990
if (virtio_net_hdr_to_skb(skb, &hdr->hdr,
@@ -5666,8 +5684,16 @@ static int virtnet_probe(struct virtio_device *vdev)
56665684
dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
56675685
/* (!csum && gso) case will be fixed by register_netdev() */
56685686
}
5669-
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
5670-
dev->features |= NETIF_F_RXCSUM;
5687+
5688+
/* 1. With VIRTIO_NET_F_GUEST_CSUM negotiation, the driver doesn't
5689+
* need to calculate checksums for partially checksummed packets,
5690+
* as they're considered valid by the upper layer.
5691+
* 2. Without VIRTIO_NET_F_GUEST_CSUM negotiation, the driver only
5692+
* receives fully checksummed packets. The device may assist in
5693+
* validating these packets' checksums, so the driver won't have to.
5694+
*/
5695+
dev->features |= NETIF_F_RXCSUM;
5696+
56715697
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
56725698
virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6))
56735699
dev->features |= NETIF_F_GRO_HW;

0 commit comments

Comments
 (0)