All of lore.kernel.org
 help / color / mirror / Atom feed
From: brouer@redhat.com (Jesper Dangaard Brouer)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH net-next] net: thunderx: Add support for xdp redirect
Date: Mon, 11 Dec 2017 13:09:02 +0100	[thread overview]
Message-ID: <20171211130902.482513d3@redhat.com> (raw)
In-Reply-To: <20171124120328.7600-1-aleksey.makarov@cavium.com>

On Fri, 24 Nov 2017 15:03:26 +0300
Aleksey Makarov <aleksey.makarov@cavium.com> wrote:

> From: Sunil Goutham <sgoutham@cavium.com>
> 
> This patch adds support for XDP_REDIRECT. Flush is not
> yet supported.
> 
> Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
> Signed-off-by: cjacob <cjacob@caviumnetworks.com>
> Signed-off-by: Aleksey Makarov <aleksey.makarov@cavium.com>
> ---
>  drivers/net/ethernet/cavium/thunder/nicvf_main.c   | 110 ++++++++++++++++-----
>  drivers/net/ethernet/cavium/thunder/nicvf_queues.c |  11 ++-
>  drivers/net/ethernet/cavium/thunder/nicvf_queues.h |   4 +
>  3 files changed, 94 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
> index a063c36c4c58..b82e28262c57 100644
> --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
> +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
> @@ -65,6 +65,11 @@ module_param(cpi_alg, int, S_IRUGO);
>  MODULE_PARM_DESC(cpi_alg,
>  		 "PFC algorithm (0=none, 1=VLAN, 2=VLAN16, 3=IP Diffserv)");
>  
> +struct nicvf_xdp_tx {
> +	u64 dma_addr;
> +	u8  qidx;
> +};
> +
[...]

>  static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
>  				struct cqe_rx_t *cqe_rx, struct snd_queue *sq,
>  				struct sk_buff **skb)
>  {
>  	struct xdp_buff xdp;
>  	struct page *page;
> +	struct nicvf_xdp_tx *xdp_tx = NULL;
>  	u32 action;
> -	u16 len, offset = 0;
> +	u16 len, err, offset = 0;
>  	u64 dma_addr, cpu_addr;
>  	void *orig_data;
>  
> @@ -521,7 +541,7 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
>  	cpu_addr = (u64)phys_to_virt(cpu_addr);
>  	page = virt_to_page((void *)cpu_addr);
>  
> -	xdp.data_hard_start = page_address(page);
> +	xdp.data_hard_start = page_address(page) + RCV_BUF_HEADROOM;
>  	xdp.data = (void *)cpu_addr;
>  	xdp_set_data_meta_invalid(&xdp);
>  	xdp.data_end = xdp.data + len;
[...]
> @@ -564,6 +573,20 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
>  	case XDP_TX:
>  		nicvf_xdp_sq_append_pkt(nic, sq, (u64)xdp.data, dma_addr, len);
>  		return true;
> +	case XDP_REDIRECT:
> +		/* Save DMA address for use while transmitting */
> +		xdp_tx = (struct nicvf_xdp_tx *)page_address(page);
> +		xdp_tx->dma_addr = dma_addr;
> +		xdp_tx->qidx = nicvf_netdev_qidx(nic, cqe_rx->rq_idx);

Hey, this sucks... You cannot just invent your own in-driver usage of
the XDP packet headroom.  That is specific to your driver only.  In
effect you can only XDP_REDIRECT from your driver out your own driver.

The XDP_TX action is for driver/port local redirect.  The XDP_REDIRECT
action is between drivers.

> +
> +		err = xdp_do_redirect(nic->pnicvf->netdev, &xdp, prog);
> +		if (!err)
> +			return true;
> +
> +		/* Free the page on error */
> +		nicvf_unmap_page(nic, page, dma_addr);
> +		put_page(page);
> +		break;
>  	default:
>  		bpf_warn_invalid_xdp_action(action);
>  		/* fall through */
[...]
> @@ -1764,6 +1776,50 @@ static int nicvf_xdp(struct net_device *netdev, struct netdev_bpf *xdp)
>  	}
>  }
>  
> +static int nicvf_xdp_xmit(struct net_device *netdev, struct xdp_buff *xdp)

