mlxsw: Fixes
Subsystems (5)
Petr Machata
maintainercover mlxsw: Fixes
In this patchset:
- Tx header should be pushed for each packet which is transmitted via Spectrum ASICs. Patch #1 adds a missing call to skb_cow_head() to make sure that there is both enough room to push the Tx header and that the SKB header is not cloned and can be modified.
- Commit b5b60bb491b2 ("mlxsw: pci: Use page pool for Rx buffers allocation") converted mlxsw to use page pool for Rx buffers allocation. Sync for CPU and for device should be done for Rx pages. In patches #2 and #3, add the missing calls to sync pages for, respectively, CPU and the device.
- Patch #4 then fixes a bug to IPv6 GRE forwarding offload. Patch #5 adds a generic forwarding test that fails with mlxsw ports prior to the fix.
Amit Cohen (3):
mlxsw: spectrum_ptp: Add missing verification before pushing Tx header
mlxsw: pci: Sync Rx buffers for CPU
mlxsw: pci: Sync Rx buffers for device
Ido Schimmel (2):
mlxsw: spectrum_ipip: Fix memory leak when changing remote IPv6
address
selftests: forwarding: Add IPv6 GRE remote change tests
drivers/net/ethernet/mellanox/mlxsw/pci.c | 25 ++++-- .../ethernet/mellanox/mlxsw/spectrum_ipip.c | 26 +++++- .../ethernet/mellanox/mlxsw/spectrum_ptp.c | 7 ++ .../selftests/net/forwarding/ip6gre_flat.sh | 14 ++++ .../net/forwarding/ip6gre_flat_key.sh | 14 ++++ .../net/forwarding/ip6gre_flat_keys.sh | 14 ++++ .../selftests/net/forwarding/ip6gre_hier.sh | 14 ++++ .../net/forwarding/ip6gre_hier_key.sh | 14 ++++ .../net/forwarding/ip6gre_hier_keys.sh | 14 ++++ .../selftests/net/forwarding/ip6gre_lib.sh | 80 +++++++++++++++++++ 10 files changed, 212 insertions(+), 10 deletions(-)
Signature · 1 line
2.45.0
Petr Machata
maintainerPATCH 1/5 mlxsw: spectrum_ptp: Add missing verification before pushing Tx header
From: Amit Cohen <[email protected]>
Tx header should be pushed for each packet which is transmitted via Spectrum ASICs. The cited commit moved the call to skb_cow_head() from mlxsw_sp_port_xmit() to functions which handle Tx header.
In case that mlxsw_sp->ptp_ops->txhdr_construct() is used to handle Tx header, and txhdr_construct() is mlxsw_sp_ptp_txhdr_construct(), there is no call for skb_cow_head() before pushing Tx header size to SKB. This flow is relevant for Spectrum-1 and Spectrum-4, for PTP packets.
Add the missing call to skb_cow_head() to make sure that there is both enough room to push the Tx header and that the SKB header is not cloned and can be modified.
An additional set will be sent to net-next to centralize the handling of the Tx header by pushing it to every packet just before transmission.
--- drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +7 -0
@@ -16,6 +16,7 @@#include "spectrum.h" #include "spectrum_ptp.h" #include "core.h" +#include "txheader.h" #define MLXSW_SP1_PTP_CLOCK_CYCLES_SHIFT 29#define MLXSW_SP1_PTP_CLOCK_FREQ_KHZ 156257/* 6.4nSec */
@@ -1684,6 +1685,12 @@ int mlxsw_sp_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core,struct sk_buff *skb, const struct mlxsw_tx_info *tx_info) { + if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) { + this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped); +dev_kfree_skb_any (skb); +return -ENOMEM ; + } +mlxsw_sp_txhdr_construct (skb, tx_info);return 0 ; }
Signature · 1 line
2.45.0
Petr Machata
maintainerPATCH 2/5 mlxsw: pci: Sync Rx buffers for CPU
In reply to Petr MachataFrom: Amit Cohen <[email protected]>
When Rx packet is received, drivers should sync the pages for CPU, to ensure the CPU reads the data written by the device and not stale data from its cache.
Add the missing sync call in Rx path, sync the actual length of data for each fragment.
--- drivers/net/ethernet/mellanox/mlxsw/pci.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-)
drivers/net/ethernet/mellanox/mlxsw/pci.c +15 -7
@@ -389,15 +389,27 @@ static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe,dma_unmap_single (&pdev->dev, mapaddr, frag_len, direction); } -static struct sk_buff *mlxsw_pci_rdq_build_skb (struct page *pages[], +static struct sk_buff *mlxsw_pci_rdq_build_skb (struct mlxsw_pci_queue *q, +struct page *pages[],u16 byte_count) { +struct mlxsw_pci_queue *cq = q->u.rdq.cq;unsigned int linear_data_size; +struct page_pool *page_pool;struct sk_buff *skb;int page_index =0 ;bool linear_only;void *data; + linear_only = byte_count +MLXSW_PCI_RX_BUF_SW_OVERHEAD <=PAGE_SIZE ; + linear_data_size = linear_only ? byte_count : +PAGE_SIZE - +MLXSW_PCI_RX_BUF_SW_OVERHEAD ; + + page_pool = cq->u.cq.page_pool; +page_pool_dma_sync_for_cpu (page_pool, pages[page_index], +MLXSW_PCI_SKB_HEADROOM , linear_data_size); + data =page_address (pages[page_index]);net_prefetch (data);
@@ -405,11 +417,6 @@ static struct sk_buff *mlxsw_pci_rdq_build_skb(struct page *pages[],if (unlikely (!skb))return ERR_PTR (-ENOMEM ); - linear_only = byte_count +MLXSW_PCI_RX_BUF_SW_OVERHEAD <=PAGE_SIZE ; - linear_data_size = linear_only ? byte_count : -PAGE_SIZE - -MLXSW_PCI_RX_BUF_SW_OVERHEAD ; -skb_reserve (skb,MLXSW_PCI_SKB_HEADROOM );skb_put (skb, linear_data_size);
@@ -425,6 +432,7 @@ static struct sk_buff *mlxsw_pci_rdq_build_skb(struct page *pages[], page = pages[page_index]; frag_size =min (byte_count,PAGE_SIZE ); +page_pool_dma_sync_for_cpu (page_pool, page,0 , frag_size);skb_add_rx_frag (skb,skb_shinfo (skb)->nr_frags, page,0 , frag_size,PAGE_SIZE ); byte_count -= frag_size;
@@ -760,7 +768,7 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci,if (err) goto out; - skb =mlxsw_pci_rdq_build_skb (pages, byte_count); + skb =mlxsw_pci_rdq_build_skb (q, pages, byte_count);if (IS_ERR (skb)) {dev_err_ratelimited (&pdev->dev,"Failed to build skb for RDQ\n" );mlxsw_pci_rdq_pages_recycle (q, pages, num_sg_entries);
Signature · 1 line
2.45.0
Re: [PATCH net 2/5] mlxsw: pci: Sync Rx buffers for CPU
From: Petr Machata <[email protected]>
Date: Fri, 25 Oct 2024 16:26:26 +0200
Quoted 5 lines
From: Amit Cohen <[email protected]>
When Rx packet is received, drivers should sync the pages for CPU, to ensure the CPU reads the data written by the device and not stale data from its cache.
[...]
Quoted 7 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +3
-1-static struct sk_buff *mlxsw_pci_rdq_build_skb (struct page *pages[], +static struct sk_buff *mlxsw_pci_rdq_build_skb (struct mlxsw_pci_queue *q, +struct page *pages[],u16 byte_count) { +struct mlxsw_pci_queue *cq = q->u.rdq.cq;unsigned int linear_data_size;
drivers/net/ethernet/mellanox/mlxsw/pci.c static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe, · line 407
Quoted 10 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +5
-0+struct page_pool *page_pool;struct sk_buff *skb;int page_index =0 ;bool linear_only;void *data; + linear_only = byte_count +MLXSW_PCI_RX_BUF_SW_OVERHEAD <=PAGE_SIZE ; + linear_data_size = linear_only ? byte_count : +PAGE_SIZE - +MLXSW_PCI_RX_BUF_SW_OVERHEAD ;
Maybe reformat the line while at it?
linear_data_size = linear_only ? byte_count : PAGE_SIZE - MLXSW_PCI_RX_BUF_SW_OVERHEAD;
drivers/net/ethernet/mellanox/mlxsw/pci.c static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe, · line 411
Quoted 4 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +4
-0+ + page_pool = cq->u.cq.page_pool; +page_pool_dma_sync_for_cpu (page_pool, pages[page_index], +MLXSW_PCI_SKB_HEADROOM , linear_data_size);
page_pool_dma_sync_for_cpu() already skips the headroom:
dma_sync_single_range_for_cpu(pool->p.dev, offset + pool->p.offset, ...
Since your pool->p.offset is MLXSW_PCI_SKB_HEADROOM, I believe you need to pass 0 here.
drivers/net/ethernet/mellanox/mlxsw/pci.c static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe, · line 414
Quoted 3 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +1
-0+ data =page_address (pages[page_index]);net_prefetch (data);
Thanks,
Olek
RE: [PATCH net 2/5] mlxsw: pci: Sync Rx buffers for CPU
Quoted 52 lines
-----Original Message-----
From: Alexander Lobakin <[email protected]>
Sent: Friday, 25 October 2024 18:00
To: Petr Machata <[email protected]>; Amit Cohen <[email protected]>
Cc: [email protected]; Andrew Lunn <[email protected]>; David S. Miller <[email protected]>; Eric Dumazet <[email protected]>; Jakub Kicinski <[email protected]>; Paolo Abeni <[email protected]>; Simon Horman <[email protected]>; Danielle Ratson <[email protected]>; Ido Schimmel <[email protected]>; mlxsw <[email protected]>; Jiri Pirko <[email protected]>
Subject: Re: [PATCH net 2/5] mlxsw: pci: Sync Rx buffers for CPUFrom: Petr Machata <[email protected]>
Date: Fri, 25 Oct 2024 16:26:26 +0200Quoted 5 lines
From: Amit Cohen <[email protected]>
When Rx packet is received, drivers should sync the pages for CPU, to ensure the CPU reads the data written by the device and not stale data from its cache.
[...]
Quoted 7 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +3
-1-static struct sk_buff *mlxsw_pci_rdq_build_skb (struct page *pages[], +static struct sk_buff *mlxsw_pci_rdq_build_skb (struct mlxsw_pci_queue *q, +struct page *pages[],u16 byte_count) { +struct mlxsw_pci_queue *cq = q->u.rdq.cq;unsigned int linear_data_size;drivers/net/ethernet/mellanox/mlxsw/pci.c static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe, · line 407
Quoted 10 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +5
-0+struct page_pool *page_pool;struct sk_buff *skb;int page_index =0 ;bool linear_only;void *data; + linear_only = byte_count +MLXSW_PCI_RX_BUF_SW_OVERHEAD <=PAGE_SIZE ; + linear_data_size = linear_only ? byte_count : +PAGE_SIZE - +MLXSW_PCI_RX_BUF_SW_OVERHEAD ;Maybe reformat the line while at it?
linear_data_size = linear_only ? byte_count : PAGE_SIZE - MLXSW_PCI_RX_BUF_SW_OVERHEAD;drivers/net/ethernet/mellanox/mlxsw/pci.c static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe, · line 411
Quoted 4 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +4
-0+ + page_pool = cq->u.cq.page_pool; +page_pool_dma_sync_for_cpu (page_pool, pages[page_index], +MLXSW_PCI_SKB_HEADROOM , linear_data_size);
page_pool_dma_sync_for_cpu()already skips the headroom:
Quoted 5 lines
dma_sync_single_range_for_cpu(pool->p.dev, offset + pool->p.offset, ...Since your
pool->p.offsetisMLXSW_PCI_SKB_HEADROOM, I believe you need to pass 0 here.
Our pool->p.offset is zero.
We use the page pool to allocate buffers for scatter/gather entries.
Only the first entry saves headroom for software usage, so only for the first buffer of the packet we pass headroom to page_pool_dma_sync_for_cpu().
Quoted 7 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c static void mlxsw_pci_wqe_frag_unmap(struct mlxsw_pci *mlxsw_pci, char *wqe, · line 414
Quoted 4 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +1
-0+ data =page_address (pages[page_index]);net_prefetch (data);Thanks,
Olek
Petr Machata
maintainerPATCH 3/5 mlxsw: pci: Sync Rx buffers for device
In reply to Petr MachataFrom: Amit Cohen <[email protected]>
Non-coherent architectures, like ARM, may require invalidating caches before the device can use the DMA mapped memory, which means that before posting pages to device, drivers should sync the memory for device.
Sync for device can be configured as page pool responsibility. Set the relevant flag and define max_len for sync.
--- drivers/net/ethernet/mellanox/mlxsw/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlxsw/pci.c +2 -1
@@ -996,12 +996,13 @@ static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q,if (cq_type !=MLXSW_PCI_CQ_RDQ )return 0 ; - pp_params.flags =PP_FLAG_DMA_MAP ; + pp_params.flags =PP_FLAG_DMA_MAP |PP_FLAG_DMA_SYNC_DEV ; pp_params.pool_size =MLXSW_PCI_WQE_COUNT * mlxsw_pci->num_sg_entries; pp_params.nid =dev_to_node (&mlxsw_pci->pdev->dev); pp_params.dev = &mlxsw_pci->pdev->dev; pp_params.napi = &q->u.cq.napi; pp_params.dma_dir =DMA_FROM_DEVICE ; + pp_params.max_len =PAGE_SIZE ; page_pool =page_pool_create (&pp_params);if (IS_ERR (page_pool))
Signature · 1 line
2.45.0
Re: [PATCH net 3/5] mlxsw: pci: Sync Rx buffers for device
From: Petr Machata <[email protected]>
Date: Fri, 25 Oct 2024 16:26:27 +0200
Quoted 24 lines
From: Amit Cohen <[email protected]>
Non-coherent architectures, like ARM, may require invalidating caches before the device can use the DMA mapped memory, which means that before posting pages to device, drivers should sync the memory for device.
Sync for device can be configured as page pool responsibility. Set the relevant flag and define
max_lenfor sync.Cc Jiri Pirko <[email protected]>Fixes b5b60bb491b2 ("mlxsw: pci: Use page pool for Rx buffers allocation")Signed-off-by Amit Cohen <[email protected]>Reviewed-by Ido Schimmel <[email protected]>Signed-off-by Petr Machata <[email protected]>--- drivers/net/ethernet/mellanox/mlxsw/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)drivers/net/ethernet/mellanox/mlxsw/pci.c +0
-0@@ -996,12 +996,13 @@ static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q,if (cq_type !=MLXSW_PCI_CQ_RDQ )
drivers/net/ethernet/mellanox/mlxsw/pci.c static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q, · line 1005
Quoted 10 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +2
-1return 0 ; - pp_params.flags =PP_FLAG_DMA_MAP ; + pp_params.flags =PP_FLAG_DMA_MAP |PP_FLAG_DMA_SYNC_DEV ; pp_params.pool_size =MLXSW_PCI_WQE_COUNT * mlxsw_pci->num_sg_entries; pp_params.nid =dev_to_node (&mlxsw_pci->pdev->dev); pp_params.dev = &mlxsw_pci->pdev->dev; pp_params.napi = &q->u.cq.napi; pp_params.dma_dir =DMA_FROM_DEVICE ; + pp_params.max_len =PAGE_SIZE ;
max_len is the maximum HW-writable area of a buffer. Headroom and tailroom must be excluded. In your case
pp_params.max_len = PAGE_SIZE - MLXSW_PCI_RX_BUF_SW_OVERHEAD;
drivers/net/ethernet/mellanox/mlxsw/pci.c static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q, · line 1008
Quoted 3 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +0
-0page_pool =page_pool_create (&pp_params);if (IS_ERR (page_pool))
Thanks,
Olek
RE: [PATCH net 3/5] mlxsw: pci: Sync Rx buffers for device
Quoted 52 lines
-----Original Message-----
From: Alexander Lobakin <[email protected]>
Sent: Friday, 25 October 2024 18:03
To: Petr Machata <[email protected]>; Amit Cohen <[email protected]>
Cc: [email protected]; Andrew Lunn <[email protected]>; David S. Miller <[email protected]>; Eric Dumazet <[email protected]>; Jakub Kicinski <[email protected]>; Paolo Abeni <[email protected]>; Simon Horman <[email protected]>; Danielle Ratson <[email protected]>; Ido Schimmel <[email protected]>; mlxsw <[email protected]>; Jiri Pirko <[email protected]>
Subject: Re: [PATCH net 3/5] mlxsw: pci: Sync Rx buffers for deviceFrom: Petr Machata <[email protected]>
Date: Fri, 25 Oct 2024 16:26:27 +0200Quoted 24 lines
From: Amit Cohen <[email protected]>
Non-coherent architectures, like ARM, may require invalidating caches before the device can use the DMA mapped memory, which means that before posting pages to device, drivers should sync the memory for device.
Sync for device can be configured as page pool responsibility. Set the relevant flag and define
max_lenfor sync.Cc Jiri Pirko <[email protected]>Fixes b5b60bb491b2 ("mlxsw: pci: Use page pool for Rx buffers allocation")Signed-off-by Amit Cohen <[email protected]>Reviewed-by Ido Schimmel <[email protected]>Signed-off-by Petr Machata <[email protected]>--- drivers/net/ethernet/mellanox/mlxsw/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)drivers/net/ethernet/mellanox/mlxsw/pci.c +0
-0@@ -996,12 +996,13 @@ static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q,if (cq_type !=MLXSW_PCI_CQ_RDQ )drivers/net/ethernet/mellanox/mlxsw/pci.c static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q, · line 1005
Quoted 10 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +2
-1return 0 ; - pp_params.flags =PP_FLAG_DMA_MAP ; + pp_params.flags =PP_FLAG_DMA_MAP |PP_FLAG_DMA_SYNC_DEV ; pp_params.pool_size =MLXSW_PCI_WQE_COUNT * mlxsw_pci->num_sg_entries; pp_params.nid =dev_to_node (&mlxsw_pci->pdev->dev); pp_params.dev = &mlxsw_pci->pdev->dev; pp_params.napi = &q->u.cq.napi; pp_params.dma_dir =DMA_FROM_DEVICE ; + pp_params.max_len =PAGE_SIZE ;
max_lenis the maximum HW-writable area of a buffer. Headroom and tailroom must be excluded. In your case
Quoted 2 lines
pp_params.max_len = PAGE_SIZE - MLXSW_PCI_RX_BUF_SW_OVERHEAD;
mlxsw driver uses fragmented buffers and the page pool is used to allocate the buffers for all scatter/gather entries.
For each packet, the HW-writable area of a buffer of the *first* entry is 'PAGE_SIZE - MLXSW_PCI_RX_BUF_SW_OVERHEAD', but for other entries we map PAGE_SIZE to HW. That's why we set page pool to sync PAGE_SIZE and use offset=0.
Quoted 6 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q, · line 1008
Quoted 3 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +0
-0page_pool =page_pool_create (&pp_params);if (IS_ERR (page_pool))Thanks,
Olek
Re: [PATCH net 3/5] mlxsw: pci: Sync Rx buffers for device
From: Amit Cohen <[email protected]>
Date: Sun, 27 Oct 2024 06:51:00 +0000
Quoted 52 lines
Quoted 52 lines
-----Original Message-----
From: Alexander Lobakin <[email protected]>
Sent: Friday, 25 October 2024 18:03
To: Petr Machata <[email protected]>; Amit Cohen <[email protected]>
Cc: [email protected]; Andrew Lunn <[email protected]>; David S. Miller <[email protected]>; Eric Dumazet <[email protected]>; Jakub Kicinski <[email protected]>; Paolo Abeni <[email protected]>; Simon Horman <[email protected]>; Danielle Ratson <[email protected]>; Ido Schimmel <[email protected]>; mlxsw <[email protected]>; Jiri Pirko <[email protected]>
Subject: Re: [PATCH net 3/5] mlxsw: pci: Sync Rx buffers for deviceFrom: Petr Machata <[email protected]>
Date: Fri, 25 Oct 2024 16:26:27 +0200Quoted 24 lines
From: Amit Cohen <[email protected]>
Non-coherent architectures, like ARM, may require invalidating caches before the device can use the DMA mapped memory, which means that before posting pages to device, drivers should sync the memory for device.
Sync for device can be configured as page pool responsibility. Set the relevant flag and define
max_lenfor sync.Cc Jiri Pirko <[email protected]>Fixes b5b60bb491b2 ("mlxsw: pci: Use page pool for Rx buffers allocation")Signed-off-by Amit Cohen <[email protected]>Reviewed-by Ido Schimmel <[email protected]>Signed-off-by Petr Machata <[email protected]>--- drivers/net/ethernet/mellanox/mlxsw/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)drivers/net/ethernet/mellanox/mlxsw/pci.c +0
-0@@ -996,12 +996,13 @@ static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q,if (cq_type !=MLXSW_PCI_CQ_RDQ )drivers/net/ethernet/mellanox/mlxsw/pci.c static int mlxsw_pci_cq_page_pool_init(struct mlxsw_pci_queue *q, · line 1005
Quoted 10 lines
drivers/net/ethernet/mellanox/mlxsw/pci.c +2
-1return 0 ; - pp_params.flags =PP_FLAG_DMA_MAP ; + pp_params.flags =PP_FLAG_DMA_MAP |PP_FLAG_DMA_SYNC_DEV ; pp_params.pool_size =MLXSW_PCI_WQE_COUNT * mlxsw_pci->num_sg_entries; pp_params.nid =dev_to_node (&mlxsw_pci->pdev->dev); pp_params.dev = &mlxsw_pci->pdev->dev; pp_params.napi = &q->u.cq.napi; pp_params.dma_dir =DMA_FROM_DEVICE ; + pp_params.max_len =PAGE_SIZE ;
max_lenis the maximum HW-writable area of a buffer. Headroom and tailroom must be excluded. In your case
Quoted 6 lines
Quoted 2 lines
pp_params.max_len = PAGE_SIZE - MLXSW_PCI_RX_BUF_SW_OVERHEAD;mlxsw driver uses fragmented buffers and the page pool is used to allocate the buffers for all scatter/gather entries.
For each packet, the HW-writable area of a buffer of the *first* entry is 'PAGE_SIZE-MLXSW_PCI_RX_BUF_SW_OVERHEAD', but for other entries we mapPAGE_SIZEto HW. That's why we set page pool to syncPAGE_SIZEand use offset=0.
Ooops, I didn't notice this particular configuration has offset == 0, sorry.
Thanks,
Olek
Petr Machata
maintainerPATCH 4/5 mlxsw: spectrum_ipip: Fix memory leak when changing remote IPv6 address
In reply to Petr MachataFrom: Ido Schimmel <[email protected]>
The device stores IPv6 addresses that are used for encapsulation in linear memory that is managed by the driver.
Changing the remote address of an ip6gre net device never worked properly, but since cited commit the following reproducer [1] would result in a warning [2] and a memory leak [3]. The problem is that the new remote address is never added by the driver to its hash table (and therefore the device) and the old address is never removed from it.
Fix by programming the new address when the configuration of the ip6gre net device changes and removing the old one. If the address did not change, then the above would result in increasing the reference count of the address and then decreasing it.
[1]
# ip link add name bla up type ip6gre local 2001:db8:1::1 remote 2001:db8:2::1 tos inherit ttl inherit # ip link set dev bla type ip6gre remote 2001:db8:3::1 # ip link del dev bla # devlink dev reload pci/0000:01:00.0
[2]
WARNING: CPU: 0 PID: 1682 at drivers/net/ethernet/mellanox/mlxsw/spectrum.c:3002 mlxsw_sp_ipv6_addr_put+0x140/0x1d0 Modules linked in: CPU: 0 UID: 0 PID: 1682 Comm: ip Not tainted 6.12.0-rc3-custom-g86b5b55bc835 #151 Hardware name: Nvidia SN5600/VMOD0013, BIOS 5.13 05/31/2023 RIP: 0010:mlxsw_sp_ipv6_addr_put+0x140/0x1d0 [...] Call Trace: <TASK> mlxsw_sp_router_netdevice_event+0x55f/0x1240 notifier_call_chain+0x5a/0xd0 call_netdevice_notifiers_info+0x39/0x90 unregister_netdevice_many_notify+0x63e/0x9d0 rtnl_dellink+0x16b/0x3a0 rtnetlink_rcv_msg+0x142/0x3f0 netlink_rcv_skb+0x50/0x100 netlink_unicast+0x242/0x390 netlink_sendmsg+0x1de/0x420 ____sys_sendmsg+0x2bd/0x320 ___sys_sendmsg+0x9a/0xe0 __sys_sendmsg+0x7a/0xd0 do_syscall_64+0x9e/0x1a0 entry_SYSCALL_64_after_hwframe+0x77/0x7f
[3]
unreferenced object 0xffff898081f597a0 (size 32):
comm "ip", pid 1626, jiffies 4294719324
hex dump (first 32 bytes):
20 01 0d b8 00 02 00 00 00 00 00 00 00 00 00 01 ...............
21 49 61 83 80 89 ff ff 00 00 00 00 01 00 00 00 !Ia.............
backtrace (crc fd9be911):
[<00000000df89c55d>] __kmalloc_cache_noprof+0x1da/0x260
[<00000000ff2a1ddb>] mlxsw_sp_ipv6_addr_kvdl_index_get+0x281/0x340
[<000000009ddd445d>] mlxsw_sp_router_netdevice_event+0x47b/0x1240
[<00000000743e7757>] notifier_call_chain+0x5a/0xd0
[<000000007c7b9e13>] call_netdevice_notifiers_info+0x39/0x90
[<000000002509645d>] register_netdevice+0x5f7/0x7a0
[<00000000c2e7d2a9>] ip6gre_newlink_common.isra.0+0x65/0x130
[<0000000087cd6d8d>] ip6gre_newlink+0x72/0x120
[<000000004df7c7cc>] rtnl_newlink+0x471/0xa20
[<0000000057ed632a>] rtnetlink_rcv_msg+0x142/0x3f0
[<0000000032e0d5b5>] netlink_rcv_skb+0x50/0x100
[<00000000908bca63>] netlink_unicast+0x242/0x390
[<00000000cdbe1c87>] netlink_sendmsg+0x1de/0x420
[<0000000011db153e>] ____sys_sendmsg+0x2bd/0x320
[<000000003b6d53eb>] ___sys_sendmsg+0x9a/0xe0
[<00000000cae27c62>] __sys_sendmsg+0x7a/0xd0--- .../ethernet/mellanox/mlxsw/spectrum_ipip.c | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c +24 -2
@@ -481,11 +481,33 @@ mlxsw_sp_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp,struct mlxsw_sp_ipip_entry *ipip_entry, struct netlink_ext_ack *extack) { + u32 new_kvdl_index, old_kvdl_index = ipip_entry->dip_kvdl_index; +struct in6_addr old_addr6 = ipip_entry->parms.daddr.addr6;struct mlxsw_sp_ipip_parms new_parms; +int err; new_parms =mlxsw_sp_ipip_netdev_parms_init_gre6 (ipip_entry->ol_dev); -return mlxsw_sp_ipip_ol_netdev_change_gre (mlxsw_sp, ipip_entry, - &new_parms, extack); + + err =mlxsw_sp_ipv6_addr_kvdl_index_get (mlxsw_sp, + &new_parms.daddr.addr6, + &new_kvdl_index); +if (err) +return err; + ipip_entry->dip_kvdl_index = new_kvdl_index; + + err =mlxsw_sp_ipip_ol_netdev_change_gre (mlxsw_sp, ipip_entry, + &new_parms, extack); +if (err) + goto err_change_gre; + +mlxsw_sp_ipv6_addr_put (mlxsw_sp, &old_addr6); + +return 0 ; + +err_change_gre: + ipip_entry->dip_kvdl_index = old_kvdl_index; +mlxsw_sp_ipv6_addr_put (mlxsw_sp, &new_parms.daddr.addr6); +return err; } static int
Signature · 1 line
2.45.0
Petr Machata
maintainerPATCH 5/5 selftests: forwarding: Add IPv6 GRE remote change tests
In reply to Petr MachataFrom: Ido Schimmel <[email protected]>
Test that after changing the remote address of an ip6gre net device traffic is forwarded as expected. Test with both flat and hierarchical topologies and with and without an input / output keys.
--- .../selftests/net/forwarding/ip6gre_flat.sh | 14 ++++ .../net/forwarding/ip6gre_flat_key.sh | 14 ++++ .../net/forwarding/ip6gre_flat_keys.sh | 14 ++++ .../selftests/net/forwarding/ip6gre_hier.sh | 14 ++++ .../net/forwarding/ip6gre_hier_key.sh | 14 ++++ .../net/forwarding/ip6gre_hier_keys.sh | 14 ++++ .../selftests/net/forwarding/ip6gre_lib.sh | 80 +++++++++++++++++++ 7 files changed, 164 insertions(+)
tools/testing/selftests/net/forwarding/ip6gre_flat.sh +14 -0
@@ -8,6 +8,7 @@ ALL_TESTS=" gre_flat gre_mtu_change + gre_flat_remote_change " NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change() test_mtu_change } +gre_flat_remote_change() +{ + flat_remote_change + + test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 (new remote)" + test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 (new remote)" + + flat_remote_restore + + test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 (old remote)" + test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 (old remote)" +} + cleanup() { pre_cleanup
tools/testing/selftests/net/forwarding/ip6gre_flat_key.sh +14 -0
@@ -8,6 +8,7 @@ ALL_TESTS=" gre_flat gre_mtu_change + gre_flat_remote_change " NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change() test_mtu_change } +gre_flat_remote_change() +{ + flat_remote_change + + test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with key (new remote)" + test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with key (new remote)" + + flat_remote_restore + + test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with key (old remote)" + test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with key (old remote)" +} + cleanup() { pre_cleanup
tools/testing/selftests/net/forwarding/ip6gre_flat_keys.sh +14 -0
@@ -8,6 +8,7 @@ ALL_TESTS=" gre_flat gre_mtu_change + gre_flat_remote_change " NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change() test_mtu_change gre } +gre_flat_remote_change() +{ + flat_remote_change + + test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with ikey/okey (new remote)" + test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with ikey/okey (new remote)" + + flat_remote_restore + + test_traffic_ip4ip6 "GRE flat IPv4-in-IPv6 with ikey/okey (old remote)" + test_traffic_ip6ip6 "GRE flat IPv6-in-IPv6 with ikey/okey (old remote)" +} + cleanup() { pre_cleanup
tools/testing/selftests/net/forwarding/ip6gre_hier.sh +14 -0
@@ -8,6 +8,7 @@ ALL_TESTS=" gre_hier gre_mtu_change + gre_hier_remote_change " NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change() test_mtu_change gre } +gre_hier_remote_change() +{ + hier_remote_change + + test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 (new remote)" + test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 (new remote)" + + hier_remote_restore + + test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 (old remote)" + test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 (old remote)" +} + cleanup() { pre_cleanup
tools/testing/selftests/net/forwarding/ip6gre_hier_key.sh +14 -0
@@ -8,6 +8,7 @@ ALL_TESTS=" gre_hier gre_mtu_change + gre_hier_remote_change " NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change() test_mtu_change gre } +gre_hier_remote_change() +{ + hier_remote_change + + test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with key (new remote)" + test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with key (new remote)" + + hier_remote_restore + + test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with key (old remote)" + test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with key (old remote)" +} + cleanup() { pre_cleanup
tools/testing/selftests/net/forwarding/ip6gre_hier_keys.sh +14 -0
@@ -8,6 +8,7 @@ ALL_TESTS=" gre_hier gre_mtu_change + gre_hier_remote_change " NUM_NETIFS=6
@@ -44,6 +45,19 @@ gre_mtu_change() test_mtu_change gre } +gre_hier_remote_change() +{ + hier_remote_change + + test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with ikey/okey (new remote)" + test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with ikey/okey (new remote)" + + hier_remote_restore + + test_traffic_ip4ip6 "GRE hierarchical IPv4-in-IPv6 with ikey/okey (old remote)" + test_traffic_ip6ip6 "GRE hierarchical IPv6-in-IPv6 with ikey/okey (old remote)" +} + cleanup() { pre_cleanup
tools/testing/selftests/net/forwarding/ip6gre_lib.sh +80 -0
83 lines not on this page · raw message
Signature · 1 line
2.45.0
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 8 lines · On Fri, 25 Oct 2024 16:26:24 +0200 you wrote:
In this patchset:
- Tx header should be pushed for each packet which is transmitted via Spectrum ASICs. Patch #1 adds a missing call to
skb_cow_head()to make sure that there is both enough room to push the Tx header and that the SKB header is not cloned and can be modified.[...]
Here is the summary with links:
- [net,1/5] mlxsw: spectrum_ptp: Add missing verification before pushing Tx header
https://git.kernel.org/netdev/net/c/0a66e5582b51 - [net,2/5] mlxsw: pci: Sync Rx buffers for CPU https://git.kernel.org/netdev/net/c/15f73e601a9c - [net,3/5] mlxsw: pci: Sync Rx buffers for device https://git.kernel.org/netdev/net/c/d0fbdc3ae9ec - [net,4/5] mlxsw: spectrum_ipip: Fix memory leak when changing remote IPv6 address https://git.kernel.org/netdev/net/c/12ae97c531fc - [net,5/5] selftests: forwarding: Add IPv6 GRE remote change tests https://git.kernel.org/netdev/net/c/d7bd61fa0222
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html