[PATCH net 1/3] net: ethernet: ti: am65-cpsw: fix memleak in certain XDP cases

Roger Quadros posted 3 patches 10 months, 1 week ago
[PATCH net 1/3] net: ethernet: ti: am65-cpsw: fix memleak in certain XDP cases
Posted by Roger Quadros 10 months, 1 week ago
If the XDP program doesn't result in XDP_PASS then we leak the
memory allocated by am65_cpsw_build_skb().

It is pointless to allocate SKB memory before running the XDP
program as we would be wasting CPU cycles for cases other than XDP_PASS.
Move the SKB allocation after evaluating the XDP program result.

This fixes the memleak. A performance boost is seen for XDP_DROP test.

XDP_DROP test:
Before: 460256 rx/s                  0 err/s
After:  784130 rx/s                  0 err/s

Fixes: 8acacc40f733 ("net: ethernet: ti: am65-cpsw: Add minimal XDP support")
Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 drivers/net/ethernet/ti/am65-cpsw-nuss.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index b663271e79f7..e26c6dc02648 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -842,7 +842,8 @@ static void am65_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma)
 
 static struct sk_buff *am65_cpsw_build_skb(void *page_addr,
 					   struct net_device *ndev,
-					   unsigned int len)
+					   unsigned int len,
+					   unsigned int headroom)
 {
 	struct sk_buff *skb;
 
@@ -852,7 +853,7 @@ static struct sk_buff *am65_cpsw_build_skb(void *page_addr,
 	if (unlikely(!skb))
 		return NULL;
 
-	skb_reserve(skb, AM65_CPSW_HEADROOM);
+	skb_reserve(skb, headroom);
 	skb->dev = ndev;
 
 	return skb;
@@ -1277,7 +1278,7 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
 	u32 flow_idx = flow->id;
 	struct sk_buff *skb;
 	struct xdp_buff	xdp;
-	int headroom, ret;
+	int headroom = AM65_CPSW_HEADROOM, ret;
 	void *page_addr;
 	u32 *psdata;
 
@@ -1315,16 +1316,8 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
 	dev_dbg(dev, "%s rx csum_info:%#x\n", __func__, csum_info);
 
 	dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
-
 	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
 
-	skb = am65_cpsw_build_skb(page_addr, ndev,
-				  AM65_CPSW_MAX_PACKET_SIZE);
-	if (unlikely(!skb)) {
-		new_page = page;
-		goto requeue;
-	}
-
 	if (port->xdp_prog) {
 		xdp_init_buff(&xdp, PAGE_SIZE, &port->xdp_rxq[flow->id]);
 		xdp_prepare_buff(&xdp, page_addr, AM65_CPSW_HEADROOM,
@@ -1334,9 +1327,14 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
 		if (*xdp_state != AM65_CPSW_XDP_PASS)
 			goto allocate;
 
-		/* Compute additional headroom to be reserved */
-		headroom = (xdp.data - xdp.data_hard_start) - skb_headroom(skb);
-		skb_reserve(skb, headroom);
+		headroom = xdp.data - xdp.data_hard_start;
+	}
+
+	skb = am65_cpsw_build_skb(page_addr, ndev,
+				  AM65_CPSW_MAX_PACKET_SIZE, headroom);
+	if (unlikely(!skb)) {
+		new_page = page;
+		goto requeue;
 	}
 
 	ndev_priv = netdev_priv(ndev);

-- 
2.34.1
Re: [PATCH net 1/3] net: ethernet: ti: am65-cpsw: fix memleak in certain XDP cases
Posted by Jakub Kicinski 10 months ago
On Mon, 10 Feb 2025 16:52:15 +0200 Roger Quadros wrote:
> -		/* Compute additional headroom to be reserved */
> -		headroom = (xdp.data - xdp.data_hard_start) - skb_headroom(skb);
> -		skb_reserve(skb, headroom);
> +		headroom = xdp.data - xdp.data_hard_start;
> +	}

I'm gonna do a minor touch up here and set the headroom in "else" hope
you don't mind. Easier to read the code if the init isnt all the way up
at definition. Also that way reverse xmas tree is maintained.
Re: [PATCH net 1/3] net: ethernet: ti: am65-cpsw: fix memleak in certain XDP cases
Posted by Roger Quadros 10 months ago

On 13/02/2025 06:14, Jakub Kicinski wrote:
> On Mon, 10 Feb 2025 16:52:15 +0200 Roger Quadros wrote:
>> -		/* Compute additional headroom to be reserved */
>> -		headroom = (xdp.data - xdp.data_hard_start) - skb_headroom(skb);
>> -		skb_reserve(skb, headroom);
>> +		headroom = xdp.data - xdp.data_hard_start;
>> +	}
> 
> I'm gonna do a minor touch up here and set the headroom in "else" hope
> you don't mind. Easier to read the code if the init isnt all the way up
> at definition. Also that way reverse xmas tree is maintained.

Thank you for the touch up.

-- 
cheers,
-roger