On 2018/04/26 5:24, Jesper Dangaard Brouer wrote: > On Tue, 24 Apr 2018 23:39:20 +0900 > Toshiaki Makita <toshiaki.maki...@gmail.com> wrote: > >> +static int veth_xdp_xmit(struct net_device *dev, struct xdp_frame *frame) >> +{ >> + struct veth_priv *rcv_priv, *priv = netdev_priv(dev); >> + int headroom = frame->data - (void *)frame; >> + struct net_device *rcv; >> + int err = 0; >> + >> + rcv = rcu_dereference(priv->peer); >> + if (unlikely(!rcv)) >> + return -ENXIO; >> + >> + rcv_priv = netdev_priv(rcv); >> + /* xdp_ring is initialized on receive side? */ >> + if (rcu_access_pointer(rcv_priv->xdp_prog)) { >> + err = xdp_ok_fwd_dev(rcv, frame->len); >> + if (unlikely(err)) >> + return err; >> + >> + err = veth_xdp_enqueue(rcv_priv, veth_xdp_to_ptr(frame)); >> + } else { >> + struct sk_buff *skb; >> + >> + skb = veth_build_skb(frame, headroom, frame->len, 0); >> + if (unlikely(!skb)) >> + return -ENOMEM; >> + >> + /* Get page ref in case skb is dropped in netif_rx. >> + * The caller is responsible for freeing the page on error. >> + */ >> + get_page(virt_to_page(frame->data)); > > I'm not sure you can make this assumption, that xdp_frames coming from > another device driver uses a refcnt based memory model. But maybe I'm > confused, as this looks like an SKB receive path, but in the > ndo_xdp_xmit().
I find this path similar to cpumap, which creates skb from redirected xdp frame. Once it is converted to skb, skb head is freed by page_frag_free, so anyway I needed to get the refcount here regardless of memory model. > > >> + if (unlikely(veth_forward_skb(rcv, skb, false) != >> NET_RX_SUCCESS)) >> + return -ENXIO; >> + >> + /* Put page ref on success */ >> + page_frag_free(frame->data); >> + } >> + >> + return err; >> +} > > -- Toshiaki Makita