Skip to content

Commit

Permalink
Merge branch 'bpf-xdp-driver-and-hw'
Browse files Browse the repository at this point in the history
Jakub Kicinski says:

====================
This set is adding support for loading driver and offload XDP
at the same time.  This enables advanced use cases where some
of the work is offloaded to the NIC and some is done by the host.
Separate netlink attributes are added for each mode of operation.
Driver callbacks for offload are cleaned up a little, including
removal of .prog_attached flag.
====================

Acked-by: Alexei Starovoitov <[email protected]>
Signed-off-by: Daniel Borkmann <[email protected]>
  • Loading branch information
borkmann committed Jul 13, 2018
2 parents 9c48b1d + 5f42840 commit ee15f7c
Show file tree
Hide file tree
Showing 23 changed files with 246 additions and 146 deletions.
1 change: 0 additions & 1 deletion drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ int bnxt_xdp(struct net_device *dev, struct netdev_bpf *xdp)
rc = bnxt_xdp_set(bp, xdp->prog);
break;
case XDP_QUERY_PROG:
xdp->prog_attached = !!bp->xdp_prog;
xdp->prog_id = bp->xdp_prog ? bp->xdp_prog->aux->id : 0;
rc = 0;
break;
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/cavium/thunder/nicvf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1848,7 +1848,6 @@ static int nicvf_xdp(struct net_device *netdev, struct netdev_bpf *xdp)
case XDP_SETUP_PROG:
return nicvf_xdp_setup(nic, xdp->prog);
case XDP_QUERY_PROG:
xdp->prog_attached = !!nic->xdp_prog;
xdp->prog_id = nic->xdp_prog ? nic->xdp_prog->aux->id : 0;
return 0;
default:
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11841,7 +11841,6 @@ static int i40e_xdp(struct net_device *dev,
case XDP_SETUP_PROG:
return i40e_xdp_setup(vsi, xdp->prog);
case XDP_QUERY_PROG:
xdp->prog_attached = i40e_enabled_xdp_vsi(vsi);
xdp->prog_id = vsi->xdp_prog ? vsi->xdp_prog->aux->id : 0;
return 0;
default:
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -9966,7 +9966,6 @@ static int ixgbe_xdp(struct net_device *dev, struct netdev_bpf *xdp)
case XDP_SETUP_PROG:
return ixgbe_xdp_setup(dev, xdp->prog);
case XDP_QUERY_PROG:
xdp->prog_attached = !!(adapter->xdp_prog);
xdp->prog_id = adapter->xdp_prog ?
adapter->xdp_prog->aux->id : 0;
return 0;
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4462,7 +4462,6 @@ static int ixgbevf_xdp(struct net_device *dev, struct netdev_bpf *xdp)
case XDP_SETUP_PROG:
return ixgbevf_xdp_setup(dev, xdp->prog);
case XDP_QUERY_PROG:
xdp->prog_attached = !!(adapter->xdp_prog);
xdp->prog_id = adapter->xdp_prog ?
adapter->xdp_prog->aux->id : 0;
return 0;
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/mellanox/mlx4/en_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2926,7 +2926,6 @@ static int mlx4_xdp(struct net_device *dev, struct netdev_bpf *xdp)
return mlx4_xdp_set(dev, xdp->prog);
case XDP_QUERY_PROG:
xdp->prog_id = mlx4_xdp_query(dev);
xdp->prog_attached = !!xdp->prog_id;
return 0;
default:
return -EINVAL;
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/en_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4192,7 +4192,6 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
return mlx5e_xdp_set(dev, xdp->prog);
case XDP_QUERY_PROG:
xdp->prog_id = mlx5e_xdp_query(dev);
xdp->prog_attached = !!xdp->prog_id;
return 0;
default:
return -EINVAL;
Expand Down
11 changes: 2 additions & 9 deletions drivers/net/ethernet/netronome/nfp/bpf/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
bool running, xdp_running;
int ret;

if (!nfp_net_ebpf_capable(nn))
return -EINVAL;

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)
return 0;
if (prog && running && !xdp_running)
return -EBUSY;

ret = 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;
return nfp_net_bpf_offload(nn, prog, running, extack);
}

