From: Magnus Karlsson <hidden> Date: 2021-09-22 07:56:44
This patch set introduces a batched interface for Rx buffer allocation
in AF_XDP buffer pool. Instead of using xsk_buff_alloc(*pool), drivers
can now use xsk_buff_alloc_batch(*pool, **xdp_buff_array,
max). Instead of returning a pointer to an xdp_buff, it returns the
number of xdp_buffs it managed to allocate up to the maximum value of
the max parameter in the function call. Pointers to the allocated
xdp_buff:s are put in the xdp_buff_array supplied in the call. This
could be a SW ring that already exists in the driver or a new
structure that the driver has allocated.
u32 xsk_buff_alloc_batch(struct xsk_buff_pool *pool,
struct xdp_buff **xdp,
u32 max);
When using this interface, the driver should also use the new
interface below to set the relevant fields in the struct xdp_buff. The
reason for this is that xsk_buff_alloc_batch() does not fill in the
data and data_meta fields for you as is the case with
xsk_buff_alloc(). So it is not sufficient to just set data_end
(effectively the size) anymore in the driver. The reason for this is
performance as explained in detail in the commit message.
void xsk_buff_set_size(struct xdp_buff *xdp, u32 size);
Patch 6 also optimizes the buffer allocation in the aligned case. In
this case, we can skip the reinitialization of most fields in the
xdp_buff_xsk struct at allocation time. As the number of elements in
the heads array is equal to the number of possible buffers in the
umem, we can initialize them once and for all at bind time and then
just point to the correct one in the xdp_buff_array that is returned
to the driver. No reason to have a stack of free head entries. In the
unaligned case, the buffers can reside anywhere in the umem, so this
optimization is not possible as we still have to fill in the right
information in the xdp_buff every single time one is allocated.
I have updated i40e and ice to use this new batched interface.
These are the throughput results on my 2.1 GHz Cascade Lake system:
Aligned mode:
ice: +11% / -9 cycles/pkt
i40e: +12% / -9 cycles/pkt
Unaligned mode:
ice: +1.5% / -1 cycle/pkt
i40e: +1% / -1 cycle/pkt
For the aligned case, batching provides around 40% of the performance
improvement and the aligned optimization the rest, around 60%. Would
have expected a ~4% boost for unaligned with this data, but I only get
around 1%. Do not know why. Note that memory consumption in aligned
mode is also reduced by this patch set.
Structure of the patch set:
Patch 1: Removes an unused entry from xdp_buff_xsk.
Patch 2: Introduce the batched buffer allocation API and implementation.
Patch 3-4: Use the batched allocation interface for ice.
Patch 5: Use the batched allocation interface for i40e.
Patch 6: Optimize the buffer allocation for the aligned case.
Patch 7-10: Fix some issues with the tests that were found while
implementing the two new tests below.
Patch 11-13: Implement two new tests: single packet and headroom validation.
Thanks: Magnus
Magnus Karlsson (13):
xsk: get rid of unused entry in struct xdp_buff_xsk
xsk: batched buffer allocation for the pool
ice: use xdp_buf instead of rx_buf for xsk zero-copy
ice: use the xsk batched rx allocation interface
i40e: use the xsk batched rx allocation interface
xsk: optimize for aligned case
selftests: xsk: fix missing initialization
selftests: xsk: put the same buffer only once in the fill ring
selftests: xsk: fix socket creation retry
selftests: xsk: introduce pacing of traffic
selftests: xsk: add single packet test
selftests: xsk: change interleaving of packets in unaligned mode
selftests: xsk: add frame_headroom test
drivers/net/ethernet/intel/i40e/i40e_xsk.c | 52 ++++----
drivers/net/ethernet/intel/ice/ice_txrx.h | 16 +--
drivers/net/ethernet/intel/ice/ice_xsk.c | 92 +++++++-------
include/net/xdp_sock_drv.h | 22 ++++
include/net/xsk_buff_pool.h | 48 +++++++-
net/xdp/xsk.c | 15 ---
net/xdp/xsk_buff_pool.c | 131 +++++++++++++++++---
net/xdp/xsk_queue.h | 12 +-
tools/testing/selftests/bpf/xdpxceiver.c | 133 ++++++++++++++++-----
tools/testing/selftests/bpf/xdpxceiver.h | 11 +-
10 files changed, 376 insertions(+), 156 deletions(-)
base-commit: 17b52c226a9a170f1611f69d12a71be05748aefd
--
2.29.0
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:56:46
From: Magnus Karlsson <magnus.karlsson@intel.com>
Get rid of the unused entry "unaligned" in struct xdp_buff_xsk.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
include/net/xsk_buff_pool.h | 1 -
1 file changed, 1 deletion(-)
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:56:48
From: Magnus Karlsson <magnus.karlsson@intel.com>
Add a new driver interface xsk_buff_alloc_batch() offering batched
buffer allocations to improve performance. The new interface takes
three arguments: the buffer pool to allocated from, a pointer to an
array of struct xdp_buff pointers which will contain pointers to the
allocated xdp_buffs, and an unsigned integer specifying the max number
of buffers to allocate. The return value is the actual number of
buffers that the allocator managed to allocate and it will be in the
range 0 <= N <= max, where max is the third parameter to the function.
u32 xsk_buff_alloc_batch(struct xsk_buff_pool *pool, struct xdp_buff **xdp,
u32 max);
A second driver interface is also introduced that need to be used in
conjunction with xsk_buff_alloc_batch(). It is a helper that sets the
size of struct xdp_buff and is used by the NIC Rx irq routine when
receiving a packet. This helper sets the three struct members data,
data_meta, and data_end. The two first ones is in the xsk_buff_alloc()
case set in the allocation routine and data_end is set when a packet
is received in the receive irq function. This unfortunately leads to
worse performance since the xdp_buff is touched twice with a long time
period in between leading to an extra cache miss. Instead, we fill out
the xdp_buff with all 3 fields at one single point in time in the
driver, when the size of the packet is known. Hence this helper. Note
that the driver has to use this helper (or set all three fields
itself) when using xsk_buff_alloc_batch(). xsk_buff_alloc() works as
before and does not require this.
void xsk_buff_set_size(struct xdp_buff *xdp, u32 size);
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
include/net/xdp_sock_drv.h | 22 ++++++++++
include/net/xsk_buff_pool.h | 1 +
net/xdp/xsk_buff_pool.c | 87 +++++++++++++++++++++++++++++++++++++
net/xdp/xsk_queue.h | 12 +++--
4 files changed, 118 insertions(+), 4 deletions(-)
@@ -77,6 +77,12 @@ static inline struct xdp_buff *xsk_buff_alloc(struct xsk_buff_pool *pool)returnxp_alloc(pool);}+/* Returns as many entries as possible up to max. 0 <= N <= max. */+staticinlineu32xsk_buff_alloc_batch(structxsk_buff_pool*pool,structxdp_buff**xdp,u32max)+{+returnxp_alloc_batch(pool,xdp,max);+}+staticinlineboolxsk_buff_can_alloc(structxsk_buff_pool*pool,u32count){returnxp_can_alloc(pool,count);
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:56:50
From: Magnus Karlsson <magnus.karlsson@intel.com>
In order to use the new xsk batched buffer allocation interface, a
pointer to an array of struct xsk_buff pointers need to be provided so
that the function can put the result of the allocation there. In the
ice driver, we already have a ring that stores pointers to
xdp_buffs. This is only used for the xsk zero-copy driver and is a
union with the structure that is used for the regular non zero-copy
path. Unfortunately, that structure is larger than the xdp_buffs
pointers which mean that there will be a stride (of 20 bytes) between
each xdp_buff pointer. And feeding this into the xsk_buff_alloc_batch
interface will not work since it assumes a regular array of xdp_buff
pointers (each 8 bytes with 0 bytes in-between them on a 64-bit
system).
To fix this, remove the xdp_buff pointer from the rx_buf union and
move it one step higher to the union above which only has pointers to
arrays in it. This solves the problem and we can directly feed the SW
ring of xdp_buff pointers straight into the allocation function in the
next patch when that interface is used. This will improve performance.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
drivers/net/ethernet/intel/ice/ice_txrx.h | 16 ++-----
drivers/net/ethernet/intel/ice/ice_xsk.c | 56 +++++++++++------------
2 files changed, 33 insertions(+), 39 deletions(-)
@@ -270,6 +263,7 @@ struct ice_ring {union{structice_tx_buf*tx_buf;structice_rx_buf*rx_buf;+structxdp_buff**xdp_buf;};/* CL2 - 2nd cacheline starts here */u16q_index;/* Queue number of ring */
@@ -521,7 +521,7 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget)while(likely(total_rx_packets<(unsignedint)budget)){unionice_32b_rx_flex_desc*rx_desc;unsignedintsize,xdp_res=0;-structice_rx_buf*rx_buf;+structxdp_buff**xdp;structsk_buff*skb;u16stat_err_bits;u16vlan_tag=0;
@@ -544,18 +544,18 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget)if(!size)break;-rx_buf=&rx_ring->rx_buf[rx_ring->next_to_clean];-rx_buf->xdp->data_end=rx_buf->xdp->data+size;-xsk_buff_dma_sync_for_cpu(rx_buf->xdp,rx_ring->xsk_pool);+xdp=&rx_ring->xdp_buf[rx_ring->next_to_clean];+(*xdp)->data_end=(*xdp)->data+size;+xsk_buff_dma_sync_for_cpu(*xdp,rx_ring->xsk_pool);-xdp_res=ice_run_xdp_zc(rx_ring,rx_buf->xdp);+xdp_res=ice_run_xdp_zc(rx_ring,*xdp);if(xdp_res){if(xdp_res&(ICE_XDP_TX|ICE_XDP_REDIR))xdp_xmit|=xdp_res;else-xsk_buff_free(rx_buf->xdp);+xsk_buff_free(*xdp);-rx_buf->xdp=NULL;+*xdp=NULL;total_rx_bytes+=size;total_rx_packets++;cleaned_count++;
@@ -565,7 +565,7 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget)}/* XDP_PASS path */-skb=ice_construct_skb_zc(rx_ring,rx_buf);+skb=ice_construct_skb_zc(rx_ring,xdp);if(!skb){rx_ring->rx_stats.alloc_buf_failed++;break;
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:56:51
From: Magnus Karlsson <magnus.karlsson@intel.com>
Use the new xsk batched rx allocation interface for the zero-copy data
path. As the array of struct xdp_buff pointers kept by the driver is
really a ring that wraps, the allocation routine is modified to detect
a wrap and in that case call the allocation function twice. The
allocation function cannot deal with wrapped rings, only arrays. As we
now know exactly how many buffers we get and that there is no
wrapping, the allocation function can be simplified even more as all
if-statements in the allocation loop can be removed, improving
performance.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
drivers/net/ethernet/intel/ice/ice_xsk.c | 44 ++++++++++--------------
1 file changed, 19 insertions(+), 25 deletions(-)
@@ -365,44 +365,38 @@ bool ice_alloc_rx_bufs_zc(struct ice_ring *rx_ring, u16 count)unionice_32b_rx_flex_desc*rx_desc;u16ntu=rx_ring->next_to_use;structxdp_buff**xdp;-boolok=true;+u32nb_buffs,i;dma_addr_tdma;-if(!count)-returntrue;-rx_desc=ICE_RX_DESC(rx_ring,ntu);xdp=&rx_ring->xdp_buf[ntu];-do{-*xdp=xsk_buff_alloc(rx_ring->xsk_pool);-if(!xdp){-ok=false;-break;-}+nb_buffs=min_t(u16,count,rx_ring->count-ntu);+nb_buffs=xsk_buff_alloc_batch(rx_ring->xsk_pool,xdp,nb_buffs);+if(!nb_buffs)+returnfalse;+i=nb_buffs;+while(i--){dma=xsk_buff_xdp_get_dma(*xdp);rx_desc->read.pkt_addr=cpu_to_le64(dma);-rx_desc->wb.status_error0=0;rx_desc++;xdp++;-ntu++;--if(unlikely(ntu==rx_ring->count)){-rx_desc=ICE_RX_DESC(rx_ring,0);-xdp=rx_ring->xdp_buf;-ntu=0;-}-}while(--count);+}-if(rx_ring->next_to_use!=ntu){-/* clear the status bits for the next_to_use descriptor */-rx_desc->wb.status_error0=0;-ice_release_rx_desc(rx_ring,ntu);+ntu+=nb_buffs;+if(ntu==rx_ring->count){+rx_desc=ICE_RX_DESC(rx_ring,0);+xdp=rx_ring->xdp_buf;+ntu=0;}-returnok;+/* clear the status bits for the next_to_use descriptor */+rx_desc->wb.status_error0=0;+ice_release_rx_desc(rx_ring,ntu);++returncount==nb_buffs?true:false;}/**
@@ -545,7 +539,7 @@ int ice_clean_rx_irq_zc(struct ice_ring *rx_ring, int budget)break;xdp=&rx_ring->xdp_buf[rx_ring->next_to_clean];-(*xdp)->data_end=(*xdp)->data+size;+xsk_buff_set_size(*xdp,size);xsk_buff_dma_sync_for_cpu(*xdp,rx_ring->xsk_pool);xdp_res=ice_run_xdp_zc(rx_ring,*xdp);
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:56:52
From: Magnus Karlsson <magnus.karlsson@intel.com>
Use the new xsk batched rx allocation interface for the zero-copy data
path. As the array of struct xdp_buff pointers kept by the driver is
really a ring that wraps, the allocation routine is modified to detect
a wrap and in that case call the allocation function twice. The
allocation function cannot deal with wrapped rings, only arrays. As we
now know exactly how many buffers we get and that there is no
wrapping, the allocation function can be simplified even more as all
if-statements in the allocation loop can be removed, improving
performance.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_xsk.c | 52 +++++++++++-----------
1 file changed, 25 insertions(+), 27 deletions(-)
@@ -193,42 +193,40 @@ bool i40e_alloc_rx_buffers_zc(struct i40e_ring *rx_ring, u16 count){u16ntu=rx_ring->next_to_use;unioni40e_rx_desc*rx_desc;-structxdp_buff**bi,*xdp;+structxdp_buff**xdp;+u32nb_buffs,i;dma_addr_tdma;-boolok=true;rx_desc=I40E_RX_DESC(rx_ring,ntu);-bi=i40e_rx_bi(rx_ring,ntu);-do{-xdp=xsk_buff_alloc(rx_ring->xsk_pool);-if(!xdp){-ok=false;-gotono_buffers;-}-*bi=xdp;-dma=xsk_buff_xdp_get_dma(xdp);+xdp=i40e_rx_bi(rx_ring,ntu);++nb_buffs=min_t(u16,count,rx_ring->count-ntu);+nb_buffs=xsk_buff_alloc_batch(rx_ring->xsk_pool,xdp,nb_buffs);+if(!nb_buffs)+returnfalse;++i=nb_buffs;+while(i--){+dma=xsk_buff_xdp_get_dma(*xdp);rx_desc->read.pkt_addr=cpu_to_le64(dma);rx_desc->read.hdr_addr=0;rx_desc++;-bi++;-ntu++;--if(unlikely(ntu==rx_ring->count)){-rx_desc=I40E_RX_DESC(rx_ring,0);-bi=i40e_rx_bi(rx_ring,0);-ntu=0;-}-}while(--count);+xdp++;+}-no_buffers:-if(rx_ring->next_to_use!=ntu){-/* clear the status bits for the next_to_use descriptor */-rx_desc->wb.qword1.status_error_len=0;-i40e_release_rx_desc(rx_ring,ntu);+ntu+=nb_buffs;+if(ntu==rx_ring->count){+rx_desc=I40E_RX_DESC(rx_ring,0);+xdp=i40e_rx_bi(rx_ring,0);+ntu=0;}-returnok;+/* clear the status bits for the next_to_use descriptor */+rx_desc->wb.qword1.status_error_len=0;+i40e_release_rx_desc(rx_ring,ntu);++returncount==nb_buffs?true:false;}/**
@@ -365,7 +363,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)break;bi=*i40e_rx_bi(rx_ring,next_to_clean);-bi->data_end=bi->data+size;+xsk_buff_set_size(bi,size);xsk_buff_dma_sync_for_cpu(bi,rx_ring->xsk_pool);xdp_res=i40e_run_xdp_zc(rx_ring,bi);
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:56:57
From: Magnus Karlsson <magnus.karlsson@intel.com>
Optimize for the aligned case by precomputing the parameter values of
the xdp_buff_xsk and xdp_buff structures in the heads array. We can do
this as the heads array size is equal to the number of chunks in the
umem for the aligned case. Then every entry in this array will reflect
a certain chunk/frame and can therefore be prepopulated with the
correct values and we can drop the use of the free_heads stack. Note
that it is not possible to allocate more buffers than what has been
allocated in the aligned case since each chunk can only contain a
single buffer.
We can unfortunately not do this in the unaligned case as one chunk
might contain multiple buffers. In this case, we keep the old scheme
of populating a heads entry every time it is used and using
the free_heads stack.
Also move xp_release() and xp_get_handle() to xsk_buff_pool.h. They
were for some reason in xsk.c even though they are buffer pool
operations.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
include/net/xsk_buff_pool.h | 46 +++++++++++++++++++++++++++++-
net/xdp/xsk.c | 15 ----------
net/xdp/xsk_buff_pool.c | 56 ++++++++++++++++++++++---------------
3 files changed, 79 insertions(+), 38 deletions(-)
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:57:01
From: Magnus Karlsson <magnus.karlsson@intel.com>
Fix missing initialization of the member rx_pkt_nb in the packet
stream. This leads to some tests declaring success too early as the
test thought all packets had already been received.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
tools/testing/selftests/bpf/xdpxceiver.c | 7 +++++++
1 file changed, 7 insertions(+)
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:57:03
From: Magnus Karlsson <magnus.karlsson@intel.com>
Fix a problem where the fill ring was populated with too many
entries. If number of buffers in the umem was smaller than the fill
ring size, the code used to loop over from the beginning of the umem
and start putting the same buffers in again. This is racy indeed as a
later packet can be received overwriting an earlier one before the Rx
thread manages to validate it.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
tools/testing/selftests/bpf/xdpxceiver.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:57:08
From: Magnus Karlsson <magnus.karlsson@intel.com>
Introduce pacing of traffic so that the Tx thread can never send more
packets than the receiver has processed plus the number of packets it
can have in its umem. So at any point in time, the number of in flight
packets (not processed by the Rx thread) are less than or equal to the
number of packets that can be held in the Rx thread's umem.
The batch size is also increased to improve running time.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
tools/testing/selftests/bpf/xdpxceiver.c | 29 +++++++++++++++++++-----
tools/testing/selftests/bpf/xdpxceiver.h | 7 +++++-
2 files changed, 29 insertions(+), 7 deletions(-)
@@ -1126,6 +1141,8 @@ static void testapp_stats(struct test_spec *test)for(i=0;i<STAT_TEST_TYPE_MAX;i++){test_spec_reset(test);stat_test_type=i;+/* No or few packets will be received so cannot pace packets */+test->ifobj_tx->pacing_on=false;switch(stat_test_type){caseSTAT_TEST_RX_DROPPED:
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:57:09
From: Magnus Karlsson <magnus.karlsson@intel.com>
Add a test where a single packet is sent and received. This might
sound like a silly test, but since many of the interfaces in xsk are
batched, it is important to be able to validate that we did not break
something as fundamental as just receiving single packets, instead of
batches of packets at high speed.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
tools/testing/selftests/bpf/xdpxceiver.c | 13 +++++++++++++
tools/testing/selftests/bpf/xdpxceiver.h | 1 +
2 files changed, 14 insertions(+)
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:57:10
From: Magnus Karlsson <magnus.karlsson@intel.com>
The socket creation retry unnecessarily registered the umem once for
every retry. No reason to do this. It wastes memory and it might lead
to too many pages being locked at some point and the failure of a
test.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
tools/testing/selftests/bpf/xdpxceiver.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:57:11
From: Magnus Karlsson <magnus.karlsson@intel.com>
Add a test for the frame_headroom feature that can be set on the
umem. The logic added validates that all offsets in all tests and
packets are valid, not just the ones that have a specifically
configured frame_headroom.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
tools/testing/selftests/bpf/xdpxceiver.c | 52 +++++++++++++++++++-----
tools/testing/selftests/bpf/xdpxceiver.h | 3 +-
2 files changed, 44 insertions(+), 11 deletions(-)
From: Magnus Karlsson <hidden> Date: 2021-09-22 07:57:12
From: Magnus Karlsson <magnus.karlsson@intel.com>
Change the interleaving of packets in unaligned mode. With the current
buffer addresses in the packet stream, the last buffer in the umem
could not be used as a large packet could potentially write over the
end of the umem. The kernel correctly threw this buffer address away
and refused to use it. This is perfectly fine for all regular packet
streams, but the ones used for unaligned mode have every other packet
being at some different offset. As we will add checks for correct
offsets in the next patch, this needs to be fixed. Just start these
page-boundary straddling buffers one page earlier so that the last
one is not on the last page of the umem, making all buffers valid.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
---
tools/testing/selftests/bpf/xdpxceiver.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
@@ -1209,7 +1209,7 @@ static bool testapp_unaligned(struct test_spec *test)test->ifobj_tx->umem->unaligned_mode=true;test->ifobj_rx->umem->unaligned_mode=true;/* Let half of the packets straddle a buffer boundrary */-pkt_stream_replace_half(test,PKT_SIZE,test->ifobj_tx->umem->frame_size-32);+pkt_stream_replace_half(test,PKT_SIZE,-PKT_SIZE/2);test->ifobj_rx->pkt_stream->use_addr_for_fill=true;testapp_validate_traffic(test);
Hello:
This series was applied to bpf/bpf-next.git (refs/heads/master):
On Wed, 22 Sep 2021 09:56:00 +0200 you wrote:
This patch set introduces a batched interface for Rx buffer allocation
in AF_XDP buffer pool. Instead of using xsk_buff_alloc(*pool), drivers
can now use xsk_buff_alloc_batch(*pool, **xdp_buff_array,
max). Instead of returning a pointer to an xdp_buff, it returns the
number of xdp_buffs it managed to allocate up to the maximum value of
the max parameter in the function call. Pointers to the allocated
xdp_buff:s are put in the xdp_buff_array supplied in the call. This
could be a SW ring that already exists in the driver or a new
structure that the driver has allocated.
[...]
On Wed, Sep 22, 2021 at 09:56:06AM +0200, Magnus Karlsson wrote:
From: Magnus Karlsson <magnus.karlsson@intel.com>
Optimize for the aligned case by precomputing the parameter values of
the xdp_buff_xsk and xdp_buff structures in the heads array. We can do
this as the heads array size is equal to the number of chunks in the
umem for the aligned case. Then every entry in this array will reflect
a certain chunk/frame and can therefore be prepopulated with the
correct values and we can drop the use of the free_heads stack. Note
that it is not possible to allocate more buffers than what has been
allocated in the aligned case since each chunk can only contain a
single buffer.
We can unfortunately not do this in the unaligned case as one chunk
might contain multiple buffers. In this case, we keep the old scheme
of populating a heads entry every time it is used and using
the free_heads stack.
Also move xp_release() and xp_get_handle() to xsk_buff_pool.h. They
were for some reason in xsk.c even though they are buffer pool
operations.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
My apologies if this has already been reported (I have not seen a report
on netdev nor a report from Intel around it) but this patch as
commit 94033cd8e73b ("xsk: Optimize for aligned case") in -next causes
the following build failure with clang + x86_64 allmodconfig:
net/xdp/xsk_buff_pool.c:465:15: error: variable 'xskb' is uninitialized when used here [-Werror,-Wuninitialized]
xp_release(xskb);
^~~~
net/xdp/xsk_buff_pool.c:455:27: note: initialize the variable 'xskb' to silence this warning
struct xdp_buff_xsk *xskb;
^
= NULL
1 error generated.
Cheers,
Nathan
From: Magnus Karlsson <hidden> Date: 2021-09-29 05:53:11
On Wed, Sep 29, 2021 at 1:15 AM Nathan Chancellor [off-list ref] wrote:
On Wed, Sep 22, 2021 at 09:56:06AM +0200, Magnus Karlsson wrote:
quoted
From: Magnus Karlsson <magnus.karlsson@intel.com>
Optimize for the aligned case by precomputing the parameter values of
the xdp_buff_xsk and xdp_buff structures in the heads array. We can do
this as the heads array size is equal to the number of chunks in the
umem for the aligned case. Then every entry in this array will reflect
a certain chunk/frame and can therefore be prepopulated with the
correct values and we can drop the use of the free_heads stack. Note
that it is not possible to allocate more buffers than what has been
allocated in the aligned case since each chunk can only contain a
single buffer.
We can unfortunately not do this in the unaligned case as one chunk
might contain multiple buffers. In this case, we keep the old scheme
of populating a heads entry every time it is used and using
the free_heads stack.
Also move xp_release() and xp_get_handle() to xsk_buff_pool.h. They
were for some reason in xsk.c even though they are buffer pool
operations.
Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
My apologies if this has already been reported (I have not seen a report
on netdev nor a report from Intel around it) but this patch as
commit 94033cd8e73b ("xsk: Optimize for aligned case") in -next causes
the following build failure with clang + x86_64 allmodconfig:
net/xdp/xsk_buff_pool.c:465:15: error: variable 'xskb' is uninitialized when used here [-Werror,-Wuninitialized]
xp_release(xskb);
^~~~
net/xdp/xsk_buff_pool.c:455:27: note: initialize the variable 'xskb' to silence this warning
struct xdp_buff_xsk *xskb;
^
= NULL
1 error generated.
Thanks for reporting this Nathan. Will fix right away.
/Magnus