Skip to content

Commit

Permalink
idpf: implement XDP_SETUP_PROG in ndo_bpf for splitq
Browse files Browse the repository at this point in the history
Implement loading the XDP program using ndo_bpf
callback for splitq and XDP_SETUP_PROG parameter.

Add functions for stopping, reconfiguring and restarting
all queues when needed.
Also, implement the XDP hot swap mechanism when the existing
XDP program is replaced by another one (without a necessity
of reconfiguring anything).

Signed-off-by: Michal Kubiak <michal.kubiak@intel.com>
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
  • Loading branch information
michalQb authored and alobakin committed Sep 3, 2024
1 parent 98e4247 commit 79d940b
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 1 deletion.
1 change: 1 addition & 0 deletions drivers/net/ethernet/intel/idpf/idpf_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -2349,4 +2349,5 @@ static const struct net_device_ops idpf_netdev_ops = {
.ndo_get_stats64 = idpf_get_stats64,
.ndo_set_features = idpf_set_features,
.ndo_tx_timeout = idpf_tx_timeout,
.ndo_bpf = idpf_xdp,
};
6 changes: 6 additions & 0 deletions drivers/net/ethernet/intel/idpf/idpf_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,8 @@ static void idpf_vport_queue_grp_rel_all(struct idpf_vport *vport)
*/
void idpf_vport_queues_rel(struct idpf_vport *vport)
{
idpf_copy_xdp_prog_to_qs(vport, NULL);

idpf_tx_desc_rel_all(vport);
idpf_rx_desc_rel_all(vport);

Expand Down Expand Up @@ -1687,6 +1689,7 @@ static int idpf_vport_queue_grp_alloc_all(struct idpf_vport *vport)
*/
int idpf_vport_queues_alloc(struct idpf_vport *vport)
{
struct bpf_prog *prog;
int err;

err = idpf_vport_queue_grp_alloc_all(vport);
Expand All @@ -1709,6 +1712,9 @@ int idpf_vport_queues_alloc(struct idpf_vport *vport)
if (err)
goto err_out;

prog = vport->adapter->vport_config[vport->idx]->user_config.xdp.prog;
idpf_copy_xdp_prog_to_qs(vport, prog);

return 0;

err_out:
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/ethernet/intel/idpf/idpf_txrx.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ struct idpf_txq_stash {
* @desc_ring: virtual descriptor ring address
* @bufq_sets: Pointer to the array of buffer queues in splitq mode
* @napi: NAPI instance corresponding to this queue (splitq)
* @xdp_prog: attached XDP program
* @rx_buf: See struct &libeth_fqe
* @pp: Page pool pointer in singleq mode
* @tail: Tail offset. Used for both queue models single and split.
Expand Down Expand Up @@ -517,13 +518,14 @@ struct idpf_rx_queue {
struct {
struct idpf_bufq_set *bufq_sets;
struct napi_struct *napi;
struct bpf_prog __rcu *xdp_prog;
};
struct {
struct libeth_fqe *rx_buf;
struct page_pool *pp;
void __iomem *tail;
};
};
void __iomem *tail;

DECLARE_BITMAP(flags, __IDPF_Q_FLAGS_NBITS);
u16 idx;
Expand Down
92 changes: 92 additions & 0 deletions drivers/net/ethernet/intel/idpf/xdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <net/libeth/xdp.h>

#include "idpf.h"
#include "idpf_virtchnl.h"
#include "xdp.h"

static int idpf_rxq_for_each(const struct idpf_vport *vport,
Expand Down Expand Up @@ -115,6 +116,33 @@ void idpf_xdp_rxq_info_deinit_all(const struct idpf_vport *vport)
(void *)(size_t)vport->rxq_model);
}

static int idpf_xdp_rxq_assign_prog(struct idpf_rx_queue *rxq, void *arg)
{
struct mutex *lock = &rxq->q_vector->vport->adapter->vport_ctrl_lock;
struct bpf_prog *prog = arg;
struct bpf_prog *old;

if (prog)
bpf_prog_inc(prog);

old = rcu_replace_pointer(rxq->xdp_prog, prog, lockdep_is_held(lock));
if (old)
bpf_prog_put(old);

return 0;
}

/**
* idpf_copy_xdp_prog_to_qs - set pointers to xdp program for each Rx queue
* @vport: vport to setup XDP for
* @xdp_prog: XDP program that should be copied to all Rx queues
*/
void idpf_copy_xdp_prog_to_qs(const struct idpf_vport *vport,
struct bpf_prog *xdp_prog)
{
idpf_rxq_for_each(vport, idpf_xdp_rxq_assign_prog, xdp_prog);
}

int idpf_vport_xdpq_get(const struct idpf_vport *vport)
{
struct libeth_xdpsq_timer **timers __free(kvfree) = NULL;
Expand Down Expand Up @@ -195,3 +223,67 @@ void idpf_vport_xdpq_put(const struct idpf_vport *vport)

libeth_xdpsq_get_end();
}

/**
* idpf_xdp_setup_prog - Add or remove XDP eBPF program
* @vport: vport to setup XDP for
* @xdp: XDP program and extack
*/
static int
idpf_xdp_setup_prog(struct idpf_vport *vport, struct netdev_bpf *xdp)
{
struct bpf_prog *prog = xdp->prog;
struct xdp_attachment_info *info;
bool reconfig;
int ret;

info = &vport->adapter->vport_config[vport->idx]->user_config.xdp;
reconfig = !!info->prog != !!prog;

xdp_attachment_setup(info, xdp);

if (!reconfig) {
idpf_copy_xdp_prog_to_qs(vport, prog);
return 0;
}

ret = idpf_initiate_soft_reset(vport, IDPF_SR_Q_CHANGE);
if (ret) {
NL_SET_ERR_MSG_MOD(xdp->extack,
"Could not reopen the vport after XDP setup");
return ret;
}

return 0;
}

/**
* idpf_xdp - implements XDP handler
* @dev: netdevice
* @xdp: XDP command
*/
int idpf_xdp(struct net_device *dev, struct netdev_bpf *xdp)
{
struct idpf_vport *vport;
int ret;

idpf_vport_ctrl_lock(dev);
vport = idpf_netdev_to_vport(dev);

if (!idpf_is_queue_model_split(vport->txq_model))
goto notsupp;

switch (xdp->command) {
case XDP_SETUP_PROG:
ret = idpf_xdp_setup_prog(vport, xdp);
break;
default:
notsupp:
ret = -EOPNOTSUPP;
break;
}

idpf_vport_ctrl_unlock(dev);

return ret;
}
7 changes: 7 additions & 0 deletions drivers/net/ethernet/intel/idpf/xdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@

#include <linux/types.h>

struct bpf_prog;
struct idpf_vport;
struct net_device;
struct netdev_bpf;

int idpf_xdp_rxq_info_init_all(const struct idpf_vport *vport);
void idpf_xdp_rxq_info_deinit_all(const struct idpf_vport *vport);
void idpf_copy_xdp_prog_to_qs(const struct idpf_vport *vport,
struct bpf_prog *xdp_prog);

int idpf_vport_xdpq_get(const struct idpf_vport *vport);
void idpf_vport_xdpq_put(const struct idpf_vport *vport);

int idpf_xdp(struct net_device *dev, struct netdev_bpf *xdp);

#endif /* _IDPF_XDP_H_ */

0 comments on commit 79d940b

Please sign in to comment.