Commit d5581966 authored by Maciej Fijalkowski's avatar Maciej Fijalkowski Committed by Alexei Starovoitov

xsk: support ZC Tx multi-buffer in batch API

Modify xskq_cons_read_desc_batch() in a way that each processed
descriptor will be checked if it is an EOP one or not and act
accordingly to that.

Change the behavior of mentioned function to break the processing when
stumbling upon invalid descriptor instead of skipping it. Furthermore,
let us give only full packets down to ZC driver.
With these two assumptions ZC drivers will not have to take care of an
intermediate state of incomplete frames, which will simplify its
implementations a lot.

Last but not least, stop processing when count of frags would exceed
max supported segments on underlying device.
Signed-off-by: default avatarMaciej Fijalkowski <maciej.fijalkowski@intel.com>
Link: https://lore.kernel.org/r/20230719132421.584801-15-maciej.fijalkowski@intel.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 1c9ba9c1
...@@ -48,6 +48,11 @@ struct xsk_queue { ...@@ -48,6 +48,11 @@ struct xsk_queue {
size_t ring_vmalloc_size; size_t ring_vmalloc_size;
}; };
struct parsed_desc {
u32 mb;
u32 valid;
};
/* The structure of the shared state of the rings are a simple /* The structure of the shared state of the rings are a simple
* circular buffer, as outlined in * circular buffer, as outlined in
* Documentation/core-api/circular-buffers.rst. For the Rx and * Documentation/core-api/circular-buffers.rst. For the Rx and
...@@ -218,30 +223,52 @@ static inline void xskq_cons_release_n(struct xsk_queue *q, u32 cnt) ...@@ -218,30 +223,52 @@ static inline void xskq_cons_release_n(struct xsk_queue *q, u32 cnt)
q->cached_cons += cnt; q->cached_cons += cnt;
} }
static inline u32 xskq_cons_read_desc_batch(struct xsk_queue *q, struct xsk_buff_pool *pool, static inline void parse_desc(struct xsk_queue *q, struct xsk_buff_pool *pool,
u32 max) struct xdp_desc *desc, struct parsed_desc *parsed)
{
parsed->valid = xskq_cons_is_valid_desc(q, desc, pool);
parsed->mb = xp_mb_desc(desc);
}
static inline
u32 xskq_cons_read_desc_batch(struct xsk_queue *q, struct xsk_buff_pool *pool,
u32 max)
{ {
u32 cached_cons = q->cached_cons, nb_entries = 0; u32 cached_cons = q->cached_cons, nb_entries = 0;
struct xdp_desc *descs = pool->tx_descs; struct xdp_desc *descs = pool->tx_descs;
u32 total_descs = 0, nr_frags = 0;
/* track first entry, if stumble upon *any* invalid descriptor, rewind
* current packet that consists of frags and stop the processing
*/
while (cached_cons != q->cached_prod && nb_entries < max) { while (cached_cons != q->cached_prod && nb_entries < max) {
struct xdp_rxtx_ring *ring = (struct xdp_rxtx_ring *)q->ring; struct xdp_rxtx_ring *ring = (struct xdp_rxtx_ring *)q->ring;
u32 idx = cached_cons & q->ring_mask; u32 idx = cached_cons & q->ring_mask;
struct parsed_desc parsed;
descs[nb_entries] = ring->desc[idx]; descs[nb_entries] = ring->desc[idx];
if (unlikely(!xskq_cons_is_valid_desc(q, &descs[nb_entries], pool))) { cached_cons++;
/* Skip the entry */ parse_desc(q, pool, &descs[nb_entries], &parsed);
cached_cons++; if (unlikely(!parsed.valid))
continue; break;
if (likely(!parsed.mb)) {
total_descs += (nr_frags + 1);
nr_frags = 0;
} else {
nr_frags++;
if (nr_frags == pool->netdev->xdp_zc_max_segs) {
nr_frags = 0;
break;
}
} }
nb_entries++; nb_entries++;
cached_cons++;
} }
cached_cons -= nr_frags;
/* Release valid plus any invalid entries */ /* Release valid plus any invalid entries */
xskq_cons_release_n(q, cached_cons - q->cached_cons); xskq_cons_release_n(q, cached_cons - q->cached_cons);
return nb_entries; return total_descs;
} }
/* Functions for consumers */ /* Functions for consumers */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment