aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2014-10-30 14:27:12 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-30 20:01:18 -0400
commit3d0ad09412ffe00c9afa201d01effdb6023d09b4 (patch)
tree5244d50331be01616a16bf6f122a8769a1a928d8
parent39bb5e62867de82b269b07df900165029b928359 (diff)
drivers/net: Disable UFO through virtio
IPv6 does not allow fragmentation by routers, so there is no fragmentation ID in the fixed header. UFO for IPv6 requires the ID to be passed separately, but there is no provision for this in the virtio net protocol. Until recently our software implementation of UFO/IPv6 generated a new ID, but this was a bug. Now we will use ID=0 for any UFO/IPv6 packet passed through a tap, which is even worse. Unfortunately there is no distinction between UFO/IPv4 and v6 features, so disable UFO on taps and virtio_net completely until we have a proper solution. We cannot depend on VM managers respecting the tap feature flags, so keep accepting UFO packets but log a warning the first time we do this. Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Fixes: 916e4cf46d02 ("ipv6: reuse ip6_frag_id from ip6_ufo_append_data") Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/macvtap.c13
-rw-r--r--drivers/net/tun.c19
-rw-r--r--drivers/net/virtio_net.c24
3 files changed, 30 insertions, 26 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 65e2892342bd..2aeaa61ece09 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -65,7 +65,7 @@ static struct cdev macvtap_cdev;
65static const struct proto_ops macvtap_socket_ops; 65static const struct proto_ops macvtap_socket_ops;
66 66
67#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ 67#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
68 NETIF_F_TSO6 | NETIF_F_UFO) 68 NETIF_F_TSO6)
69#define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) 69#define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
70#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) 70#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
71 71
@@ -569,6 +569,8 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb,
569 gso_type = SKB_GSO_TCPV6; 569 gso_type = SKB_GSO_TCPV6;
570 break; 570 break;
571 case VIRTIO_NET_HDR_GSO_UDP: 571 case VIRTIO_NET_HDR_GSO_UDP:
572 pr_warn_once("macvtap: %s: using disabled UFO feature; please fix this program\n",
573 current->comm);
572 gso_type = SKB_GSO_UDP; 574 gso_type = SKB_GSO_UDP;
573 break; 575 break;
574 default: 576 default:
@@ -614,8 +616,6 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
614 vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; 616 vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
615 else if (sinfo->gso_type & SKB_GSO_TCPV6) 617 else if (sinfo->gso_type & SKB_GSO_TCPV6)
616 vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; 618 vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
617 else if (sinfo->gso_type & SKB_GSO_UDP)
618 vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
619 else 619 else
620 BUG(); 620 BUG();
621 if (sinfo->gso_type & SKB_GSO_TCP_ECN) 621 if (sinfo->gso_type & SKB_GSO_TCP_ECN)
@@ -950,9 +950,6 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
950 if (arg & TUN_F_TSO6) 950 if (arg & TUN_F_TSO6)
951 feature_mask |= NETIF_F_TSO6; 951 feature_mask |= NETIF_F_TSO6;
952 } 952 }
953
954 if (arg & TUN_F_UFO)
955 feature_mask |= NETIF_F_UFO;
956 } 953 }
957 954
958 /* tun/tap driver inverts the usage for TSO offloads, where 955 /* tun/tap driver inverts the usage for TSO offloads, where
@@ -963,7 +960,7 @@ static int set_offload(struct macvtap_queue *q, unsigned long arg)
963 * When user space turns off TSO, we turn off GSO/LRO so that 960 * When user space turns off TSO, we turn off GSO/LRO so that
964 * user-space will not receive TSO frames. 961 * user-space will not receive TSO frames.
965 */ 962 */
966 if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO)) 963 if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6))
967 features |= RX_OFFLOADS; 964 features |= RX_OFFLOADS;
968 else 965 else
969 features &= ~RX_OFFLOADS; 966 features &= ~RX_OFFLOADS;
@@ -1064,7 +1061,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
1064 case TUNSETOFFLOAD: 1061 case TUNSETOFFLOAD:
1065 /* let the user check for future flags */ 1062 /* let the user check for future flags */
1066 if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | 1063 if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
1067 TUN_F_TSO_ECN | TUN_F_UFO)) 1064 TUN_F_TSO_ECN))
1068 return -EINVAL; 1065 return -EINVAL;
1069 1066
1070 rtnl_lock(); 1067 rtnl_lock();
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 186ce541c657..280d3d2a9792 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -174,7 +174,7 @@ struct tun_struct {
174 struct net_device *dev; 174 struct net_device *dev;
175 netdev_features_t set_features; 175 netdev_features_t set_features;
176#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ 176#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
177 NETIF_F_TSO6|NETIF_F_UFO) 177 NETIF_F_TSO6)
178 178
179 int vnet_hdr_sz; 179 int vnet_hdr_sz;
180 int sndbuf; 180 int sndbuf;
@@ -1149,8 +1149,18 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
1149 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; 1149 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
1150 break; 1150 break;
1151 case VIRTIO_NET_HDR_GSO_UDP: 1151 case VIRTIO_NET_HDR_GSO_UDP:
1152 {
1153 static bool warned;
1154
1155 if (!warned) {
1156 warned = true;
1157 netdev_warn(tun->dev,
1158 "%s: using disabled UFO feature; please fix this program\n",
1159 current->comm);
1160 }
1152 skb_shinfo(skb)->gso_type = SKB_GSO_UDP; 1161 skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
1153 break; 1162 break;
1163 }
1154 default: 1164 default:
1155 tun->dev->stats.rx_frame_errors++; 1165 tun->dev->stats.rx_frame_errors++;
1156 kfree_skb(skb); 1166 kfree_skb(skb);
@@ -1251,8 +1261,6 @@ static ssize_t tun_put_user(struct tun_struct *tun,
1251 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; 1261 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
1252 else if (sinfo->gso_type & SKB_GSO_TCPV6) 1262 else if (sinfo->gso_type & SKB_GSO_TCPV6)
1253 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; 1263 gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
1254 else if (sinfo->gso_type & SKB_GSO_UDP)
1255 gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
1256 else { 1264 else {
1257 pr_err("unexpected GSO type: " 1265 pr_err("unexpected GSO type: "
1258 "0x%x, gso_size %d, hdr_len %d\n", 1266 "0x%x, gso_size %d, hdr_len %d\n",
@@ -1762,11 +1770,6 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
1762 features |= NETIF_F_TSO6; 1770 features |= NETIF_F_TSO6;
1763 arg &= ~(TUN_F_TSO4|TUN_F_TSO6); 1771 arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
1764 } 1772 }
1765
1766 if (arg & TUN_F_UFO) {
1767 features |= NETIF_F_UFO;
1768 arg &= ~TUN_F_UFO;
1769 }
1770 } 1773 }
1771 1774
1772 /* This gives the user a way to test for new features in future by 1775 /* This gives the user a way to test for new features in future by
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index d75256bd1a6a..ec2a8b41ed41 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -491,8 +491,17 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
491 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; 491 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
492 break; 492 break;
493 case VIRTIO_NET_HDR_GSO_UDP: 493 case VIRTIO_NET_HDR_GSO_UDP:
494 {
495 static bool warned;
496
497 if (!warned) {
498 warned = true;
499 netdev_warn(dev,
500 "host using disabled UFO feature; please fix it\n");
501 }
494 skb_shinfo(skb)->gso_type = SKB_GSO_UDP; 502 skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
495 break; 503 break;
504 }
496 case VIRTIO_NET_HDR_GSO_TCPV6: 505 case VIRTIO_NET_HDR_GSO_TCPV6:
497 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; 506 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
498 break; 507 break;
@@ -881,8 +890,6 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
881 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; 890 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
882 else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) 891 else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
883 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; 892 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
884 else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
885 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP;
886 else 893 else
887 BUG(); 894 BUG();
888 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) 895 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
@@ -1705,7 +1712,7 @@ static int virtnet_probe(struct virtio_device *vdev)
1705 dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; 1712 dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
1706 1713
1707 if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { 1714 if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
1708 dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO 1715 dev->hw_features |= NETIF_F_TSO
1709 | NETIF_F_TSO_ECN | NETIF_F_TSO6; 1716 | NETIF_F_TSO_ECN | NETIF_F_TSO6;
1710 } 1717 }
1711 /* Individual feature bits: what can host handle? */ 1718 /* Individual feature bits: what can host handle? */
@@ -1715,11 +1722,9 @@ static int virtnet_probe(struct virtio_device *vdev)
1715 dev->hw_features |= NETIF_F_TSO6; 1722 dev->hw_features |= NETIF_F_TSO6;
1716 if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) 1723 if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
1717 dev->hw_features |= NETIF_F_TSO_ECN; 1724 dev->hw_features |= NETIF_F_TSO_ECN;
1718 if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO))
1719 dev->hw_features |= NETIF_F_UFO;
1720 1725
1721 if (gso) 1726 if (gso)
1722 dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO); 1727 dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
1723 /* (!csum && gso) case will be fixed by register_netdev() */ 1728 /* (!csum && gso) case will be fixed by register_netdev() */
1724 } 1729 }
1725 if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM)) 1730 if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
@@ -1757,8 +1762,7 @@ static int virtnet_probe(struct virtio_device *vdev)
1757 /* If we can receive ANY GSO packets, we must allocate large ones. */ 1762 /* If we can receive ANY GSO packets, we must allocate large ones. */
1758 if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || 1763 if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
1759 virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) || 1764 virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
1760 virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) || 1765 virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
1761 virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO))
1762 vi->big_packets = true; 1766 vi->big_packets = true;
1763 1767
1764 if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) 1768 if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
@@ -1952,9 +1956,9 @@ static struct virtio_device_id id_table[] = {
1952static unsigned int features[] = { 1956static unsigned int features[] = {
1953 VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, 1957 VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM,
1954 VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, 1958 VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
1955 VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, 1959 VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6,
1956 VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, 1960 VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
1957 VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO, 1961 VIRTIO_NET_F_GUEST_ECN,
1958 VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, 1962 VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
1959 VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, 1963 VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
1960 VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, 1964 VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,