On Mon, 30 Jan 2017 20:49:34 -0500, Michael Chan wrote: > +#ifdef CONFIG_BNXT_XDP > +/* returns the following: > + * true - packet consumed by XDP and new buffer is allocated. > + * false - packet should be passed to the stack. > + */ > +bool bnxt_rx_xdp(struct bnxt_rx_ring_info *rxr, u16 cons, void *data, > + u8 *data_ptr, unsigned int len, dma_addr_t dma_addr, > + u8 *event) > +{ > + struct bpf_prog *xdp_prog = READ_ONCE(rxr->xdp_prog); > + struct xdp_buff xdp; > + u32 act; > + > + if (!xdp_prog) > + return false; > + > + xdp.data = data_ptr; > + xdp.data_end = xdp.data + len; > + rcu_read_lock(); > + act = bpf_prog_run_xdp(xdp_prog, &xdp); > + rcu_read_unlock(); > + > + switch (act) { > + case XDP_PASS: > + return false; > + > + default: > + bpf_warn_invalid_xdp_action(act); > + /* Fall thru */ > + case XDP_DROP: > + case XDP_ABORTED: > + bnxt_reuse_rx_data(rxr, cons, data); > + break; > + } > + return true; > +}
It would be cool if you could populate the appropriate paths with tracepoints Daniel added in a67edbf4fb6d ("bpf: add initial bpf tracepoints"). > + if (netif_running(dev)) > + bnxt_close_nic(bp, true, false); > + > + old = xchg(&bp->xdp_prog, prog); > + if (old) > + bpf_prog_put(old); > + > + if (prog) { > + bnxt_set_rx_skb_mode(bp, true); > + } else { > + bool sh = (bp->flags & BNXT_FLAG_SHARED_RINGS) ? true : false; > + int rx, tx; > + > + bnxt_set_rx_skb_mode(bp, false); > + bnxt_get_max_rings(bp, &rx, &tx, sh); > + if (rx > 1) { > + bp->flags &= ~BNXT_FLAG_NO_AGG_RINGS; > + bp->dev->hw_features |= NETIF_F_LRO; > + } > + } > + bp->tx_nr_rings_xdp = tx_xdp; > + bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc + tx_xdp; > + bp->cp_nr_rings = max_t(int, bp->tx_nr_rings, bp->rx_nr_rings); > + bp->num_stat_ctxs = bp->cp_nr_rings; > + bnxt_set_tpa_flags(bp); > + bnxt_set_ring_params(bp); > + > + if (netif_running(dev)) > + return bnxt_open_nic(bp, true, false); Mm.. I thought doing open/close like this and risking you won't be able to come back up was frowned upon [1]. I must be misunderstanding things... [1] https://www.spinics.net/lists/netdev/msg365229.html > +int bnxt_xdp(struct net_device *dev, struct netdev_xdp *xdp) > +{ > + struct bnxt *bp = netdev_priv(dev); > + int rc; > + > + switch (xdp->command) { > + case XDP_SETUP_PROG: > + rc = bnxt_xdp_set(bp, xdp->prog); > + break; > + case XDP_QUERY_PROG: > + xdp->prog_attached = !!bp->xdp_prog; > + rc = 0; > + break; > + default: > + rc = -EINVAL; > + break; > + } > + return rc; > +} Nit: why not simply return?