diff --git a/drivers/net/tun.c b/drivers/net/tun.c index dfc1054e4cbd..a998b6a9c245 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -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 diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 915ba5789f0e..3f5fd523b49d 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -62,6 +62,7 @@ #define TUN_F_TSO4 0x02 /* I can handle TSO for IPv4 packets */ #define TUN_F_TSO6 0x04 /* I can handle TSO for IPv6 packets */ #define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ +#define TUN_F_UFO 0x10 /* I can handle UFO packets */ /* Protocol info prepended to the packets (when IFF_NO_PI is not set) */ #define TUN_PKT_STRIP 0x0001