From: "Toke Høiland-Jørgensen" <toke@redhat.com>
To: Vladimir Oltean <olteanv@gmail.com>,
Jakub Kicinski <kuba@kernel.org>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Jesper Dangaard Brouer <hawk@kernel.org>,
John Fastabend <john.fastabend@gmail.com>,
Andrii Nakryiko <andrii@kernel.org>,
Martin KaFai Lau <kafai@fb.com>, Song Liu <songliubraving@fb.com>,
Yonghong Song <yhs@fb.com>, KP Singh <kpsingh@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
netdev@vger.kernel.org, bpf@vger.kernel.org
Cc: Alexander Duyck <alexander.duyck@gmail.com>,
Ioana Ciornei <ioana.ciornei@nxp.com>,
Alex Marginean <alexandru.marginean@nxp.com>,
Claudiu Manoil <claudiu.manoil@nxp.com>,
Ilias Apalodimas <ilias.apalodimas@linaro.org>,
Vladimir Oltean <vladimir.oltean@nxp.com>
Subject: Re: [PATCH net-next 9/9] net: enetc: add support for XDP_REDIRECT
Date: Thu, 01 Apr 2021 13:26:02 +0200 [thread overview]
Message-ID: <87blaynt4l.fsf@toke.dk> (raw)
In-Reply-To: <20210331200857.3274425-10-olteanv@gmail.com>
Vladimir Oltean <olteanv@gmail.com> writes:
> From: Vladimir Oltean <vladimir.oltean@nxp.com>
>
> The driver implementation of the XDP_REDIRECT action reuses parts from
> XDP_TX, most notably the enetc_xdp_tx function which transmits an array
> of TX software BDs. Only this time, the buffers don't have DMA mappings,
> we need to create them.
>
> When a BPF program reaches the XDP_REDIRECT verdict for a frame, we can
> employ the same buffer reuse strategy as for the normal processing path
> and for XDP_PASS: we can flip to the other page half and seed that to
> the RX ring.
>
> Note that scatter/gather support is there, but disabled due to lack of
> multi-buffer support in XDP (which is added by this series):
> https://patchwork.kernel.org/project/netdevbpf/cover/cover.1616179034.git.lorenzo@kernel.org/
>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
> drivers/net/ethernet/freescale/enetc/enetc.c | 212 +++++++++++++++++-
> drivers/net/ethernet/freescale/enetc/enetc.h | 11 +-
> .../ethernet/freescale/enetc/enetc_ethtool.c | 6 +
> .../net/ethernet/freescale/enetc/enetc_pf.c | 1 +
> 4 files changed, 218 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
> index ba5313a5d7a4..57049ae97201 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc.c
> @@ -8,6 +8,23 @@
> #include <linux/vmalloc.h>
> #include <net/pkt_sched.h>
>
> +static struct sk_buff *enetc_tx_swbd_get_skb(struct enetc_tx_swbd *tx_swbd)
> +{
> + if (tx_swbd->is_xdp_tx || tx_swbd->is_xdp_redirect)
> + return NULL;
> +
> + return tx_swbd->skb;
> +}
> +
> +static struct xdp_frame *
> +enetc_tx_swbd_get_xdp_frame(struct enetc_tx_swbd *tx_swbd)
> +{
> + if (tx_swbd->is_xdp_redirect)
> + return tx_swbd->xdp_frame;
> +
> + return NULL;
> +}
> +
> static void enetc_unmap_tx_buff(struct enetc_bdr *tx_ring,
> struct enetc_tx_swbd *tx_swbd)
> {
> @@ -25,14 +42,20 @@ static void enetc_unmap_tx_buff(struct enetc_bdr *tx_ring,
> tx_swbd->dma = 0;
> }
>
> -static void enetc_free_tx_skb(struct enetc_bdr *tx_ring,
> - struct enetc_tx_swbd *tx_swbd)
> +static void enetc_free_tx_frame(struct enetc_bdr *tx_ring,
> + struct enetc_tx_swbd *tx_swbd)
> {
> + struct xdp_frame *xdp_frame = enetc_tx_swbd_get_xdp_frame(tx_swbd);
> + struct sk_buff *skb = enetc_tx_swbd_get_skb(tx_swbd);
> +
> if (tx_swbd->dma)
> enetc_unmap_tx_buff(tx_ring, tx_swbd);
>
> - if (tx_swbd->skb) {
> - dev_kfree_skb_any(tx_swbd->skb);
> + if (xdp_frame) {
> + xdp_return_frame(tx_swbd->xdp_frame);
> + tx_swbd->xdp_frame = NULL;
> + } else if (skb) {
> + dev_kfree_skb_any(skb);
> tx_swbd->skb = NULL;
> }
> }
> @@ -183,7 +206,7 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb,
>
> do {
> tx_swbd = &tx_ring->tx_swbd[i];
> - enetc_free_tx_skb(tx_ring, tx_swbd);
> + enetc_free_tx_frame(tx_ring, tx_swbd);
> if (i == 0)
> i = tx_ring->bd_count;
> i--;
> @@ -381,6 +404,9 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
> do_tstamp = false;
>
> while (bds_to_clean && tx_frm_cnt < ENETC_DEFAULT_TX_WORK) {
> + struct xdp_frame *xdp_frame = enetc_tx_swbd_get_xdp_frame(tx_swbd);
> + struct sk_buff *skb = enetc_tx_swbd_get_skb(tx_swbd);
> +
> if (unlikely(tx_swbd->check_wb)) {
> struct enetc_ndev_priv *priv = netdev_priv(ndev);
> union enetc_tx_bd *txbd;
> @@ -400,12 +426,15 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
> else if (likely(tx_swbd->dma))
> enetc_unmap_tx_buff(tx_ring, tx_swbd);
>
> - if (tx_swbd->skb) {
> + if (xdp_frame) {
> + xdp_return_frame(xdp_frame);
> + tx_swbd->xdp_frame = NULL;
> + } else if (skb) {
> if (unlikely(do_tstamp)) {
> - enetc_tstamp_tx(tx_swbd->skb, tstamp);
> + enetc_tstamp_tx(skb, tstamp);
> do_tstamp = false;
> }
> - napi_consume_skb(tx_swbd->skb, napi_budget);
> + napi_consume_skb(skb, napi_budget);
> tx_swbd->skb = NULL;
> }
>
> @@ -827,6 +856,109 @@ static bool enetc_xdp_tx(struct enetc_bdr *tx_ring,
> return true;
> }
>
> +static int enetc_xdp_frame_to_xdp_tx_swbd(struct enetc_bdr *tx_ring,
> + struct enetc_tx_swbd *xdp_tx_arr,
> + struct xdp_frame *xdp_frame)
> +{
> + struct enetc_tx_swbd *xdp_tx_swbd = &xdp_tx_arr[0];
> + struct skb_shared_info *shinfo;
> + void *data = xdp_frame->data;
> + int len = xdp_frame->len;
> + skb_frag_t *frag;
> + dma_addr_t dma;
> + unsigned int f;
> + int n = 0;
> +
> + dma = dma_map_single(tx_ring->dev, data, len, DMA_TO_DEVICE);
> + if (unlikely(dma_mapping_error(tx_ring->dev, dma))) {
> + netdev_err(tx_ring->ndev, "DMA map error\n");
> + return -1;
> + }
> +
> + xdp_tx_swbd->dma = dma;
> + xdp_tx_swbd->dir = DMA_TO_DEVICE;
> + xdp_tx_swbd->len = len;
> + xdp_tx_swbd->is_xdp_redirect = true;
> + xdp_tx_swbd->is_eof = false;
> + xdp_tx_swbd->xdp_frame = NULL;
> +
> + n++;
> + xdp_tx_swbd = &xdp_tx_arr[n];
> +
> + shinfo = xdp_get_shared_info_from_frame(xdp_frame);
> +
> + for (f = 0, frag = &shinfo->frags[0]; f < shinfo->nr_frags;
> + f++, frag++) {
> + data = skb_frag_address(frag);
> + len = skb_frag_size(frag);
> +
> + dma = dma_map_single(tx_ring->dev, data, len, DMA_TO_DEVICE);
> + if (unlikely(dma_mapping_error(tx_ring->dev, dma))) {
> + /* Undo the DMA mapping for all fragments */
> + while (n-- >= 0)
> + enetc_unmap_tx_buff(tx_ring, &xdp_tx_arr[n]);
> +
> + netdev_err(tx_ring->ndev, "DMA map error\n");
> + return -1;
> + }
> +
> + xdp_tx_swbd->dma = dma;
> + xdp_tx_swbd->dir = DMA_TO_DEVICE;
> + xdp_tx_swbd->len = len;
> + xdp_tx_swbd->is_xdp_redirect = true;
> + xdp_tx_swbd->is_eof = false;
> + xdp_tx_swbd->xdp_frame = NULL;
> +
> + n++;
> + xdp_tx_swbd = &xdp_tx_arr[n];
> + }
> +
> + xdp_tx_arr[n - 1].is_eof = true;
> + xdp_tx_arr[n - 1].xdp_frame = xdp_frame;
> +
> + return n;
> +}
> +
> +int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
> + struct xdp_frame **frames, u32 flags)
> +{
> + struct enetc_tx_swbd xdp_redirect_arr[ENETC_MAX_SKB_FRAGS] = {0};
> + struct enetc_ndev_priv *priv = netdev_priv(ndev);
> + struct enetc_bdr *tx_ring;
> + int xdp_tx_bd_cnt, i, k;
> + int xdp_tx_frm_cnt = 0;
> +
> + tx_ring = priv->tx_ring[smp_processor_id()];
What mechanism guarantees that this won't overflow the array? :)
-Toke
next prev parent reply other threads:[~2021-04-01 17:57 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-31 20:08 [PATCH net-next 0/9] XDP for NXP ENETC Vladimir Oltean
2021-03-31 20:08 ` [PATCH net-next 1/9] net: enetc: consume the error RX buffer descriptors in a dedicated function Vladimir Oltean
2021-03-31 20:08 ` [PATCH net-next 2/9] net: enetc: move skb creation into enetc_build_skb Vladimir Oltean
2021-03-31 20:08 ` [PATCH net-next 3/9] net: enetc: add a dedicated is_eof bit in the TX software BD Vladimir Oltean
2021-03-31 20:08 ` [PATCH net-next 4/9] net: enetc: clean the TX software BD on the TX confirmation path Vladimir Oltean
2021-03-31 20:08 ` [PATCH net-next 5/9] net: enetc: move up enetc_reuse_page and enetc_page_reusable Vladimir Oltean
2021-03-31 20:08 ` [PATCH net-next 6/9] net: enetc: add support for XDP_DROP and XDP_PASS Vladimir Oltean
2021-03-31 20:08 ` [PATCH net-next 7/9] net: enetc: add support for XDP_TX Vladimir Oltean
2021-03-31 20:08 ` [PATCH net-next 8/9] net: enetc: increase RX ring default size Vladimir Oltean
2021-03-31 20:08 ` [PATCH net-next 9/9] net: enetc: add support for XDP_REDIRECT Vladimir Oltean
2021-04-01 11:26 ` Toke Høiland-Jørgensen [this message]
2021-04-01 11:31 ` Vladimir Oltean
2021-04-01 11:39 ` Toke Høiland-Jørgensen
2021-04-01 16:09 ` Vladimir Oltean
2021-04-01 18:01 ` Toke Høiland-Jørgensen
2021-04-01 19:38 ` Vladimir Oltean
2021-04-02 10:56 ` Vladimir Oltean
2021-04-03 11:07 ` Toke Høiland-Jørgensen
2021-04-03 12:12 ` Vladimir Oltean
2021-04-06 11:23 ` Toke Høiland-Jørgensen
2021-03-31 22:20 ` [PATCH net-next 0/9] XDP for NXP ENETC patchwork-bot+netdevbpf
2021-03-31 22:55 ` Vladimir Oltean
2021-04-01 11:28 ` Toke Høiland-Jørgensen
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=87blaynt4l.fsf@toke.dk \
--to=toke@redhat.com \
--cc=alexander.duyck@gmail.com \
--cc=alexandru.marginean@nxp.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=claudiu.manoil@nxp.com \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=hawk@kernel.org \
--cc=ilias.apalodimas@linaro.org \
--cc=ioana.ciornei@nxp.com \
--cc=john.fastabend@gmail.com \
--cc=kafai@fb.com \
--cc=kpsingh@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=songliubraving@fb.com \
--cc=vladimir.oltean@nxp.com \
--cc=yhs@fb.com \
/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.