aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c25
1 files changed, 9 insertions, 16 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 8c8dc16839a7..10f9e4021b5a 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -65,7 +65,6 @@
65#include <linux/nsproxy.h> 65#include <linux/nsproxy.h>
66#include <linux/virtio_net.h> 66#include <linux/virtio_net.h>
67#include <linux/rcupdate.h> 67#include <linux/rcupdate.h>
68#include <net/ipv6.h>
69#include <net/net_namespace.h> 68#include <net/net_namespace.h>
70#include <net/netns/generic.h> 69#include <net/netns/generic.h>
71#include <net/rtnetlink.h> 70#include <net/rtnetlink.h>
@@ -187,7 +186,7 @@ struct tun_struct {
187 struct net_device *dev; 186 struct net_device *dev;
188 netdev_features_t set_features; 187 netdev_features_t set_features;
189#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ 188#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
190 NETIF_F_TSO6) 189 NETIF_F_TSO6|NETIF_F_UFO)
191 190
192 int vnet_hdr_sz; 191 int vnet_hdr_sz;
193 int sndbuf; 192 int sndbuf;
@@ -1167,8 +1166,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
1167 break; 1166 break;
1168 } 1167 }
1169 1168
1170 skb_reset_network_header(skb);
1171
1172 if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { 1169 if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
1173 pr_debug("GSO!\n"); 1170 pr_debug("GSO!\n");
1174 switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { 1171 switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
@@ -1179,20 +1176,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
1179 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; 1176 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
1180 break; 1177 break;
1181 case VIRTIO_NET_HDR_GSO_UDP: 1178 case VIRTIO_NET_HDR_GSO_UDP:
1182 {
1183 static bool warned;
1184
1185 if (!warned) {
1186 warned = true;
1187 netdev_warn(tun->dev,
1188 "%s: using disabled UFO feature; please fix this program\n",
1189 current->comm);
1190 }
1191 skb_shinfo(skb)->gso_type = SKB_GSO_UDP; 1179 skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
1192 if (skb->protocol == htons(ETH_P_IPV6))
1193 ipv6_proxy_select_ident(skb);
1194 break; 1180 break;
1195 }
1196 default: 1181 default:
1197 tun->dev->stats.rx_frame_errors++; 1182 tun->dev->stats.rx_frame_errors++;
1198 kfree_skb(skb); 1183 kfree_skb(skb);
@@ -1221,6 +1206,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
1221 skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; 1206 skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
1222 } 1207 }
1223 1208
1209 skb_reset_network_header(skb);
1224 skb_probe_transport_header(skb, 0); 1210 skb_probe_transport_header(skb, 0);
1225 1211
1226 rxhash = skb_get_hash(skb); 1212 rxhash = skb_get_hash(skb);
@@ -1298,6 +1284,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
1298 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; 1284 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
1299 else if (sinfo->gso_type & SKB_GSO_TCPV6) 1285 else if (sinfo->gso_type & SKB_GSO_TCPV6)
1300 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; 1286 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
1287 else if (sinfo->gso_type & SKB_GSO_UDP)
1288 gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
1301 else { 1289 else {
1302 pr_err("unexpected GSO type: " 1290 pr_err("unexpected GSO type: "
1303 "0x%x, gso_size %d, hdr_len %d\n", 1291 "0x%x, gso_size %d, hdr_len %d\n",
@@ -1746,6 +1734,11 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
1746 features |= NETIF_F_TSO6; 1734 features |= NETIF_F_TSO6;
1747 arg &= ~(TUN_F_TSO4|TUN_F_TSO6); 1735 arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
1748 } 1736 }
1737
1738 if (arg & TUN_F_UFO) {
1739 features |= NETIF_F_UFO;
1740 arg &= ~TUN_F_UFO;
1741 }
1749 } 1742 }
1750 1743
1751 /* This gives the user a way to test for new features in future by 1744 /* This gives the user a way to test for new features in future by