Commit 34a48579 authored by Rusty Russell's avatar Rusty Russell

virtio: Tweak virtio_net defines

1) Turn GSO on virtio net into an all-or-nothing (keep checksumming
   separate).  Having multiple bits is a pain: if you can't support something
   you should handle it in software, which is still a performance win.

2) Make VIRTIO_NET_HDR_GSO_ECN a flag in the header, so it can apply to
   IPv6 or v4.

3) Rename VIRTIO_NET_F_NO_CSUM to VIRTIO_NET_F_CSUM (ie. means we do
   checksumming).

4) Add csum and gso params to virtio_net to allow more testing.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 50c8ea80
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
#include <linux/virtio_net.h> #include <linux/virtio_net.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
static int csum = 1, gso = 1;
module_param(csum, bool, 0444);
module_param(gso, bool, 0444);
/* FIXME: MTU in config. */ /* FIXME: MTU in config. */
#define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN) #define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN)
...@@ -88,13 +92,10 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, ...@@ -88,13 +92,10 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
pr_debug("GSO!\n"); pr_debug("GSO!\n");
switch (hdr->gso_type) { switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
case VIRTIO_NET_HDR_GSO_TCPV4: case VIRTIO_NET_HDR_GSO_TCPV4:
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
break; break;
case VIRTIO_NET_HDR_GSO_TCPV4_ECN:
skb_shinfo(skb)->gso_type = SKB_GSO_TCP_ECN;
break;
case VIRTIO_NET_HDR_GSO_UDP: case VIRTIO_NET_HDR_GSO_UDP:
skb_shinfo(skb)->gso_type = SKB_GSO_UDP; skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
break; break;
...@@ -108,6 +109,9 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, ...@@ -108,6 +109,9 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
goto frame_err; goto frame_err;
} }
if (hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN)
skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
skb_shinfo(skb)->gso_size = hdr->gso_size; skb_shinfo(skb)->gso_size = hdr->gso_size;
if (skb_shinfo(skb)->gso_size == 0) { if (skb_shinfo(skb)->gso_size == 0) {
if (net_ratelimit()) if (net_ratelimit())
...@@ -244,9 +248,7 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -244,9 +248,7 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb_is_gso(skb)) { if (skb_is_gso(skb)) {
hdr->hdr_len = skb_transport_header(skb) - skb->data; hdr->hdr_len = skb_transport_header(skb) - skb->data;
hdr->gso_size = skb_shinfo(skb)->gso_size; hdr->gso_size = skb_shinfo(skb)->gso_size;
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4_ECN;
else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
...@@ -254,6 +256,8 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -254,6 +256,8 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
else else
BUG(); BUG();
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN;
} else { } else {
hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
hdr->gso_size = hdr->hdr_len = 0; hdr->gso_size = hdr->hdr_len = 0;
...@@ -330,17 +334,13 @@ static int virtnet_probe(struct virtio_device *vdev) ...@@ -330,17 +334,13 @@ static int virtnet_probe(struct virtio_device *vdev)
SET_NETDEV_DEV(dev, &vdev->dev); SET_NETDEV_DEV(dev, &vdev->dev);
/* Do we support "hardware" checksums? */ /* Do we support "hardware" checksums? */
if (vdev->config->feature(vdev, VIRTIO_NET_F_NO_CSUM)) { if (csum && vdev->config->feature(vdev, VIRTIO_NET_F_CSUM)) {
/* This opens up the world of extra features. */ /* This opens up the world of extra features. */
dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
if (vdev->config->feature(vdev, VIRTIO_NET_F_TSO4)) if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_GSO)) {
dev->features |= NETIF_F_TSO; dev->features |= NETIF_F_TSO | NETIF_F_UFO
if (vdev->config->feature(vdev, VIRTIO_NET_F_UFO)) | NETIF_F_TSO_ECN | NETIF_F_TSO6;
dev->features |= NETIF_F_UFO; }
if (vdev->config->feature(vdev, VIRTIO_NET_F_TSO4_ECN))
dev->features |= NETIF_F_TSO_ECN;
if (vdev->config->feature(vdev, VIRTIO_NET_F_TSO6))
dev->features |= NETIF_F_TSO6;
} }
/* Configuration may specify what MAC to use. Otherwise random. */ /* Configuration may specify what MAC to use. Otherwise random. */
......
...@@ -6,12 +6,9 @@ ...@@ -6,12 +6,9 @@
#define VIRTIO_ID_NET 1 #define VIRTIO_ID_NET 1
/* The feature bitmap for virtio net */ /* The feature bitmap for virtio net */
#define VIRTIO_NET_F_NO_CSUM 0 #define VIRTIO_NET_F_CSUM 0 /* Can handle pkts w/ partial csum */
#define VIRTIO_NET_F_TSO4 1 #define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
#define VIRTIO_NET_F_UFO 2 #define VIRTIO_NET_F_GSO 6 /* Can handle pkts w/ any GSO type */
#define VIRTIO_NET_F_TSO4_ECN 3
#define VIRTIO_NET_F_TSO6 4
#define VIRTIO_NET_F_MAC 5
struct virtio_net_config struct virtio_net_config
{ {
...@@ -27,10 +24,9 @@ struct virtio_net_hdr ...@@ -27,10 +24,9 @@ struct virtio_net_hdr
__u8 flags; __u8 flags;
#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame #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_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
/* FIXME: Do we need this? If they said they can handle ECN, do they care? */
#define VIRTIO_NET_HDR_GSO_TCPV4_ECN 2 // GSO frame, IPv4 TCP w/ ECN
#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO) #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_TCPV6 4 // GSO frame, IPv6 TCP
#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set
__u8 gso_type; __u8 gso_type;
__u16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ __u16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */
__u16 gso_size; /* Bytes to append to gso_hdr_len per frame */ __u16 gso_size; /* Bytes to append to gso_hdr_len per frame */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment