From patchwork Wed Jun 6 15:23:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Willem de Bruijn X-Patchwork-Id: 925913 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="GD8/3s1c"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 411C9l6JrJz9s1B for ; Thu, 7 Jun 2018 01:23:23 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752492AbeFFPXV (ORCPT ); Wed, 6 Jun 2018 11:23:21 -0400 Received: from mail-qt0-f194.google.com ([209.85.216.194]:35280 "EHLO mail-qt0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752442AbeFFPXE (ORCPT ); Wed, 6 Jun 2018 11:23:04 -0400 Received: by mail-qt0-f194.google.com with SMTP id s9-v6so6752487qtg.2 for ; Wed, 06 Jun 2018 08:23:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=8cLGF3ZCQKAE3NPd3fxYZGRFbuoFqVi7GnXaTiK/0Ms=; b=GD8/3s1cFj64W3rUwGoHWGW2DKo19yPixaq1O599dVcUK9LYKiiB91uUtQvLIbWxy7 9r3FSX4lSSeDZKuxSXwUGlQ34cZukkwl0c1GlJ9pCroPhs4m8oFt6NywsITTRETAtI9C bsvCoT7C88PqKPPs37GLamXSx3q/4+bMJ15GSwBbMm8+5AwTN5PnDA1FrWn/whOvIosB mJt2rXpZZ3svrdnUCPI5fFYnX566xsU5z4r2X2Q1foaH0k5fLbzmMzBS/d35HfIXev1Z HEZnQKY3BTI5ELdHVIXoDeCuk8W9RZ5KTk3x0ArRNTOrsPJyFK3jjjLWZ7fCD4AQDbDn 6aWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=8cLGF3ZCQKAE3NPd3fxYZGRFbuoFqVi7GnXaTiK/0Ms=; b=g3y9GYUWZpetNvewiRffVXPvNfFBY4vdEikZ46etRStYSMYipSwv7849KMvVyYsiU9 o2J4ErRS+WxqQ0RggBLhGvCyks18ep/C1rQjwqC9fb6jUIr3lY2Hzm2mnUIsG2sCsbyZ 9sZI26hU2rUcOK6MbowU6VyRdWllHi003ZaszpsIxKKOu4G6JGP30t3xEjQwUrCz0sGC lUrkTqul3wBZSXvTsZkwVhp8Xko3ZeGZMlat/kt00nRVjIu/ry1fwNQCBaKPyYtr3P02 YDkpzfQl9DOtoj/j0Ys6FuPXH7N3YaWE89NGQ6nU5s3gkhAg+kiJF3fnXldN2L3R62l7 2fLg== X-Gm-Message-State: APt69E1eHw4RtTigVAVeF7V9TMv/h+R42U063X6ry+hYNPfxLtHxNF+W PN7lYv2nRJfO6yYcUjjPKGechJm/ X-Google-Smtp-Source: ADUXVKLRyMgyh3UcbZvnz5UXxdlD5D7rG/7bd/rQkwZGtKp1byHS5JtjTagzOG0kGMJPbjkkGwzLTQ== X-Received: by 2002:ac8:2439:: with SMTP id c54-v6mr3274325qtc.21.1528298583553; Wed, 06 Jun 2018 08:23:03 -0700 (PDT) Received: from willemb1.nyc.corp.google.com ([2620:0:1003:315:3fa1:a34c:1128:1d39]) by smtp.gmail.com with ESMTPSA id c77-v6sm26046448qkj.3.2018.06.06.08.23.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 06 Jun 2018 08:23:02 -0700 (PDT) From: Willem de Bruijn To: netdev@vger.kernel.org Cc: davem@davemloft.net, rppt@linux.vnet.ibm.com, herbert@gondor.apana.org.au, anton.ivanov@cambridgegreys.com, Willem de Bruijn Subject: [PATCH net] net: in virtio_net_hdr only add VLAN_HLEN to csum_start if payload holds vlan Date: Wed, 6 Jun 2018 11:23:01 -0400 Message-Id: <20180606152301.33240-1-willemdebruijn.kernel@gmail.com> X-Mailer: git-send-email 2.17.1.1185.g55be947832-goog Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Willem de Bruijn Tun, tap, virtio, packet and uml vector all use struct virtio_net_hdr to communicate packet metadata to userspace. For skbuffs with vlan, the first two return the packet as it may have existed on the wire, inserting the VLAN tag in the user buffer. Then virtio_net_hdr.csum_start needs to be adjusted by VLAN_HLEN bytes. Commit f09e2249c4f5 ("macvtap: restore vlan header on user read") added this feature to macvtap. Commit 3ce9b20f1971 ("macvtap: Fix csum_start when VLAN tags are present") then fixed up csum_start. Virtio, packet and uml do not insert the vlan header in the user buffer. When introducing virtio_net_hdr_from_skb to deduplicate filling in the virtio_net_hdr, the variant from macvtap which adds VLAN_HLEN was applied uniformly, breaking csum offset for packets with vlan on virtio and packet. Make insertion of VLAN_HLEN optional. Convert the callers to pass it when needed. Fixes: e858fae2b0b8f4 ("virtio_net: use common code for virtio_net_hdr and skb GSO conversion") Fixes: 1276f24eeef2 ("packet: use common code for virtio_net_hdr and skb GSO conversion") Signed-off-by: Willem de Bruijn --- arch/um/drivers/vector_transports.c | 3 ++- drivers/net/tap.c | 5 ++++- drivers/net/tun.c | 3 ++- drivers/net/virtio_net.c | 3 ++- include/linux/virtio_net.h | 11 ++++------- net/packet/af_packet.c | 4 ++-- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/arch/um/drivers/vector_transports.c b/arch/um/drivers/vector_transports.c index 9065047f844b..77e4ebc206ae 100644 --- a/arch/um/drivers/vector_transports.c +++ b/arch/um/drivers/vector_transports.c @@ -120,7 +120,8 @@ static int raw_form_header(uint8_t *header, skb, vheader, virtio_legacy_is_little_endian(), - false + false, + 0 ); return 0; diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 9b6cb780affe..f0f7cd977667 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -774,13 +774,16 @@ static ssize_t tap_put_user(struct tap_queue *q, int total; if (q->flags & IFF_VNET_HDR) { + int vlan_hlen = skb_vlan_tag_present(skb) ? VLAN_HLEN : 0; struct virtio_net_hdr vnet_hdr; + vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz); if (iov_iter_count(iter) < vnet_hdr_len) return -EINVAL; if (virtio_net_hdr_from_skb(skb, &vnet_hdr, - tap_is_little_endian(q), true)) + tap_is_little_endian(q), true, + vlan_hlen)) BUG(); if (copy_to_iter(&vnet_hdr, sizeof(vnet_hdr), iter) != diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 23e9eb66197f..409eb8b74740 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -2078,7 +2078,8 @@ static ssize_t tun_put_user(struct tun_struct *tun, return -EINVAL; if (virtio_net_hdr_from_skb(skb, &gso, - tun_is_little_endian(tun), true)) { + tun_is_little_endian(tun), true, + vlan_hlen)) { struct skb_shared_info *sinfo = skb_shinfo(skb); pr_err("unexpected GSO type: " "0x%x, gso_size %d, hdr_len %d\n", diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 032e1ac10a30..8c7207535179 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1358,7 +1358,8 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) hdr = skb_vnet_hdr(skb); if (virtio_net_hdr_from_skb(skb, &hdr->hdr, - virtio_is_little_endian(vi->vdev), false)) + virtio_is_little_endian(vi->vdev), false, + 0)) BUG(); if (vi->mergeable_rx_bufs) diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index f144216febc6..9397628a1967 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -58,7 +58,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, struct virtio_net_hdr *hdr, bool little_endian, - bool has_data_valid) + bool has_data_valid, + int vlan_hlen) { memset(hdr, 0, sizeof(*hdr)); /* no info leak */ @@ -83,12 +84,8 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, if (skb->ip_summed == CHECKSUM_PARTIAL) { hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; - if (skb_vlan_tag_present(skb)) - hdr->csum_start = __cpu_to_virtio16(little_endian, - skb_checksum_start_offset(skb) + VLAN_HLEN); - else - hdr->csum_start = __cpu_to_virtio16(little_endian, - skb_checksum_start_offset(skb)); + hdr->csum_start = __cpu_to_virtio16(little_endian, + skb_checksum_start_offset(skb) + vlan_hlen); hdr->csum_offset = __cpu_to_virtio16(little_endian, skb->csum_offset); } else if (has_data_valid && diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index acb7b86574cd..9198997b39d1 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2037,7 +2037,7 @@ static int packet_rcv_vnet(struct msghdr *msg, const struct sk_buff *skb, return -EINVAL; *len -= sizeof(vnet_hdr); - if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true)) + if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true, 0)) return -EINVAL; return memcpy_to_msg(msg, (void *)&vnet_hdr, sizeof(vnet_hdr)); @@ -2304,7 +2304,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, if (do_vnet) { if (virtio_net_hdr_from_skb(skb, h.raw + macoff - sizeof(struct virtio_net_hdr), - vio_le(), true)) { + vio_le(), true, 0)) { spin_lock(&sk->sk_receive_queue.lock); goto drop_n_account; }