diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 23:50:02 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 07:50:02 -0500 |
commit | 34a48579e4fb380604d06f0409db3851bd22d785 (patch) | |
tree | 0bf5091284b456719b527a288bc79111987fd0f2 | |
parent | 50c8ea8080700014872f2bbd7466d31ce0476290 (diff) |
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: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | drivers/net/virtio_net.c | 32 | ||||
-rw-r--r-- | include/linux/virtio_net.h | 12 |
2 files changed, 20 insertions, 24 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3492ae0951de..73f01db59ab9 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -24,6 +24,10 @@ | |||
24 | #include <linux/virtio_net.h> | 24 | #include <linux/virtio_net.h> |
25 | #include <linux/scatterlist.h> | 25 | #include <linux/scatterlist.h> |
26 | 26 | ||
27 | static int csum = 1, gso = 1; | ||
28 | module_param(csum, bool, 0444); | ||
29 | module_param(gso, bool, 0444); | ||
30 | |||
27 | /* FIXME: MTU in config. */ | 31 | /* FIXME: MTU in config. */ |
28 | #define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN) | 32 | #define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN) |
29 | 33 | ||
@@ -88,13 +92,10 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, | |||
88 | 92 | ||
89 | if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { | 93 | if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { |
90 | pr_debug("GSO!\n"); | 94 | pr_debug("GSO!\n"); |
91 | switch (hdr->gso_type) { | 95 | switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { |
92 | case VIRTIO_NET_HDR_GSO_TCPV4: | 96 | case VIRTIO_NET_HDR_GSO_TCPV4: |
93 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | 97 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; |
94 | break; | 98 | break; |
95 | case VIRTIO_NET_HDR_GSO_TCPV4_ECN: | ||
96 | skb_shinfo(skb)->gso_type = SKB_GSO_TCP_ECN; | ||
97 | break; | ||
98 | case VIRTIO_NET_HDR_GSO_UDP: | 99 | case VIRTIO_NET_HDR_GSO_UDP: |
99 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 100 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; |
100 | break; | 101 | break; |
@@ -108,6 +109,9 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, | |||
108 | goto frame_err; | 109 | goto frame_err; |
109 | } | 110 | } |
110 | 111 | ||
112 | if (hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN) | ||
113 | skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; | ||
114 | |||
111 | skb_shinfo(skb)->gso_size = hdr->gso_size; | 115 | skb_shinfo(skb)->gso_size = hdr->gso_size; |
112 | if (skb_shinfo(skb)->gso_size == 0) { | 116 | if (skb_shinfo(skb)->gso_size == 0) { |
113 | if (net_ratelimit()) | 117 | if (net_ratelimit()) |
@@ -244,9 +248,7 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
244 | if (skb_is_gso(skb)) { | 248 | if (skb_is_gso(skb)) { |
245 | hdr->hdr_len = skb_transport_header(skb) - skb->data; | 249 | hdr->hdr_len = skb_transport_header(skb) - skb->data; |
246 | hdr->gso_size = skb_shinfo(skb)->gso_size; | 250 | hdr->gso_size = skb_shinfo(skb)->gso_size; |
247 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) | 251 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) |
248 | hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4_ECN; | ||
249 | else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) | ||
250 | hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; | 252 | hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; |
251 | else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) | 253 | else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) |
252 | hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; | 254 | 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 | hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; | 256 | hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; |
255 | else | 257 | else |
256 | BUG(); | 258 | BUG(); |
259 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) | ||
260 | hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN; | ||
257 | } else { | 261 | } else { |
258 | hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; | 262 | hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; |
259 | hdr->gso_size = hdr->hdr_len = 0; | 263 | hdr->gso_size = hdr->hdr_len = 0; |
@@ -330,17 +334,13 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
330 | SET_NETDEV_DEV(dev, &vdev->dev); | 334 | SET_NETDEV_DEV(dev, &vdev->dev); |
331 | 335 | ||
332 | /* Do we support "hardware" checksums? */ | 336 | /* Do we support "hardware" checksums? */ |
333 | if (vdev->config->feature(vdev, VIRTIO_NET_F_NO_CSUM)) { | 337 | if (csum && vdev->config->feature(vdev, VIRTIO_NET_F_CSUM)) { |
334 | /* This opens up the world of extra features. */ | 338 | /* This opens up the world of extra features. */ |
335 | dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; | 339 | dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; |
336 | if (vdev->config->feature(vdev, VIRTIO_NET_F_TSO4)) | 340 | if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_GSO)) { |
337 | dev->features |= NETIF_F_TSO; | 341 | dev->features |= NETIF_F_TSO | NETIF_F_UFO |
338 | if (vdev->config->feature(vdev, VIRTIO_NET_F_UFO)) | 342 | | NETIF_F_TSO_ECN | NETIF_F_TSO6; |
339 | dev->features |= NETIF_F_UFO; | 343 | } |
340 | if (vdev->config->feature(vdev, VIRTIO_NET_F_TSO4_ECN)) | ||
341 | dev->features |= NETIF_F_TSO_ECN; | ||
342 | if (vdev->config->feature(vdev, VIRTIO_NET_F_TSO6)) | ||
343 | dev->features |= NETIF_F_TSO6; | ||
344 | } | 344 | } |
345 | 345 | ||
346 | /* Configuration may specify what MAC to use. Otherwise random. */ | 346 | /* Configuration may specify what MAC to use. Otherwise random. */ |
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 1456f7b936d0..1ea3351df609 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h | |||
@@ -6,12 +6,9 @@ | |||
6 | #define VIRTIO_ID_NET 1 | 6 | #define VIRTIO_ID_NET 1 |
7 | 7 | ||
8 | /* The feature bitmap for virtio net */ | 8 | /* The feature bitmap for virtio net */ |
9 | #define VIRTIO_NET_F_NO_CSUM 0 | 9 | #define VIRTIO_NET_F_CSUM 0 /* Can handle pkts w/ partial csum */ |
10 | #define VIRTIO_NET_F_TSO4 1 | 10 | #define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ |
11 | #define VIRTIO_NET_F_UFO 2 | 11 | #define VIRTIO_NET_F_GSO 6 /* Can handle pkts w/ any GSO type */ |
12 | #define VIRTIO_NET_F_TSO4_ECN 3 | ||
13 | #define VIRTIO_NET_F_TSO6 4 | ||
14 | #define VIRTIO_NET_F_MAC 5 | ||
15 | 12 | ||
16 | struct virtio_net_config | 13 | struct virtio_net_config |
17 | { | 14 | { |
@@ -27,10 +24,9 @@ struct virtio_net_hdr | |||
27 | __u8 flags; | 24 | __u8 flags; |
28 | #define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame | 25 | #define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame |
29 | #define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO) | 26 | #define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO) |
30 | /* FIXME: Do we need this? If they said they can handle ECN, do they care? */ | ||
31 | #define VIRTIO_NET_HDR_GSO_TCPV4_ECN 2 // GSO frame, IPv4 TCP w/ ECN | ||
32 | #define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO) | 27 | #define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO) |
33 | #define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP | 28 | #define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP |
29 | #define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set | ||
34 | __u8 gso_type; | 30 | __u8 gso_type; |
35 | __u16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ | 31 | __u16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ |
36 | __u16 gso_size; /* Bytes to append to gso_hdr_len per frame */ | 32 | __u16 gso_size; /* Bytes to append to gso_hdr_len per frame */ |