On Thu, May 28, 2020 at 10:07 AM Willem de Bruijn <willemdebruijn.ker...@gmail.com> wrote: > > From: Willem de Bruijn <will...@google.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 <will...@google.com>
Acked-by: Petar Penkov <ppen...@google.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 >