static const char *nfp_bpf_extra_cap(struct nfp_app *app, struct nfp_net *nn)
Expand Down
10 changes: 4 additions & 6 deletions drivers/net/ethernet/netronome/nfp/nfp_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,6 @@ struct nfp_stat_pair {
* @dev: Backpointer to struct device
* @netdev: Backpointer to net_device structure
* @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
* @rx_dma_dir: Mapping direction for RX buffers
* @rx_dma_off: Offset at which DMA packets (for XDP headroom)
Expand All @@ -510,7 +509,6 @@ struct nfp_net_dp {
struct net_device *netdev;

u8 is_vf:1;
u8 bpf_offload_xdp:1;
u8 chained_metadata_format:1;

u8 rx_dma_dir;
Expand Down Expand Up @@ -553,8 +551,8 @@ struct nfp_net_dp {
* @rss_cfg: RSS configuration
* @rss_key: RSS secret key
* @rss_itbl: RSS indirection table
* @xdp_flags: Flags with which XDP prog was loaded
* @xdp_prog: XDP prog (for ctrl path, both DRV and HW modes)
* @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_tx_rings: Maximum number of TX rings supported by the Firmware
* @max_rx_rings: Maximum number of RX rings supported by the Firmware
Expand Down Expand Up @@ -610,8 +608,8 @@ struct nfp_net {
u8 rss_key[NFP_NET_CFG_RSS_KEY_SZ];
u8 rss_itbl[NFP_NET_CFG_RSS_ITBL_SZ];

u32 xdp_flags;
struct bpf_prog *xdp_prog;
struct xdp_attachment_info xdp;
struct xdp_attachment_info xdp_hw;

unsigned int max_tx_rings;
unsigned int max_rx_rings;
Expand Down
58 changes: 23 additions & 35 deletions drivers/net/ethernet/netronome/nfp/nfp_net_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
dp->bpf_offload_xdp) && !meta.portid) {
if (xdp_prog && !meta.portid) {
void *orig_data = rxbuf->frag + pkt_off;
unsigned int dma_off;
int act;
Expand Down Expand Up @@ -3393,14 +3392,18 @@ static void nfp_net_del_vxlan_port(struct net_device *netdev,
nfp_net_set_vxlan_port(nn, idx, 0);
}

static int
nfp_net_xdp_setup_drv(struct nfp_net *nn, struct bpf_prog *prog,
struct netlink_ext_ack *extack)
static int nfp_net_xdp_setup_drv(struct nfp_net *nn, struct netdev_bpf *bpf)
{
struct bpf_prog *prog = bpf->prog;
struct nfp_net_dp *dp;
int err;

if (!xdp_attachment_flags_ok(&nn->xdp, bpf))
return -EBUSY;

if (!prog == !nn->dp.xdp_prog) {
WRITE_ONCE(nn->dp.xdp_prog, prog);
xdp_attachment_setup(&nn->xdp, bpf);
return 0;
}

Expand All @@ -3414,38 +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;

/* 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 bpf_prog *prog, u32 flags,
struct netlink_ext_ack *extack)
static int nfp_net_xdp_setup_hw(struct nfp_net *nn, struct netdev_bpf *bpf)
{
struct bpf_prog *drv_prog, *offload_prog;
int err;

if (nn->xdp_prog && (flags ^ nn->xdp_flags) & XDP_FLAGS_MODES)
if (!xdp_attachment_flags_ok(&nn->xdp_hw, bpf))
return -EBUSY;

/* Load both when no flags set to allow easy activation of driver path
* when program is replaced by one which can't be offloaded.
*/
drv_prog = flags & XDP_FLAGS_HW_MODE ? NULL : prog;
offload_prog = flags & XDP_FLAGS_DRV_MODE ? NULL : prog;

err = nfp_net_xdp_setup_drv(nn, drv_prog, extack);
err = nfp_app_xdp_offload(nn->app, nn, bpf->prog, bpf->extack);
if (err)
return err;

err = nfp_app_xdp_offload(nn->app, nn, offload_prog, extack);
if (err && flags & XDP_FLAGS_HW_MODE)
return err;

if (nn->xdp_prog)
bpf_prog_put(nn->xdp_prog);
nn->xdp_prog = prog;
nn->xdp_flags = flags;

xdp_attachment_setup(&nn->xdp_hw, bpf);
return 0;
}

Expand All @@ -3455,16 +3446,13 @@ static int nfp_net_xdp(struct net_device *netdev, struct netdev_bpf *xdp)

switch (xdp->command) {
case XDP_SETUP_PROG:
return nfp_net_xdp_setup_drv(nn, xdp);
case XDP_SETUP_PROG_HW:
return nfp_net_xdp_setup(nn, xdp->prog, xdp->flags,
xdp->extack);
return nfp_net_xdp_setup_hw(nn, xdp);
case XDP_QUERY_PROG:
xdp->prog_attached = !!nn->xdp_prog;
if (nn->dp.bpf_offload_xdp)
xdp->prog_attached = XDP_ATTACHED_HW;
xdp->prog_id = nn->xdp_prog ? nn->xdp_prog->aux->id : 0;
xdp->prog_flags = nn->xdp_prog ? nn->xdp_flags : 0;
return 0;
return xdp_attachment_query(&nn->xdp, xdp);
case XDP_QUERY_PROG_HW:
return xdp_attachment_query(&nn->xdp_hw, xdp);
default:
return nfp_app_bpf(nn->app, nn, xdp);
}
Expand Down
1 change: 0 additions & 1 deletion drivers/net/ethernet/qlogic/qede/qede_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,6 @@ int qede_xdp(struct net_device *dev, struct netdev_bpf *xdp)
case XDP_SETUP_PROG:
return qede_xdp_set(edev, xdp->prog);
case XDP_QUERY_PROG:
xdp->prog_attached = !!edev->xdp_prog;
xdp->prog_id = edev->xdp_prog ? edev->xdp_prog->aux->id : 0;
return 0;
default:
Expand Down
41 changes: 13 additions & 28 deletions drivers/net/netdevsim/bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static const struct bpf_prog_offload_ops nsim_bpf_analyzer_ops = {

static bool nsim_xdp_offload_active(struct netdevsim *ns)
{
return ns->xdp_prog_mode == XDP_ATTACHED_HW;
return ns->xdp_hw.prog;
}

static void nsim_prog_set_loaded(struct bpf_prog *prog, bool loaded)
Expand Down Expand Up @@ -195,14 +195,14 @@ static int nsim_xdp_offload_prog(struct netdevsim *ns, struct netdev_bpf *bpf)
return nsim_bpf_offload(ns, bpf->prog, nsim_xdp_offload_active(ns));
}

static int nsim_xdp_set_prog(struct netdevsim *ns, struct netdev_bpf *bpf)
static int
nsim_xdp_set_prog(struct netdevsim *ns, struct netdev_bpf *bpf,
struct xdp_attachment_info *xdp)
{
int err;

if (ns->xdp_prog && (bpf->flags ^ ns->xdp_flags) & XDP_FLAGS_MODES) {
NSIM_EA(bpf->extack, "program loaded with different flags");
if (!xdp_attachment_flags_ok(xdp, bpf))
return -EBUSY;
}

if (bpf->command == XDP_SETUP_PROG && !ns->bpf_xdpdrv_accept) {
NSIM_EA(bpf->extack, "driver XDP disabled in DebugFS");
Expand All @@ -219,18 +219,7 @@ static int nsim_xdp_set_prog(struct netdevsim *ns, struct netdev_bpf *bpf)
return err;
}

if (ns->xdp_prog)
bpf_prog_put(ns->xdp_prog);

ns->xdp_prog = bpf->prog;
ns->xdp_flags = bpf->flags;

if (!bpf->prog)
ns->xdp_prog_mode = XDP_ATTACHED_NONE;
else if (bpf->command == XDP_SETUP_PROG)
ns->xdp_prog_mode = XDP_ATTACHED_DRV;
else
ns->xdp_prog_mode = XDP_ATTACHED_HW;
xdp_attachment_setup(xdp, bpf);

return 0;
}
Expand Down Expand Up @@ -290,10 +279,6 @@ static int nsim_setup_prog_checks(struct netdevsim *ns, struct netdev_bpf *bpf)
NSIM_EA(bpf->extack, "MTU too large w/ XDP enabled");
return -EINVAL;
}
if (nsim_xdp_offload_active(ns)) {
NSIM_EA(bpf->extack, "xdp offload active, can't load drv prog");
return -EBUSY;
}
return 0;
}

Expand Down Expand Up @@ -567,22 +552,21 @@ int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf)
nsim_bpf_destroy_prog(bpf->offload.prog);
return 0;
case XDP_QUERY_PROG:
bpf->prog_attached = ns->xdp_prog_mode;
bpf->prog_id = ns->xdp_prog ? ns->xdp_prog->aux->id : 0;
bpf->prog_flags = ns->xdp_prog ? ns->xdp_flags : 0;
return 0;
return xdp_attachment_query(&ns->xdp, bpf);
case XDP_QUERY_PROG_HW:
return xdp_attachment_query(&ns->xdp_hw, bpf);
case XDP_SETUP_PROG:
err = nsim_setup_prog_checks(ns, bpf);
if (err)
return err;

return nsim_xdp_set_prog(ns, bpf);
return nsim_xdp_set_prog(ns, bpf, &ns->xdp);
case XDP_SETUP_PROG_HW:
err = nsim_setup_prog_hw_checks(ns, bpf);
if (err)
return err;

return nsim_xdp_set_prog(ns, bpf);
return nsim_xdp_set_prog(ns, bpf, &ns->xdp_hw);
case BPF_OFFLOAD_MAP_ALLOC:
if (!ns->bpf_map_accept)
return -EOPNOTSUPP;
Expand Down Expand Up @@ -637,6 +621,7 @@ void nsim_bpf_uninit(struct netdevsim *ns)
{
WARN_ON(!list_empty(&ns->bpf_bound_progs));
WARN_ON(!list_empty(&ns->bpf_bound_maps));
WARN_ON(ns->xdp_prog);
WARN_ON(ns->xdp.prog);
WARN_ON(ns->xdp_hw.prog);
WARN_ON(ns->bpf_offloaded);
}
3 changes: 1 addition & 2 deletions drivers/net/netdevsim/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,7 @@ static int nsim_change_mtu(struct net_device *dev, int new_mtu)
{
struct netdevsim *ns = netdev_priv(dev);

if (ns->xdp_prog_mode == XDP_ATTACHED_DRV &&
new_mtu > NSIM_XDP_MAX_MTU)
if (ns->xdp.prog && new_mtu > NSIM_XDP_MAX_MTU)
return -EBUSY;

dev->mtu = new_mtu;
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/netdevsim/netdevsim.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/u64_stats_sync.h>
#include <net/xdp.h>

#define DRV_NAME "netdevsim"

Expand Down Expand Up @@ -67,9 +68,8 @@ struct netdevsim {
struct bpf_prog *bpf_offloaded;
u32 bpf_offloaded_id;

u32 xdp_flags;
int xdp_prog_mode;
struct bpf_prog *xdp_prog;
struct xdp_attachment_info xdp;
struct xdp_attachment_info xdp_hw;

u32 prog_id_gen;

Expand Down
1 change: 0 additions & 1 deletion drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,6 @@ static int tun_xdp(struct net_device *dev, struct netdev_bpf *xdp)
return tun_xdp_set(dev, xdp->prog, xdp->extack);
case XDP_QUERY_PROG:
xdp->prog_id = tun_xdp_query(dev);
xdp->prog_attached = !!xdp->prog_id;
return 0;
default:
return -EINVAL;
Expand Down
1 change: 0 additions & 1 deletion drivers/net/virtio_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -2343,7 +2343,6 @@ static int virtnet_xdp(struct net_device *dev, struct netdev_bpf *xdp)
return virtnet_xdp_set(dev, xdp->prog, xdp->extack);
case XDP_QUERY_PROG:
xdp->prog_id = virtnet_xdp_query(dev);
xdp->prog_attached = !!xdp->prog_id;
return 0;
default:
return -EINVAL;
Expand Down
Loading

0 comments on commit ee15f7c

Please sign in to comment.