ENA driver XDP bug fixes
Subsystems (3)
[email protected]
maintainerv2 cover ENA driver XDP bug fixes
From: David Arinzon <[email protected]>
This patchset contains multiple XDP-related bug fixes in the ENA driver.
Changes in v2:
- Added missing Signed-off-by as well as relevant Cc.
David Arinzon (4):
net: ena: Destroy correct number of xdp queues upon failure
net: ena: Fix xdp drops handling due to multibuf packets
net: ena: Fix DMA syncing in XDP path when SWIOTLB is on
net: ena: Fix XDP redirection error
drivers/net/ethernet/amazon/ena/ena_eth_com.c | 3 -- drivers/net/ethernet/amazon/ena/ena_netdev.c | 53 +++++++++---------- 2 files changed, 26 insertions(+), 30 deletions(-)
Signature · 1 line
2.40.1
[email protected]
maintainerPATCH v2 1/4 net: ena: Destroy correct number of xdp queues upon failure
From: David Arinzon <[email protected]>
The ena_setup_and_create_all_xdp_queues() function freed all the resources upon failure, after creating only xdp_num_queues queues, instead of freeing just the created ones.
In this patch, the only resources that are freed, are the ones allocated right before the failure occurs.
--- drivers/net/ethernet/amazon/ena/ena_netdev.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/net/ethernet/amazon/ena/ena_netdev.c +7 -6
@@ -74,6 +74,8 @@ static void ena_unmap_tx_buff(struct ena_ring *tx_ring, struct ena_tx_buffer *tx_info);static int ena_create_io_tx_queues_in_range (struct ena_adapter *adapter,int first_index,int count); +static void ena_free_all_io_tx_resources_in_range (struct ena_adapter *adapter, +int first_index,int count);/* Increase a stat by cnt while holding syncp seqlock on 32bit machines */ static void ena_increase_stat(u64 *statp, u64 cnt,
@@ -457,23 +459,22 @@ static void ena_init_all_xdp_queues(struct ena_adapter *adapter)static int ena_setup_and_create_all_xdp_queues (struct ena_adapter *adapter) { +u32 xdp_first_ring = adapter->xdp_first_ring; +u32 xdp_num_queues = adapter->xdp_num_queues;int rc =0 ; - rc =ena_setup_tx_resources_in_range (adapter, adapter->xdp_first_ring, - adapter->xdp_num_queues); + rc =ena_setup_tx_resources_in_range (adapter, xdp_first_ring, xdp_num_queues);if (rc) goto setup_err; - rc =ena_create_io_tx_queues_in_range (adapter, - adapter->xdp_first_ring, - adapter->xdp_num_queues); + rc =ena_create_io_tx_queues_in_range (adapter, xdp_first_ring, xdp_num_queues);if (rc) goto create_err;return 0 ; create_err: -ena_free_all_io_tx_resources (adapter); +ena_free_all_io_tx_resources_in_range (adapter, xdp_first_ring, xdp_num_queues); setup_err:return rc; }
Signature · 1 line
2.40.1
[email protected]
maintainerPATCH v2 2/4 net: ena: Fix xdp drops handling due to multibuf packets
In reply to [email protected]From: David Arinzon <[email protected]>
Current xdp code drops packets larger than ENA_XDP_MAX_MTU. This is an incorrect condition since the problem is not the size of the packet, rather the number of buffers it contains.
This commit:
1. Identifies and drops XDP multi-buffer packets at the beginning of the function.
2. Increases the xdp drop statistic when this drop occurs.
3. Adds a one-time print that such drops are happening to give better indication to the user.
--- drivers/net/ethernet/amazon/ena/ena_netdev.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
drivers/net/ethernet/amazon/ena/ena_netdev.c +10 -7
@@ -1672,20 +1672,23 @@ static void ena_set_rx_hash(struct ena_ring *rx_ring, } } -static int ena_xdp_handle_buff (struct ena_ring *rx_ring,struct xdp_buff *xdp) +static int ena_xdp_handle_buff (struct ena_ring *rx_ring,struct xdp_buff *xdp,u16 num_descs) {struct ena_rx_buffer *rx_info;int ret; +/* XDP multi-buffer packets not supported */ +if (unlikely (num_descs >1 )) { +netdev_err_once (rx_ring->adapter->netdev, +"xdp: dropped unsupported multi-buffer packets\n" ); +ena_increase_stat (&rx_ring->rx_stats.xdp_drop,1 , &rx_ring->syncp); +return ENA_XDP_DROP ; + } + rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0 ].req_id];xdp_prepare_buff (xdp,page_address (rx_info->page), rx_info->buf_offset, rx_ring->ena_bufs[0 ].len, false); -/* If for some reason we received a bigger packet than -* we expect, then we simply drop it -*/ -if (unlikely (rx_ring->ena_bufs[0 ].len >ENA_XDP_MAX_MTU )) -return ENA_XDP_DROP ; ret =ena_xdp_execute (rx_ring, xdp);
@@ -1754,7 +1757,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, ena_rx_ctx.l4_proto, ena_rx_ctx.hash);if (ena_xdp_present_ring (rx_ring)) - xdp_verdict =ena_xdp_handle_buff (rx_ring, &xdp); + xdp_verdict =ena_xdp_handle_buff (rx_ring, &xdp, ena_rx_ctx.descs);/* allocate skb and fill it */ if (xdp_verdict ==ENA_XDP_PASS )
Signature · 1 line
2.40.1
[email protected]
maintainerPATCH v2 3/4 net: ena: Fix DMA syncing in XDP path when SWIOTLB is on
In reply to [email protected]From: David Arinzon <[email protected]>
This patch fixes two issues:
Issue 1
-------
Description
``````````` Current code does not call dma_sync_single_for_cpu() to sync data from the device side memory to the CPU side memory before the XDP code path uses the CPU side data. This causes the XDP code path to read the unset garbage data in the CPU side memory, resulting in incorrect handling of the packet by XDP. Solution ````````
1. Add a call to dma_sync_single_for_cpu() before the XDP code starts to use the data in the CPU side memory.
2. The XDP code verdict can be XDP_PASS, in which case there is a fallback to the non-XDP code, which also calls dma_sync_single_for_cpu().
To avoid calling dma_sync_single_for_cpu() twice:
2.1. Put the dma_sync_single_for_cpu() in the code in such a place where
it happens before XDP and non-XDP code.
2.2. Remove the calls to dma_sync_single_for_cpu() in the non-XDP code
for the first buffer only (rx_copybreak and non-rx_copybreak cases), since the new call that was added covers these cases. The call to dma_sync_single_for_cpu() for the second buffer and on stays because only the first buffer is handled by the newly added dma_sync_single_for_cpu(). And there is no need for special handling of the second buffer and on for the XDP path since currently the driver supports only single buffer packets.
Issue 2
-------
Description
```````````
In case the XDP code forwarded the packet (ENA_XDP_FORWARDED),
ena_unmap_rx_buff_attrs() is called with attrs set to 0.
This means that before unmapping the buffer, the internal function
dma_unmap_page_attrs() will also call dma_sync_single_for_cpu() on
the whole buffer (not only on the data part of it).
This sync is both wasteful (since a sync was already explicitly
called before) and also causes a bug, which will be explained
using the below diagram.
The following diagram shows the flow of events causing the bug.
The order of events is (1)-(4) as shown in the diagram.
CPU side memory area
(3)convert_to_xdp_frame() initializes the
headroom with xdpf metadata
||
\/
___________________________________
| |
0 | V 4K
---------------------------------------------------------------------
| xdpf->data | other xdpf | < data > | tailroom ||...|
| | fields | | GARBAGE || |
---------------------------------------------------------------------
/\ /\
|| ||
(4)ena_unmap_rx_buff_attrs() calls (2)dma_sync_single_for_cpu()
dma_sync_single_for_cpu() on the copies data from device
whole buffer page, overwriting side to CPU side memory
the xdpf->data with GARBAGE. ||
0 4K
---------------------------------------------------------------------
| headroom | < data > | tailroom ||...|
| GARBAGE | | GARBAGE || |
---------------------------------------------------------------------
Device side memory area /\
||
(1) device writes RX packet data
After the call to ena_unmap_rx_buff_attrs() in (4), the xdpf->data
becomes corrupted, and so when it is later accessed in
ena_clean_xdp_irq()->xdp_return_frame(), it causes a page fault,
crashing the kernel.
Solution
````````Explicitly tell ena_unmap_rx_buff_attrs() not to call dma_sync_single_for_cpu() by passing it the ENA_DMA_ATTR_SKIP_CPU_SYNC flag.
--- drivers/net/ethernet/amazon/ena/ena_netdev.c | 23 ++++++++------------ 1 file changed, 9 insertions(+), 14 deletions(-)
drivers/net/ethernet/amazon/ena/ena_netdev.c +9 -14
@@ -1493,11 +1493,6 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring,if (unlikely (!skb))return NULL ; -/* sync this buffer for CPU use */ -dma_sync_single_for_cpu (rx_ring->dev, -dma_unmap_addr (&rx_info->ena_buf, paddr) + pkt_offset, - len, -DMA_FROM_DEVICE );skb_copy_to_linear_data (skb, buf_addr + buf_offset, len); dma_sync_single_for_device(rx_ring->dev, dma_unmap_addr(&rx_info->ena_buf, paddr) + pkt_offset,
@@ -1516,17 +1511,10 @@ static struct sk_buff *ena_rx_skb(struct ena_ring *rx_ring, buf_len =SKB_DATA_ALIGN (len + buf_offset + tailroom); - pre_reuse_paddr =dma_unmap_addr (&rx_info->ena_buf, paddr); -/* If XDP isn't loaded try to reuse part of the RX buffer */ reuse_rx_buf_page = !is_xdp_loaded &&ena_try_rx_buf_page_reuse (rx_info, buf_len, len, pkt_offset); -dma_sync_single_for_cpu (rx_ring->dev, - pre_reuse_paddr + pkt_offset, - len, -DMA_FROM_DEVICE ); -if (!reuse_rx_buf_page)ena_unmap_rx_buff_attrs (rx_ring, rx_info,DMA_ATTR_SKIP_CPU_SYNC );
@@ -1723,6 +1711,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,int xdp_flags =0 ;int total_len =0 ;int xdp_verdict; +u8 pkt_offset;int rc =0 ;int i;
@@ -1749,13 +1738,19 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,/* First descriptor might have an offset set by the device */ rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0 ].req_id]; - rx_info->buf_offset += ena_rx_ctx.pkt_offset; + pkt_offset = ena_rx_ctx.pkt_offset; + rx_info->buf_offset += pkt_offset;netif_dbg (rx_ring->adapter, rx_status, rx_ring->netdev,"rx_poll: q %d got packet from ena. descs #: %d l3 proto %d l4 proto %d hash: %x\n" , rx_ring->qid, ena_rx_ctx.descs, ena_rx_ctx.l3_proto, ena_rx_ctx.l4_proto, ena_rx_ctx.hash); +dma_sync_single_for_cpu (rx_ring->dev, +dma_unmap_addr (&rx_info->ena_buf, paddr) + pkt_offset, + rx_ring->ena_bufs[0 ].len, +DMA_FROM_DEVICE ); +if (ena_xdp_present_ring (rx_ring)) xdp_verdict =ena_xdp_handle_buff (rx_ring, &xdp, ena_rx_ctx.descs);
@@ -1781,7 +1776,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi,if (xdp_verdict &ENA_XDP_FORWARDED ) {ena_unmap_rx_buff_attrs (rx_ring, &rx_ring->rx_buffer_info[req_id], -0 ); +DMA_ATTR_SKIP_CPU_SYNC ); rx_ring->rx_buffer_info[req_id].page =NULL ; } }
Signature · 1 line
2.40.1
[email protected]
maintainerPATCH v2 4/4 net: ena: Fix XDP redirection error
In reply to [email protected]From: David Arinzon <[email protected]>
When sending TX packets, the meta descriptor can be all zeroes as no meta information is required (as in XDP).
This patch removes the validity check, as when disable_meta_caching is enabled, such TX packets will be dropped otherwise.
--- drivers/net/ethernet/amazon/ena/ena_eth_com.c | 3 --- 1 file changed, 3 deletions(-)
drivers/net/ethernet/amazon/ena/ena_eth_com.c +0 -3
@@ -328,9 +328,6 @@ static int ena_com_create_and_store_tx_meta_desc(struct ena_com_io_sq *io_sq,* compare it to the stored version, just create the meta */ if (io_sq->disable_meta_caching) { -if (unlikely (!ena_tx_ctx->meta_valid)) -return -EINVAL ; - *have_meta = true;return ena_com_create_meta (io_sq, ena_meta); }
Signature · 1 line
2.40.1
This series was applied to netdev/net.git (main) by Jakub Kicinski <[email protected]>:
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <[email protected]>:
Quoted 9 lines · On Mon, 11 Dec 2023 06:27:57 +0000 you wrote:
From: David Arinzon <[email protected]>
This patchset contains multiple XDP-related bug fixes in the ENA driver.
Changes in v2:
- Added missing Signed-off-by as well as relevant Cc.[...]
Here is the summary with links:
- [v2,net,1/4] net: ena: Destroy correct number of xdp queues upon failure
https://git.kernel.org/netdev/net/c/41db6f99b548 - [v2,net,2/4] net: ena: Fix xdp drops handling due to multibuf packets https://git.kernel.org/netdev/net/c/505b1a88d311 - [v2,net,3/4] net: ena: Fix DMA syncing in XDP path when SWIOTLB is on https://git.kernel.org/netdev/net/c/d760117060cf - [v2,net,4/4] net: ena: Fix XDP redirection error https://git.kernel.org/netdev/net/c/4ab138ca0a34
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html