[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAGdtWsQCyrg3otDtxw62k8xeXp5td8rxxfXydhSzBOAMbH3VzA@mail.gmail.com>
Date: Thu, 28 May 2020 13:34:45 -0700
From: Petar Penkov <ppenkov.kernel@...il.com>
To: Willem de Bruijn <willemdebruijn.kernel@...il.com>
Cc: Networking <netdev@...r.kernel.org>,
"David S. Miller" <davem@...emloft.net>,
Willem de Bruijn <willemb@...gle.com>
Subject: Re: [PATCH net] tun: correct header offsets in napi frags mode
On Thu, May 28, 2020 at 10:07 AM Willem de Bruijn
<willemdebruijn.kernel@...il.com> wrote:
>
> From: Willem de Bruijn <willemb@...gle.com>
>
> Tun in IFF_NAPI_FRAGS mode calls napi_gro_frags. Unlike netif_rx and
> netif_gro_receive, this expects skb->data to point to the mac layer.
>
> But skb_probe_transport_header, __skb_get_hash_symmetric, and
> xdp_do_generic in tun_get_user need skb->data to point to the network
> header. Flow dissection also needs skb->protocol set, so
> eth_type_trans has to be called.
>
> Temporarily pull ETH_HLEN to make control flow the same for frags and
> not frags. Then push the header just before calling napi_gro_frags.
>
> Fixes: 90e33d459407 ("tun: enable napi_gro_frags() for TUN/TAP driver")
> Signed-off-by: Willem de Bruijn <willemb@...gle.com>
Acked-by: Petar Penkov <ppenkov@...gle.com>
> ---
> drivers/net/tun.c | 14 ++++++++++----
> 1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index 44889eba1dbc..b984733c6c31 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -1871,8 +1871,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
> skb->dev = tun->dev;
> break;
> case IFF_TAP:
> - if (!frags)
> - skb->protocol = eth_type_trans(skb, tun->dev);
> + if (frags && !pskb_may_pull(skb, ETH_HLEN)) {
> + err = -ENOMEM;
> + goto drop;
> + }
> + skb->protocol = eth_type_trans(skb, tun->dev);
> break;
> }
>
> @@ -1929,9 +1932,12 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
> }
>
> if (frags) {
> + u32 headlen;
> +
> /* Exercise flow dissector code path. */
> - u32 headlen = eth_get_headlen(tun->dev, skb->data,
> - skb_headlen(skb));
> + skb_push(skb, ETH_HLEN);
> + headlen = eth_get_headlen(tun->dev, skb->data,
> + skb_headlen(skb));
>
> if (unlikely(headlen > skb_headlen(skb))) {
> this_cpu_inc(tun->pcpu_stats->rx_dropped);
> --
> 2.27.0.rc0.183.gde8f92d652-goog
>
Powered by blists - more mailing lists