Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 208e0b17 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-sched-add-extack-support-for-cls-offloads'



Jakub Kicinski says:

====================
net: sched: add extack support for cls offloads

I've dropped the tests from the series because test_offloads.py changes
will conflict with bpf-next patches.  I will send four more patches with
tests once bpf-next is merged back, hopefully still making it into 4.16 :)

v4:
 - rebase on top of Alex's changes.

---

Quentin says:

This series tries to improve user experience when eBPF hardware offload
hits error paths at load time. In particular, it introduces netlink
extended ack support in the nfp driver.

To that aim, transmission of the pointer to the extack object is piped
through the `change()` operation of the existing classifiers (patch 1 to
6). Then it is used for TC offload in the nfp driver (patch 8) and in
netdevsim (patch 9, selftest in patch 10). Patch 7 adds a helper to handle
extack messages in the core when TC offload is disabled on the net device.

For completeness extack is propagated for classifiers other than cls_bpf,
but it's up to the drivers to make use of it.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 25a39f7f 52be9a7c
Loading
Loading
Loading
Loading
+25 −10
Original line number Original line Diff line number Diff line
@@ -54,7 +54,7 @@ static bool nfp_net_ebpf_capable(struct nfp_net *nn)


static int
static int
nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
		    struct bpf_prog *prog)
		    struct bpf_prog *prog, struct netlink_ext_ack *extack)
{
{
	bool running, xdp_running;
	bool running, xdp_running;
	int ret;
	int ret;
@@ -70,10 +70,10 @@ nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
	if (prog && running && !xdp_running)
	if (prog && running && !xdp_running)
		return -EBUSY;
		return -EBUSY;


	ret = nfp_net_bpf_offload(nn, prog, running);
	ret = nfp_net_bpf_offload(nn, prog, running, extack);
	/* Stop offload if replace not possible */
	/* Stop offload if replace not possible */
	if (ret && prog)
	if (ret && prog)
		nfp_bpf_xdp_offload(app, nn, NULL);
		nfp_bpf_xdp_offload(app, nn, NULL, extack);


	nn->dp.bpf_offload_xdp = prog && !ret;
	nn->dp.bpf_offload_xdp = prog && !ret;
	return ret;
	return ret;
@@ -125,17 +125,31 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
	struct nfp_bpf_vnic *bv;
	struct nfp_bpf_vnic *bv;
	int err;
	int err;


	if (type != TC_SETUP_CLSBPF ||
	if (type != TC_SETUP_CLSBPF) {
	    !tc_can_offload(nn->dp.netdev) ||
		NL_SET_ERR_MSG_MOD(cls_bpf->common.extack,
	    !nfp_net_ebpf_capable(nn) ||
				   "only offload of BPF classifiers supported");
	    cls_bpf->common.protocol != htons(ETH_P_ALL) ||
		return -EOPNOTSUPP;
	    cls_bpf->common.chain_index)
	}
	if (!tc_can_offload_extack(nn->dp.netdev, cls_bpf->common.extack))
		return -EOPNOTSUPP;
	if (!nfp_net_ebpf_capable(nn)) {
		NL_SET_ERR_MSG_MOD(cls_bpf->common.extack,
				   "NFP firmware does not support eBPF offload");
		return -EOPNOTSUPP;
	}
	if (cls_bpf->common.protocol != htons(ETH_P_ALL)) {
		NL_SET_ERR_MSG_MOD(cls_bpf->common.extack,
				   "only ETH_P_ALL supported as filter protocol");
		return -EOPNOTSUPP;
	}
	if (cls_bpf->common.chain_index)
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;


	/* Only support TC direct action */
	/* Only support TC direct action */
	if (!cls_bpf->exts_integrated ||
	if (!cls_bpf->exts_integrated ||
	    tcf_exts_has_actions(cls_bpf->exts)) {
	    tcf_exts_has_actions(cls_bpf->exts)) {
		nn_err(nn, "only direct action with no legacy actions supported\n");
		NL_SET_ERR_MSG_MOD(cls_bpf->common.extack,
				   "only direct action with no legacy actions supported");
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;
	}
	}


@@ -152,7 +166,8 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
			return 0;
			return 0;
	}
	}


	err = nfp_net_bpf_offload(nn, cls_bpf->prog, oldprog);
	err = nfp_net_bpf_offload(nn, cls_bpf->prog, oldprog,
				  cls_bpf->common.extack);
	if (err)
	if (err)
		return err;
		return err;


+1 −1
Original line number Original line Diff line number Diff line
@@ -335,7 +335,7 @@ struct nfp_net;
int nfp_ndo_bpf(struct nfp_app *app, struct nfp_net *nn,
int nfp_ndo_bpf(struct nfp_app *app, struct nfp_net *nn,
		struct netdev_bpf *bpf);
		struct netdev_bpf *bpf);
int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
			bool old_prog);
			bool old_prog, struct netlink_ext_ack *extack);


struct nfp_insn_meta *
struct nfp_insn_meta *
nfp_bpf_goto_meta(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
nfp_bpf_goto_meta(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
+15 −9
Original line number Original line Diff line number Diff line
@@ -281,7 +281,9 @@ int nfp_ndo_bpf(struct nfp_app *app, struct nfp_net *nn, struct netdev_bpf *bpf)
	}
	}
}
}


static int nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog)
static int
nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog,
		 struct netlink_ext_ack *extack)
{
{
	struct nfp_prog *nfp_prog = prog->aux->offload->dev_priv;
	struct nfp_prog *nfp_prog = prog->aux->offload->dev_priv;
	unsigned int max_mtu;
	unsigned int max_mtu;
@@ -291,7 +293,7 @@ static int nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog)