This is a generic ndo_xdp_xmit that other drivers can call.

> +{
> +	struct nicvf *nic = netdev_priv(netdev);
> +	struct nicvf *snic = nic;
> +	struct nicvf_xdp_tx *xdp_tx;
> +	struct snd_queue *sq;
> +	struct page *page;
> +	int err, qidx;
> +
> +	if (!netif_running(netdev) || !nic->xdp_prog)
> +		return -EINVAL;
> +
> +	page = virt_to_page(xdp->data);
> +	xdp_tx = (struct nicvf_xdp_tx *)page_address(page);
> +	qidx = xdp_tx->qidx;

What is another driver XDP_REDIRECT a frame to your driver?

> +
> +	if (xdp_tx->qidx >= nic->xdp_tx_queues)
> +		return -EINVAL;
> +
> +	/* Get secondary Qset's info */
> +	if (xdp_tx->qidx >= MAX_SND_QUEUES_PER_QS) {
> +		qidx = xdp_tx->qidx / MAX_SND_QUEUES_PER_QS;
> +		snic = (struct nicvf *)nic->snicvf[qidx - 1];
> +		if (!snic)
> +			return -EINVAL;
> +		qidx = xdp_tx->qidx % MAX_SND_QUEUES_PER_QS;
> +	}
> +
> +	sq = &snic->qs->sq[qidx];
> +	err = nicvf_xdp_sq_append_pkt(snic, sq, (u64)xdp->data,
> +				      xdp_tx->dma_addr,
> +				      xdp->data_end - xdp->data);
> +	if (err)
> +		return -ENOMEM;
> +
> +	nicvf_xdp_sq_doorbell(snic, sq, qidx);
> +	return 0;
> +}
> +
> +static void nicvf_xdp_flush(struct net_device *dev)
> +{
> +	return;
> +}
> +
>  static const struct net_device_ops nicvf_netdev_ops = {
>  	.ndo_open		= nicvf_open,
>  	.ndo_stop		= nicvf_stop,
> @@ -1775,6 +1831,8 @@ static const struct net_device_ops nicvf_netdev_ops = {
>  	.ndo_fix_features       = nicvf_fix_features,
>  	.ndo_set_features       = nicvf_set_features,
>  	.ndo_bpf		= nicvf_xdp,
> +	.ndo_xdp_xmit		= nicvf_xdp_xmit,
> +	.ndo_xdp_flush          = nicvf_xdp_flush,
>  };
[...]


> diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
> index 67d1a3230773..178ab6e8e3c5 100644
> --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
> +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
> @@ -11,6 +11,7 @@
>  
>  #include <linux/netdevice.h>
>  #include <linux/iommu.h>
> +#include <linux/bpf.h>
>  #include "q_struct.h"
>  
>  #define MAX_QUEUE_SET			128
> @@ -92,6 +93,9 @@
>  #define RCV_FRAG_LEN	 (SKB_DATA_ALIGN(DMA_BUFFER_LEN + NET_SKB_PAD) + \
>  			 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
>  
> +#define RCV_BUF_HEADROOM	128 /* To store dma address for XDP redirect */
> +#define XDP_HEADROOM		(XDP_PACKET_HEADROOM + RCV_BUF_HEADROOM)
> +
>  #define MAX_CQES_FOR_TX		((SND_QUEUE_LEN / MIN_SQ_DESC_PER_PKT_XMIT) * \
>  				 MAX_CQE_PER_PKT_XMIT)
>  



-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  LinkedIn: http://www.linkedin.com/in/brouer

WARNING: multiple messages have this Message-ID (diff)
From: Jesper Dangaard Brouer <brouer@redhat.com>
To: Aleksey Makarov <aleksey.makarov@cavium.com>
Cc: brouer@redhat.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, "Goutham,
	Sunil" <Sunil.Goutham@cavium.com>,
	Robert Richter <rric@kernel.org>,
	cjacob <cjacob@caviumnetworks.com>,
	Sunil Goutham <sgoutham@cavium.com>,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH net-next] net: thunderx: Add support for xdp redirect
