Skip to content

Commit

Permalink
virtio_net: introduce VIRTIO_NET_HDR_F_DATA_VALID
Browse files Browse the repository at this point in the history
There's no need for the guest to validate the checksum if it have been
validated by host nics. So this patch introduces a new flag -
VIRTIO_NET_HDR_F_DATA_VALID which is used to bypass the checksum
examing in guest. The backend (tap/macvtap) may set this flag when
met skbs with CHECKSUM_UNNECESSARY to save cpu utilization.

No feature negotiation is needed as old driver just ignore this flag.

Iperf shows 12%-30% performance improvement for UDP traffic. For TCP,
when gro is on no difference as it produces skb with partial
checksum. But when gro is disabled, 20% or even higher improvement
could be measured by netperf.

Signed-off-by: Jason Wang <[email protected]>
Acked-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
jasowang authored and davem330 committed Jun 11, 2011
1 parent 40d15cd commit 10a8d94
Show file tree
Hide file tree
Showing 5 changed files with 9 additions and 0 deletions.
2 changes: 2 additions & 0 deletions drivers/net/macvtap.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,8 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
vnet_hdr->csum_start = skb_checksum_start_offset(skb);
vnet_hdr->csum_offset = skb->csum_offset;
} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
} /* else everything is zero */

return 0;
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
gso.csum_start = skb_checksum_start_offset(skb);
gso.csum_offset = skb->csum_offset;
} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
gso.flags = VIRTIO_NET_HDR_F_DATA_VALID;
} /* else everything is zero */

if (unlikely(memcpy_toiovecend(iv, (void *)&gso, total,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/virtio_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
hdr->hdr.csum_start,
hdr->hdr.csum_offset))
goto frame_err;
} else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
}

skb->protocol = eth_type_trans(skb, dev);
Expand Down
1 change: 1 addition & 0 deletions include/linux/virtio_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct virtio_net_config {
* specify GSO or CSUM features, you can simply ignore the header. */
struct virtio_net_hdr {
#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset
#define VIRTIO_NET_HDR_F_DATA_VALID 2 // Csum is valid
__u8 flags;
#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame
#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
Expand Down
2 changes: 2 additions & 0 deletions net/packet/af_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1685,6 +1685,8 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
vnet_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
vnet_hdr.csum_start = skb_checksum_start_offset(skb);
vnet_hdr.csum_offset = skb->csum_offset;
} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
vnet_hdr.flags = VIRTIO_NET_HDR_F_DATA_VALID;
} /* else everything is zero */

err = memcpy_toiovec(msg->msg_iov, (void *)&vnet_hdr,
Expand Down

0 comments on commit 10a8d94

Please sign in to comment.