| From foo@baz Wed May 28 21:03:54 PDT 2014 |
| From: Vlad Yasevich <vyasevic@redhat.com> |
| Date: Tue, 29 Apr 2014 10:09:50 -0400 |
| Subject: mactap: Fix checksum errors for non-gso packets in |
| bridge mode |
| |
| From: Vlad Yasevich <vyasevic@redhat.com> |
| |
| [ Upstream commit cbdb04279ccaefcc702c8757757eea8ed76e50cf ] |
| |
| The following is a problematic configuration: |
| |
| VM1: virtio-net device connected to macvtap0@eth0 |
| VM2: e1000 device connect to macvtap1@eth0 |
| |
| The problem is is that virtio-net supports checksum offloading |
| and thus sends the packets to the host with CHECKSUM_PARTIAL set. |
| On the other hand, e1000 does not support any acceleration. |
| |
| For small TCP packets (and this includes the 3-way handshake), |
| e1000 ends up receiving packets that only have a partial checksum |
| set. This causes TCP to fail checksum validation and to drop |
| packets. As a result tcp connections can not be established. |
| |
| Commit 3e4f8b787370978733ca6cae452720a4f0c296b8 |
| macvtap: Perform GSO on forwarding path. |
| fixes this issue for large packets wthat will end up undergoing GSO. |
| This commit adds a check for the non-GSO case and attempts to |
| compute the checksum for partially checksummed packets in the |
| non-GSO case. |
| |
| CC: Daniel Lezcano <daniel.lezcano@free.fr> |
| CC: Patrick McHardy <kaber@trash.net> |
| CC: Andrian Nord <nightnord@gmail.com> |
| CC: Eric Dumazet <eric.dumazet@gmail.com> |
| CC: Michael S. Tsirkin <mst@redhat.com> |
| CC: Jason Wang <jasowang@redhat.com> |
| Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> |
| Acked-by: Jason Wang <jasowang@redhat.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/macvtap.c | 9 +++++++++ |
| 1 file changed, 9 insertions(+) |
| |
| --- a/drivers/net/macvtap.c |
| +++ b/drivers/net/macvtap.c |
| @@ -322,6 +322,15 @@ static rx_handler_result_t macvtap_handl |
| segs = nskb; |
| } |
| } else { |
| + /* If we receive a partial checksum and the tap side |
| + * doesn't support checksum offload, compute the checksum. |
| + * Note: it doesn't matter which checksum feature to |
| + * check, we either support them all or none. |
| + */ |
| + if (skb->ip_summed == CHECKSUM_PARTIAL && |
| + !(features & NETIF_F_ALL_CSUM) && |
| + skb_checksum_help(skb)) |
| + goto drop; |
| skb_queue_tail(&q->sk.sk_receive_queue, skb); |
| } |
| |