	max_mtu = nn_readb(nn, NFP_NET_CFG_BPF_INL_MTU) * 64 - 32;
	max_mtu = nn_readb(nn, NFP_NET_CFG_BPF_INL_MTU) * 64 - 32;
	if (max_mtu < nn->dp.netdev->mtu) {
	if (max_mtu < nn->dp.netdev->mtu) {
		nn_info(nn, "BPF offload not supported with MTU larger than HW packet split boundary\n");
		NL_SET_ERR_MSG_MOD(extack, "BPF offload not supported with MTU larger than HW packet split boundary");
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;
	}
	}


@@ -313,7 +315,8 @@ static int nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog)
	/* Load up the JITed code */
	/* Load up the JITed code */
	err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_BPF);
	err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_BPF);
	if (err)
	if (err)
		nn_err(nn, "FW command error while loading BPF: %d\n", err);
		NL_SET_ERR_MSG_MOD(extack,
				   "FW command error while loading BPF");


	dma_unmap_single(nn->dp.dev, dma_addr, nfp_prog->prog_len * sizeof(u64),
	dma_unmap_single(nn->dp.dev, dma_addr, nfp_prog->prog_len * sizeof(u64),
			 DMA_TO_DEVICE);
			 DMA_TO_DEVICE);
@@ -322,7 +325,8 @@ static int nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog)
	return err;
	return err;
}
}


static void nfp_net_bpf_start(struct nfp_net *nn)
static void
nfp_net_bpf_start(struct nfp_net *nn, struct netlink_ext_ack *extack)
{
{
	int err;
	int err;


@@ -331,7 +335,8 @@ static void nfp_net_bpf_start(struct nfp_net *nn)
	nn_writel(nn, NFP_NET_CFG_CTRL, nn->dp.ctrl);
	nn_writel(nn, NFP_NET_CFG_CTRL, nn->dp.ctrl);
	err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_GEN);
	err = nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_GEN);
	if (err)
	if (err)
		nn_err(nn, "FW command error while enabling BPF: %d\n", err);
		NL_SET_ERR_MSG_MOD(extack,
				   "FW command error while enabling BPF");
}
}


static int nfp_net_bpf_stop(struct nfp_net *nn)
static int nfp_net_bpf_stop(struct nfp_net *nn)
@@ -346,7 +351,7 @@ static int nfp_net_bpf_stop(struct nfp_net *nn)
}
}


int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
			bool old_prog)
			bool old_prog, struct netlink_ext_ack *extack)
{
{
	int err;
	int err;


@@ -364,7 +369,8 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,


		cap = nn_readb(nn, NFP_NET_CFG_BPF_CAP);
		cap = nn_readb(nn, NFP_NET_CFG_BPF_CAP);
		if (!(cap & NFP_NET_BPF_CAP_RELO)) {
		if (!(cap & NFP_NET_BPF_CAP_RELO)) {
			nn_err(nn, "FW does not support live reload\n");
			NL_SET_ERR_MSG_MOD(extack,
					   "FW does not support live reload");
			return -EBUSY;
			return -EBUSY;
		}
		}
	}
	}
@@ -376,12 +382,12 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct bpf_prog *prog,
	if (old_prog && !prog)
	if (old_prog && !prog)
		return nfp_net_bpf_stop(nn);
		return nfp_net_bpf_stop(nn);


	err = nfp_net_bpf_load(nn, prog);
	err = nfp_net_bpf_load(nn, prog, extack);
	if (err)
	if (err)
		return err;
		return err;


	if (!old_prog)
	if (!old_prog)
		nfp_net_bpf_start(nn);
		nfp_net_bpf_start(nn, extack);


	return 0;
	return 0;
}
}
+6 −3
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@
struct bpf_prog;
struct bpf_prog;
struct net_device;
struct net_device;
struct netdev_bpf;
struct netdev_bpf;
struct netlink_ext_ack;
struct pci_dev;
struct pci_dev;
struct sk_buff;
struct sk_buff;
struct sk_buff;
struct sk_buff;
@@ -138,7 +139,8 @@ struct nfp_app_type {
	int (*bpf)(struct nfp_app *app, struct nfp_net *nn,
	int (*bpf)(struct nfp_app *app, struct nfp_net *nn,
		   struct netdev_bpf *xdp);
		   struct netdev_bpf *xdp);
	int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn,
	int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn,
			   struct bpf_prog *prog);
			   struct bpf_prog *prog,
			   struct netlink_ext_ack *extack);


	int (*sriov_enable)(struct nfp_app *app, int num_vfs);
	int (*sriov_enable)(struct nfp_app *app, int num_vfs);
	void (*sriov_disable)(struct nfp_app *app);
	void (*sriov_disable)(struct nfp_app *app);
@@ -324,11 +326,12 @@ static inline int nfp_app_bpf(struct nfp_app *app, struct nfp_net *nn,
}
}


static inline int nfp_app_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
static inline int nfp_app_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
				      struct bpf_prog *prog)
				      struct bpf_prog *prog,
				      struct netlink_ext_ack *extack)
{
{
	if (!app || !app->type->xdp_offload)
	if (!app || !app->type->xdp_offload)
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;
	return app->type->xdp_offload(app, nn, prog);
	return app->type->xdp_offload(app, nn, prog, extack);
}
}


static inline bool __nfp_app_ctrl_tx(struct nfp_app *app, struct sk_buff *skb)
static inline bool __nfp_app_ctrl_tx(struct nfp_app *app, struct sk_buff *skb)
+1 −1
Original line number Original line Diff line number Diff line
@@ -3403,7 +3403,7 @@ nfp_net_xdp_setup(struct nfp_net *nn, struct bpf_prog *prog, u32 flags,
	if (err)
	if (err)
		return err;
		return err;


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


Loading