diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2014-10-30 14:27:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-10-30 20:01:18 -0400 |
commit | 3d0ad09412ffe00c9afa201d01effdb6023d09b4 (patch) | |
tree | 5244d50331be01616a16bf6f122a8769a1a928d8 /drivers/net/virtio_net.c | |
parent | 39bb5e62867de82b269b07df900165029b928359 (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>
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r-- | drivers/net/virtio_net.c | 24 |
1 files changed, 14 insertions, 10 deletions
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[] = { | |||
1952 | static unsigned int features[] = { | 1956 | static 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, |