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(). > + 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; > +} -- Best regards, Jesper Dangaard Brouer MSc.CS, Principal Kernel Engineer at Red Hat LinkedIn: http://www.linkedin.com/in/brouer