|
@@ -641,6 +641,9 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun,
|
|
|
case VIRTIO_NET_HDR_GSO_TCPV6:
|
|
|
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
|
|
|
break;
|
|
|
+ case VIRTIO_NET_HDR_GSO_UDP:
|
|
|
+ skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
|
|
+ break;
|
|
|
default:
|
|
|
tun->dev->stats.rx_frame_errors++;
|
|
|
kfree_skb(skb);
|
|
@@ -726,6 +729,8 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
|
|
|
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
|
|
|
else if (sinfo->gso_type & SKB_GSO_TCPV6)
|
|
|
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
|
|
|
+ else if (sinfo->gso_type & SKB_GSO_UDP)
|
|
|
+ gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
|
|
|
else
|
|
|
BUG();
|
|
|
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
|
|
@@ -1073,7 +1078,8 @@ static int set_offload(struct net_device *dev, unsigned long arg)
|
|
|
old_features = dev->features;
|
|
|
/* Unset features, set them as we chew on the arg. */
|
|
|
features = (old_features & ~(NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST
|
|
|
- |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6));
|
|
|
+ |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6
|
|
|
+ |NETIF_F_UFO));
|
|
|
|
|
|
if (arg & TUN_F_CSUM) {
|
|
|
features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
|
|
@@ -1090,6 +1096,11 @@ static int set_offload(struct net_device *dev, unsigned long arg)
|
|
|
features |= NETIF_F_TSO6;
|
|
|
arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
|
|
|
}
|
|
|
+
|
|
|
+ if (arg & TUN_F_UFO) {
|
|
|
+ features |= NETIF_F_UFO;
|
|
|
+ arg &= ~TUN_F_UFO;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* This gives the user a way to test for new features in future by
|