Subject: lguest: Don't set impossible combinations of tun features
Date: Fri, 13 Jun 2008 14:27:38 +0100
From: Mark McLoughlin <markmc@redhat.com>

If a guest says that it supports e.g. TSO4, but not CSUM,
then we blindly try and set this combination of features
on the tun iface. However, TUNSETFEATURES will return EINVAL
if we pass a senseless combination of features like this.

Let's do our best to avoid that.

(Fixes misc:tun-gso-csum-features.patch)

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 Documentation/lguest/lguest.c |   20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index b1997b4..630e159 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -1398,16 +1398,18 @@ static void tun_ring_set_features(struct device *dev)
 	unsigned int features = 0;
 
 	/* They tell us what they can handle, we tell tun to give it to us. */
-	if (has_feature(dev, VIRTIO_NET_F_GUEST_CSUM))
+	if (has_feature(dev, VIRTIO_NET_F_GUEST_CSUM)) {
 		features |= TUN_F_CSUM;
-	if (has_feature(dev, VIRTIO_NET_F_GUEST_TSO4))
-		features |= TUN_F_TSO4;
-	if (has_feature(dev, VIRTIO_NET_F_GUEST_TSO6))
-		features |= TUN_F_TSO6;
-	if (has_feature(dev, VIRTIO_NET_F_GUEST_ECN))
-		features |= TUN_F_TSO_ECN;
-	if (has_feature(dev, VIRTIO_NET_F_HOST_UFO))
-		features |= TUN_F_UFO;
+		if (has_feature(dev, VIRTIO_NET_F_GUEST_TSO4))
+			features |= TUN_F_TSO4;
+		if (has_feature(dev, VIRTIO_NET_F_GUEST_TSO6))
+			features |= TUN_F_TSO6;
+		if (has_feature(dev, VIRTIO_NET_F_GUEST_UFO))
+			features |= TUN_F_UFO;
+		if (features & (TUN_F_TSO4|TUN_F_TSO6) &&
+		    has_feature(dev, VIRTIO_NET_F_GUEST_ECN))
+			features |= TUN_F_TSO_ECN;
+	}
 
 	if (ioctl(dev->fd, TUNSETFEATURES, features) != 0)
 		errx(1, "Could not set features %#x for tun device", features);
