Commit 5f428401 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Daniel Borkmann

nfp: add support for simultaneous driver and hw XDP

Split handling of offloaded and driver programs completely.  Since
offloaded programs always come with XDP_FLAGS_HW_MODE set in reality
there could be no sharing, anyway, programs would only be installed
in driver or in hardware.  Splitting the handling allows us to install
programs in HW and in driver at the same time.
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarQuentin Monnet <quentin.monnet@netronome.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 99dadb6e
...@@ -66,26 +66,19 @@ nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn, ...@@ -66,26 +66,19 @@ nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
struct bpf_prog *prog, struct netlink_ext_ack *extack) struct bpf_prog *prog, struct netlink_ext_ack *extack)
{ {
bool running, xdp_running; bool running, xdp_running;
int ret;
if (!nfp_net_ebpf_capable(nn)) if (!nfp_net_ebpf_capable(nn))
return -EINVAL; return -EINVAL;
running = nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF; running = nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF;
xdp_running = running && nn->dp.bpf_offload_xdp; xdp_running = running && nn->xdp_hw.prog;
if (!prog && !xdp_running) if (!prog && !xdp_running)
return 0; return 0;
if (prog && running && !xdp_running) if (prog && running && !xdp_running)
return -EBUSY; return -EBUSY;
ret = nfp_net_bpf_offload(nn, prog, running, extack); return nfp_net_bpf_offload(nn, prog, running, extack);
/* Stop offload if replace not possible */
if (ret)
return ret;
nn->dp.bpf_offload_xdp = !!prog;
return ret;
} }
static const char *nfp_bpf_extra_cap(struct nfp_app *app, struct nfp_net *nn) static const char *nfp_bpf_extra_cap(struct nfp_app *app, struct nfp_net *nn)
......
...@@ -485,7 +485,6 @@ struct nfp_stat_pair { ...@@ -485,7 +485,6 @@ struct nfp_stat_pair {
* @dev: Backpointer to struct device * @dev: Backpointer to struct device
* @netdev: Backpointer to net_device structure * @netdev: Backpointer to net_device structure
* @is_vf: Is the driver attached to a VF? * @is_vf: Is the driver attached to a VF?
* @bpf_offload_xdp: Offloaded BPF program is XDP
* @chained_metadata_format: Firemware will use new metadata format * @chained_metadata_format: Firemware will use new metadata format
* @rx_dma_dir: Mapping direction for RX buffers * @rx_dma_dir: Mapping direction for RX buffers
* @rx_dma_off: Offset at which DMA packets (for XDP headroom) * @rx_dma_off: Offset at which DMA packets (for XDP headroom)
...@@ -510,7 +509,6 @@ struct nfp_net_dp { ...@@ -510,7 +509,6 @@ struct nfp_net_dp {
struct net_device *netdev; struct net_device *netdev;
u8 is_vf:1; u8 is_vf:1;
u8 bpf_offload_xdp:1;
u8 chained_metadata_format:1; u8 chained_metadata_format:1;
u8 rx_dma_dir; u8 rx_dma_dir;
...@@ -553,7 +551,8 @@ struct nfp_net_dp { ...@@ -553,7 +551,8 @@ struct nfp_net_dp {
* @rss_cfg: RSS configuration * @rss_cfg: RSS configuration
* @rss_key: RSS secret key * @rss_key: RSS secret key
* @rss_itbl: RSS indirection table * @rss_itbl: RSS indirection table
* @xdp: Information about the attached XDP program * @xdp: Information about the driver XDP program
* @xdp_hw: Information about the HW XDP program
* @max_r_vecs: Number of allocated interrupt vectors for RX/TX * @max_r_vecs: Number of allocated interrupt vectors for RX/TX
* @max_tx_rings: Maximum number of TX rings supported by the Firmware * @max_tx_rings: Maximum number of TX rings supported by the Firmware
* @max_rx_rings: Maximum number of RX rings supported by the Firmware * @max_rx_rings: Maximum number of RX rings supported by the Firmware
...@@ -610,6 +609,7 @@ struct nfp_net { ...@@ -610,6 +609,7 @@ struct nfp_net {
u8 rss_itbl[NFP_NET_CFG_RSS_ITBL_SZ]; u8 rss_itbl[NFP_NET_CFG_RSS_ITBL_SZ];
struct xdp_attachment_info xdp; struct xdp_attachment_info xdp;
struct xdp_attachment_info xdp_hw;
unsigned int max_tx_rings; unsigned int max_tx_rings;
unsigned int max_rx_rings; unsigned int max_rx_rings;
......
...@@ -1710,8 +1710,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) ...@@ -1710,8 +1710,7 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget)
} }
} }
if (xdp_prog && !(rxd->rxd.flags & PCIE_DESC_RX_BPF && if (xdp_prog && !meta.portid) {
dp->bpf_offload_xdp) && !meta.portid) {
void *orig_data = rxbuf->frag + pkt_off; void *orig_data = rxbuf->frag + pkt_off;
unsigned int dma_off; unsigned int dma_off;
int act; int act;
...@@ -3393,14 +3392,18 @@ static void nfp_net_del_vxlan_port(struct net_device *netdev, ...@@ -3393,14 +3392,18 @@ static void nfp_net_del_vxlan_port(struct net_device *netdev,
nfp_net_set_vxlan_port(nn, idx, 0); nfp_net_set_vxlan_port(nn, idx, 0);
} }
static int static int nfp_net_xdp_setup_drv(struct nfp_net *nn, struct netdev_bpf *bpf)
nfp_net_xdp_setup_drv(struct nfp_net *nn, struct bpf_prog *prog,
struct netlink_ext_ack *extack)
{ {
struct bpf_prog *prog = bpf->prog;
struct nfp_net_dp *dp; struct nfp_net_dp *dp;
int err;
if (!xdp_attachment_flags_ok(&nn->xdp, bpf))
return -EBUSY;
if (!prog == !nn->dp.xdp_prog) { if (!prog == !nn->dp.xdp_prog) {
WRITE_ONCE(nn->dp.xdp_prog, prog); WRITE_ONCE(nn->dp.xdp_prog, prog);
xdp_attachment_setup(&nn->xdp, bpf);
return 0; return 0;
} }
...@@ -3414,33 +3417,26 @@ nfp_net_xdp_setup_drv(struct nfp_net *nn, struct bpf_prog *prog, ...@@ -3414,33 +3417,26 @@ nfp_net_xdp_setup_drv(struct nfp_net *nn, struct bpf_prog *prog,
dp->rx_dma_off = prog ? XDP_PACKET_HEADROOM - nn->dp.rx_offset : 0; dp->rx_dma_off = prog ? XDP_PACKET_HEADROOM - nn->dp.rx_offset : 0;
/* We need RX reconfig to remap the buffers (BIDIR vs FROM_DEV) */ /* We need RX reconfig to remap the buffers (BIDIR vs FROM_DEV) */
return nfp_net_ring_reconfig(nn, dp, extack); err = nfp_net_ring_reconfig(nn, dp, bpf->extack);
if (err)
return err;
xdp_attachment_setup(&nn->xdp, bpf);
return 0;
} }
static int nfp_net_xdp_setup(struct nfp_net *nn, struct netdev_bpf *bpf) static int nfp_net_xdp_setup_hw(struct nfp_net *nn, struct netdev_bpf *bpf)
{ {
struct bpf_prog *drv_prog, *offload_prog;
int err; int err;
if (!xdp_attachment_flags_ok(&nn->xdp, bpf)) if (!xdp_attachment_flags_ok(&nn->xdp_hw, bpf))
return -EBUSY; return -EBUSY;
/* Load both when no flags set to allow easy activation of driver path err = nfp_app_xdp_offload(nn->app, nn, bpf->prog, bpf->extack);
* when program is replaced by one which can't be offloaded.
*/
drv_prog = bpf->flags & XDP_FLAGS_HW_MODE ? NULL : bpf->prog;
offload_prog = bpf->flags & XDP_FLAGS_DRV_MODE ? NULL : bpf->prog;
err = nfp_net_xdp_setup_drv(nn, drv_prog, bpf->extack);
if (err) if (err)
return err; return err;
err = nfp_app_xdp_offload(nn->app, nn, offload_prog, bpf->extack); xdp_attachment_setup(&nn->xdp_hw, bpf);
if (err && bpf->flags & XDP_FLAGS_HW_MODE)
return err;
xdp_attachment_setup(&nn->xdp, bpf);
return 0; return 0;
} }
...@@ -3450,16 +3446,13 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_bpf *xdp) ...@@ -3450,16 +3446,13 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_bpf *xdp)
switch (xdp->command) { switch (xdp->command) {
case XDP_SETUP_PROG: case XDP_SETUP_PROG:
return nfp_net_xdp_setup_drv(nn, xdp);
case XDP_SETUP_PROG_HW: case XDP_SETUP_PROG_HW:
return nfp_net_xdp_setup(nn, xdp); return nfp_net_xdp_setup_hw(nn, xdp);
case XDP_QUERY_PROG: case XDP_QUERY_PROG:
if (nn->dp.bpf_offload_xdp)
return 0;
return xdp_attachment_query(&nn->xdp, xdp); return xdp_attachment_query(&nn->xdp, xdp);
case XDP_QUERY_PROG_HW: case XDP_QUERY_PROG_HW:
if (!nn->dp.bpf_offload_xdp) return xdp_attachment_query(&nn->xdp_hw, xdp);
return 0;
return xdp_attachment_query(&nn->xdp, xdp);
default: default:
return nfp_app_bpf(nn->app, nn, xdp); return nfp_app_bpf(nn->app, nn, xdp);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment