3f2c31d903
If segmentation offload is enabled by the host, we currently allocate maximum sized packet buffers and pass them to the host. This uses up 20 ring entries, allowing us to supply only 20 packet buffers to the host with a 256 entry ring. This is a huge overhead when receiving small packets, and is most keenly felt when receiving MTU sized packets from off-host. The VIRTIO_NET_F_MRG_RXBUF feature flag is set by hosts which support using receive buffers which are smaller than the maximum packet size. In order to transfer large packets to the guest, the host merges together multiple receive buffers to form a larger logical buffer. The number of merged buffers is returned to the guest via a field in the virtio_net_hdr. Make use of this support by supplying single page receive buffers to the host. On receive, we extract the virtio_net_hdr, copy 128 bytes of the payload to the skb's linear data buffer and adjust the fragment offset to point to the remaining data. This ensures proper alignment and allows us to not use any paged data for small packets. If the payload occupies multiple pages, we simply append those pages as fragments and free the associated skbs. This scheme allows us to be efficient in our use of ring entries while still supporting large packets. Benchmarking using netperf from an external machine to a guest over a 10Gb/s network shows a 100% improvement from ~1Gb/s to ~2Gb/s. With a local host->guest benchmark with GSO disabled on the host side, throughput was seen to increase from 700Mb/s to 1.7Gb/s. Based on a patch from Herbert Xu. Signed-off-by: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (use netdev_priv) Signed-off-by: David S. Miller <davem@davemloft.net>
57 lines
2.3 KiB
C
57 lines
2.3 KiB
C
#ifndef _LINUX_VIRTIO_NET_H
|
|
#define _LINUX_VIRTIO_NET_H
|
|
/* This header is BSD licensed so anyone can use the definitions to implement
|
|
* compatible drivers/servers. */
|
|
#include <linux/virtio_config.h>
|
|
|
|
/* The ID for virtio_net */
|
|
#define VIRTIO_ID_NET 1
|
|
|
|
/* The feature bitmap for virtio net */
|
|
#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
|
|
#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
|
|
#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
|
|
#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
|
|
#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
|
|
#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */
|
|
#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */
|
|
#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */
|
|
#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */
|
|
#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */
|
|
#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */
|
|
#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
|
|
#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */
|
|
|
|
struct virtio_net_config
|
|
{
|
|
/* The config defining mac address (if VIRTIO_NET_F_MAC) */
|
|
__u8 mac[6];
|
|
} __attribute__((packed));
|
|
|
|
/* This is the first element of the scatter-gather list. If you don't
|
|
* 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
|
|
__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)
|
|
#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO)
|
|
#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP
|
|
#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set
|
|
__u8 gso_type;
|
|
__u16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */
|
|
__u16 gso_size; /* Bytes to append to hdr_len per frame */
|
|
__u16 csum_start; /* Position to start checksumming from */
|
|
__u16 csum_offset; /* Offset after that to place checksum */
|
|
};
|
|
|
|
/* This is the version of the header to use when the MRG_RXBUF
|
|
* feature has been negotiated. */
|
|
struct virtio_net_hdr_mrg_rxbuf {
|
|
struct virtio_net_hdr hdr;
|
|
__u16 num_buffers; /* Number of merged rx buffers */
|
|
};
|
|
|
|
#endif /* _LINUX_VIRTIO_NET_H */
|