Date: Mon, 11 Dec 2017 13:09:02 +0100	[thread overview]
Message-ID: <20171211130902.482513d3@redhat.com> (raw)
In-Reply-To: <20171124120328.7600-1-aleksey.makarov@cavium.com>

On Fri, 24 Nov 2017 15:03:26 +0300
Aleksey Makarov <aleksey.makarov@cavium.com> wrote:

> From: Sunil Goutham <sgoutham@cavium.com>
> 
> This patch adds support for XDP_REDIRECT. Flush is not
> yet supported.
> 
> Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
> Signed-off-by: cjacob <cjacob@caviumnetworks.com>
> Signed-off-by: Aleksey Makarov <aleksey.makarov@cavium.com>
> ---
>  drivers/net/ethernet/cavium/thunder/nicvf_main.c   | 110 ++++++++++++++++-----
>  drivers/net/ethernet/cavium/thunder/nicvf_queues.c |  11 ++-
>  drivers/net/ethernet/cavium/thunder/nicvf_queues.h |   4 +
>  3 files changed, 94 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
> index a063c36c4c58..b82e28262c57 100644
> --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
> +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
> @@ -65,6 +65,11 @@ module_param(cpi_alg, int, S_IRUGO);
>  MODULE_PARM_DESC(cpi_alg,
>  		 "PFC algorithm (0=none, 1=VLAN, 2=VLAN16, 3=IP Diffserv)");
>  
> +struct nicvf_xdp_tx {
> +	u64 dma_addr;
> +	u8  qidx;
> +};
> +
[...]

>  static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
>  				struct cqe_rx_t *cqe_rx, struct snd_queue *sq,
>  				struct sk_buff **skb)
>  {
>  	struct xdp_buff xdp;
>  	struct page *page;
> +	struct nicvf_xdp_tx *xdp_tx = NULL;
>  	u32 action;
> -	u16 len, offset = 0;
> +	u16 len, err, offset = 0;
>  	u64 dma_addr, cpu_addr;
>  	void *orig_data;
>  
> @@ -521,7 +541,7 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
>  	cpu_addr = (u64)phys_to_virt(cpu_addr);
>  	page = virt_to_page((void *)cpu_addr);
>  
> -	xdp.data_hard_start = page_address(page);
> +	xdp.data_hard_start = page_address(page) + RCV_BUF_HEADROOM;
>  	xdp.data = (void *)cpu_addr;
>  	xdp_set_data_meta_invalid(&xdp);
>  	xdp.data_end = xdp.data + len;
[...]
> @@ -564,6 +573,20 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog,
>  	case XDP_TX:
>  		nicvf_xdp_sq_append_pkt(nic, sq, (u64)xdp.data, dma_addr, len);
>  		return true;
> +	case XDP_REDIRECT:
> +		/* Save DMA address for use while transmitting */
> +		xdp_tx = (struct nicvf_xdp_tx *)page_address(page);
> +		xdp_tx->dma_addr = dma_addr;
> +		xdp_tx->qidx = nicvf_netdev_qidx(nic, cqe_rx->rq_idx);

Hey, this sucks... You cannot just invent your own in-driver usage of
the XDP packet headroom.  That is specific to your driver only.  In
effect you can only XDP_REDIRECT from your driver out your own driver.

The XDP_TX action is for driver/port local redirect.  The XDP_REDIRECT
action is between drivers.

> +
> +		err = xdp_do_redirect(nic->pnicvf->netdev, &xdp, prog);
> +		if (!err)
> +			return true;
> +
> +		/* Free the page on error */
> +		nicvf_unmap_page(nic, page, dma_addr);
> +		put_page(page);
> +		break;
>  	default:
>  		bpf_warn_invalid_xdp_action(action);
>  		/* fall through */
[...]
> @@ -1764,6 +1776,50 @@ static int nicvf_xdp(struct net_device *netdev, struct netdev_bpf *xdp)
>  	}
>  }
>  
> +static int nicvf_xdp_xmit(struct net_device *netdev, struct xdp_buff *xdp)

This is a generic ndo_xdp_xmit that other drivers can call.

> +{
> +	struct nicvf *nic = netdev_priv(netdev);
> +	struct nicvf *snic = nic;
> +	struct nicvf_xdp_tx *xdp_tx;
> +	struct snd_queue *sq;
> +	struct page *page;
> +	int err, qidx;
> +
> +	if (!netif_running(netdev) || !nic->xdp_prog)
> +		return -EINVAL;
> +
> +	page = virt_to_page(xdp->data);
> +	xdp_tx = (struct nicvf_xdp_tx *)page_address(page);
> +	qidx = xdp_tx->qidx;

What is another driver XDP_REDIRECT a frame to your driver?

> +
> +	if (xdp_tx->qidx >= nic->xdp_tx_queues)
> +		return -EINVAL;
> +
> +	/* Get secondary Qset's info */
> +	if (xdp_tx->qidx >= MAX_SND_QUEUES_PER_QS) {
> +		qidx = xdp_tx->qidx / MAX_SND_QUEUES_PER_QS;
> +		snic = (struct nicvf *)nic->snicvf[qidx - 1];
> +		if (!snic)
> +			return -EINVAL;
> +		qidx = xdp_tx->qidx % MAX_SND_QUEUES_PER_QS;
> +	}
> +
> +	sq = &snic->qs->sq[qidx];
> +	err = nicvf_xdp_sq_append_pkt(snic, sq, (u64)xdp->data,
> +				      xdp_tx->dma_addr,
> +				      xdp->data_end - xdp->data);
> +	if (err)
> +		return -ENOMEM;
> +
> +	nicvf_xdp_sq_doorbell(snic, sq, qidx);
> +	return 0;
> +}
> +
> +static void nicvf_xdp_flush(struct net_device *dev)
> +{
> +	return;
> +}
> +
>  static const struct net_device_ops nicvf_netdev_ops = {
>  	.ndo_open		= nicvf_open,
>  	.ndo_stop		= nicvf_stop,
> @@ -1775,6 +1831,8 @@ static const struct net_device_ops nicvf_netdev_ops = {
>  	.ndo_fix_features       = nicvf_fix_features,
>  	.ndo_set_features       = nicvf_set_features,
>  	.ndo_bpf		= nicvf_xdp,
> +	.ndo_xdp_xmit		= nicvf_xdp_xmit,
> +	.ndo_xdp_flush          = nicvf_xdp_flush,
>  };
[...]


> diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
> index 67d1a3230773..178ab6e8e3c5 100644
> --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
> +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
> @@ -11,6 +11,7 @@
>  
>  #include <linux/netdevice.h>
>  #include <linux/iommu.h>
> +#include <linux/bpf.h>
>  #include "q_struct.h"
>  
>  #define MAX_QUEUE_SET			128
> @@ -92,6 +93,9 @@
>  #define RCV_FRAG_LEN	 (SKB_DATA_ALIGN(DMA_BUFFER_LEN + NET_SKB_PAD) + \
>  			 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
>  
> +#define RCV_BUF_HEADROOM	128 /* To store dma address for XDP redirect */
> +#define XDP_HEADROOM		(XDP_PACKET_HEADROOM + RCV_BUF_HEADROOM)
> +
>  #define MAX_CQES_FOR_TX		((SND_QUEUE_LEN / MIN_SQ_DESC_PER_PKT_XMIT) * \
>  				 MAX_CQE_PER_PKT_XMIT)
>  



-- 
Best regards,
  Jesper Dangaard Brouer
  MSc.CS, Principal Kernel Engineer at Red Hat
  LinkedIn: http://www.linkedin.com/in/brouer

  parent reply	other threads:[~2017-12-11 12:09 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-24 12:03 [PATCH net-next] net: thunderx: Add support for xdp redirect Aleksey Makarov
2017-11-24 12:03 ` Aleksey Makarov
2017-11-30 14:24 ` David Miller
2017-11-30 14:24   ` David Miller
2017-12-11 12:09 ` Jesper Dangaard Brouer [this message]
2017-12-11 12:09   ` Jesper Dangaard Brouer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171211130902.482513d3@redhat.com \
    --to=brouer@redhat.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.